NT4/private/ntos/dbgk/udbgk.c
2020-09-30 17:12:29 +02:00

473 lines
11 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
udbg.c
Abstract:
Usermode test for debugger
Author:
Mark Lucovsky (markl) 19-Jan-1990
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntdbg.h>
HANDLE DebugPort;
NTSTATUS
ThreadThatExits (
IN PVOID ThreadParameter
)
{
NtTerminateThread(NtCurrentThread(),(NTSTATUS) ThreadParameter );
}
ULONG
foo(PULONG l)
{
//ULONG x;
//x = *l;
//return x + 1;
return *l;
}
NTSTATUS
ThreadThatExcepts (
IN PVOID ThreadParameter
)
{
foo((PULONG)0x00000001);
NtTerminateThread(NtCurrentThread(),(NTSTATUS) ThreadParameter );
}
NTSTATUS
ThreadThatSpins (
IN PVOID ThreadParameter
)
{
for(;;);
NtTerminateThread(NtCurrentThread(),STATUS_SUCCESS);
}
UdbgTest1()
{
NTSTATUS st;
HANDLE ExitThread, SpinThread, DebugProcess;
CLIENT_ID ExitClientId, SpinClientId;
DBGKM_APIMSG m;
PDBGKM_CREATE_THREAD CreateThreadArgs;
PDBGKM_CREATE_PROCESS CreateProcessArgs;
PDBGKM_EXIT_THREAD ExitThreadArgs;
PDBGKM_EXIT_PROCESS ExitProcessArgs;
ULONG Psp;
DbgPrint("UdbgTest1: (1)...\n");
//
// Verify that a process can be created with a debug
// port.
//
st = NtCreateProcess(
&DebugProcess,
PROCESS_ALL_ACCESS,
NULL,
NtCurrentProcess(),
FALSE,
NULL,
DebugPort,
NULL
);
ASSERT(NT_SUCCESS(st));
st = RtlCreateUserThread(
DebugProcess,
NULL,
TRUE,
0L,
0L,
0L,
ThreadThatExits,
(PVOID) STATUS_ABANDONED,
&ExitThread,
&ExitClientId
);
ASSERT(NT_SUCCESS(st));
st = RtlCreateUserThread(
DebugProcess,
NULL,
TRUE,
0L,
0L,
0L,
ThreadThatSpins,
NULL,
&SpinThread,
&SpinClientId
);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest1: (2)...\n");
//
// Verify that CreateProcess Messages Arrive, and that
// they are correct
//
st = NtResumeThread(SpinThread,NULL);
ASSERT(NT_SUCCESS(st));
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmCreateProcessApi);
CreateThreadArgs = &m.u.CreateProcess.InitialThread;
CreateProcessArgs = &m.u.CreateProcess;
ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatSpins );
ASSERT( CreateProcessArgs->SubSystemKey == 0);
DbgPrint("UdbgTest1: (3)...\n");
//
// Verify that other threads in the process are properly suspended
//
st = NtSuspendThread(ExitThread,&Psp);
ASSERT(NT_SUCCESS(st) && Psp == 2);
st = NtResumeThread(ExitThread,&Psp);
ASSERT(NT_SUCCESS(st) && Psp == 3);
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest1: (4)...\n");
//
// Verify that CreateThread Messages Arrive, and that
// they are correct
//
st = NtResumeThread(ExitThread,&Psp);
ASSERT(NT_SUCCESS(st));
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmCreateThreadApi);
CreateThreadArgs = &m.u.CreateThread;
ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExits );
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest1: (5)...\n");
//
// Verify that ExitThread Messages Arrive, and that
// they are correct
//
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmExitThreadApi);
ExitThreadArgs = &m.u.ExitThread;
ASSERT( ExitThreadArgs->ExitStatus == STATUS_ABANDONED );
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
st = NtWaitForSingleObject(ExitThread,FALSE,NULL);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest1: (6)...\n");
//
// Verify that ExitThread Messages Arrive, and that
// they are correct
//
st = NtTerminateProcess(DebugProcess,STATUS_REPARSE);
ASSERT(NT_SUCCESS(st));
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmExitThreadApi);
ExitThreadArgs = &m.u.ExitThread;
ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE );
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest1: (7)...\n");
//
// Verify that ExitProcess Messages Arrive, and that
// they are correct
//
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmExitProcessApi);
ExitProcessArgs = &m.u.ExitProcess;
ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE );
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
st = NtWaitForSingleObject(ExitThread,FALSE,NULL);
ASSERT(NT_SUCCESS(st));
st = NtWaitForSingleObject(DebugProcess,FALSE,NULL);
ASSERT(NT_SUCCESS(st));
NtClose(ExitThread);
NtClose(SpinThread);
NtClose(DebugProcess);
DbgPrint("UdbgTest1: END OF TEST ***\n");
}
UdbgTest2()
{
NTSTATUS st;
HANDLE ExceptionThread, DebugProcess;
DBGKM_APIMSG m;
PDBGKM_CREATE_THREAD CreateThreadArgs;
PDBGKM_CREATE_PROCESS CreateProcessArgs;
PDBGKM_EXIT_THREAD ExitThreadArgs;
PDBGKM_EXIT_PROCESS ExitProcessArgs;
PDBGKM_EXCEPTION ExceptionArgs;
ULONG Psp;
DbgPrint("UdbgTest2: (1)...\n");
//
// Verify that a process can be created with a debug
// port.
//
st = NtCreateProcess(
&DebugProcess,
PROCESS_ALL_ACCESS,
NULL,
NtCurrentProcess(),
FALSE,
NULL,
DebugPort,
NULL
);
ASSERT(NT_SUCCESS(st));
st = RtlCreateUserThread(
DebugProcess,
NULL,
TRUE,
0L,
0L,
0L,
ThreadThatExcepts,
(PVOID) STATUS_ABANDONED,
&ExceptionThread,
NULL
);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest2: (2)...\n");
//
// Verify that CreateThread Messages Arrive, and that
// they are correct
//
st = NtResumeThread(ExceptionThread,NULL);
ASSERT(NT_SUCCESS(st));
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmCreateProcessApi);
CreateThreadArgs = &m.u.CreateProcess.InitialThread;
CreateProcessArgs = &m.u.CreateProcess;
ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExcepts );
ASSERT( CreateProcessArgs->SubSystemKey == 0);
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest2: (3)...\n");
//
// Verify that First Chance Exception Messages Arrive, and that
// they are correct
//
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmExceptionApi);
ExceptionArgs = &m.u.Exception;
ASSERT( ExceptionArgs->FirstChance == TRUE );
m.ReturnedStatus = DBG_EXCEPTION_NOT_HANDLED;
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest2: (4)...\n");
//
// Verify that First Chance Exception Messages Arrive, and that
// they are correct
//
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmExceptionApi);
ExceptionArgs = &m.u.Exception;
ASSERT( ExceptionArgs->FirstChance == FALSE );
m.ReturnedStatus = DBG_EXCEPTION_HANDLED;
skip4:
st = NtTerminateProcess(DebugProcess,STATUS_REPARSE);
ASSERT(NT_SUCCESS(st));
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmExitThreadApi);
ExitThreadArgs = &m.u.ExitThread;
ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE );
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
DbgPrint("UdbgTest2: (5)...\n");
//
// Verify that ExitProcess Messages Arrive, and that
// they are correct
//
st = NtReplyWaitReceivePort(
DebugPort,
NULL,
NULL,
(PPORT_MESSAGE)&m
);
ASSERT(NT_SUCCESS(st));
ASSERT(m.ApiNumber == DbgKmExitProcessApi);
ExitProcessArgs = &m.u.ExitProcess;
ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE );
st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
ASSERT(NT_SUCCESS(st));
st = NtWaitForSingleObject(ExceptionThread,FALSE,NULL);
ASSERT(NT_SUCCESS(st));
st = NtWaitForSingleObject(DebugProcess,FALSE,NULL);
ASSERT(NT_SUCCESS(st));
NtClose(ExceptionThread);
NtClose(DebugProcess);
DbgPrint("UdbgTest2: END OF TEST ***\n");
}
main()
{
NTSTATUS st;
OBJECT_ATTRIBUTES Obja;
InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL);
st = NtCreatePort(
&DebugPort,
&Obja,
0L,
256,
256 * 16
);
ASSERT(NT_SUCCESS(st));
UdbgTest2();
UdbgTest1();
}