[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:
Alex Ionescu 2011-11-05 01:19:52 +00:00
parent c0f989c66a
commit d30964b0fb
7 changed files with 313 additions and 273 deletions

View file

@ -13,8 +13,6 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* TYPES **********************************************************************/
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
/* /*

View file

@ -209,6 +209,9 @@ DllMain(HANDLE hDll,
switch (dwReason) switch (dwReason)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
/* Set no filter intially */
GlobalTopLevelExceptionFilter = RtlEncodePointer(NULL);
/* Don't bother us for each thread */ /* Don't bother us for each thread */
LdrDisableThreadCalloutsForDll((PVOID)hDll); LdrDisableThreadCalloutsForDll((PVOID)hDll);

View file

@ -11,12 +11,13 @@
* Created 01/11/98 * Created 01/11/98
*/ */
/* INCLUDES *******************************************************************/
#include <k32.h> #include <k32.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
/* /*

View file

@ -10,14 +10,13 @@
* Created 01/11/98 * Created 01/11/98
*/ */
/* INCLUDES *******************************************************************/
#include <k32.h> #include <k32.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter = NULL;
DWORD g_dwLastErrorToBreakOn;
/* /*
* Private helper function to lookup the module name from a given address. * Private helper function to lookup the module name from a given address.
* The address can point to anywhere within the module. * The address can point to anywhere within the module.
@ -69,63 +68,6 @@ _dump_context(PCONTEXT pc)
#endif #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 static VOID
PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo) PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo)
{ {
@ -188,6 +130,70 @@ PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo)
#endif #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 UINT
WINAPI WINAPI
GetErrorMode(VOID) GetErrorMode(VOID)
@ -272,9 +278,11 @@ UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
return EXCEPTION_CONTINUE_SEARCH; 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) if (ret != EXCEPTION_CONTINUE_SEARCH)
return ret; return ret;
} }
@ -351,20 +359,14 @@ RaiseException(IN DWORD dwExceptionCode,
nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS; nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS;
} }
/* Set the count of parameters */ /* Set the count of parameters and copy them */
ExceptionRecord.NumberParameters = nNumberOfArguments; ExceptionRecord.NumberParameters = nNumberOfArguments;
RtlCopyMemory(ExceptionRecord.ExceptionInformation,
/* Loop each parameter */ lpArguments,
for (nNumberOfArguments = 0; nNumberOfArguments * sizeof(ULONG));
(nNumberOfArguments < ExceptionRecord.NumberParameters);
nNumberOfArguments ++)
{
/* Copy the exception information */
ExceptionRecord.ExceptionInformation[nNumberOfArguments] =
*lpArguments++;
}
} }
/* Better handling of Delphi Exceptions... a ReactOS Hack */
if (dwExceptionCode == 0xeedface || dwExceptionCode == 0xeedfade) if (dwExceptionCode == 0xeedface || dwExceptionCode == 0xeedfade)
{ {
DPRINT1("Delphi Exception at address: %p\n", ExceptionRecord.ExceptionInformation[0]); DPRINT1("Delphi Exception at address: %p\n", ExceptionRecord.ExceptionInformation[0]);
@ -413,12 +415,14 @@ SetErrorMode(IN UINT uMode)
NewMode |= SEM_FAILCRITICALERRORS; NewMode |= SEM_FAILCRITICALERRORS;
} }
/* Always keep no alignment faults if they were set */
NewMode |= (PrevErrMode & SEM_NOALIGNMENTFAULTEXCEPT);
/* Set the new mode */ /* Set the new mode */
Status = NtSetInformationProcess(NtCurrentProcess(), Status = NtSetInformationProcess(NtCurrentProcess(),
ProcessDefaultHardErrorMode, ProcessDefaultHardErrorMode,
(PVOID)&NewMode, (PVOID)&NewMode,
sizeof(NewMode)); sizeof(NewMode));
if(!NT_SUCCESS(Status)) BaseSetLastNTError(Status);
/* Return the previous mode */ /* Return the previous mode */
return PrevErrMode; return PrevErrMode;
@ -429,11 +433,14 @@ SetErrorMode(IN UINT uMode)
*/ */
LPTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER
WINAPI WINAPI
SetUnhandledExceptionFilter( SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
{ {
return InterlockedExchangePointer(&GlobalTopLevelExceptionFilter, PVOID EncodedPointer, NewPointer;
lpTopLevelExceptionFilter);
EncodedPointer = RtlEncodePointer(lpTopLevelExceptionFilter);
NewPointer = InterlockedExchangePointer(&GlobalTopLevelExceptionFilter,
EncodedPointer);
return RtlDecodePointer(EncodedPointer);
} }
/* /*
@ -444,7 +451,7 @@ WINAPI
IsBadReadPtr(IN LPCVOID lp, IsBadReadPtr(IN LPCVOID lp,
IN UINT_PTR ucb) IN UINT_PTR ucb)
{ {
//ULONG PageSize; ULONG PageSize;
BOOLEAN Result = FALSE; BOOLEAN Result = FALSE;
volatile CHAR *Current; volatile CHAR *Current;
PCHAR Last; PCHAR Last;
@ -454,25 +461,31 @@ IsBadReadPtr(IN LPCVOID lp,
if (!lp) return TRUE; if (!lp) return TRUE;
/* Get the page size */ /* 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); Last = (PCHAR)((ULONG_PTR)lp + ucb - 1);
/* Another quick failure case */ /* Another quick failure case */
if ((ULONG_PTR)Last < (ULONG_PTR)lp) return TRUE; if (Last < Current) return TRUE;
/* Enter SEH */ /* Enter SEH */
_SEH2_TRY _SEH2_TRY
{ {
/* Do an initial probe */
*Current;
/* Align the addresses */
Current = (volatile CHAR *)ROUND_DOWN(Current, PageSize);
Last = (PCHAR)ROUND_DOWN(Last, PageSize);
/* Probe the entire range */ /* Probe the entire range */
Current = (volatile CHAR*)lp; while (Current != Last)
Last = (PCHAR)(PAGE_ROUND_DOWN(Last));
do
{ {
Current += PageSize;
*Current; *Current;
Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE); }
} while (Current <= Last);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -513,10 +526,10 @@ IsBadCodePtr(FARPROC lpfn)
*/ */
BOOL BOOL
NTAPI NTAPI
IsBadWritePtr(LPVOID lp, IsBadWritePtr(IN LPVOID lp,
UINT_PTR ucb) IN UINT_PTR ucb)
{ {
//ULONG PageSize; ULONG PageSize;
BOOLEAN Result = FALSE; BOOLEAN Result = FALSE;
volatile CHAR *Current; volatile CHAR *Current;
PCHAR Last; PCHAR Last;
@ -526,25 +539,31 @@ IsBadWritePtr(LPVOID lp,
if (!lp) return TRUE; if (!lp) return TRUE;
/* Get the page size */ /* 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); Last = (PCHAR)((ULONG_PTR)lp + ucb - 1);
/* Another quick failure case */ /* Another quick failure case */
if ((ULONG_PTR)Last < (ULONG_PTR)lp) return TRUE; if (Last < Current) return TRUE;
/* Enter SEH */ /* Enter SEH */
_SEH2_TRY _SEH2_TRY
{ {
/* Do an initial probe */
*Current = *Current;
/* Align the addresses */
Current = (volatile CHAR *)ROUND_DOWN(Current, PageSize);
Last = (PCHAR)ROUND_DOWN(Last, PageSize);
/* Probe the entire range */ /* Probe the entire range */
Current = (volatile CHAR*)lp; while (Current != Last)
Last = (PCHAR)(PAGE_ROUND_DOWN(Last));
do
{ {
Current += PageSize;
*Current = *Current; *Current = *Current;
Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE); }
} while (Current <= Last);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -562,8 +581,8 @@ IsBadWritePtr(LPVOID lp,
*/ */
BOOL BOOL
NTAPI NTAPI
IsBadHugeWritePtr(LPVOID lp, IsBadHugeWritePtr(IN LPVOID lp,
UINT_PTR ucb) IN UINT_PTR ucb)
{ {
/* Implementation is the same on 32-bit */ /* Implementation is the same on 32-bit */
return IsBadWritePtr(lp, ucb); return IsBadWritePtr(lp, ucb);
@ -575,7 +594,7 @@ IsBadHugeWritePtr(LPVOID lp,
BOOL BOOL
NTAPI NTAPI
IsBadStringPtrW(IN LPCWSTR lpsz, IsBadStringPtrW(IN LPCWSTR lpsz,
UINT_PTR ucchMax) IN UINT_PTR ucchMax)
{ {
BOOLEAN Result = FALSE; BOOLEAN Result = FALSE;
volatile WCHAR *Current; volatile WCHAR *Current;
@ -586,20 +605,16 @@ IsBadStringPtrW(IN LPCWSTR lpsz,
if (!ucchMax) return FALSE; if (!ucchMax) return FALSE;
if (!lpsz) return TRUE; if (!lpsz) return TRUE;
/* Calculate the last page */ /* Calculate start and end */
Current = (volatile WCHAR*)lpsz;
Last = (PWCHAR)((ULONG_PTR)lpsz + (ucchMax * 2) - 2); Last = (PWCHAR)((ULONG_PTR)lpsz + (ucchMax * 2) - 2);
/* Enter SEH */ /* Enter SEH */
_SEH2_TRY _SEH2_TRY
{ {
/* Probe the entire range */ /* Probe the entire range */
Current = (volatile WCHAR*)lpsz; Char = *Current++;
Last = (PWCHAR)(PAGE_ROUND_DOWN(Last)); while ((Char) && (Current != Last)) Char = *Current++;
do
{
Char = *Current;
Current++;
} while (Char && (Current != Last + 1));
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -618,7 +633,7 @@ IsBadStringPtrW(IN LPCWSTR lpsz,
BOOL BOOL
NTAPI NTAPI
IsBadStringPtrA(IN LPCSTR lpsz, IsBadStringPtrA(IN LPCSTR lpsz,
UINT_PTR ucchMax) IN UINT_PTR ucchMax)
{ {
BOOLEAN Result = FALSE; BOOLEAN Result = FALSE;
volatile CHAR *Current; volatile CHAR *Current;
@ -629,20 +644,16 @@ IsBadStringPtrA(IN LPCSTR lpsz,
if (!ucchMax) return FALSE; if (!ucchMax) return FALSE;
if (!lpsz) return TRUE; if (!lpsz) return TRUE;
/* Calculate the last page */ /* Calculate start and end */
Current = (volatile CHAR*)lpsz;
Last = (PCHAR)((ULONG_PTR)lpsz + ucchMax - 1); Last = (PCHAR)((ULONG_PTR)lpsz + ucchMax - 1);
/* Enter SEH */ /* Enter SEH */
_SEH2_TRY _SEH2_TRY
{ {
/* Probe the entire range */ /* Probe the entire range */
Current = (volatile CHAR*)lpsz; Char = *Current++;
Last = (PCHAR)(PAGE_ROUND_DOWN(Last)); while ((Char) && (Current != Last)) Char = *Current++;
do
{
Char = *Current;
Current++;
} while (Char && (Current != Last + 1));
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {

View file

@ -9,14 +9,14 @@
* Created 9/23/2004 * Created 9/23/2004
*/ */
/* INCLUDES ****************************************************************/ /* INCLUDES *******************************************************************/
#include <k32.h> #include <k32.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ******************************************************************/
/* /*
* @implemented * @implemented
@ -47,9 +47,9 @@ CreateJobObjectW(IN LPSECURITY_ATTRIBUTES lpJobAttributes,
*/ */
HANDLE HANDLE
WINAPI WINAPI
OpenJobObjectW(DWORD dwDesiredAccess, OpenJobObjectW(IN DWORD dwDesiredAccess,
BOOL bInheritHandle, IN BOOL bInheritHandle,
LPCWSTR lpName) IN LPCWSTR lpName)
{ {
/* Open the NT object */ /* Open the NT object */
OpenNtObjectFromWin32Api(JobObject, dwDesiredAccess, bInheritHandle, lpName); OpenNtObjectFromWin32Api(JobObject, dwDesiredAccess, bInheritHandle, lpName);
@ -61,23 +61,22 @@ OpenJobObjectW(DWORD dwDesiredAccess,
*/ */
HANDLE HANDLE
WINAPI WINAPI
OpenJobObjectA(DWORD dwDesiredAccess, OpenJobObjectA(IN DWORD dwDesiredAccess,
BOOL bInheritHandle, IN BOOL bInheritHandle,
LPCSTR lpName) IN LPCSTR lpName)
{ {
/* Call the W(ide) function */ /* Call the W(ide) function */
ConvertOpenWin32AnsiObjectApiToUnicodeApi(JobObject, dwDesiredAccess, bInheritHandle, lpName); ConvertOpenWin32AnsiObjectApiToUnicodeApi(JobObject, dwDesiredAccess, bInheritHandle, lpName);
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
IsProcessInJob(HANDLE ProcessHandle, IsProcessInJob(IN HANDLE ProcessHandle,
HANDLE JobHandle, IN HANDLE JobHandle,
PBOOL Result) OUT PBOOL Result)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -92,14 +91,13 @@ IsProcessInJob(HANDLE ProcessHandle,
return FALSE; return FALSE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
AssignProcessToJobObject(HANDLE hJob, AssignProcessToJobObject(IN HANDLE hJob,
HANDLE hProcess) IN HANDLE hProcess)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -113,81 +111,92 @@ AssignProcessToJobObject(HANDLE hJob,
return TRUE; return TRUE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
QueryInformationJobObject(HANDLE hJob, QueryInformationJobObject(IN HANDLE hJob,
JOBOBJECTINFOCLASS JobObjectInformationClass, IN JOBOBJECTINFOCLASS JobObjectInformationClass,
LPVOID lpJobObjectInformation, IN LPVOID lpJobObjectInformation,
DWORD cbJobObjectInformationLength, IN DWORD cbJobObjectInformationLength,
LPDWORD lpReturnLength) OUT LPDWORD lpReturnLength)
{ {
NTSTATUS Status; 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, Status = NtQueryInformationJobObject(hJob,
JobObjectInformationClass, JobObjectInformationClass,
lpJobObjectInformation, JobInfo,
cbJobObjectInformationLength, ExpectedSize,
lpReturnLength); lpReturnLength);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicInfo; if (JobInfo != &LocalInfo) return TRUE;
switch (JobObjectInformationClass) switch (LocalInfo.BasicLimitInformation.PriorityClass)
{ {
case JobObjectBasicLimitInformation: case PROCESS_PRIORITY_CLASS_IDLE:
BasicInfo = (PJOBOBJECT_BASIC_LIMIT_INFORMATION)lpJobObjectInformation; LocalInfo.BasicLimitInformation.PriorityClass =
IDLE_PRIORITY_CLASS;
break; break;
case JobObjectExtendedLimitInformation: case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
BasicInfo = &((PJOBOBJECT_EXTENDED_LIMIT_INFORMATION)lpJobObjectInformation)->BasicLimitInformation; LocalInfo.BasicLimitInformation.PriorityClass =
BELOW_NORMAL_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_NORMAL:
LocalInfo.BasicLimitInformation.PriorityClass =
NORMAL_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
LocalInfo.BasicLimitInformation.PriorityClass =
ABOVE_NORMAL_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_HIGH:
LocalInfo.BasicLimitInformation.PriorityClass =
HIGH_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_REALTIME:
LocalInfo.BasicLimitInformation.PriorityClass =
REALTIME_PRIORITY_CLASS;
break; break;
default: default:
BasicInfo = NULL; LocalInfo.BasicLimitInformation.PriorityClass =
NORMAL_PRIORITY_CLASS;
break; break;
} }
if (BasicInfo != NULL) RtlCopyMemory(lpJobObjectInformation, &LocalInfo, ExpectedSize);
{
/* 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)
{
case PROCESS_PRIORITY_CLASS_IDLE:
BasicInfo->PriorityClass = IDLE_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
BasicInfo->PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_NORMAL:
BasicInfo->PriorityClass = NORMAL_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
BasicInfo->PriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_HIGH:
BasicInfo->PriorityClass = HIGH_PRIORITY_CLASS;
break;
case PROCESS_PRIORITY_CLASS_REALTIME:
BasicInfo->PriorityClass = REALTIME_PRIORITY_CLASS;
break;
default:
BasicInfo->PriorityClass = NORMAL_PRIORITY_CLASS;
break;
}
}
return TRUE; return TRUE;
} }
@ -195,112 +204,119 @@ QueryInformationJobObject(HANDLE hJob,
return FALSE; return FALSE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
SetInformationJobObject(HANDLE hJob, SetInformationJobObject(IN HANDLE hJob,
JOBOBJECTINFOCLASS JobObjectInformationClass, IN JOBOBJECTINFOCLASS JobObjectInformationClass,
LPVOID lpJobObjectInformation, IN LPVOID lpJobObjectInformation,
DWORD cbJobObjectInformationLength) IN DWORD cbJobObjectInformationLength)
{ {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimitInfo;
PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicInfo;
PVOID ObjectInfo;
NTSTATUS Status; 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: ExpectedSize = sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION);
if (cbJobObjectInformationLength != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION)) JobInfo = &LocalInfo;
{ }
SetLastError(ERROR_BAD_LENGTH); else if (JobObjectInformationClass == JobObjectBasicLimitInformation)
return FALSE; {
} ExpectedSize = sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION);
JobInfo = &LocalInfo;
ObjectInfo = &ExtendedLimitInfo.BasicLimitInformation; }
BasicInfo = (PJOBOBJECT_BASIC_LIMIT_INFORMATION)ObjectInfo; else
RtlCopyMemory(ObjectInfo, lpJobObjectInformation, cbJobObjectInformationLength); {
break; ExpectedSize = cbJobObjectInformationLength;
JobInfo = lpJobObjectInformation;
case JobObjectExtendedLimitInformation:
if (cbJobObjectInformationLength != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))
{
SetLastError(ERROR_BAD_LENGTH);
return FALSE;
}
ObjectInfo = &ExtendedLimitInfo;
BasicInfo = &ExtendedLimitInfo.BasicLimitInformation;
RtlCopyMemory(ObjectInfo, lpJobObjectInformation, cbJobObjectInformationLength);
break;
default:
ObjectInfo = lpJobObjectInformation;
BasicInfo = NULL;
break;
} }
if (BasicInfo != NULL) if (cbJobObjectInformationLength != ExpectedSize)
{ {
/* we need to convert the process priority classes in the BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
JOBOBJECT_BASIC_LIMIT_INFORMATION structure the same way as return FALSE;
SetPriorityClass() converts it! */ }
switch(BasicInfo->PriorityClass)
if (JobInfo == &LocalInfo)
{
RtlCopyMemory(&LocalInfo, lpJobObjectInformation, ExpectedSize);
if (LocalInfo.BasicLimitInformation.LimitFlags &
JOB_OBJECT_LIMIT_PRIORITY_CLASS)
{ {
case IDLE_PRIORITY_CLASS: switch (LocalInfo.BasicLimitInformation.PriorityClass)
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_IDLE; {
break; case IDLE_PRIORITY_CLASS:
LocalInfo.BasicLimitInformation.PriorityClass =
PROCESS_PRIORITY_CLASS_IDLE;
break;
case BELOW_NORMAL_PRIORITY_CLASS: case BELOW_NORMAL_PRIORITY_CLASS:
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; LocalInfo.BasicLimitInformation.PriorityClass =
break; PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
break;
case NORMAL_PRIORITY_CLASS: case NORMAL_PRIORITY_CLASS:
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; LocalInfo.BasicLimitInformation.PriorityClass =
break; PROCESS_PRIORITY_CLASS_NORMAL;
break;
case ABOVE_NORMAL_PRIORITY_CLASS: case ABOVE_NORMAL_PRIORITY_CLASS:
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; LocalInfo.BasicLimitInformation.PriorityClass =
break; PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
break;
case HIGH_PRIORITY_CLASS: case HIGH_PRIORITY_CLASS:
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; LocalInfo.BasicLimitInformation.PriorityClass =
break; PROCESS_PRIORITY_CLASS_HIGH;
break;
case REALTIME_PRIORITY_CLASS: case REALTIME_PRIORITY_CLASS:
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME; LocalInfo.BasicLimitInformation.PriorityClass =
break; PROCESS_PRIORITY_CLASS_REALTIME;
break;
default: default:
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; LocalInfo.BasicLimitInformation.PriorityClass =
break; PROCESS_PRIORITY_CLASS_NORMAL;
break;
}
}
if (LocalInfo.BasicLimitInformation.LimitFlags &
JOB_OBJECT_LIMIT_WORKINGSET)
{
Status = RtlAcquirePrivilege(&Privilege, TRUE, FALSE, &State);
} }
} }
Status = NtSetInformationJobObject(hJob, Status = NtSetInformationJobObject(hJob,
JobObjectInformationClass, JobObjectInformationClass,
ObjectInfo, JobInfo,
cbJobObjectInformationLength); ExpectedSize);
if (!NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
BaseSetLastNTError(Status); if (State != NULL) RtlReleasePrivilege(State);
return FALSE; return TRUE;
} }
return TRUE; BaseSetLastNTError(Status);
return FALSE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
TerminateJobObject(HANDLE hJob, TerminateJobObject(IN HANDLE hJob,
UINT uExitCode) IN UINT uExitCode)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -315,17 +331,24 @@ TerminateJobObject(HANDLE hJob,
} }
/* /*
* @unimplemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
CreateJobSet ( CreateJobSet(IN ULONG NumJob,
ULONG NumJob, IN PJOB_SET_ARRAY UserJobSet,
PJOB_SET_ARRAY UserJobSet, IN ULONG Flags)
ULONG Flags)
{ {
STUB; NTSTATUS Status;
return 0;
Status = NtCreateJobSet(NumJob, UserJobSet, Flags);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
} }
/* EOF */ /* EOF */

View file

@ -49,12 +49,14 @@ static
LONG BaseExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo) LONG BaseExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo)
{ {
LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER; LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
LPTOP_LEVEL_EXCEPTION_FILTER RealFilter;
RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter);
if (GlobalTopLevelExceptionFilter != NULL) if (RealFilter != NULL)
{ {
_SEH2_TRY _SEH2_TRY
{ {
ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo); ExceptionDisposition = RealFilter(ExceptionInfo);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -62,7 +64,7 @@ LONG BaseExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo)
_SEH2_END; _SEH2_END;
} }
if ((ExceptionDisposition == EXCEPTION_CONTINUE_SEARCH || ExceptionDisposition == EXCEPTION_EXECUTE_HANDLER) && if ((ExceptionDisposition == EXCEPTION_CONTINUE_SEARCH || ExceptionDisposition == EXCEPTION_EXECUTE_HANDLER) &&
GlobalTopLevelExceptionFilter != UnhandledExceptionFilter) RealFilter != UnhandledExceptionFilter)
{ {
ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo); ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo);
} }

View file

@ -29,12 +29,14 @@ static
LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo) LONG BaseThreadExceptionFilter(EXCEPTION_POINTERS * ExceptionInfo)
{ {
LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER; LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
LPTOP_LEVEL_EXCEPTION_FILTER RealFilter;
if (GlobalTopLevelExceptionFilter != NULL) RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter);
if (RealFilter != NULL)
{ {
_SEH2_TRY _SEH2_TRY
{ {
ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo); ExceptionDisposition = RealFilter(ExceptionInfo);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {