[CSRSRV/KERNEL32]: Do the Windows thing and send a unified LPC message when a new process is created, which includes the thread information as well, instead of sending two LPC messages per process. Perf++.

[CSRSRV/kERNEL32]: Switch to using the Windows CSRSS message structure for a new process, minus the bInheritHandles field which we still support for ReactOS compatibility.
[CSRSRV]: Port CsrCreateProcess from CSRSRV2, rewrite CsrSrvCreateProcess to use this API, and add required ReactOS compatibility hacks. A lot of stuff is still not supported, but the minimum (ie: previous ReactOS functionality) has been maintained during the transition. Processes are now tracked correctly, but there are still refcount leaks (known, to be fixed later).
Will let this breathe for a bit now to catch regressions. Work can now continue back on the kernel32 side while that happens.

svn path=/trunk/; revision=55711
This commit is contained in:
Alex Ionescu 2012-02-19 11:39:07 +00:00
parent 83ad639dc9
commit 2a5d344d96
6 changed files with 367 additions and 131 deletions

View file

@ -485,42 +485,6 @@ BaseProcessStartup(PPROCESS_START_ROUTINE lpStartAddress)
ExitProcess(uExitCode);
}
/*
* Tells CSR that a new process was created
*/
NTSTATUS
WINAPI
BasepNotifyCsrOfCreation(ULONG dwCreationFlags,
IN HANDLE ProcessId,
IN BOOL InheritHandles)
{
ULONG Request = CREATE_PROCESS;
CSR_API_MESSAGE CsrRequest;
NTSTATUS Status;
DPRINT("BasepNotifyCsrOfCreation: Process: %lx, Flags %lx\n",
ProcessId, dwCreationFlags);
/* Fill out the request */
CsrRequest.Data.CreateProcessRequest.NewProcessId = ProcessId;
CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags;
CsrRequest.Data.CreateProcessRequest.bInheritHandles = InheritHandles;
/* Call CSR */
Status = CsrClientCallServer(&CsrRequest,
NULL,
MAKE_CSR_API(Request, CSR_NATIVE),
sizeof(CSR_API_MESSAGE));
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
{
DPRINT1("Failed to tell csrss about new process: %lx %lx\n", Status, CsrRequest.Status);
return CsrRequest.Status;
}
/* Return Success */
return STATUS_SUCCESS;
}
NTSTATUS
WINAPI
BasepNotifyCsrOfThread(IN HANDLE ThreadHandle,
@ -560,7 +524,9 @@ WINAPI
BasepCreateFirstThread(HANDLE ProcessHandle,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
PSECTION_IMAGE_INFORMATION SectionImageInfo,
PCLIENT_ID ClientId)
PCLIENT_ID ClientId,
BOOLEAN InheritHandles,
DWORD dwCreationFlags)
{
OBJECT_ATTRIBUTES LocalObjectAttributes;
POBJECT_ATTRIBUTES ObjectAttributes;
@ -568,7 +534,8 @@ BasepCreateFirstThread(HANDLE ProcessHandle,
INITIAL_TEB InitialTeb;
NTSTATUS Status;
HANDLE hThread;
ULONG Request = CREATE_PROCESS;
CSR_API_MESSAGE CsrRequest;
DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle);
/* Create the Thread's Stack */
@ -603,10 +570,22 @@ BasepCreateFirstThread(HANDLE ProcessHandle,
return NULL;
}
Status = BasepNotifyCsrOfThread(hThread, ClientId);
if (!NT_SUCCESS(Status))
/* Fill out the request to notify CSRSS */
CsrRequest.Data.CreateProcessRequest.ClientId = *ClientId;
CsrRequest.Data.CreateProcessRequest.ProcessHandle = ProcessHandle;
CsrRequest.Data.CreateProcessRequest.ThreadHandle = hThread;
CsrRequest.Data.CreateProcessRequest.CreationFlags = dwCreationFlags;
CsrRequest.Data.CreateProcessRequest.bInheritHandles = InheritHandles;
/* Call CSR */
Status = CsrClientCallServer(&CsrRequest,
NULL,
MAKE_CSR_API(Request, CSR_NATIVE),
sizeof(CSR_API_MESSAGE));
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
{
ASSERT(FALSE);
DPRINT1("Failed to tell csrss about new process: %lx %lx\n", Status, CsrRequest.Status);
return NULL;
}
/* Success */
@ -3240,25 +3219,15 @@ GetAppName:
&RemoteParameters->StandardError);
}
/* Notify CSRSS */
Status = BasepNotifyCsrOfCreation(dwCreationFlags,
(HANDLE)ProcessBasicInfo.UniqueProcessId,
bInheritHandles);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSR Notification Failed\n");
BaseSetLastNTError(Status);
goto Cleanup;
}
/* Create the first thread */
DPRINT("Creating thread for process (EntryPoint = 0x%p)\n",
SectionImageInfo.TransferAddress);
hThread = BasepCreateFirstThread(hProcess,
lpThreadAttributes,
&SectionImageInfo,
&ClientId);
&ClientId,
bInheritHandles,
dwCreationFlags);
if (hThread == NULL)
{

View file

@ -69,8 +69,6 @@ typedef struct
//
// ReactOS Data
//
HANDLE NewProcessId;
ULONG Flags;
BOOL bInheritHandles;
} CSRSS_CREATE_PROCESS, *PCSRSS_CREATE_PROCESS;

View file

@ -31,58 +31,6 @@ PCSR_PROCESS WINAPI CsrGetProcessData(HANDLE ProcessId)
return CsrProcess;
}
PCSR_PROCESS WINAPI CsrCreateProcessData(HANDLE ProcessId)
{
PCSR_PROCESS pProcessData;
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientId;
NTSTATUS Status;
LOCK;
pProcessData = CsrAllocateProcess();
ASSERT(pProcessData != NULL);
pProcessData->ClientId.UniqueProcess = ProcessId;
ClientId.UniqueThread = NULL;
ClientId.UniqueProcess = pProcessData->ClientId.UniqueProcess;
InitializeObjectAttributes(&ObjectAttributes,
NULL,
0,
NULL,
NULL);
/* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */
Status = NtOpenProcess(&pProcessData->ProcessHandle,
PROCESS_ALL_ACCESS,
&ObjectAttributes,
&ClientId);
DPRINT("CSR Process: %p Handle: %p\n", pProcessData, pProcessData->ProcessHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed\n");
CsrDeallocateProcess(pProcessData);
CsrReleaseProcessLock();
return NULL;
}
else
{
RtlInitializeCriticalSection(&pProcessData->HandleTableLock);
}
/* Set default shutdown parameters */
pProcessData->ShutdownLevel = 0x280;
pProcessData->ShutdownFlags = 0;
/* Insert the Process */
CsrInsertProcess(NULL, NULL, pProcessData);
/* Release lock and return */
CsrReleaseProcessLock();
return pProcessData;
}
NTSTATUS WINAPI CsrFreeProcessData(HANDLE Pid)
{
PCSR_PROCESS pProcessData;
@ -135,34 +83,114 @@ NTSTATUS WINAPI CsrFreeProcessData(HANDLE Pid)
* CSRSS API
*********************************************************************/
CSR_API(CsrCreateProcess)
CSR_API(CsrSrvCreateProcess)
{
PCSR_PROCESS NewProcessData;
NTSTATUS Status;
HANDLE ProcessHandle, ThreadHandle;
PCSR_THREAD CsrThread;
PCSR_PROCESS NewProcessData;
ULONG Flags, VdmPower = 0, DebugFlags = 0;
NewProcessData = CsrCreateProcessData(Request->Data.CreateProcessRequest.NewProcessId);
if (NewProcessData == NULL)
/* Get the current client thread */
CsrThread = NtCurrentTeb()->CsrClientThread;
ASSERT(CsrThread != NULL);
/* Extract the flags out of the process handle */
Flags = (ULONG_PTR)Request->Data.CreateProcessRequest.ProcessHandle & 3;
Request->Data.CreateProcessRequest.ProcessHandle = (HANDLE)((ULONG_PTR)Request->Data.CreateProcessRequest.ProcessHandle & ~3);
/* Duplicate the process handle */
Status = NtDuplicateObject(CsrThread->Process->ProcessHandle,
Request->Data.CreateProcessRequest.ProcessHandle,
NtCurrentProcess(),
&ProcessHandle,
0,
0,
DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status))
{
return(STATUS_NO_MEMORY);
DPRINT1("Failed to duplicate process handle\n");
return Status;
}
if (!(Request->Data.CreateProcessRequest.Flags & (CREATE_NEW_CONSOLE|DETACHED_PROCESS)))
{
NewProcessData->ParentConsole = ProcessData->Console;
NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles;
}
CallProcessCreated(ProcessData, NewProcessData);
/* Duplicate the thread handle */
Status = NtDuplicateObject(CsrThread->Process->ProcessHandle,
Request->Data.CreateProcessRequest.ThreadHandle,
NtCurrentProcess(),
&ThreadHandle,
0,
0,
DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to duplicate process handle\n");
NtClose(ProcessHandle);
return Status;
}
if (Request->Data.CreateProcessRequest.Flags & CREATE_NEW_PROCESS_GROUP)
{
NewProcessData->ProcessGroupId = (DWORD)(ULONG_PTR)NewProcessData->ClientId.UniqueProcess;
}
else
{
NewProcessData->ProcessGroupId = ProcessData->ProcessGroupId;
}
/* See if this is a VDM process */
if (VdmPower)
{
/* Request VDM powers */
Status = NtSetInformationProcess(ProcessHandle,
ProcessWx86Information,
&VdmPower,
sizeof(VdmPower));
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get VDM powers\n");
NtClose(ProcessHandle);
NtClose(ThreadHandle);
return Status;
}
}
/* Convert some flags. FIXME: More need conversion */
if (Request->Data.CreateProcessRequest.CreationFlags & CREATE_NEW_PROCESS_GROUP)
{
DebugFlags |= CsrProcessCreateNewGroup;
}
return(STATUS_SUCCESS);
/* FIXME: SxS Stuff */
/* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */
Status = CsrCreateProcess(ProcessHandle,
ThreadHandle,
&Request->Data.CreateProcessRequest.ClientId,
CsrThread->Process->NtSession,
DebugFlags,
NULL);
if (Status == STATUS_THREAD_IS_TERMINATING)
{
DPRINT1("Thread already dead\n");
return Status;
}
/* Check for other failures */
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create process/thread structures: %lx\n", Status);
return Status;
}
/* FIXME: Should notify user32 */
/* FIXME: VDM vodoo */
/* ReactOS Compatibility */
Status = CsrLockProcessByClientId(Request->Data.CreateProcessRequest.ClientId.UniqueProcess, &NewProcessData);
ASSERT(Status == STATUS_SUCCESS);
if (!(Request->Data.CreateProcessRequest.CreationFlags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)))
{
NewProcessData->ParentConsole = ProcessData->Console;
NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles;
}
RtlInitializeCriticalSection(&NewProcessData->HandleTableLock);
CallProcessCreated(ProcessData, NewProcessData);
CsrUnlockProcess(NewProcessData);
/* Return the result of this operation */
return Status;
}
CSR_API(CsrSrvCreateThread)

View file

@ -86,7 +86,7 @@ CallProcessCreated(IN PCSR_PROCESS SourceProcessData,
CSRSS_API_DEFINITION NativeDefinitions[] =
{
CSRSS_DEFINE_API(CREATE_PROCESS, CsrCreateProcess),
CSRSS_DEFINE_API(CREATE_PROCESS, CsrSrvCreateProcess),
CSRSS_DEFINE_API(CREATE_THREAD, CsrSrvCreateThread),
CSRSS_DEFINE_API(TERMINATE_PROCESS, CsrTerminateProcess),
CSRSS_DEFINE_API(CONNECT_PROCESS, CsrConnectProcess),

View file

@ -497,6 +497,219 @@ CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess)
}
}
/*++
* @name CsrCreateProcess
* @implemented NT4
*
* Do nothing for 500ms.
*
* @param ArgumentCount
* Description of the parameter. Wrapped to more lines on ~70th
* column.
*
* @param Arguments
* Description of the parameter. Wrapped to more lines on ~70th
* column.
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
* othwerwise.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrCreateProcess(IN HANDLE hProcess,
IN HANDLE hThread,
IN PCLIENT_ID ClientId,
IN PCSR_NT_SESSION NtSession,
IN ULONG Flags,
IN PCLIENT_ID DebugCid)
{
PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
CLIENT_ID CurrentCid;
PCSR_PROCESS CurrentProcess;
// PVOID ProcessData;
// ULONG i;
PCSR_PROCESS CsrProcess;
NTSTATUS Status;
PCSR_THREAD CsrThread;
KERNEL_USER_TIMES KernelTimes;
/* Get the current CID and lock Processes */
CurrentCid = CurrentThread->ClientId;
CsrAcquireProcessLock();
/* Get the current CSR Thread */
CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid);
if (!CurrentThread)
{
/* We've failed to locate the thread */
CsrReleaseProcessLock();
return STATUS_THREAD_IS_TERMINATING;
}
/* Allocate a new Process Object */
CsrProcess = CsrAllocateProcess();
if (!CsrProcess)
{
/* Couldn't allocate Process */
CsrReleaseProcessLock();
return STATUS_NO_MEMORY;
}
#if 0
/* Inherit the Process Data */
CurrentProcess = CurrentThread->Process;
ProcessData = &CurrentProcess->ServerData[CSR_SERVER_DLL_MAX];
for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
{
/* Check if the DLL is Loaded and has Per Process Data */
if ((CsrLoadedServerDll[i]) && (CsrLoadedServerDll[i]->SizeOfProcessData))
{
/* Set the pointer */
CsrProcess->ServerData[i] = ProcessData;
/* Copy the Data */
RtlMoveMemory(ProcessData,
CurrentProcess->ServerData[i],
CsrLoadedServerDll[i]->SizeOfProcessData);
/* Update next data pointer */
ProcessData = (PVOID)((ULONG_PTR)ProcessData +
CsrLoadedServerDll[i]->SizeOfProcessData);
}
else
{
/* No data for this Server */
CsrProcess->ServerData[i] = NULL;
}
}
#endif
/* Set the Exception port to us */
Status = NtSetInformationProcess(hProcess,
ProcessExceptionPort,
&CsrApiPort,
sizeof(HANDLE));
if (!NT_SUCCESS(Status))
{
/* Failed */
CsrDeallocateProcess(CsrProcess);
CsrReleaseProcessLock();
return STATUS_NO_MEMORY;
}
/* If Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */
if (!(Flags & CsrProcessCreateNewGroup))
{
/* Create new data */
CsrProcess->ProcessGroupId = HandleToUlong(ClientId->UniqueProcess);
CsrProcess->ProcessGroupSequence = CsrProcess->SequenceNumber;
}
else
{
/* Copy it from the current process */
CsrProcess->ProcessGroupId = CurrentProcess->ProcessGroupId;
CsrProcess->ProcessGroupSequence = CurrentProcess->ProcessGroupSequence;
}
/* Check if this is a console process */
if (Flags & CsrProcessIsConsoleApp) CsrProcess->Flags |= CsrProcessIsConsoleApp;
/* Mask out non-debug flags */
Flags &= ~(CsrProcessIsConsoleApp | CsrProcessCreateNewGroup | CsrProcessPriorityFlags);
/* Check if every process will be debugged */
if (!(Flags) && (CurrentProcess->DebugFlags & CsrDebugProcessChildren))
{
/* Pass it on to the current process */
CsrProcess->DebugFlags = CsrDebugProcessChildren;
CsrProcess->DebugCid = CurrentProcess->DebugCid;
}
/* Check if Debugging was used on this process */
if ((Flags & (CsrDebugOnlyThisProcess | CsrDebugProcessChildren)) && (DebugCid))
{
/* Save the debug flag used */
CsrProcess->DebugFlags = Flags;
/* Save the CID */
CsrProcess->DebugCid = *DebugCid;
}
/* Check if we debugging is enabled */
if (CsrProcess->DebugFlags)
{
/* Set the Debug Port to us */
Status = NtSetInformationProcess(hProcess,
ProcessDebugPort,
&CsrApiPort,
sizeof(HANDLE));
ASSERT(NT_SUCCESS(Status));
if (!NT_SUCCESS(Status))
{
/* Failed */
CsrDeallocateProcess(CsrProcess);
CsrReleaseProcessLock();
return STATUS_NO_MEMORY;
}
}
/* Get the Thread Create Time */
Status = NtQueryInformationThread(hThread,
ThreadTimes,
(PVOID)&KernelTimes,
sizeof(KernelTimes),
NULL);
if (!NT_SUCCESS(Status))
{
/* Failed */
CsrDeallocateProcess(CsrProcess);
CsrReleaseProcessLock();
return STATUS_NO_MEMORY;
}
/* Allocate a CSR Thread Structure */
CsrThread = CsrAllocateThread(CsrProcess);
if (!CsrThread)
{
/* Failed */
CsrDeallocateProcess(CsrProcess);
CsrReleaseProcessLock();
return STATUS_NO_MEMORY;
}
/* Save the data we have */
CsrThread->CreateTime = KernelTimes.CreateTime;
CsrThread->ClientId = *ClientId;
CsrThread->ThreadHandle = hThread;
ProtectHandle(hThread);
CsrThread->Flags = 0;
/* Insert the Thread into the Process */
CsrInsertThread(CsrProcess, CsrThread);
/* Reference the session */
CsrReferenceNtSession(NtSession);
CsrProcess->NtSession = NtSession;
/* Setup Process Data */
CsrProcess->ClientId = *ClientId;
CsrProcess->ProcessHandle = hProcess;
CsrProcess->ShutdownLevel = 0x280;
/* Set the Priority to Background */
CsrSetBackgroundPriority(CsrProcess);
/* Insert the Process */
CsrInsertProcess(NULL, CurrentProcess, CsrProcess);
/* Release lock and return */
CsrReleaseProcessLock();
return Status;
}
/*++
* @name CsrUnlockProcess
* @implemented NT4

View file

@ -56,16 +56,31 @@ typedef enum _CSR_SHUTDOWN_FLAGS
CsrShutdownOther = 8
} CSR_SHUTDOWN_FLAGS, *PCSR_SHUTDOWN_FLAGS;
typedef enum _CSR_DEBUG_FLAGS
{
CsrDebugOnlyThisProcess = 1,
CsrDebugProcessChildren = 2
} CSR_PROCESS_DEBUG_FLAGS, *PCSR_PROCESS_DEBUG_FLAGS;
typedef enum _CSR_PROCESS_FLAGS
{
CsrProcessTerminating = 0x1,
CsrProcessSkipShutdown = 0x2,
CsrProcessNormalPriority = 0x10,
CsrProcessIdlePriority = 0x20,
CsrProcessHighPriority = 0x40,
CsrProcessRealtimePriority = 0x80,
CsrProcessCreateNewGroup = 0x100,
CsrProcessTerminated = 0x200,
CsrProcessLastThreadTerminated = 0x400,
CsrProcessIsConsoleApp = 0x800
} CSR_PROCESS_FLAGS, *PCSR_PROCESS_FLAGS;
#define CsrProcessPriorityFlags (CsrProcessNormalPriority | \
CsrProcessIdlePriority | \
CsrProcessHighPriority | \
CsrProcessRealtimePriority)
typedef struct _CSRSS_CON_PROCESS_DATA
{
HANDLE ConsoleEvent;
@ -251,7 +266,7 @@ NTSTATUS NTAPI CsrServerInitialization(ULONG ArgumentCount, PCHAR Arguments[]);
/* api/process.c */
CSR_API(CsrConnectProcess);
CSR_API(CsrCreateProcess);
CSR_API(CsrSrvCreateProcess);
CSR_API(CsrTerminateProcess);
CSR_API(CsrSrvCreateThread);
CSR_API(CsrGetShutdownParameters);
@ -319,6 +334,15 @@ NTSTATUS
NTAPI
CsrApiPortInitialize(VOID);
NTSTATUS
NTAPI
CsrCreateProcess(IN HANDLE hProcess,
IN HANDLE hThread,
IN PCLIENT_ID ClientId,
IN PCSR_NT_SESSION NtSession,
IN ULONG Flags,
IN PCLIENT_ID DebugCid);
BOOLEAN
NTAPI
ProtectHandle(IN HANDLE ObjectHandle);
@ -391,6 +415,10 @@ CsrSrvSetPriorityClass(
IN OUT PULONG Reply
);
VOID
NTAPI
CsrReferenceNtSession(IN PCSR_NT_SESSION Session);
LONG
NTAPI
CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo);