[NTOSKRNL]: Implement ProcessDebugObjectHandle and a bunch more query/set process classes. Fixes Winetests.

[NTOSKRNL]: We should not be setting *ReturnLength in most failure cases, so no longer do so. Fixes Winetests.

svn path=/trunk/; revision=55734
This commit is contained in:
Alex Ionescu 2012-02-20 06:42:02 +00:00
parent 62930b0461
commit 1e172203a6
5 changed files with 291 additions and 15 deletions

View file

@ -1504,6 +1504,46 @@ DbgkInitialize(VOID)
&DbgkDebugObjectType);
}
NTSTATUS
NTAPI
DbgkOpenProcessDebugPort(IN PEPROCESS Process,
IN KPROCESSOR_MODE PreviousMode,
OUT HANDLE *DebugHandle)
{
PDEBUG_OBJECT DebugObject;
NTSTATUS Status;
PAGED_CODE();
/* If there's no debug port, just exit */
if (!Process->DebugPort) return STATUS_PORT_NOT_SET;
/* Otherwise, acquire the lock while we grab the port */
ExAcquireFastMutex(&DbgkpProcessDebugPortMutex);
/* Grab it and reference it if it exists */
DebugObject = Process->DebugPort;
if (DebugObject) ObReferenceObject(DebugObject);
/* Release the lock now */
ExReleaseFastMutex(&DbgkpProcessDebugPortMutex);
/* Bail out if it doesn't exist */
if (!DebugObject) return STATUS_PORT_NOT_SET;
/* Now get a handle to it */
Status = ObOpenObjectByPointer(DebugObject,
0,
NULL,
MAXIMUM_ALLOWED,
DbgkDebugObjectType,
PreviousMode,
DebugHandle);
if (!NT_SUCCESS(Status)) ObDereferenceObject(DebugObject);
/* Return status */
return Status;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*

View file

@ -134,6 +134,14 @@ DbgkClearProcessDebugObject(
IN PDEBUG_OBJECT SourceDebugObject
);
NTSTATUS
NTAPI
DbgkOpenProcessDebugPort(
IN PEPROCESS Process,
IN KPROCESSOR_MODE PreviousMode,
OUT HANDLE *DebugHandle
);
extern ULONG DbgkpTraceLevel;
extern POBJECT_TYPE DbgkDebugObjectType;

View file

@ -1507,6 +1507,10 @@ NTSTATUS
NTAPI
MmSetExecuteOptions(IN ULONG ExecuteOptions);
NTSTATUS
NTAPI
MmGetExecuteOptions(IN PULONG ExecuteOptions);
VOID
NTAPI
MmDeleteProcessPageDirectory(struct _EPROCESS *Process);

View file

@ -1094,11 +1094,52 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
return Status;
}
NTSTATUS
NTAPI
MmGetExecuteOptions(IN PULONG ExecuteOptions)
{
PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
*ExecuteOptions = 0;
if (CurrentProcess->Flags.ExecuteDisable)
{
*ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE;
}
if (CurrentProcess->Flags.ExecuteEnable)
{
*ExecuteOptions |= MEM_EXECUTE_OPTION_ENABLE;
}
if (CurrentProcess->Flags.DisableThunkEmulation)
{
*ExecuteOptions |= MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION;
}
if (CurrentProcess->Flags.Permanent)
{
*ExecuteOptions |= MEM_EXECUTE_OPTION_PERMANENT;
}
if (CurrentProcess->Flags.ExecuteDispatchEnable)
{
*ExecuteOptions |= MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE;
}
if (CurrentProcess->Flags.ImageDispatchEnable)
{
*ExecuteOptions |= MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
MmSetExecuteOptions(IN ULONG ExecuteOptions)
{
PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb;
KLOCK_QUEUE_HANDLE ProcessLock;
NTSTATUS Status = STATUS_ACCESS_DENIED;

View file

@ -69,6 +69,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
ULONG Length = 0;
HANDLE DebugPort = 0;
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
@ -81,7 +82,8 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation;
PROCESS_DEVICEMAP_INFORMATION DeviceMap;
PUNICODE_STRING ImageName;
ULONG Cookie;
ULONG Cookie, ExecuteOptions = 0;
ULONG_PTR Wow64 = 0;
PAGED_CODE();
/* Check for user-mode caller */
@ -443,9 +445,6 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
break;
}
/* Set the return length */
Length = ProcessInformationLength;
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
@ -471,6 +470,10 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
VmCounters->PagefileUsage = Process->QuotaUsage[2] << PAGE_SHIFT;
VmCounters->PeakPagefileUsage = Process->QuotaPeak[2] << PAGE_SHIFT;
//VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
//
/* Set the return length */
Length = ProcessInformationLength;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -825,8 +828,42 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
break;
case ProcessDebugObjectHandle:
DPRINT1("Debug Object Query Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
/* Set the return length */
Length = sizeof(HANDLE);
if (ProcessInformationLength != Length)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
PsProcessType,
PreviousMode,
(PVOID*)&Process,
NULL);
if (!NT_SUCCESS(Status)) break;
/* Get the debug port */
Status = DbgkOpenProcessDebugPort(Process, PreviousMode, &DebugPort);
/* Let go of the process */
ObDereferenceObject(Process);
/* Protect write in SEH */
_SEH2_TRY
{
/* Return the count of handles */
*(PHANDLE)ProcessInformation = DebugPort;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
break;
case ProcessHandleTracing:
@ -835,6 +872,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
break;
case ProcessLUIDDeviceMapsEnabled:
/* Set the return length */
Length = sizeof(ULONG);
if (ProcessInformationLength != Length)
@ -860,15 +898,118 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
_SEH2_END;
break;
case ProcessExecuteFlags:
DPRINT1("No execute Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
case ProcessWx86Information:
/* Set the return length */
Length = sizeof(ULONG);
if (ProcessInformationLength != Length)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Indicate success */
Status = STATUS_SUCCESS;
/* Protect write in SEH */
_SEH2_TRY
{
/* Return if the flag is set */
*(PULONG)ProcessInformation = (ULONG)Process->VdmAllowed;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
break;
case ProcessWow64Information:
/* Set return length */
Length = sizeof(ULONG_PTR);
if (ProcessInformationLength != Length)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
PsProcessType,
PreviousMode,
(PVOID*)&Process,
NULL);
if (!NT_SUCCESS(Status)) break;
/* Make sure the process isn't dying */
if (ExAcquireRundownProtection(&Process->RundownProtect))
{
/* Get the WOW64 process structure */
#ifdef _WIN64
Wow64 = Process->Wow64Process;
#else
Wow64 = 0;
#endif
/* Release the lock */
ExReleaseRundownProtection(&Process->RundownProtect);
}
/* Protect write with SEH */
_SEH2_TRY
{
/* Return whether or not we have a debug port */
*(PULONG_PTR)ProcessInformation = Wow64;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
/* Dereference the process */
ObDereferenceObject(Process);
break;
case ProcessExecuteFlags:
/* Set return length */
Length = sizeof(ULONG);
if (ProcessInformationLength != Length)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (ProcessHandle != NtCurrentProcess())
{
return STATUS_INVALID_PARAMETER;
}
/* Get the options */
Status = MmGetExecuteOptions(&ExecuteOptions);
if (NT_SUCCESS(Status))
{
/* Protect write with SEH */
_SEH2_TRY
{
/* Return them */
*(PULONG)ProcessInformation = ExecuteOptions;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
}
break;
case ProcessLdtInformation:
case ProcessWx86Information:
DPRINT1("VDM/16-bit implemented: %lx\n", ProcessInformationClass);
DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
@ -892,7 +1033,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
_SEH2_TRY
{
/* Check if caller wanted return length */
if (ReturnLength) *ReturnLength = Length;
if ((ReturnLength) && (Length)) *ReturnLength = Length;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -928,7 +1069,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
KAFFINITY ValidAffinity, Affinity = 0;
ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
ULONG NoExecute = 0;
ULONG NoExecute = 0, VdmPower = 0;
BOOLEAN HasPrivilege;
PLIST_ENTRY Next;
PETHREAD Thread;
@ -970,6 +1111,49 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
/* Check what kind of information class this is */
switch (ProcessInformationClass)
{
case ProcessWx86Information:
/* Check buffer length */
if (ProcessInformationLength != sizeof(HANDLE))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Use SEH for capture */
_SEH2_TRY
{
/* Capture the boolean */
VdmPower = *(PULONG)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
_SEH2_YIELD(break);
}
_SEH2_END;
/* Getting VDM powers requires the SeTcbPrivilege */
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
{
/* Bail out */
Status = STATUS_PRIVILEGE_NOT_HELD;
DPRINT1("Need TCB privilege\n");
break;
}
/* Set or clear the flag */
if (VdmPower)
{
PspSetProcessFlag(Process, PSF_VDM_ALLOWED_BIT);
}
else
{
PspClearProcessFlag(Process, PSF_VDM_ALLOWED_BIT);
}
break;
/* Error/Exception Port */
case ProcessExceptionPort:
@ -1670,7 +1854,6 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
case ProcessLdtInformation:
case ProcessLdtSize:
case ProcessIoPortHandlers:
case ProcessWx86Information:
DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;