Process, Thread, Message, Flags);
/* Check if we have to allocate a debug event */
- NewEvent = (Flags & 2) ? TRUE : FALSE;
+ NewEvent = (Flags & DEBUG_EVENT_NOWAIT) ? TRUE : FALSE;
if (NewEvent)
{
/* Allocate it */
DebugEvent = ExAllocatePoolWithTag(NonPagedPool,
sizeof(DEBUG_EVENT),
- TAG('D', 'b', 'g', 'E'));
+ 'EgbD');
if (!DebugEvent) return STATUS_INSUFFICIENT_RESOURCES;
/* Set flags */
- DebugEvent->Flags = Flags | 4;
+ DebugEvent->Flags = Flags | DEBUG_EVENT_INACTIVE;
/* Reference the thread and process */
ObReferenceObject(Thread);
{
NTSTATUS Status;
UCHAR Buffer[PORT_MAXIMUM_MESSAGE_LENGTH];
+ BOOLEAN Suspended = FALSE;
PAGED_CODE();
/* Suspend process if required */
- if (SuspendProcess) DbgkpSuspendProcess();
+ if (SuspendProcess) Suspended = DbgkpSuspendProcess();
/* Set return status */
Message->ReturnedStatus = STATUS_PENDING;
/* Set create process reported state */
- PsGetCurrentProcess()->CreateReported = TRUE;
+ PspSetProcessFlag(PsGetCurrentProcess(), PSF_CREATE_REPORTED_BIT);
/* Send the LPC command */
Status = LpcRequestWaitReplyPort(Port,
if (NT_SUCCESS(Status)) RtlCopyMemory(Message, Buffer, sizeof(DBGKM_MSG));
/* Resume the process if it was suspended */
- if (SuspendProcess) DbgkpResumeProcess();
+ if (Suspended) DbgkpResumeProcess();
return Status;
}
NTSTATUS
NTAPI
DbgkpSendApiMessage(IN OUT PDBGKM_MSG ApiMsg,
- IN ULONG Flags)
+ IN BOOLEAN SuspendProcess)
{
NTSTATUS Status;
+ BOOLEAN Suspended = FALSE;
PAGED_CODE();
- DBGKTRACE(DBGK_MESSAGE_DEBUG, "ApiMsg: %p Flags: %lx\n", ApiMsg, Flags);
+ DBGKTRACE(DBGK_MESSAGE_DEBUG, "ApiMsg: %p SuspendProcess: %lx\n", ApiMsg, SuspendProcess);
/* Suspend process if required */
- if (Flags) DbgkpSuspendProcess();
+ if (SuspendProcess) Suspended = DbgkpSuspendProcess();
/* Set return status */
ApiMsg->ReturnedStatus = STATUS_PENDING;
/* Set create process reported state */
- PsGetCurrentProcess()->CreateReported = TRUE;
+ PspSetProcessFlag(PsGetCurrentProcess(), PSF_CREATE_REPORTED_BIT);
/* Send the LPC command */
Status = DbgkpQueueMessage(PsGetCurrentProcess(),
ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
/* Resume the process if it was suspended */
- if (Flags) DbgkpResumeProcess();
+ if (Suspended) DbgkpResumeProcess();
return Status;
}
/* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
(8 + sizeof(DBGKM_EXCEPTION));
- ApiMessage.h.u2.ZeroInit = LPC_DEBUG_EVENT;
+ ApiMessage.h.u2.ZeroInit = 0;
+ ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
ApiMessage.ApiNumber = DbgKmExceptionApi;
/* Check if this is to be sent on the debug port */
{
/* Otherwise, use the exception port */
Port = Process->ExceptionPort;
- ApiMessage.h.u2.ZeroInit = LPC_EXCEPTION;
+ ApiMessage.h.u2.ZeroInit = 0;
+ ApiMessage.h.u2.s2.Type = LPC_EXCEPTION;
UseLpc = TRUE;
}
DBGKTRACE(DBGK_OBJECT_DEBUG, "DebugEvent: %p\n", DebugEvent);
/* Check if we have to wake the thread */
- if (DebugEvent->Flags & 20) PsResumeThread(Thread, NULL);
+ if (DebugEvent->Flags & DEBUG_EVENT_SUSPEND) PsResumeThread(Thread, NULL);
/* Check if we had locked the thread */
- if (DebugEvent->Flags & 8)
+ if (DebugEvent->Flags & DEBUG_EVENT_RELEASE)
{
/* Unlock it */
ExReleaseRundownProtection(&Thread->RundownProtect);
}
/* Check if we have to wake up the event */
- if (DebugEvent->Flags & 2)
+ if (DebugEvent->Flags & DEBUG_EVENT_NOWAIT)
{
/* Otherwise, free the debug event */
DbgkpFreeDebugEvent(DebugEvent);
Status = DbgkpQueueMessage(Process,
Thread,
&ApiMessage,
- 2,
+ DEBUG_EVENT_NOWAIT,
DebugObject);
if (!NT_SUCCESS(Status))
{
else
{
/* Get the first thread ourselves */
- ThisThread = PsGetNextProcessThread(Process, OldThread);
+ ThisThread = PsGetNextProcessThread(Process, NULL);
IsFirstThread = TRUE;
}
if (ExAcquireRundownProtection(&ThisThread->RundownProtect))
{
/* Acquire worked, set flags */
- Flags = 0x8 | 0x2;
+ Flags = DEBUG_EVENT_RELEASE | DEBUG_EVENT_NOWAIT;
/* Check if this is a user thread */
if (!ThisThread->SystemThread)
if (NT_SUCCESS(PsSuspendThread(ThisThread, NULL)))
{
/* Remember this */
- Flags = 0x8 | 0x2 | 0x20;
+ Flags |= DEBUG_EVENT_SUSPEND;
}
}
}
else
{
/* Couldn't acquire rundown */
- Flags = 0x10 | 0x2;
+ Flags = DEBUG_EVENT_PROTECT_FAILED | DEBUG_EVENT_NOWAIT;
}
/* Clear the API Message */
/* Check if this is the first thread */
if ((IsFirstThread) &&
- !(Flags & 0x10) &&
+ !(Flags & DEBUG_EVENT_PROTECT_FAILED) &&
!(ThisThread->SystemThread) &&
(ThisThread->GrantedAccess))
{
DebugObject);
if (!NT_SUCCESS(Status))
{
- /* We failed. FIXME: Handle this */
- DPRINT1("Unhandled Dbgk codepath!\n");
- ASSERT(FALSE);
+ /* Resume the thread if it was suspended */
+ if (Flags & DEBUG_EVENT_SUSPEND) PsResumeThread(ThisThread, NULL);
+
+ /* Check if we acquired rundown */
+ if (Flags & DEBUG_EVENT_RELEASE)
+ {
+ /* Release it */
+ ExReleaseRundownProtection(&ThisThread->RundownProtect);
+ }
+
+ /* If this was a process create, check if we got a handle */
+ if ((ApiMessage.ApiNumber == DbgKmCreateProcessApi) &&
+ (CreateProcess->FileHandle))
+ {
+ /* Close it */
+ ObCloseHandle(CreateProcess->FileHandle, KernelMode);
+ }
+
+ /* Release our reference and break out */
+ ObDereferenceObject(ThisThread);
+ break;
}
/* Check if this was the first message */
/* Check the API status */
if (!NT_SUCCESS(Status))
{
- /* We failed. FIXME: Handle this */
- DPRINT1("Unhandled Dbgk codepath!\n");
- ASSERT(FALSE);
+ /* Dereference and fail */
+ if (pFirstThread) ObDereferenceObject(pFirstThread);
+ if (pLastThread) ObDereferenceObject(pLastThread);
+ return Status;
}
/* Make sure we have a first thread */
case DbgKmExceptionApi:
/* Look at the exception code */
- if (DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
+ if ((NTSTATUS)DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
STATUS_BREAKPOINT)
{
/* Update this as a breakpoint exception */
WaitStateChange->NewState = DbgBreakpointStateChange;
}
- else if (DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
+ else if ((NTSTATUS)DebugEvent->ApiMsg.Exception.ExceptionRecord.ExceptionCode ==
STATUS_SINGLE_STEP)
{
/* Update this as a single step exception */
BOOLEAN DebugPortCleared = FALSE;
PLIST_ENTRY DebugEventList;
PDEBUG_EVENT DebugEvent;
+ PAGED_CODE();
DBGKTRACE(DBGK_OBJECT_DEBUG, "OwnerProcess: %p DebugObject: %p\n",
OwnerProcess, DebugObject);
else
{
/* Set the process flags */
- InterlockedOr((PLONG)&Process->Flags,
- PSF_NO_DEBUG_INHERIT_BIT | PSF_CREATE_REPORTED_BIT);
+ PspSetProcessFlag(Process,
+ PSF_NO_DEBUG_INHERIT_BIT |
+ PSF_CREATE_REPORTED_BIT);
/* Reference the debug object */
ObReferenceObject(DebugObject);
NextEntry = DebugObject->EventList.Flink;
while (NextEntry != &DebugObject->EventList)
{
- /* Get the debug event */
+ /* Get the debug event and go to the next entry */
DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
+ NextEntry = NextEntry->Flink;
DBGKTRACE(DBGK_PROCESS_DEBUG, "DebugEvent: %p Flags: %lx TH: %p/%p\n",
DebugEvent, DebugEvent->Flags,
DebugEvent->BackoutThread, PsGetCurrentThread());
/* Check for if the debug event queue needs flushing */
- if ((DebugEvent->Flags & 4) &&
+ if ((DebugEvent->Flags & DEBUG_EVENT_INACTIVE) &&
(DebugEvent->BackoutThread == PsGetCurrentThread()))
{
/* Get the event's thread */
(!EventThread->SystemThread))
{
/* Check if we couldn't acquire rundown for it */
- if (DebugEvent->Flags & 0x10)
+ if (DebugEvent->Flags & DEBUG_EVENT_PROTECT_FAILED)
{
/* Set the skip termination flag */
PspSetCrossThreadFlag(EventThread, CT_SKIP_CREATION_MSG_BIT);
if (DoSetEvent)
{
/* Do it */
- DebugEvent->Flags &= ~4;
+ DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE;
KeSetEvent(&DebugObject->EventsPresent,
IO_NO_INCREMENT,
FALSE);
}
/* Check if the lock is held */
- if (DebugEvent->Flags & 8)
+ if (DebugEvent->Flags & DEBUG_EVENT_RELEASE)
{
/* Release it */
- DebugEvent->Flags &= ~8;
+ DebugEvent->Flags &= ~DEBUG_EVENT_RELEASE;
ExReleaseRundownProtection(&EventThread->RundownProtect);
}
}
-
- /* Go to the next entry */
- NextEntry = NextEntry->Flink;
}
/* Release the debug object */
{
/* Remove the event */
NextEntry = RemoveHeadList(&TempList);
- DebugEvent = CONTAINING_RECORD (NextEntry, DEBUG_EVENT, EventList);
+ DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
/* Wake it */
DbgkpWakeTarget(DebugEvent);
NTSTATUS
NTAPI
DbgkClearProcessDebugObject(IN PEPROCESS Process,
- IN PDEBUG_OBJECT SourceDebugObject)
+ IN PDEBUG_OBJECT SourceDebugObject OPTIONAL)
{
- /* FIXME: TODO */
- DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p DebugObject: %p\n",
+ PDEBUG_OBJECT DebugObject;
+ PDEBUG_EVENT DebugEvent;
+ LIST_ENTRY TempList;
+ PLIST_ENTRY NextEntry;
+ PAGED_CODE();
+ DBGKTRACE(DBGK_OBJECT_DEBUG, "Process: %p DebugObject: %p\n",
Process, SourceDebugObject);
- return STATUS_UNSUCCESSFUL;
+
+ /* Acquire the port lock */
+ ExAcquireFastMutex(&DbgkpProcessDebugPortMutex);
+
+ /* Get the Process Debug Object */
+ DebugObject = Process->DebugPort;
+
+ /*
+ * Check if the process had an object and it matches,
+ * or if the process had an object but none was specified
+ * (in which we are called from NtTerminateProcess)
+ */
+ if ((DebugObject) &&
+ ((DebugObject == SourceDebugObject) ||
+ (SourceDebugObject == NULL)))
+ {
+ /* Clear the debug port */
+ Process->DebugPort = NULL;
+
+ /* Release the port lock and remove the PEB flag */
+ ExReleaseFastMutex(&DbgkpProcessDebugPortMutex);
+ DbgkpMarkProcessPeb(Process);
+ }
+ else
+ {
+ /* Release the port lock and fail */
+ ExReleaseFastMutex(&DbgkpProcessDebugPortMutex);
+ return STATUS_PORT_NOT_SET;
+ }
+
+ /* Initialize the temporary list */
+ InitializeListHead(&TempList);
+
+ /* Acquire the Object */
+ ExAcquireFastMutex(&DebugObject->Mutex);
+
+ /* Loop the events */
+ NextEntry = DebugObject->EventList.Flink;
+ while (NextEntry != &DebugObject->EventList)
+ {
+ /* Get the Event and go to the next entry */
+ DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
+ NextEntry = NextEntry->Flink;
+
+ /* Check that it belongs to the specified process */
+ if (DebugEvent->Process == Process)
+ {
+ /* Insert it into the temporary list */
+ RemoveEntryList(&DebugEvent->EventList);
+ InsertTailList(&TempList, &DebugEvent->EventList);
+ }
+ }
+
+ /* Release the Object */
+ ExReleaseFastMutex(&DebugObject->Mutex);
+
+ /* Release the initial reference */
+ ObDereferenceObject(DebugObject);
+
+ /* Loop our temporary list */
+ while (!IsListEmpty(&TempList))
+ {
+ /* Remove the event */
+ NextEntry = RemoveHeadList(&TempList);
+ DebugEvent = CONTAINING_RECORD(NextEntry, DEBUG_EVENT, EventList);
+
+ /* Wake it up */
+ DebugEvent->Status = STATUS_DEBUGGER_INACTIVE;
+ DbgkpWakeTarget(DebugEvent);
+ }
+
+ /* Return Success */
+ return STATUS_SUCCESS;
}
VOID
/* PUBLIC FUNCTIONS **********************************************************/
+/*
+ * @implemented
+ */
NTSTATUS
NTAPI
NtCreateDebugObject(OUT PHANDLE DebugHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN BOOLEAN KillProcessOnExit)
+ IN ULONG Flags)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PDEBUG_OBJECT DebugObject;
HANDLE hDebug;
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
PAGED_CODE();
/* Check if we were called from user mode*/
if (PreviousMode != KernelMode)
{
/* Enter SEH for probing */
- _SEH_TRY
+ _SEH2_TRY
{
/* Probe the handle */
ProbeForWriteHandle(DebugHandle);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Get exception error */
- Status = _SEH_GetExceptionCode();
- } _SEH_END;
- if (!NT_SUCCESS(Status)) return Status;
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ } _SEH2_END;
}
+ /* Check for invalid flags */
+ if (Flags & ~DBGK_ALL_FLAGS) return STATUS_INVALID_PARAMETER;
+
/* Create the Object */
Status = ObCreateObject(PreviousMode,
DbgkDebugObjectType,
FALSE);
/* Set the Flags */
- DebugObject->KillProcessOnExit = KillProcessOnExit;
+ DebugObject->Flags = 0;
+ if (Flags & DBGK_KILL_PROCESS_ON_EXIT)
+ {
+ DebugObject->KillProcessOnExit = TRUE;
+ }
/* Insert it */
Status = ObInsertObject((PVOID)DebugObject,
&hDebug);
if (NT_SUCCESS(Status))
{
- _SEH_TRY
+ /* Enter SEH to protect the write */
+ _SEH2_TRY
{
+ /* Return the handle */
*DebugHandle = hDebug;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(ExSystemExceptionFilter())
{
- Status = _SEH_GetExceptionCode();
- } _SEH_END;
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ } _SEH2_END;
}
}
return Status;
}
+/*
+ * @implemented
+ */
NTSTATUS
NTAPI
NtDebugContinue(IN HANDLE DebugHandle,
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PDEBUG_OBJECT DebugObject;
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
PDEBUG_EVENT DebugEvent = NULL, DebugEventToWake = NULL;
PLIST_ENTRY ListHead, NextEntry;
BOOLEAN NeedsWake = FALSE;
if (PreviousMode != KernelMode)
{
/* Enter SEH for probing */
- _SEH_TRY
+ _SEH2_TRY
{
/* Probe the handle */
ProbeForRead(AppClientId, sizeof(CLIENT_ID), sizeof(ULONG));
ClientId = *AppClientId;
AppClientId = &ClientId;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Get exception error */
- Status = _SEH_GetExceptionCode();
- } _SEH_END;
- if (!NT_SUCCESS(Status)) return Status;
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ } _SEH2_END;
}
/* Make sure that the status is valid */
if (NeedsWake)
{
/* Wake it up and break out */
- DebugEvent->Flags &= ~4;
- KeSetEvent(&DebugEvent->ContinueEvent,
+ DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE;
+ KeSetEvent(&DebugObject->EventsPresent,
IO_NO_INCREMENT,
FALSE);
break;
/* Compare thread ID and flag */
if ((DebugEvent->ClientId.UniqueThread ==
- AppClientId->UniqueThread) && (DebugEvent->Flags & 1))
+ AppClientId->UniqueThread) && (DebugEvent->Flags & DEBUG_EVENT_READ))
{
/* Remove the event from the list */
RemoveEntryList(NextEntry);
if (NeedsWake)
{
/* Set the continue status */
- DebugEvent->ApiMsg.ReturnedStatus = ContinueStatus;
- DebugEvent->Status = STATUS_SUCCESS;
+ DebugEventToWake->ApiMsg.ReturnedStatus = ContinueStatus;
+ DebugEventToWake->Status = STATUS_SUCCESS;
/* Wake the target */
- DbgkpWakeTarget(DebugEvent);
+ DbgkpWakeTarget(DebugEventToWake);
}
else
{
return Status;
}
+/*
+ * @implemented
+ */
NTSTATUS
NTAPI
NtDebugActiveProcess(IN HANDLE ProcessHandle,
{
PEPROCESS Process;
PDEBUG_OBJECT DebugObject;
- KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PETHREAD LastThread;
NTSTATUS Status;
PAGED_CODE();
NULL);
if (!NT_SUCCESS(Status)) return Status;
- /* Don't allow debugging the initial system process */
- if (Process == PsInitialSystemProcess)
+ /* Don't allow debugging the current process or the system process */
+ if ((Process == PsGetCurrentProcess()) ||
+ (Process == PsInitialSystemProcess))
{
/* Dereference and fail */
ObDereferenceObject(Process);
return Status;
}
+/*
+ * @implemented
+ */
NTSTATUS
NTAPI
NtRemoveProcessDebug(IN HANDLE ProcessHandle,
{
PEPROCESS Process;
PDEBUG_OBJECT DebugObject;
- KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PAGED_CODE();
DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n",
return Status;
}
+/*
+ * @implemented
+ */
NTSTATUS
NTAPI
NtSetInformationDebugObject(IN HANDLE DebugHandle,
{
PDEBUG_OBJECT DebugObject;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
PDEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION DebugInfo = DebugInformation;
PAGED_CODE();
DebugInformation,
DebugInformationLength,
PreviousMode);
+ if (!NT_SUCCESS(Status)) return Status;
/* Check if the caller wanted the return length */
if (ReturnLength)
{
/* Enter SEH for probe */
- _SEH_TRY
+ _SEH2_TRY
{
/* Return required length to user-mode */
ProbeForWriteUlong(ReturnLength);
*ReturnLength = sizeof(*DebugInfo);
}
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ _SEH2_EXCEPT(ExSystemExceptionFilter())
{
- /* Get SEH Exception code */
- Status = _SEH_GetExceptionCode();
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
- _SEH_END;
+ _SEH2_END;
}
- if (!NT_SUCCESS(Status)) return Status;
/* Open the Object */
Status = ObReferenceObjectByHandle(DebugHandle,
return Status;
}
+/*
+ * @implemented
+ */
NTSTATUS
NTAPI
NtWaitForDebugEvent(IN HANDLE DebugHandle,
OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- LARGE_INTEGER SafeTimeOut;
+ LARGE_INTEGER LocalTimeOut;
PEPROCESS Process;
LARGE_INTEGER StartTime;
PETHREAD Thread;
LARGE_INTEGER NewTime;
PDEBUG_OBJECT DebugObject;
DBGUI_WAIT_STATE_CHANGE WaitStateChange;
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
PDEBUG_EVENT DebugEvent = NULL, DebugEvent2;
PLIST_ENTRY ListHead, NextEntry, NextEntry2;
PAGED_CODE();
DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle);
- /* Clear the initial wait state change structure */
+ /* Clear the initial wait state change structure and the timeout */
RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange));
+ LocalTimeOut.QuadPart = 0;
- /* Protect probe in SEH */
- _SEH_TRY
+ /* Check if we were called from user mode */
+ if (PreviousMode != KernelMode)
{
- /* Check if we came with a timeout */
- if (Timeout)
+ /* Protect probe in SEH */
+ _SEH2_TRY
{
- /* Check if the call was from user mode */
- if (PreviousMode != KernelMode)
+ /* Check if we came with a timeout */
+ if (Timeout)
{
/* Probe it */
ProbeForReadLargeInteger(Timeout);
- }
-
- /* Make a local copy */
- SafeTimeOut = *Timeout;
- Timeout = &SafeTimeOut;
- /* Query the current time */
- KeQuerySystemTime(&StartTime);
- }
+ /* Make a local copy */
+ LocalTimeOut = *Timeout;
+ Timeout = &LocalTimeOut;
+ }
- /* Check if the call was from user mode */
- if (PreviousMode != KernelMode)
- {
/* Probe the state change structure */
ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
}
- _SEH_HANDLE
+ else
{
- /* Get the exception code */
- Status = _SEH_GetExceptionCode();
+ /* Copy directly */
+ if (Timeout) LocalTimeOut = *Timeout;
}
- _SEH_END;
- if (!NT_SUCCESS(Status)) return Status;
+
+ /* If we were passed a timeout, query the current time */
+ if (Timeout) KeQuerySystemTime(&StartTime);
/* Get the debug object */
Status = ObReferenceObjectByHandle(DebugHandle,
/* Wait on the debug object given to us */
while (TRUE)
{
- Status = KeWaitForSingleObject(DebugObject,
+ Status = KeWaitForSingleObject(&DebugObject->EventsPresent,
Executive,
PreviousMode,
Alertable,
DebugEvent, DebugEvent->Flags);
/* Check flags */
- if (!(DebugEvent->Flags & (4 | 1)))
+ if (!(DebugEvent->Flags & (DEBUG_EVENT_INACTIVE | DEBUG_EVENT_READ)))
{
/* We got an event */
GotEvent = TRUE;
DebugEvent->ClientId.UniqueProcess)
{
/* Found it, break out */
- DebugEvent->Flags |= 4;
+ DebugEvent->Flags |= DEBUG_EVENT_INACTIVE;
DebugEvent->BackoutThread = NULL;
GotEvent = FALSE;
break;
DebugEvent);
/* Set flag */
- DebugEvent->Flags |= 1;
+ DebugEvent->Flags |= DEBUG_EVENT_READ;
}
else
{
if (!GotEvent)
{
/* Check if we can wait again */
- if (SafeTimeOut.QuadPart < 0)
+ if (LocalTimeOut.QuadPart < 0)
{
/* Query the new time */
KeQuerySystemTime(&NewTime);
/* Substract times */
- SafeTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
+ LocalTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
StartTime = NewTime;
/* Check if we've timed out */
- if (SafeTimeOut.QuadPart >= 0)
+ if (LocalTimeOut.QuadPart >= 0)
{
/* We have, break out of the loop */
Status = STATUS_TIMEOUT;
ObDereferenceObject(DebugObject);
/* Protect write with SEH */
- _SEH_TRY
+ _SEH2_TRY
{
/* Return our wait state change structure */
*StateChange = WaitStateChange;
}
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ _SEH2_EXCEPT(ExSystemExceptionFilter())
{
/* Get SEH Exception code */
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
/* Return status */
return Status;
}
-
-/* EOF */