mirror of
https://github.com/reactos/reactos.git
synced 2024-08-07 19:58:21 +00:00
[KERNEL32]: Implement CreateJobSet
[KERNEL32]: Acquire SE_INCREASE_WORKING_SET_PRIVILEGE in SetInformationJobObject if needed. [KERNEL32]: Only do conversion of Process Priority Class in SetInformationJobObject if the limit flags request it. [KERNEL32]: Add missing size checks in QueryInformationJobObject. [KERNEL32]: Use RtlEncode/DecodePointer to protect the top level exception handler pointer, as done on NT 5.2+ [KERNEL32]: Fix IsBadRead/WritePtr to use the correct page size from the CSRSS shared section. [KERNEL32]: Fix IsBad(String)Read/WritePtr loops [KERNEL32]: SetErrorMode now handles SEM_NOALIGNMENTFAULTEXCEPT. [KERNEL32]: Set/GetErrorMode do not set LastError on failure. [KERNEL32]: RaiseException can simply use memcpy instead of copying argument by argument. [KERNEL32]: Minor formatting changes. svn path=/trunk/; revision=54291
This commit is contained in:
parent
c0f989c66a
commit
d30964b0fb
|
@ -13,8 +13,6 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* TYPES **********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
/*
|
||||
|
|
|
@ -210,6 +210,9 @@ DllMain(HANDLE hDll,
|
|||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
/* Set no filter intially */
|
||||
GlobalTopLevelExceptionFilter = RtlEncodePointer(NULL);
|
||||
|
||||
/* Don't bother us for each thread */
|
||||
LdrDisableThreadCalloutsForDll((PVOID)hDll);
|
||||
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
* Created 01/11/98
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <k32.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,14 +10,13 @@
|
|||
* Created 01/11/98
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <k32.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter = NULL;
|
||||
DWORD g_dwLastErrorToBreakOn;
|
||||
|
||||
/*
|
||||
* Private helper function to lookup the module name from a given address.
|
||||
* The address can point to anywhere within the module.
|
||||
|
@ -69,63 +68,6 @@ _dump_context(PCONTEXT pc)
|
|||
#endif
|
||||
}
|
||||
|
||||
static LONG
|
||||
BasepCheckForReadOnlyResource(IN PVOID Ptr)
|
||||
{
|
||||
PVOID Data;
|
||||
ULONG Size, OldProtect;
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
NTSTATUS Status;
|
||||
LONG Ret = EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
/* Check if it was an attempt to write to a read-only image section! */
|
||||
Status = NtQueryVirtualMemory(NtCurrentProcess(),
|
||||
Ptr,
|
||||
MemoryBasicInformation,
|
||||
&mbi,
|
||||
sizeof(mbi),
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status) &&
|
||||
mbi.Protect == PAGE_READONLY && mbi.Type == MEM_IMAGE)
|
||||
{
|
||||
/* Attempt to treat it as a resource section. We need to
|
||||
use SEH here because we don't know if it's actually a
|
||||
resource mapping */
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
Data = RtlImageDirectoryEntryToData(mbi.AllocationBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_RESOURCE,
|
||||
&Size);
|
||||
|
||||
if (Data != NULL &&
|
||||
(ULONG_PTR)Ptr >= (ULONG_PTR)Data &&
|
||||
(ULONG_PTR)Ptr < (ULONG_PTR)Data + Size)
|
||||
{
|
||||
/* The user tried to write into the resources. Make the page
|
||||
writable... */
|
||||
Size = 1;
|
||||
Status = NtProtectVirtualMemory(NtCurrentProcess(),
|
||||
&Ptr,
|
||||
&Size,
|
||||
PAGE_READWRITE,
|
||||
&OldProtect);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Ret = EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static VOID
|
||||
PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo)
|
||||
{
|
||||
|
@ -188,6 +130,70 @@ PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter;
|
||||
DWORD g_dwLastErrorToBreakOn;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
LONG
|
||||
WINAPI
|
||||
BasepCheckForReadOnlyResource(IN PVOID Ptr)
|
||||
{
|
||||
PVOID Data;
|
||||
ULONG Size, OldProtect;
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
NTSTATUS Status;
|
||||
LONG Ret = EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
/* Check if it was an attempt to write to a read-only image section! */
|
||||
Status = NtQueryVirtualMemory(NtCurrentProcess(),
|
||||
Ptr,
|
||||
MemoryBasicInformation,
|
||||
&mbi,
|
||||
sizeof(mbi),
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status) &&
|
||||
mbi.Protect == PAGE_READONLY && mbi.Type == MEM_IMAGE)
|
||||
{
|
||||
/* Attempt to treat it as a resource section. We need to
|
||||
use SEH here because we don't know if it's actually a
|
||||
resource mapping */
|
||||
_SEH2_TRY
|
||||
{
|
||||
Data = RtlImageDirectoryEntryToData(mbi.AllocationBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_RESOURCE,
|
||||
&Size);
|
||||
|
||||
if (Data != NULL &&
|
||||
(ULONG_PTR)Ptr >= (ULONG_PTR)Data &&
|
||||
(ULONG_PTR)Ptr < (ULONG_PTR)Data + Size)
|
||||
{
|
||||
/* The user tried to write into the resources. Make the page
|
||||
writable... */
|
||||
Size = 1;
|
||||
Status = NtProtectVirtualMemory(NtCurrentProcess(),
|
||||
&Ptr,
|
||||
&Size,
|
||||
PAGE_READWRITE,
|
||||
&OldProtect);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Ret = EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
UINT
|
||||
WINAPI
|
||||
GetErrorMode(VOID)
|
||||
|
@ -272,9 +278,11 @@ UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
|
|||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
if (GlobalTopLevelExceptionFilter)
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER RealFilter;
|
||||
RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter);
|
||||
if (RealFilter)
|
||||
{
|
||||
LONG ret = GlobalTopLevelExceptionFilter(ExceptionInfo);
|
||||
LONG ret = RealFilter(ExceptionInfo);
|
||||
if (ret != EXCEPTION_CONTINUE_SEARCH)
|
||||
return ret;
|
||||
}
|
||||
|
@ -351,20 +359,14 @@ RaiseException(IN DWORD dwExceptionCode,
|
|||
nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS;
|
||||
}
|
||||
|
||||
/* Set the count of parameters */
|
||||
/* Set the count of parameters and copy them */
|
||||
ExceptionRecord.NumberParameters = nNumberOfArguments;
|
||||
|
||||
/* Loop each parameter */
|
||||
for (nNumberOfArguments = 0;
|
||||
(nNumberOfArguments < ExceptionRecord.NumberParameters);
|
||||
nNumberOfArguments ++)
|
||||
{
|
||||
/* Copy the exception information */
|
||||
ExceptionRecord.ExceptionInformation[nNumberOfArguments] =
|
||||
*lpArguments++;
|
||||
}
|
||||
RtlCopyMemory(ExceptionRecord.ExceptionInformation,
|
||||
lpArguments,
|
||||
nNumberOfArguments * sizeof(ULONG));
|
||||
}
|
||||
|
||||
/* Better handling of Delphi Exceptions... a ReactOS Hack */
|
||||
if (dwExceptionCode == 0xeedface || dwExceptionCode == 0xeedfade)
|
||||
{
|
||||
DPRINT1("Delphi Exception at address: %p\n", ExceptionRecord.ExceptionInformation[0]);
|
||||
|
@ -413,12 +415,14 @@ SetErrorMode(IN UINT uMode)
|
|||
NewMode |= SEM_FAILCRITICALERRORS;
|
||||
}
|
||||
|
||||
/* Always keep no alignment faults if they were set */
|
||||
NewMode |= (PrevErrMode & SEM_NOALIGNMENTFAULTEXCEPT);
|
||||
|
||||
/* Set the new mode */
|
||||
Status = NtSetInformationProcess(NtCurrentProcess(),
|
||||
ProcessDefaultHardErrorMode,
|
||||
(PVOID)&NewMode,
|
||||
sizeof(NewMode));
|
||||
if(!NT_SUCCESS(Status)) BaseSetLastNTError(Status);
|
||||
|
||||
/* Return the previous mode */
|
||||
return PrevErrMode;
|
||||
|
@ -429,11 +433,14 @@ SetErrorMode(IN UINT uMode)
|
|||
*/
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER
|
||||
WINAPI
|
||||
SetUnhandledExceptionFilter(
|
||||
IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
|
||||
SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
|
||||
{
|
||||
return InterlockedExchangePointer(&GlobalTopLevelExceptionFilter,
|
||||
lpTopLevelExceptionFilter);
|
||||
PVOID EncodedPointer, NewPointer;
|
||||
|
||||
EncodedPointer = RtlEncodePointer(lpTopLevelExceptionFilter);
|
||||
NewPointer = InterlockedExchangePointer(&GlobalTopLevelExceptionFilter,
|
||||
EncodedPointer);
|
||||
return RtlDecodePointer(EncodedPointer);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -444,7 +451,7 @@ WINAPI
|
|||
IsBadReadPtr(IN LPCVOID lp,
|
||||
IN UINT_PTR ucb)
|
||||
{
|
||||
//ULONG PageSize;
|
||||
ULONG PageSize;
|
||||
BOOLEAN Result = FALSE;
|
||||
volatile CHAR *Current;
|
||||
PCHAR Last;
|
||||
|
@ -454,25 +461,31 @@ IsBadReadPtr(IN LPCVOID lp,
|
|||
if (!lp) return TRUE;
|
||||
|
||||
/* Get the page size */
|
||||
//PageSize = BaseStaticServerData->SysInfo.PageSize;
|
||||
PageSize = BaseStaticServerData->SysInfo.PageSize;
|
||||
|
||||
/* Calculate the last page */
|
||||
/* Calculate start and end */
|
||||
Current = (volatile CHAR*)lp;
|
||||
Last = (PCHAR)((ULONG_PTR)lp + ucb - 1);
|
||||
|
||||
/* Another quick failure case */
|
||||
if ((ULONG_PTR)Last < (ULONG_PTR)lp) return TRUE;
|
||||
if (Last < Current) return TRUE;
|
||||
|
||||
/* Enter SEH */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe the entire range */
|
||||
Current = (volatile CHAR*)lp;
|
||||
Last = (PCHAR)(PAGE_ROUND_DOWN(Last));
|
||||
do
|
||||
{
|
||||
/* Do an initial probe */
|
||||
*Current;
|
||||
Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE);
|
||||
} while (Current <= Last);
|
||||
|
||||
/* Align the addresses */
|
||||
Current = (volatile CHAR *)ROUND_DOWN(Current, PageSize);
|
||||
Last = (PCHAR)ROUND_DOWN(Last, PageSize);
|
||||
|
||||
/* Probe the entire range */
|
||||
while (Current != Last)
|
||||
{
|
||||
Current += PageSize;
|
||||
*Current;
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -513,10 +526,10 @@ IsBadCodePtr(FARPROC lpfn)
|
|||
*/
|
||||
BOOL
|
||||
NTAPI
|
||||
IsBadWritePtr(LPVOID lp,
|
||||
UINT_PTR ucb)
|
||||
IsBadWritePtr(IN LPVOID lp,
|
||||
IN UINT_PTR ucb)
|
||||
{
|
||||
//ULONG PageSize;
|
||||
ULONG PageSize;
|
||||
BOOLEAN Result = FALSE;
|
||||
volatile CHAR *Current;
|
||||
PCHAR Last;
|
||||
|
@ -526,25 +539,31 @@ IsBadWritePtr(LPVOID lp,
|
|||
if (!lp) return TRUE;
|
||||
|
||||
/* Get the page size */
|
||||
//PageSize = BaseStaticServerData->SysInfo.PageSize;
|
||||
PageSize = BaseStaticServerData->SysInfo.PageSize;
|
||||
|
||||
/* Calculate the last page */
|
||||
/* Calculate start and end */
|
||||
Current = (volatile CHAR*)lp;
|
||||
Last = (PCHAR)((ULONG_PTR)lp + ucb - 1);
|
||||
|
||||
/* Another quick failure case */
|
||||
if ((ULONG_PTR)Last < (ULONG_PTR)lp) return TRUE;
|
||||
if (Last < Current) return TRUE;
|
||||
|
||||
/* Enter SEH */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe the entire range */
|
||||
Current = (volatile CHAR*)lp;
|
||||
Last = (PCHAR)(PAGE_ROUND_DOWN(Last));
|
||||
do
|
||||
{
|
||||
/* Do an initial probe */
|
||||
*Current = *Current;
|
||||
Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE);
|
||||
} while (Current <= Last);
|
||||
|
||||
/* Align the addresses */
|
||||
Current = (volatile CHAR *)ROUND_DOWN(Current, PageSize);
|
||||
Last = (PCHAR)ROUND_DOWN(Last, PageSize);
|
||||
|
||||
/* Probe the entire range */
|
||||
while (Current != Last)
|
||||
{
|
||||
Current += PageSize;
|
||||
*Current = *Current;
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -562,8 +581,8 @@ IsBadWritePtr(LPVOID lp,
|
|||
*/
|
||||
BOOL
|
||||
NTAPI
|
||||
IsBadHugeWritePtr(LPVOID lp,
|
||||
UINT_PTR ucb)
|
||||
IsBadHugeWritePtr(IN LPVOID lp,
|
||||
IN UINT_PTR ucb)
|
||||
{
|
||||
/* Implementation is the same on 32-bit */
|
||||
return IsBadWritePtr(lp, ucb);
|
||||
|
@ -575,7 +594,7 @@ IsBadHugeWritePtr(LPVOID lp,
|
|||
BOOL
|
||||
NTAPI
|
||||
IsBadStringPtrW(IN LPCWSTR lpsz,
|
||||
UINT_PTR ucchMax)
|
||||
IN UINT_PTR ucchMax)
|
||||
{
|
||||
BOOLEAN Result = FALSE;
|
||||
volatile WCHAR *Current;
|
||||
|
@ -586,20 +605,16 @@ IsBadStringPtrW(IN LPCWSTR lpsz,
|
|||
if (!ucchMax) return FALSE;
|
||||
if (!lpsz) return TRUE;
|
||||
|
||||
/* Calculate the last page */
|
||||
/* Calculate start and end */
|
||||
Current = (volatile WCHAR*)lpsz;
|
||||
Last = (PWCHAR)((ULONG_PTR)lpsz + (ucchMax * 2) - 2);
|
||||
|
||||
/* Enter SEH */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe the entire range */
|
||||
Current = (volatile WCHAR*)lpsz;
|
||||
Last = (PWCHAR)(PAGE_ROUND_DOWN(Last));
|
||||
do
|
||||
{
|
||||
Char = *Current;
|
||||
Current++;
|
||||
} while (Char && (Current != Last + 1));
|
||||
Char = *Current++;
|
||||
while ((Char) && (Current != Last)) Char = *Current++;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -618,7 +633,7 @@ IsBadStringPtrW(IN LPCWSTR lpsz,
|
|||
BOOL
|
||||
NTAPI
|
||||
IsBadStringPtrA(IN LPCSTR lpsz,
|
||||
UINT_PTR ucchMax)
|
||||
IN UINT_PTR ucchMax)
|
||||
{
|
||||
BOOLEAN Result = FALSE;
|
||||
volatile CHAR *Current;
|
||||
|
@ -629,20 +644,16 @@ IsBadStringPtrA(IN LPCSTR lpsz,
|
|||
if (!ucchMax) return FALSE;
|
||||
if (!lpsz) return TRUE;
|
||||
|
||||
/* Calculate the last page */
|
||||
/* Calculate start and end */
|
||||
Current = (volatile CHAR*)lpsz;
|
||||
Last = (PCHAR)((ULONG_PTR)lpsz + ucchMax - 1);
|
||||
|
||||
/* Enter SEH */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe the entire range */
|
||||
Current = (volatile CHAR*)lpsz;
|
||||
Last = (PCHAR)(PAGE_ROUND_DOWN(Last));
|
||||
do
|
||||
{
|
||||
Char = *Current;
|
||||
Current++;
|
||||
} while (Char && (Current != Last + 1));
|
||||
Char = *Current++;
|
||||
while ((Char) && (Current != Last)) Char = *Current++;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
* Created 9/23/2004
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <k32.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
@ -47,9 +47,9 @@ CreateJobObjectW(IN LPSECURITY_ATTRIBUTES lpJobAttributes,
|
|||
*/
|
||||
HANDLE
|
||||
WINAPI
|
||||
OpenJobObjectW(DWORD dwDesiredAccess,
|
||||
BOOL bInheritHandle,
|
||||
LPCWSTR lpName)
|
||||
OpenJobObjectW(IN DWORD dwDesiredAccess,
|
||||
IN BOOL bInheritHandle,
|
||||
IN LPCWSTR lpName)
|
||||
{
|
||||
/* Open the NT object */
|
||||
OpenNtObjectFromWin32Api(JobObject, dwDesiredAccess, bInheritHandle, lpName);
|
||||
|
@ -61,23 +61,22 @@ OpenJobObjectW(DWORD dwDesiredAccess,
|
|||
*/
|
||||
HANDLE
|
||||
WINAPI
|
||||
OpenJobObjectA(DWORD dwDesiredAccess,
|
||||
BOOL bInheritHandle,
|
||||
LPCSTR lpName)
|
||||
OpenJobObjectA(IN DWORD dwDesiredAccess,
|
||||
IN BOOL bInheritHandle,
|
||||
IN LPCSTR lpName)
|
||||
{
|
||||
/* Call the W(ide) function */
|
||||
ConvertOpenWin32AnsiObjectApiToUnicodeApi(JobObject, dwDesiredAccess, bInheritHandle, lpName);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
IsProcessInJob(HANDLE ProcessHandle,
|
||||
HANDLE JobHandle,
|
||||
PBOOL Result)
|
||||
IsProcessInJob(IN HANDLE ProcessHandle,
|
||||
IN HANDLE JobHandle,
|
||||
OUT PBOOL Result)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -92,14 +91,13 @@ IsProcessInJob(HANDLE ProcessHandle,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
AssignProcessToJobObject(HANDLE hJob,
|
||||
HANDLE hProcess)
|
||||
AssignProcessToJobObject(IN HANDLE hJob,
|
||||
IN HANDLE hProcess)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -113,81 +111,92 @@ AssignProcessToJobObject(HANDLE hJob,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
QueryInformationJobObject(HANDLE hJob,
|
||||
JOBOBJECTINFOCLASS JobObjectInformationClass,
|
||||
LPVOID lpJobObjectInformation,
|
||||
DWORD cbJobObjectInformationLength,
|
||||
LPDWORD lpReturnLength)
|
||||
QueryInformationJobObject(IN HANDLE hJob,
|
||||
IN JOBOBJECTINFOCLASS JobObjectInformationClass,
|
||||
IN LPVOID lpJobObjectInformation,
|
||||
IN DWORD cbJobObjectInformationLength,
|
||||
OUT LPDWORD lpReturnLength)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PVOID JobInfo;
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION LocalInfo;
|
||||
ULONG ExpectedSize;
|
||||
|
||||
if (JobObjectInformationClass == JobObjectBasicLimitInformation)
|
||||
{
|
||||
ExpectedSize = sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION);
|
||||
JobInfo = &LocalInfo;
|
||||
}
|
||||
else if (JobObjectInformationClass == JobObjectBasicLimitInformation)
|
||||
{
|
||||
ExpectedSize = sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION);
|
||||
JobInfo = &LocalInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpectedSize = cbJobObjectInformationLength;
|
||||
JobInfo = lpJobObjectInformation;
|
||||
}
|
||||
|
||||
if (cbJobObjectInformationLength != ExpectedSize)
|
||||
{
|
||||
BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = NtQueryInformationJobObject(hJob,
|
||||
JobObjectInformationClass,
|
||||
lpJobObjectInformation,
|
||||
cbJobObjectInformationLength,
|
||||
JobInfo,
|
||||
ExpectedSize,
|
||||
lpReturnLength);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicInfo;
|
||||
if (JobInfo != &LocalInfo) return TRUE;
|
||||
|
||||
switch (JobObjectInformationClass)
|
||||
{
|
||||
case JobObjectBasicLimitInformation:
|
||||
BasicInfo = (PJOBOBJECT_BASIC_LIMIT_INFORMATION)lpJobObjectInformation;
|
||||
break;
|
||||
|
||||
case JobObjectExtendedLimitInformation:
|
||||
BasicInfo = &((PJOBOBJECT_EXTENDED_LIMIT_INFORMATION)lpJobObjectInformation)->BasicLimitInformation;
|
||||
break;
|
||||
|
||||
default:
|
||||
BasicInfo = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BasicInfo != NULL)
|
||||
{
|
||||
/* we need to convert the process priority classes in the
|
||||
JOBOBJECT_BASIC_LIMIT_INFORMATION structure the same way as
|
||||
GetPriorityClass() converts it! */
|
||||
switch (BasicInfo->PriorityClass)
|
||||
switch (LocalInfo.BasicLimitInformation.PriorityClass)
|
||||
{
|
||||
case PROCESS_PRIORITY_CLASS_IDLE:
|
||||
BasicInfo->PriorityClass = IDLE_PRIORITY_CLASS;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
IDLE_PRIORITY_CLASS;
|
||||
break;
|
||||
|
||||
case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
|
||||
BasicInfo->PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
BELOW_NORMAL_PRIORITY_CLASS;
|
||||
break;
|
||||
|
||||
case PROCESS_PRIORITY_CLASS_NORMAL:
|
||||
BasicInfo->PriorityClass = NORMAL_PRIORITY_CLASS;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
NORMAL_PRIORITY_CLASS;
|
||||
break;
|
||||
|
||||
case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
|
||||
BasicInfo->PriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
ABOVE_NORMAL_PRIORITY_CLASS;
|
||||
break;
|
||||
|
||||
case PROCESS_PRIORITY_CLASS_HIGH:
|
||||
BasicInfo->PriorityClass = HIGH_PRIORITY_CLASS;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
HIGH_PRIORITY_CLASS;
|
||||
break;
|
||||
|
||||
case PROCESS_PRIORITY_CLASS_REALTIME:
|
||||
BasicInfo->PriorityClass = REALTIME_PRIORITY_CLASS;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
REALTIME_PRIORITY_CLASS;
|
||||
break;
|
||||
|
||||
default:
|
||||
BasicInfo->PriorityClass = NORMAL_PRIORITY_CLASS;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
NORMAL_PRIORITY_CLASS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RtlCopyMemory(lpJobObjectInformation, &LocalInfo, ExpectedSize);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -195,112 +204,119 @@ QueryInformationJobObject(HANDLE hJob,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
SetInformationJobObject(HANDLE hJob,
|
||||
JOBOBJECTINFOCLASS JobObjectInformationClass,
|
||||
LPVOID lpJobObjectInformation,
|
||||
DWORD cbJobObjectInformationLength)
|
||||
SetInformationJobObject(IN HANDLE hJob,
|
||||
IN JOBOBJECTINFOCLASS JobObjectInformationClass,
|
||||
IN LPVOID lpJobObjectInformation,
|
||||
IN DWORD cbJobObjectInformationLength)
|
||||
{
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimitInfo;
|
||||
PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicInfo;
|
||||
PVOID ObjectInfo;
|
||||
NTSTATUS Status;
|
||||
PVOID JobInfo;
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION LocalInfo;
|
||||
ULONG ExpectedSize;
|
||||
PVOID State = NULL;
|
||||
ULONG Privilege = SE_INC_BASE_PRIORITY_PRIVILEGE;
|
||||
|
||||
switch (JobObjectInformationClass)
|
||||
if (JobObjectInformationClass == JobObjectBasicLimitInformation)
|
||||
{
|
||||
case JobObjectBasicLimitInformation:
|
||||
if (cbJobObjectInformationLength != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION))
|
||||
ExpectedSize = sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION);
|
||||
JobInfo = &LocalInfo;
|
||||
}
|
||||
else if (JobObjectInformationClass == JobObjectBasicLimitInformation)
|
||||
{
|
||||
SetLastError(ERROR_BAD_LENGTH);
|
||||
ExpectedSize = sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION);
|
||||
JobInfo = &LocalInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpectedSize = cbJobObjectInformationLength;
|
||||
JobInfo = lpJobObjectInformation;
|
||||
}
|
||||
|
||||
if (cbJobObjectInformationLength != ExpectedSize)
|
||||
{
|
||||
BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ObjectInfo = &ExtendedLimitInfo.BasicLimitInformation;
|
||||
BasicInfo = (PJOBOBJECT_BASIC_LIMIT_INFORMATION)ObjectInfo;
|
||||
RtlCopyMemory(ObjectInfo, lpJobObjectInformation, cbJobObjectInformationLength);
|
||||
break;
|
||||
|
||||
case JobObjectExtendedLimitInformation:
|
||||
if (cbJobObjectInformationLength != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))
|
||||
if (JobInfo == &LocalInfo)
|
||||
{
|
||||
SetLastError(ERROR_BAD_LENGTH);
|
||||
return FALSE;
|
||||
}
|
||||
RtlCopyMemory(&LocalInfo, lpJobObjectInformation, ExpectedSize);
|
||||
|
||||
ObjectInfo = &ExtendedLimitInfo;
|
||||
BasicInfo = &ExtendedLimitInfo.BasicLimitInformation;
|
||||
RtlCopyMemory(ObjectInfo, lpJobObjectInformation, cbJobObjectInformationLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
ObjectInfo = lpJobObjectInformation;
|
||||
BasicInfo = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BasicInfo != NULL)
|
||||
if (LocalInfo.BasicLimitInformation.LimitFlags &
|
||||
JOB_OBJECT_LIMIT_PRIORITY_CLASS)
|
||||
{
|
||||
/* we need to convert the process priority classes in the
|
||||
JOBOBJECT_BASIC_LIMIT_INFORMATION structure the same way as
|
||||
SetPriorityClass() converts it! */
|
||||
switch(BasicInfo->PriorityClass)
|
||||
switch (LocalInfo.BasicLimitInformation.PriorityClass)
|
||||
{
|
||||
case IDLE_PRIORITY_CLASS:
|
||||
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
PROCESS_PRIORITY_CLASS_IDLE;
|
||||
break;
|
||||
|
||||
case BELOW_NORMAL_PRIORITY_CLASS:
|
||||
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
|
||||
break;
|
||||
|
||||
case NORMAL_PRIORITY_CLASS:
|
||||
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
PROCESS_PRIORITY_CLASS_NORMAL;
|
||||
break;
|
||||
|
||||
case ABOVE_NORMAL_PRIORITY_CLASS:
|
||||
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
|
||||
break;
|
||||
|
||||
case HIGH_PRIORITY_CLASS:
|
||||
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
PROCESS_PRIORITY_CLASS_HIGH;
|
||||
break;
|
||||
|
||||
case REALTIME_PRIORITY_CLASS:
|
||||
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
PROCESS_PRIORITY_CLASS_REALTIME;
|
||||
break;
|
||||
|
||||
default:
|
||||
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
|
||||
LocalInfo.BasicLimitInformation.PriorityClass =
|
||||
PROCESS_PRIORITY_CLASS_NORMAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (LocalInfo.BasicLimitInformation.LimitFlags &
|
||||
JOB_OBJECT_LIMIT_WORKINGSET)
|
||||
{
|
||||
Status = RtlAcquirePrivilege(&Privilege, TRUE, FALSE, &State);
|
||||
}
|
||||
}
|
||||
|
||||
Status = NtSetInformationJobObject(hJob,
|
||||
JobObjectInformationClass,
|
||||
ObjectInfo,
|
||||
cbJobObjectInformationLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
JobInfo,
|
||||
ExpectedSize);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
if (State != NULL) RtlReleasePrivilege(State);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
TerminateJobObject(HANDLE hJob,
|
||||
UINT uExitCode)
|
||||
TerminateJobObject(IN HANDLE hJob,
|
||||
IN UINT uExitCode)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -315,17 +331,24 @@ TerminateJobObject(HANDLE hJob,
|
|||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
CreateJobSet (
|
||||
ULONG NumJob,
|
||||
PJOB_SET_ARRAY UserJobSet,
|
||||
ULONG Flags)
|
||||
CreateJobSet(IN ULONG NumJob,
|
||||
IN PJOB_SET_ARRAY UserJobSet,
|
||||
IN ULONG Flags)
|
||||
{
|
||||
STUB;
|
||||
return 0;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = NtCreateJobSet(NumJob, UserJobSet, Flags);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -49,12 +49,14 @@ static
|
|||
LONG BaseExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo)
|
||||
{
|
||||
LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER RealFilter;
|
||||
RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter);
|
||||
|
||||
if (GlobalTopLevelExceptionFilter != NULL)
|
||||
if (RealFilter != NULL)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo);
|
||||
ExceptionDisposition = RealFilter(ExceptionInfo);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -62,7 +64,7 @@ LONG BaseExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo)
|
|||
_SEH2_END;
|
||||
}
|
||||
if ((ExceptionDisposition == EXCEPTION_CONTINUE_SEARCH || ExceptionDisposition == EXCEPTION_EXECUTE_HANDLER) &&
|
||||
GlobalTopLevelExceptionFilter != UnhandledExceptionFilter)
|
||||
RealFilter != UnhandledExceptionFilter)
|
||||
{
|
||||
ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo);
|
||||
}
|
||||
|
|
|
@ -29,12 +29,14 @@ static
|
|||
LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo)
|
||||
{
|
||||
LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER RealFilter;
|
||||
RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter);
|
||||
|
||||
if (GlobalTopLevelExceptionFilter != NULL)
|
||||
if (RealFilter != NULL)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo);
|
||||
ExceptionDisposition = RealFilter(ExceptionInfo);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue