/*++ 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 */ #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); }