Author: ion
Date: Sat Oct 21 23:26:54 2006
New Revision: 24595
URL:
http://svn.reactos.org/svn/reactos?rev=24595&view=rev
Log:
- Implement DbgkpQueueMessage. This is the main bi-directional communication routine for
the newer non-LPC Debug Object.
- Implement DbgkPostFakeProcessCreateMessages (and stub DbgkpPostFakeThreadMessages and
DbgkpPostFakeModuleMessages). These are required when attaching to a process after threads
have been created and modules loaded, so that the debugger can have a valid state.
- Still missing the two functions to Set/Clear the Debug Object, will do these next.
Modified:
trunk/reactos/ntoskrnl/dbgk/debug.c
Modified: trunk/reactos/ntoskrnl/dbgk/debug.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/dbgk/debug.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/dbgk/debug.c (original)
+++ trunk/reactos/ntoskrnl/dbgk/debug.c Sat Oct 21 23:26:54 2006
@@ -23,7 +23,35 @@
DEBUG_OBJECT_ALL_ACCESS
};
+static const INFORMATION_CLASS_INFO DbgkpDebugObjectInfoClass[] =
+{
+ /* DebugObjectUnusedInformation */
+ ICI_SQ_SAME(sizeof(ULONG), sizeof(ULONG), 0),
+ /* DebugObjectKillProcessOnExitInformation */
+ ICI_SQ_SAME(sizeof(DEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION), sizeof(ULONG),
ICIF_SET),
+};
+
/* PRIVATE FUNCTIONS *********************************************************/
+
+NTSTATUS
+NTAPI
+DbgkpSetProcessDebugObject(IN PEPROCESS Process,
+ IN PDEBUG_OBJECT DebugObject,
+ IN NTSTATUS MsgStatus,
+ IN PETHREAD LastThread)
+{
+ /* FIXME: TODO */
+ return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+NTAPI
+DbgkClearProcessDebugObject(IN PEPROCESS Process,
+ IN PDEBUG_OBJECT SourceDebugObject)
+{
+ /* FIXME: TODO */
+ return STATUS_UNSUCCESSFUL;
+}
NTSTATUS
NTAPI
@@ -33,8 +61,157 @@
IN ULONG Flags,
IN PDEBUG_OBJECT TargetObject OPTIONAL)
{
- /* FIXME: TODO */
- return STATUS_UNSUCCESSFUL;
+ PDEBUG_EVENT DebugEvent;
+ DEBUG_EVENT LocalDebugEvent;
+ PDEBUG_OBJECT DebugObject;
+ NTSTATUS Status;
+ BOOLEAN NewEvent;
+ PAGED_CODE();
+
+ /* Check if we have to allocate a debug event */
+ NewEvent = (Flags & 2) ? TRUE : FALSE;
+ if (NewEvent)
+ {
+ /* Allocate it */
+ DebugEvent = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(DEBUG_EVENT),
+ TAG('D', 'b', 'g',
'E'));
+ if (!DebugEvent) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Set flags */
+ DebugEvent->Flags = Flags | 4;
+
+ /* Reference the thread and process */
+ ObReferenceObject(Thread);
+ ObReferenceObject(Process);
+
+ /* Set the current thread */
+ DebugEvent->BackoutThread = PsGetCurrentThread();
+
+ /* Set the debug object */
+ DebugObject = TargetObject;
+ }
+ else
+ {
+ /* Use the debug event on the stack */
+ DebugEvent = &LocalDebugEvent;
+ DebugEvent->Flags = Flags;
+
+ /* Acquire the port lock */
+ ExAcquireFastMutex(&DbgkpProcessDebugPortMutex);
+
+ /* Get the debug object */
+ DebugObject = Process->DebugPort;
+
+ /* Check what kind of API message this is */
+ switch (Message->ApiNumber)
+ {
+ /* Process or thread creation */
+ case DbgKmCreateThreadApi:
+ case DbgKmCreateProcessApi:
+
+ /* Make sure we're not skipping creation messages */
+ if (Thread->SkipCreationMsg) DebugObject = NULL;
+ break;
+
+ /* Process or thread exit */
+ case DbgKmExitThreadApi:
+ case DbgKmExitProcessApi:
+
+ /* Make sure we're not skipping exit messages */
+ if (Thread->SkipTerminationMsg) DebugObject = NULL;
+
+ /* No special handling for other messages */
+ default:
+ break;
+ }
+ }
+
+ /* Setup the Debug Event */
+ KeInitializeEvent(&DebugEvent->ContinueEvent, SynchronizationEvent, FALSE);
+ DebugEvent->Process = Process;
+ DebugEvent->Thread = Thread;
+ RtlMoveMemory(&DebugEvent->ApiMsg, Message, sizeof(DBGKM_MSG));
+ DebugEvent->ClientId = Thread->Cid;
+
+ /* Check if we have a port object */
+ if (!DebugObject)
+ {
+ /* Fail */
+ Status = STATUS_PORT_NOT_SET;
+ }
+ else
+ {
+ /* Acquire the debug object mutex */
+ ExAcquireFastMutex(&DebugObject->Mutex);
+
+ /* Check if a debugger is active */
+ if (!DebugObject->DebuggerInactive)
+ {
+ /* Add the event into the object's list */
+ InsertTailList(&DebugObject->EventList,
&DebugEvent->EventList);
+
+ /* Check if we have to signal it */
+ if (!NewEvent)
+ {
+ /* Signal it */
+ KeSetEvent(&DebugObject->EventsPresent,
+ IO_NO_INCREMENT,
+ FALSE);
+ }
+
+ /* Set success */
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* No debugger */
+ Status = STATUS_DEBUGGER_INACTIVE;
+ }
+
+ /* Release the object lock */
+ ExReleaseFastMutex(&DebugObject->Mutex);
+ }
+
+ /* Check if we had acquired the port lock */
+ if (!NewEvent)
+ {
+ /* Release it */
+ ExReleaseFastMutex(&DbgkpProcessDebugPortMutex);
+
+ /* Check if we got here through success */
+ if (NT_SUCCESS(Status))
+ {
+ /* Wait on the continue event */
+ KeWaitForSingleObject(&DebugEvent->ContinueEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+
+ /* Copy API Message back */
+ RtlMoveMemory(Message, &DebugEvent->ApiMsg, sizeof(DBGKM_MSG));
+
+ /* Set return status */
+ Status = DebugEvent->Status;
+ }
+ }
+ else
+ {
+ /* Check if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Dereference the process and thread */
+ ObDereferenceObject(Thread);
+ ObDereferenceObject(Process);
+
+ /* Free the debug event */
+ ExFreePool(DebugEvent);
+ }
+ }
+
+ /* Return status */
+ return Status;
}
NTSTATUS
@@ -283,33 +460,74 @@
NTSTATUS
NTAPI
+DbgkpPostFakeModuleMessages(IN PEPROCESS Process,
+ IN PETHREAD Thread,
+ IN PDEBUG_OBJECT DebugObject)
+{
+ /* FIXME: TODO */
+ return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+NTAPI
+DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
+ IN PDEBUG_OBJECT DebugObject,
+ IN PETHREAD StartThread,
+ OUT PETHREAD *FirstThread,
+ OUT PETHREAD *LastThread)
+{
+ /* FIXME: TODO */
+ return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+NTAPI
DbgkpPostFakeProcessCreateMessages(IN PEPROCESS Process,
IN PDEBUG_OBJECT DebugObject,
- IN PETHREAD *LastThread)
-{
- /* FIXME: Implement */
- *LastThread = NULL;
- return STATUS_UNSUCCESSFUL;
-}
-
-NTSTATUS
-NTAPI
-DbgkpSetProcessDebugObject(IN PEPROCESS Process,
- IN PDEBUG_OBJECT DebugObject,
- IN NTSTATUS MsgStatus,
- IN PETHREAD LastThread)
-{
- /* FIXME: TODO */
- return STATUS_UNSUCCESSFUL;
-}
-
-NTSTATUS
-NTAPI
-DbgkClearProcessDebugObject(IN PEPROCESS Process,
- IN PDEBUG_OBJECT SourceDebugObject)
-{
- /* FIXME: TODO */
- return STATUS_UNSUCCESSFUL;
+ OUT PETHREAD *LastThread)
+{
+ KAPC_STATE ApcState;
+ PETHREAD FirstThread, FinalThread;
+ PETHREAD ReturnThread = NULL;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* Attach to the process */
+ KeStackAttachProcess(&Process->Pcb, &ApcState);
+
+ /* Post the fake thread messages */
+ Status = DbgkpPostFakeThreadMessages(Process,
+ DebugObject,
+ NULL,
+ &FirstThread,
+ &FinalThread);
+ if (NT_SUCCESS(Status))
+ {
+ /* Send the fake module messages too */
+ Status = DbgkpPostFakeModuleMessages(Process,
+ FirstThread,
+ DebugObject);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We failed, dereference the final thread */
+ ObDereferenceObject(FinalThread);
+ }
+ else
+ {
+ /* Set the final thread */
+ ReturnThread = FinalThread;
+ }
+
+ /* Dereference the first thread */
+ ObDereferenceObject(FirstThread);
+ }
+
+ /* Detach from the process */
+ KeUnstackDetachProcess(&ApcState);
+
+ /* Return the last thread */
+ *LastThread = ReturnThread;
+ return Status;
}
VOID
@@ -1003,14 +1221,6 @@
return Status;
}
-static const INFORMATION_CLASS_INFO DbgkpDebugObjectInfoClass[] =
-{
- /* DebugObjectUnusedInformation */
- ICI_SQ_SAME(sizeof(ULONG), sizeof(ULONG), 0),
- /* DebugObjectKillProcessOnExitInformation */
- ICI_SQ_SAME(sizeof(DEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION), sizeof(ULONG),
ICIF_SET),
-};
-
NTSTATUS
NTAPI
NtSetInformationDebugObject(IN HANDLE DebugHandle,
@@ -1034,16 +1244,19 @@
DebugInformationLength,
PreviousMode);
- /* Return required length to user-mode */
+ /* Check if the caller wanted the return length */
if (ReturnLength)
{
+ /* Enter SEH for probe */
_SEH_TRY
{
+ /* Return required length to user-mode */
ProbeForWriteUlong(ReturnLength);
*ReturnLength = sizeof(*DebugInfo);
}
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
+ /* Get SEH Exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
@@ -1108,11 +1321,13 @@
/* Clear the initial wait state change structure */
RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange));
- /* Check if we came with a timeout from user mode */
+ /* Check if the call was from user mode */
if (PreviousMode != KernelMode)
{
+ /* Protect probe in SEH */
_SEH_TRY
{
+ /* Check if we came with a timeout */
if (Timeout)
{
/* Make a copy on the stack */
@@ -1120,6 +1335,7 @@
Timeout = &SafeTimeOut;
}
+ /* Probe the state change structure */
ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
}
_SEH_HANDLE
@@ -1279,19 +1495,22 @@
/* We're, dereference the object */
ObDereferenceObject(DebugObject);
- /* Return our wait state change structure */
+ /* Protect write with SEH */
_SEH_TRY
{
- RtlCopyMemory(StateChange,
+ /* Return our wait state change structure */
+ RtlMoveMemory(StateChange,
&WaitStateChange,
sizeof(DBGUI_WAIT_STATE_CHANGE));
}
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
+ /* Get SEH Exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
+ /* Return status */
return Status;
}