345 lines
9.7 KiB
C
345 lines
9.7 KiB
C
|
//++
|
||
|
//
|
||
|
//Copyright (c) Microsoft Corporation
|
||
|
//
|
||
|
//Abstract:
|
||
|
//
|
||
|
//User Mode Test header file for common definitions shared by userver.c
|
||
|
//and uclient.c
|
||
|
//
|
||
|
//--
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#define PORT_NAME L"\\RPC Control\\LpcTestPort"
|
||
|
|
||
|
UNICODE_STRING PortName;
|
||
|
|
||
|
char * LpcMsgTypes[] = {
|
||
|
"** INVALID **",
|
||
|
"LPC_REQUEST",
|
||
|
"LPC_REPLY",
|
||
|
"LPC_DATAGRAM",
|
||
|
"LPC_LOST_REPLY",
|
||
|
"LPC_PORT_CLOSED",
|
||
|
"LPC_CLIENT_DIED",
|
||
|
"LPC_EXCEPTION",
|
||
|
"LPC_DEBUG_EVENT",
|
||
|
"LPC_ERROR_EVENT",
|
||
|
"LPC_CONNECTION_REQUEST",
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
SECURITY_QUALITY_OF_SERVICE DynamicQos = {
|
||
|
SecurityImpersonation,
|
||
|
SECURITY_DYNAMIC_TRACKING,
|
||
|
TRUE
|
||
|
};
|
||
|
|
||
|
#define TLPC_MAX_MSG_DATA_LENGTH 16
|
||
|
|
||
|
typedef struct _TLPC_PORTMSG {
|
||
|
PORT_MESSAGE h;
|
||
|
ULONG Data[ TLPC_MAX_MSG_DATA_LENGTH ];
|
||
|
} TLPC_PORTMSG, *PTLPC_PORTMSG;
|
||
|
|
||
|
PCH ClientMemoryBase = 0;
|
||
|
ULONG ClientMemorySize = 0;
|
||
|
PCH ServerMemoryBase = 0;
|
||
|
ULONG ServerMemoryDelta = 0;
|
||
|
|
||
|
typedef struct _PAGE {
|
||
|
CHAR Data[ 4096 ];
|
||
|
} PAGE, *PPAGE;
|
||
|
|
||
|
int
|
||
|
xatoi(const char* s)
|
||
|
{
|
||
|
int result = 0;
|
||
|
char c;
|
||
|
while (((c = *s) != '\0') && (c >= '0' && c <= '9'))
|
||
|
{
|
||
|
result *= 10;
|
||
|
result += (int)(c - '0');
|
||
|
s++;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
PPORT_MESSAGE
|
||
|
InitTlpcMsg(
|
||
|
PTLPC_PORTMSG Msg,
|
||
|
PVOID Context,
|
||
|
ULONG MsgLength
|
||
|
)
|
||
|
{
|
||
|
ULONG i;
|
||
|
ULONG ClientIndex;
|
||
|
ULONG cbData = MsgLength % (TLPC_MAX_MSG_DATA_LENGTH * sizeof( ULONG ));
|
||
|
PULONG ClientMemoryPtr;
|
||
|
|
||
|
Msg->h.u1.Length = ((sizeof( Msg->h ) + cbData) << 16) | cbData;
|
||
|
Msg->h.u2.ZeroInit = 0;
|
||
|
ClientIndex = (ULONG)Context & 0xF;
|
||
|
ClientIndex -= 1;
|
||
|
if (cbData) {
|
||
|
Msg->Data[ 0 ] = (ULONG)Context;
|
||
|
ClientMemoryPtr = (PULONG)(ClientMemoryBase + (ClientIndex * 0x1000));
|
||
|
for (i=1; i<(cbData/sizeof(ULONG)); i++) {
|
||
|
*ClientMemoryPtr = (ULONG)Context;
|
||
|
Msg->Data[ i ] = (ULONG)ClientMemoryPtr + ServerMemoryDelta;
|
||
|
ClientMemoryPtr++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return( (PPORT_MESSAGE)Msg );
|
||
|
}
|
||
|
|
||
|
#if DO_CHECK
|
||
|
BOOLEAN
|
||
|
CheckTlpcMsg(
|
||
|
NTSTATUS Status,
|
||
|
PTLPC_PORTMSG Msg
|
||
|
)
|
||
|
{
|
||
|
ULONG i;
|
||
|
ULONG ClientIndex;
|
||
|
ULONG cbData = Msg->h.u1.s1.DataLength;
|
||
|
ULONG Context;
|
||
|
PULONG ServerMemoryPtr;
|
||
|
PULONG ClientMemoryPtr;
|
||
|
ULONG ExpectedContext;
|
||
|
BOOLEAN Result;
|
||
|
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
fprintf( stderr, " - FAILED. Status == %X\n", Status );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
if (Msg->h.u2.s2.Type == LPC_CONNECTION_REQUEST) {
|
||
|
fprintf( stderr, " connection request" );
|
||
|
}
|
||
|
else
|
||
|
if (cbData) {
|
||
|
Context = Msg->Data[ 0 ];
|
||
|
ClientIndex = Context & 0xF;
|
||
|
ClientIndex -= 1;
|
||
|
ClientMemoryPtr = (PULONG)(ClientMemoryBase + (ClientIndex * 0x1000));
|
||
|
for (i=1; i<(cbData/sizeof( ULONG )); i++) {
|
||
|
if (Msg->h.u2.s2.Type == LPC_REPLY) {
|
||
|
if (Msg->Data[ i ] != ((ULONG)ClientMemoryPtr + ServerMemoryDelta) ||
|
||
|
*ClientMemoryPtr != (ULONG)Context
|
||
|
) {
|
||
|
fprintf( stderr, " incorrectly\n" );
|
||
|
fprintf( stderr, " Msg->Data[ %ld ] == %lx != %lx || %lx -> %lx != %lx\n",
|
||
|
i, Msg->Data[ i ], (ULONG)ClientMemoryPtr + ServerMemoryDelta,
|
||
|
ClientMemoryPtr, *ClientMemoryPtr, Context
|
||
|
);
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
ClientMemoryPtr++;
|
||
|
}
|
||
|
else {
|
||
|
ServerMemoryPtr = (PULONG)(Msg->Data[ i ]);
|
||
|
__try {
|
||
|
ExpectedContext = *ServerMemoryPtr;
|
||
|
Result = (ExpectedContext != Context) ? FALSE : TRUE;
|
||
|
}
|
||
|
__except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
|
ExpectedContext = 0xFEFEFEFE;
|
||
|
Result = FALSE;
|
||
|
}
|
||
|
|
||
|
if (!Result) {
|
||
|
fprintf( stderr, " incorrectly\n" );
|
||
|
fprintf( stderr, " Msg->Data[ %ld ] == %lx -> %lx != %lx\n",
|
||
|
i, Msg->Data[ i ], ExpectedContext, Context
|
||
|
);
|
||
|
return( FALSE );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// fprintf( stderr, " correctly\n" );
|
||
|
return( TRUE );
|
||
|
}
|
||
|
#else
|
||
|
#define CheckTlpcMsg(x, y) (1)
|
||
|
#endif // DO_CHECK
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
ShowHandleOrStatus(
|
||
|
NTSTATUS Status,
|
||
|
HANDLE Handle
|
||
|
)
|
||
|
{
|
||
|
if (NT_SUCCESS( Status )) {
|
||
|
fprintf( stderr, " - Handle = 0x%lx\n", Handle );
|
||
|
return( TRUE );
|
||
|
}
|
||
|
else {
|
||
|
fprintf( stderr, " - *** FAILED *** Status == %X\n", Status );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
ShowStatus(
|
||
|
NTSTATUS Status
|
||
|
)
|
||
|
{
|
||
|
if (NT_SUCCESS( Status )) {
|
||
|
fprintf( stderr, " - success\n" );
|
||
|
return( TRUE );
|
||
|
}
|
||
|
else {
|
||
|
fprintf( stderr, " - *** FAILED *** Status == %X\n", Status );
|
||
|
return( FALSE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PCH EnterString = ">>>>>>>>>>";
|
||
|
PCH InnerString = "||||||||||";
|
||
|
PCH LeaveString = "<<<<<<<<<<";
|
||
|
|
||
|
NTSTATUS
|
||
|
SendRequest(
|
||
|
ULONG Level,
|
||
|
PSZ ThreadName,
|
||
|
HANDLE PortHandle,
|
||
|
PVOID Context,
|
||
|
ULONG MsgLength,
|
||
|
PTLPC_PORTMSG CallBackTarget,
|
||
|
BOOLEAN ServerCallingClient
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
TLPC_PORTMSG Request, Reply;
|
||
|
PTEB Teb = NtCurrentTeb();
|
||
|
|
||
|
//
|
||
|
//fprintf( stderr, "%.*sEnter SendRequest, %lx.%lx",
|
||
|
// Level, EnterString,
|
||
|
// Teb->ClientId.UniqueProcess,
|
||
|
// Teb->ClientId.UniqueThread
|
||
|
// );
|
||
|
//
|
||
|
|
||
|
InitTlpcMsg( &Request, Context, MsgLength );
|
||
|
if (CallBackTarget == NULL) {
|
||
|
// fprintf( stderr, " - Request");
|
||
|
}
|
||
|
else {
|
||
|
Request.h.u2.s2.Type = LPC_REQUEST;
|
||
|
Request.h.ClientId = CallBackTarget->h.ClientId;
|
||
|
Request.h.MessageId = CallBackTarget->h.MessageId;
|
||
|
fprintf( stderr, " - Callback to %lx.%lx, ID: %ld",
|
||
|
Request.h.ClientId.UniqueProcess,
|
||
|
Request.h.ClientId.UniqueThread,
|
||
|
Request.h.MessageId
|
||
|
);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//fprintf( stderr, " (%ld bytes)...\n", Request.h.u1.s1.DataLength );
|
||
|
//
|
||
|
|
||
|
Status = NtRequestWaitReplyPort( PortHandle,
|
||
|
(PPORT_MESSAGE)&Request,
|
||
|
(PPORT_MESSAGE)&Reply
|
||
|
);
|
||
|
//
|
||
|
//fprintf( stderr, "%.*s %lx.%lx, ID: %u received ",
|
||
|
// Level, InnerString,
|
||
|
// Teb->ClientId.UniqueProcess,
|
||
|
// Teb->ClientId.UniqueThread,
|
||
|
// Reply.h.MessageId
|
||
|
// );
|
||
|
//
|
||
|
if (Reply.h.u2.s2.Type == LPC_REPLY) {
|
||
|
if (!CheckTlpcMsg( Status, &Reply )) {
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
fprintf( stderr, "SendRequest got invalid reply message at %x\n", &Reply );
|
||
|
DbgBreakPoint();
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
fprintf( stderr, "callback from %lx.%lx, ID: %ld",
|
||
|
Reply.h.ClientId.UniqueProcess,
|
||
|
Reply.h.ClientId.UniqueThread,
|
||
|
Reply.h.MessageId
|
||
|
);
|
||
|
if (!CheckTlpcMsg( Status, &Reply )) {
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
fprintf( stderr, "SendRequest got invalid callback message at %x\n", &Reply );
|
||
|
DbgBreakPoint();
|
||
|
}
|
||
|
else {
|
||
|
MsgLength = Reply.h.u1.s1.DataLength / 2;
|
||
|
if (MsgLength) {
|
||
|
Status = SendRequest( Level+1,
|
||
|
ThreadName,
|
||
|
PortHandle,
|
||
|
Context,
|
||
|
MsgLength,
|
||
|
&Reply,
|
||
|
ServerCallingClient
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (!ServerCallingClient || Level > 1) {
|
||
|
fprintf( stderr, "%.*s %lx.%lx sending ",
|
||
|
Level, InnerString,
|
||
|
Teb->ClientId.UniqueProcess,
|
||
|
Teb->ClientId.UniqueThread
|
||
|
);
|
||
|
fprintf( stderr, " callback (%u) reply to %lx.%lx, ID: %u (%ld bytes)...\n",
|
||
|
Level,
|
||
|
Reply.h.ClientId.UniqueProcess,
|
||
|
Reply.h.ClientId.UniqueThread,
|
||
|
Reply.h.MessageId,
|
||
|
Reply.h.u1.s1.DataLength
|
||
|
);
|
||
|
if (Level > 1) {
|
||
|
Status = NtReplyWaitReplyPort( PortHandle,
|
||
|
(PPORT_MESSAGE)&Reply
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//fprintf( stderr, "%.*sLeave SendRequest, %lx.%lx - Status == %X\n",
|
||
|
// Level, LeaveString,
|
||
|
// Teb->ClientId.UniqueProcess,
|
||
|
// Teb->ClientId.UniqueThread,
|
||
|
// Status
|
||
|
// );
|
||
|
//
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
EnterThread(
|
||
|
PSZ ThreadName,
|
||
|
ULONG Context
|
||
|
)
|
||
|
{
|
||
|
fprintf( stderr, "Entering %s thread, Context = 0x%lx\n",
|
||
|
ThreadName,
|
||
|
Context
|
||
|
);
|
||
|
}
|