/*++ Copyright (c) 1989 Microsoft Corporation Module Name: ulpc.h Abstract: User Mode Test header file for common definitions shared by userver.c and uclient.c Author: Steve Wood (stevewo) 28-Aug-1989 Revision History: --*/ #include #include #include #include #include #include #include #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; 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 ); } 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 ); } 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 ); }