mirror of
https://github.com/reactos/reactos.git
synced 2025-06-11 23:58:30 +00:00
[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:
parent
62930b0461
commit
1e172203a6
5 changed files with 291 additions and 15 deletions
|
@ -1504,6 +1504,46 @@ DbgkInitialize(VOID)
|
||||||
&DbgkDebugObjectType);
|
&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 **********************************************************/
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -134,6 +134,14 @@ DbgkClearProcessDebugObject(
|
||||||
IN PDEBUG_OBJECT SourceDebugObject
|
IN PDEBUG_OBJECT SourceDebugObject
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
DbgkOpenProcessDebugPort(
|
||||||
|
IN PEPROCESS Process,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode,
|
||||||
|
OUT HANDLE *DebugHandle
|
||||||
|
);
|
||||||
|
|
||||||
extern ULONG DbgkpTraceLevel;
|
extern ULONG DbgkpTraceLevel;
|
||||||
extern POBJECT_TYPE DbgkDebugObjectType;
|
extern POBJECT_TYPE DbgkDebugObjectType;
|
||||||
|
|
||||||
|
|
|
@ -1507,6 +1507,10 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmSetExecuteOptions(IN ULONG ExecuteOptions);
|
MmSetExecuteOptions(IN ULONG ExecuteOptions);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MmGetExecuteOptions(IN PULONG ExecuteOptions);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
MmDeleteProcessPageDirectory(struct _EPROCESS *Process);
|
MmDeleteProcessPageDirectory(struct _EPROCESS *Process);
|
||||||
|
|
|
@ -1094,11 +1094,52 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
||||||
return Status;
|
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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
MmSetExecuteOptions(IN ULONG ExecuteOptions)
|
MmSetExecuteOptions(IN ULONG ExecuteOptions)
|
||||||
{
|
{
|
||||||
|
|
||||||
PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb;
|
PKPROCESS CurrentProcess = &PsGetCurrentProcess()->Pcb;
|
||||||
KLOCK_QUEUE_HANDLE ProcessLock;
|
KLOCK_QUEUE_HANDLE ProcessLock;
|
||||||
NTSTATUS Status = STATUS_ACCESS_DENIED;
|
NTSTATUS Status = STATUS_ACCESS_DENIED;
|
||||||
|
|
|
@ -69,6 +69,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG Length = 0;
|
ULONG Length = 0;
|
||||||
|
HANDLE DebugPort = 0;
|
||||||
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
|
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
|
||||||
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
|
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
|
||||||
PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
|
PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
|
||||||
|
@ -81,7 +82,8 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation;
|
PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation;
|
||||||
PROCESS_DEVICEMAP_INFORMATION DeviceMap;
|
PROCESS_DEVICEMAP_INFORMATION DeviceMap;
|
||||||
PUNICODE_STRING ImageName;
|
PUNICODE_STRING ImageName;
|
||||||
ULONG Cookie;
|
ULONG Cookie, ExecuteOptions = 0;
|
||||||
|
ULONG_PTR Wow64 = 0;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Check for user-mode caller */
|
/* Check for user-mode caller */
|
||||||
|
@ -443,9 +445,6 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the return length */
|
|
||||||
Length = ProcessInformationLength;
|
|
||||||
|
|
||||||
/* Reference the process */
|
/* Reference the process */
|
||||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||||
PROCESS_QUERY_INFORMATION,
|
PROCESS_QUERY_INFORMATION,
|
||||||
|
@ -471,6 +470,10 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
VmCounters->PagefileUsage = Process->QuotaUsage[2] << PAGE_SHIFT;
|
VmCounters->PagefileUsage = Process->QuotaUsage[2] << PAGE_SHIFT;
|
||||||
VmCounters->PeakPagefileUsage = Process->QuotaPeak[2] << PAGE_SHIFT;
|
VmCounters->PeakPagefileUsage = Process->QuotaPeak[2] << PAGE_SHIFT;
|
||||||
//VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
|
//VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
|
||||||
|
//
|
||||||
|
|
||||||
|
/* Set the return length */
|
||||||
|
Length = ProcessInformationLength;
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
|
@ -825,8 +828,42 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProcessDebugObjectHandle:
|
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;
|
break;
|
||||||
|
|
||||||
case ProcessHandleTracing:
|
case ProcessHandleTracing:
|
||||||
|
@ -835,6 +872,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProcessLUIDDeviceMapsEnabled:
|
case ProcessLUIDDeviceMapsEnabled:
|
||||||
|
|
||||||
/* Set the return length */
|
/* Set the return length */
|
||||||
Length = sizeof(ULONG);
|
Length = sizeof(ULONG);
|
||||||
if (ProcessInformationLength != Length)
|
if (ProcessInformationLength != Length)
|
||||||
|
@ -860,15 +898,118 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProcessExecuteFlags:
|
case ProcessWx86Information:
|
||||||
DPRINT1("No execute Not implemented: %lx\n", ProcessInformationClass);
|
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
/* 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;
|
break;
|
||||||
|
|
||||||
case ProcessWow64Information:
|
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 ProcessLdtInformation:
|
||||||
case ProcessWx86Information:
|
DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass);
|
||||||
DPRINT1("VDM/16-bit implemented: %lx\n", ProcessInformationClass);
|
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -892,7 +1033,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
/* Check if caller wanted return length */
|
/* Check if caller wanted return length */
|
||||||
if (ReturnLength) *ReturnLength = Length;
|
if ((ReturnLength) && (Length)) *ReturnLength = Length;
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
|
@ -928,7 +1069,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
||||||
KAFFINITY ValidAffinity, Affinity = 0;
|
KAFFINITY ValidAffinity, Affinity = 0;
|
||||||
ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
|
ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
|
||||||
ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
|
ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
|
||||||
ULONG NoExecute = 0;
|
ULONG NoExecute = 0, VdmPower = 0;
|
||||||
BOOLEAN HasPrivilege;
|
BOOLEAN HasPrivilege;
|
||||||
PLIST_ENTRY Next;
|
PLIST_ENTRY Next;
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
|
@ -970,6 +1111,49 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
||||||
/* Check what kind of information class this is */
|
/* Check what kind of information class this is */
|
||||||
switch (ProcessInformationClass)
|
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 */
|
/* Error/Exception Port */
|
||||||
case ProcessExceptionPort:
|
case ProcessExceptionPort:
|
||||||
|
|
||||||
|
@ -1670,7 +1854,6 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
|
||||||
case ProcessLdtInformation:
|
case ProcessLdtInformation:
|
||||||
case ProcessLdtSize:
|
case ProcessLdtSize:
|
||||||
case ProcessIoPortHandlers:
|
case ProcessIoPortHandlers:
|
||||||
case ProcessWx86Information:
|
|
||||||
DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
|
DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue