2005-09-08 00:09:32 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS system libraries
|
|
|
|
* FILE: lib/rtl/process.c
|
|
|
|
* PURPOSE: Process functions
|
|
|
|
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
|
|
|
* Ariadne (ariadne@xs4all.nl)
|
2010-05-29 18:22:47 +00:00
|
|
|
* Eric Kohl
|
2005-04-02 00:18:46 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ****************************************************************/
|
|
|
|
|
2005-07-26 08:39:07 +00:00
|
|
|
#include <rtl.h>
|
2005-04-02 00:18:46 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
2005-05-08 05:14:46 +00:00
|
|
|
#include <debug.h>
|
2005-04-02 00:18:46 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* INTERNAL FUNCTIONS *******************************************************/
|
2005-04-02 00:18:46 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
NTSTATUS
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2005-04-02 00:18:46 +00:00
|
|
|
RtlpMapFile(PUNICODE_STRING ImageFileName,
|
2005-07-12 04:41:41 +00:00
|
|
|
ULONG Attributes,
|
|
|
|
PHANDLE Section)
|
2005-04-02 00:18:46 +00:00
|
|
|
{
|
2005-07-12 04:41:41 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE hFile = NULL;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
|
|
|
|
/* Open the Image File */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
ImageFileName,
|
|
|
|
Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
Status = ZwOpenFile(&hFile,
|
|
|
|
SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
FILE_SHARE_DELETE | FILE_SHARE_READ,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2013-08-14 14:08:40 +00:00
|
|
|
DPRINT1("Failed to read image file from disk, Status = 0x%08X\n", Status);
|
2010-05-29 20:40:28 +00:00
|
|
|
return Status;
|
2005-07-12 04:41:41 +00:00
|
|
|
}
|
2006-06-11 08:25:10 +00:00
|
|
|
|
|
|
|
/* Now create a section for this image */
|
2005-07-12 04:41:41 +00:00
|
|
|
Status = ZwCreateSection(Section,
|
|
|
|
SECTION_ALL_ACCESS,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
PAGE_EXECUTE,
|
|
|
|
SEC_IMAGE,
|
|
|
|
hFile);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2013-08-14 14:08:40 +00:00
|
|
|
DPRINT1("Failed to create section for image file, Status = 0x%08X\n", Status);
|
2005-07-12 04:41:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ZwClose(hFile);
|
|
|
|
return Status;
|
2005-04-02 00:18:46 +00:00
|
|
|
}
|
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
2005-04-02 00:18:46 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
NTSTATUS
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2005-07-12 04:41:41 +00:00
|
|
|
RtlpInitEnvironment(HANDLE ProcessHandle,
|
|
|
|
PPEB Peb,
|
|
|
|
PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID BaseAddress = NULL;
|
2007-07-28 21:30:16 +00:00
|
|
|
SIZE_T EnviroSize;
|
|
|
|
SIZE_T Size;
|
2005-07-12 04:41:41 +00:00
|
|
|
PWCHAR Environment = 0;
|
2006-06-05 16:41:03 +00:00
|
|
|
DPRINT("RtlpInitEnvironment (hProcess: %p, Peb: %p Params: %p)\n",
|
2005-07-12 04:41:41 +00:00
|
|
|
ProcessHandle, Peb, ProcessParameters);
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Give the caller 1MB if he requested it */
|
2005-11-27 18:24:32 +00:00
|
|
|
if (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB)
|
2005-07-12 04:41:41 +00:00
|
|
|
{
|
|
|
|
/* Give 1MB starting at 0x4 */
|
|
|
|
BaseAddress = (PVOID)4;
|
[NTOS]: Blimey this was a hard one. When using the reserved flag to request 1MB in a new process (which is used for starting SMSS and CSRSS), we must request 1MB - 256 bytes (or any number, actually) to offset the fact that with a base address of 0x4, a 1MB region gets us at 0x100FFF, and not 0xFFFF, because Windows computes ending address *before* alignment, and then returns a new region size for you (so if you pass in 1MB, you get 1MB + 4096KB). In Win32csr, when the code is trying to release 1MB, this ended up in our "Case A", because it would still leave a page in the VAD. Fixed rtl to request just shy off a MB. Verified on Windows as well.
[NTOS]: The fix above was due to fixing "EndingAddress" which was being initialized to zero too late (after writing to it!). This caused allocations with a fixed base address that were already on top of another allocation not to be seen as a conflict, then we tried inserting a VAD and received an ASSERT saying we've already found a VAD there. After fixing the sizing code, the bug above creeped up.
Whoever wrote the NtFreeVirtualMemory test is a godsend. It has been nailing bug after bug in the VAD implementation. Thank you.
svn path=/trunk/; revision=55990
2012-03-04 06:42:49 +00:00
|
|
|
EnviroSize = (1024 * 1024) - 256;
|
2005-07-12 04:41:41 +00:00
|
|
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
|
|
|
&BaseAddress,
|
|
|
|
0,
|
|
|
|
&EnviroSize,
|
|
|
|
MEM_RESERVE,
|
|
|
|
PAGE_READWRITE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to reserve 1MB of space \n");
|
2010-05-29 20:40:28 +00:00
|
|
|
return Status;
|
2005-07-12 04:41:41 +00:00
|
|
|
}
|
|
|
|
}
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Find the end of the Enviroment Block */
|
|
|
|
if ((Environment = (PWCHAR)ProcessParameters->Environment))
|
|
|
|
{
|
|
|
|
while (*Environment++) while (*Environment++);
|
|
|
|
|
|
|
|
/* Calculate the size of the block */
|
|
|
|
EnviroSize = (ULONG)((ULONG_PTR)Environment -
|
|
|
|
(ULONG_PTR)ProcessParameters->Environment);
|
|
|
|
|
|
|
|
/* Allocate and Initialize new Environment Block */
|
|
|
|
Size = EnviroSize;
|
|
|
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
|
|
|
&BaseAddress,
|
|
|
|
0,
|
|
|
|
&Size,
|
|
|
|
MEM_RESERVE | MEM_COMMIT,
|
|
|
|
PAGE_READWRITE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to allocate Environment Block\n");
|
2010-05-29 20:40:28 +00:00
|
|
|
return Status;
|
2005-07-12 04:41:41 +00:00
|
|
|
}
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Write the Environment Block */
|
|
|
|
ZwWriteVirtualMemory(ProcessHandle,
|
|
|
|
BaseAddress,
|
|
|
|
ProcessParameters->Environment,
|
|
|
|
EnviroSize,
|
|
|
|
NULL);
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Save pointer */
|
|
|
|
ProcessParameters->Environment = BaseAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now allocate space for the Parameter Block */
|
|
|
|
BaseAddress = NULL;
|
2006-06-11 08:25:10 +00:00
|
|
|
Size = ProcessParameters->MaximumLength;
|
2005-07-12 04:41:41 +00:00
|
|
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
|
|
|
&BaseAddress,
|
|
|
|
0,
|
|
|
|
&Size,
|
|
|
|
MEM_COMMIT,
|
|
|
|
PAGE_READWRITE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to allocate Parameter Block\n");
|
2010-05-29 20:40:28 +00:00
|
|
|
return Status;
|
2005-07-12 04:41:41 +00:00
|
|
|
}
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Write the Parameter Block */
|
|
|
|
ZwWriteVirtualMemory(ProcessHandle,
|
|
|
|
BaseAddress,
|
|
|
|
ProcessParameters,
|
|
|
|
ProcessParameters->Length,
|
|
|
|
NULL);
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Write pointer to Parameter Block */
|
|
|
|
ZwWriteVirtualMemory(ProcessHandle,
|
|
|
|
&Peb->ProcessParameters,
|
|
|
|
&BaseAddress,
|
|
|
|
sizeof(BaseAddress),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Return */
|
|
|
|
return STATUS_SUCCESS;
|
2005-04-02 00:18:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*
|
|
|
|
* Creates a process and its initial thread.
|
|
|
|
*
|
|
|
|
* NOTES:
|
|
|
|
* - The first thread is created suspended, so it needs a manual resume!!!
|
|
|
|
* - If ParentProcess is NULL, current process is used
|
|
|
|
* - ProcessParameters must be normalized
|
2005-05-09 01:41:02 +00:00
|
|
|
* - Attributes are object attribute flags used when opening the ImageFileName.
|
2005-04-02 00:18:46 +00:00
|
|
|
* Valid flags are OBJ_INHERIT and OBJ_CASE_INSENSITIVE.
|
|
|
|
*
|
|
|
|
* -Gunnar
|
|
|
|
*/
|
2005-07-12 04:41:41 +00:00
|
|
|
NTSTATUS
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2005-07-12 04:41:41 +00:00
|
|
|
RtlCreateUserProcess(IN PUNICODE_STRING ImageFileName,
|
|
|
|
IN ULONG Attributes,
|
|
|
|
IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
|
|
|
|
IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
|
|
|
|
IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
|
|
|
|
IN HANDLE ParentProcess OPTIONAL,
|
|
|
|
IN BOOLEAN InheritHandles,
|
|
|
|
IN HANDLE DebugPort OPTIONAL,
|
|
|
|
IN HANDLE ExceptionPort OPTIONAL,
|
|
|
|
OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo)
|
2005-04-02 00:18:46 +00:00
|
|
|
{
|
2005-07-12 04:41:41 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE hSection;
|
|
|
|
PROCESS_BASIC_INFORMATION ProcessBasicInfo;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
2008-07-27 05:39:17 +00:00
|
|
|
UNICODE_STRING DebugString = RTL_CONSTANT_STRING(L"\\WindowsSS");
|
2005-07-12 04:41:41 +00:00
|
|
|
DPRINT("RtlCreateUserProcess: %wZ\n", ImageFileName);
|
|
|
|
|
|
|
|
/* Map and Load the File */
|
|
|
|
Status = RtlpMapFile(ImageFileName,
|
|
|
|
Attributes,
|
|
|
|
&hSection);
|
2012-08-22 11:35:19 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2005-07-12 04:41:41 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Could not map process image\n");
|
|
|
|
return Status;
|
|
|
|
}
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Clean out the CurDir Handle if we won't use it */
|
|
|
|
if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL;
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Use us as parent if none other specified */
|
|
|
|
if (!ParentProcess) ParentProcess = NtCurrentProcess();
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Initialize the Object Attributes */
|
2007-10-19 23:21:45 +00:00
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
NULL,
|
|
|
|
0,
|
2005-07-12 04:41:41 +00:00
|
|
|
NULL,
|
|
|
|
ProcessSecurityDescriptor);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If FLG_ENABLE_CSRDEBUG is used, then CSRSS is created under the
|
|
|
|
* watch of WindowsSS
|
|
|
|
*/
|
|
|
|
if ((RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG) &&
|
|
|
|
(wcsstr(ImageFileName->Buffer, L"csrss")))
|
|
|
|
{
|
2006-11-27 14:26:48 +00:00
|
|
|
ObjectAttributes.ObjectName = &DebugString;
|
2005-07-12 04:41:41 +00:00
|
|
|
}
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Create Kernel Process Object */
|
|
|
|
Status = ZwCreateProcess(&ProcessInfo->ProcessHandle,
|
|
|
|
PROCESS_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
|
|
|
ParentProcess,
|
|
|
|
InheritHandles,
|
|
|
|
hSection,
|
|
|
|
DebugPort,
|
|
|
|
ExceptionPort);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Could not create Kernel Process Object\n");
|
|
|
|
ZwClose(hSection);
|
2010-05-29 20:40:28 +00:00
|
|
|
return Status;
|
2005-07-12 04:41:41 +00:00
|
|
|
}
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Get some information on the image */
|
|
|
|
Status = ZwQuerySection(hSection,
|
|
|
|
SectionImageInformation,
|
|
|
|
&ProcessInfo->ImageInformation,
|
|
|
|
sizeof(SECTION_IMAGE_INFORMATION),
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Could not query Section Info\n");
|
|
|
|
ZwClose(ProcessInfo->ProcessHandle);
|
|
|
|
ZwClose(hSection);
|
2010-05-29 20:40:28 +00:00
|
|
|
return Status;
|
2005-07-12 04:41:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get some information about the process */
|
2012-08-22 11:35:19 +00:00
|
|
|
Status = ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
|
|
|
|
ProcessBasicInformation,
|
|
|
|
&ProcessBasicInfo,
|
|
|
|
sizeof(ProcessBasicInfo),
|
|
|
|
NULL);
|
2005-07-12 04:41:41 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Could not query Process Info\n");
|
|
|
|
ZwClose(ProcessInfo->ProcessHandle);
|
|
|
|
ZwClose(hSection);
|
2010-05-29 20:40:28 +00:00
|
|
|
return Status;
|
2006-06-11 08:25:10 +00:00
|
|
|
}
|
2005-07-12 04:41:41 +00:00
|
|
|
|
|
|
|
/* Create Process Environment */
|
|
|
|
RtlpInitEnvironment(ProcessInfo->ProcessHandle,
|
|
|
|
ProcessBasicInfo.PebBaseAddress,
|
|
|
|
ProcessParameters);
|
|
|
|
|
|
|
|
/* Create the first Thread */
|
|
|
|
Status = RtlCreateUserThread(ProcessInfo->ProcessHandle,
|
|
|
|
ThreadSecurityDescriptor,
|
|
|
|
TRUE,
|
|
|
|
ProcessInfo->ImageInformation.ZeroBits,
|
|
|
|
ProcessInfo->ImageInformation.MaximumStackSize,
|
|
|
|
ProcessInfo->ImageInformation.CommittedStackSize,
|
|
|
|
ProcessInfo->ImageInformation.TransferAddress,
|
|
|
|
ProcessBasicInfo.PebBaseAddress,
|
|
|
|
&ProcessInfo->ThreadHandle,
|
|
|
|
&ProcessInfo->ClientId);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Could not Create Thread\n");
|
|
|
|
ZwClose(ProcessInfo->ProcessHandle);
|
|
|
|
ZwClose(hSection); /* Don't try to optimize this on top! */
|
|
|
|
return Status;
|
|
|
|
}
|
2006-06-11 08:25:10 +00:00
|
|
|
|
2005-07-12 04:41:41 +00:00
|
|
|
/* Close the Section Handle and return */
|
|
|
|
ZwClose(hSection);
|
|
|
|
return STATUS_SUCCESS;
|
2005-04-02 00:18:46 +00:00
|
|
|
}
|
|
|
|
|
2005-09-08 00:09:32 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PVOID
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2005-09-08 00:09:32 +00:00
|
|
|
RtlEncodePointer(IN PVOID Pointer)
|
|
|
|
{
|
2010-05-29 20:40:28 +00:00
|
|
|
ULONG Cookie;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = ZwQueryInformationProcess(NtCurrentProcess(),
|
|
|
|
ProcessCookie,
|
|
|
|
&Cookie,
|
|
|
|
sizeof(Cookie),
|
|
|
|
NULL);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to receive the process cookie! Status: 0x%lx\n", Status);
|
|
|
|
return Pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (PVOID)((ULONG_PTR)Pointer ^ Cookie);
|
2005-09-08 00:09:32 +00:00
|
|
|
}
|
|
|
|
|
2009-05-04 13:26:24 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PVOID
|
|
|
|
NTAPI
|
|
|
|
RtlDecodePointer(IN PVOID Pointer)
|
|
|
|
{
|
2010-05-29 20:40:28 +00:00
|
|
|
return RtlEncodePointer(Pointer);
|
2009-05-04 13:26:24 +00:00
|
|
|
}
|
|
|
|
|
2008-09-12 15:09:17 +00:00
|
|
|
/*
|
2010-05-29 21:15:48 +00:00
|
|
|
* @implemented
|
2008-09-12 15:09:17 +00:00
|
|
|
*/
|
|
|
|
PVOID
|
|
|
|
NTAPI
|
|
|
|
RtlEncodeSystemPointer(IN PVOID Pointer)
|
|
|
|
{
|
2010-05-29 21:15:48 +00:00
|
|
|
return (PVOID)((ULONG_PTR)Pointer ^ SharedUserData->Cookie);
|
2008-09-12 15:09:17 +00:00
|
|
|
}
|
|
|
|
|
2005-10-02 15:50:30 +00:00
|
|
|
/*
|
2010-05-29 18:22:47 +00:00
|
|
|
* @implemented
|
|
|
|
*
|
|
|
|
* NOTES:
|
|
|
|
* Implementation based on the documentation from:
|
|
|
|
* http://www.geoffchappell.com/studies/windows/win32/ntdll/api/rtl/peb/setprocessiscritical.htm
|
2005-10-02 15:50:30 +00:00
|
|
|
*/
|
2010-05-29 18:22:47 +00:00
|
|
|
NTSTATUS
|
2014-01-07 20:23:44 +00:00
|
|
|
__cdecl
|
2010-05-29 18:22:47 +00:00
|
|
|
RtlSetProcessIsCritical(IN BOOLEAN NewValue,
|
|
|
|
OUT PBOOLEAN OldValue OPTIONAL,
|
|
|
|
IN BOOLEAN NeedBreaks)
|
2005-10-02 15:50:30 +00:00
|
|
|
{
|
2012-01-30 01:14:33 +00:00
|
|
|
ULONG BreakOnTermination;
|
2010-05-29 18:22:47 +00:00
|
|
|
|
2012-01-30 01:14:33 +00:00
|
|
|
/* Initialize to FALSE */
|
|
|
|
if (OldValue) *OldValue = FALSE;
|
2010-05-29 18:22:47 +00:00
|
|
|
|
|
|
|
/* Fail, if the critical breaks flag is required but is not set */
|
2012-01-30 01:14:33 +00:00
|
|
|
if ((NeedBreaks) &&
|
2010-05-29 18:22:47 +00:00
|
|
|
!(NtCurrentPeb()->NtGlobalFlag & FLG_ENABLE_SYSTEM_CRIT_BREAKS))
|
2012-01-30 01:14:33 +00:00
|
|
|
{
|
2010-05-29 18:22:47 +00:00
|
|
|
return STATUS_UNSUCCESSFUL;
|
2012-01-30 01:14:33 +00:00
|
|
|
}
|
2010-05-29 18:22:47 +00:00
|
|
|
|
2012-01-30 01:14:33 +00:00
|
|
|
/* Check if the caller wants the old value */
|
2010-05-29 18:22:47 +00:00
|
|
|
if (OldValue)
|
|
|
|
{
|
|
|
|
/* Query and return the old break on termination flag for the process */
|
|
|
|
ZwQueryInformationProcess(NtCurrentProcess(),
|
|
|
|
ProcessBreakOnTermination,
|
|
|
|
&BreakOnTermination,
|
|
|
|
sizeof(ULONG),
|
|
|
|
NULL);
|
|
|
|
*OldValue = (BOOLEAN)BreakOnTermination;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the break on termination flag for the process */
|
|
|
|
BreakOnTermination = NewValue;
|
|
|
|
return ZwSetInformationProcess(NtCurrentProcess(),
|
|
|
|
ProcessBreakOnTermination,
|
|
|
|
&BreakOnTermination,
|
|
|
|
sizeof(ULONG));
|
2005-10-02 15:50:30 +00:00
|
|
|
}
|
|
|
|
|
2008-09-12 15:09:17 +00:00
|
|
|
ULONG
|
|
|
|
NTAPI
|
|
|
|
RtlGetCurrentProcessorNumber(VOID)
|
|
|
|
{
|
|
|
|
/* Forward to kernel */
|
|
|
|
return NtGetCurrentProcessorNumber();
|
|
|
|
}
|