//++ // //Copyright (c) Microsoft Corporation // //Abstract: // // User Mode Server Test program for the LPC subcomponent of the NTOS project // //-- #include "ulpc.h" #define MAX_REQUEST_THREADS 9 #define MAX_CONNECTIONS 4 HANDLE ServerConnectionPortHandle; HANDLE ServerThreadHandles[ MAX_REQUEST_THREADS ]; DWORD ServerThreadClientIds[ MAX_REQUEST_THREADS ]; HANDLE ServerClientPortHandles[ MAX_CONNECTIONS ]; ULONG CountServerClientPortHandles = 0; ULONG CountClosedServerClientPortHandles = 0; BOOLEAN TestCallBacks; VOID ServerHandleConnectionRequest( IN PTLPC_PORTMSG Msg ) { BOOLEAN AcceptConnection; LPSTR ConnectionInformation; ULONG ConnectionInformationLength; NTSTATUS Status; PORT_VIEW ServerView; REMOTE_PORT_VIEW ClientView; ULONG i; PULONG p; ConnectionInformation = (LPSTR)&Msg->Data[ 0 ]; ConnectionInformationLength = Msg->h.u1.s1.DataLength; AcceptConnection = FALSE; fprintf( stderr, "\nConnection Request Received from CLIENT_ID 0x%08lx.0x%08lx:\n", Msg->h.ClientId.UniqueProcess, Msg->h.ClientId.UniqueThread ); fprintf( stderr, " MessageId: %ld\n", Msg->h.MessageId ); fprintf( stderr, " ClientViewSize: 0x%08lx\n", Msg->h.ClientViewSize ); fprintf( stderr, " ConnectionInfo: (%ld) '%.*s'\n", ConnectionInformationLength, ConnectionInformationLength, (PSZ)&ConnectionInformation[0] ); ClientView.Length = sizeof( ClientView ); ClientView.ViewSize = 0; ClientView.ViewBase = 0; if (CountServerClientPortHandles >= MAX_CONNECTIONS) { AcceptConnection = FALSE; } else { AcceptConnection = TRUE; } if (AcceptConnection) { LARGE_INTEGER MaximumSize; fprintf( stderr, "Creating Port Memory Section" ); MaximumSize.QuadPart = 0x4000; Status = NtCreateSection( &ServerView.SectionHandle, SECTION_MAP_READ | SECTION_MAP_WRITE, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, NULL ); if (ShowHandleOrStatus( Status, ServerView.SectionHandle )) { ServerView.Length = sizeof( ServerView ); ServerView.SectionOffset = 0; ServerView.ViewSize = 0x4000; ServerView.ViewBase = 0; ServerView.ViewRemoteBase = 0; } else { AcceptConnection = FALSE; } } fprintf( stderr, "Server calling NtAcceptConnectPort( AcceptConnection = %ld )", AcceptConnection ); if (AcceptConnection) { strcpy( ConnectionInformation, "Server Accepting Connection" ); } else { strcpy( ConnectionInformation, "Server Rejecting Connection" ); } Msg->h.u1.s1.DataLength = strlen( ConnectionInformation ) + 1; Msg->h.u1.s1.TotalLength = Msg->h.u1.s1.DataLength + sizeof( Msg->h ); Status = NtAcceptConnectPort( &ServerClientPortHandles[ CountServerClientPortHandles ], (PVOID)(CountServerClientPortHandles+1), &Msg->h, AcceptConnection, &ServerView, &ClientView ); if (ShowHandleOrStatus( Status, ServerClientPortHandles[ CountServerClientPortHandles ] )) { fprintf( stderr, " ServerView: Base=%lx, Size=%lx, RemoteBase: %lx\n", ServerView.ViewBase, ServerView.ViewSize, ServerView.ViewRemoteBase ); fprintf( stderr, " ClientView: Base=%lx, Size=%lx\n", ClientView.ViewBase, ClientView.ViewSize ); ClientMemoryBase = ServerView.ViewBase; ClientMemorySize = ServerView.ViewSize; ServerMemoryBase = ServerView.ViewRemoteBase; ServerMemoryDelta = (ULONG)ServerMemoryBase - (ULONG)ClientMemoryBase; p = (PULONG)(ClientView.ViewBase); i =ClientView.ViewSize; while (i) { *p = (ULONG)p; fprintf( stderr, "Server setting ClientView[ %lx ] = %lx\n", p, *p ); p += (0x1000/sizeof(ULONG)); i -= 0x1000; } p = (PULONG)(ServerView.ViewBase); i = ServerView.ViewSize; while (i) { *p = (ULONG)p - ServerMemoryDelta; fprintf( stderr, "Server setting ServerView[ %lx ] = %lx\n", p, *p ); p += (0x1000/sizeof(ULONG)); i -= 0x1000; } Status = NtCompleteConnectPort( ServerClientPortHandles[ CountServerClientPortHandles ] ); CountServerClientPortHandles++; } return; } DWORD ServerThread( LPVOID Context ) { NTSTATUS Status; CHAR ThreadName[ 64 ]; TLPC_PORTMSG Msg; PTLPC_PORTMSG ReplyMsg; HANDLE ReplyPortHandle; ULONG PortContext; PTEB Teb = NtCurrentTeb(); Teb->ActiveRpcHandle = NULL; strcpy( ThreadName, "Server Thread Id: " ); RtlIntegerToChar( (ULONG)Teb->ClientId.UniqueProcess, 16, 9, ThreadName + strlen( ThreadName ) ); strcat( ThreadName, "." ); RtlIntegerToChar( (ULONG)Teb->ClientId.UniqueThread, 16, 9, ThreadName + strlen( ThreadName ) ); EnterThread( ThreadName, (ULONG)Context ); ReplyMsg = NULL; ReplyPortHandle = ServerConnectionPortHandle; while (TRUE) { // fprintf( stderr, "%s waiting for message...\n", ThreadName ); Status = NtReplyWaitReceivePort( ReplyPortHandle, (PVOID)&PortContext, (PPORT_MESSAGE)ReplyMsg, (PPORT_MESSAGE)&Msg ); ReplyMsg = NULL; ReplyPortHandle = ServerConnectionPortHandle; // //fprintf( stderr, "%s Receive (%s) Id: %u", ThreadName, LpcMsgTypes[ Msg.h.u2.s2.Type ], Msg.h.MessageId ); // PortContext -= 1; if (!NT_SUCCESS( Status )) { fprintf( stderr, " (Status == %08x)\n", Status ); } else if (Msg.h.u2.s2.Type == LPC_CONNECTION_REQUEST) { ServerHandleConnectionRequest( &Msg ); continue; } else if (PortContext >= CountServerClientPortHandles) { fprintf( stderr, "*** Invalid PortContext (%lx) received\n", PortContext ); } else if (Msg.h.u2.s2.Type == LPC_PORT_CLOSED || Msg.h.u2.s2.Type == LPC_CLIENT_DIED ) { fprintf( stderr, " - disconnect for client %08x\n", PortContext ); CloseHandle( ServerClientPortHandles[ (ULONG)PortContext ] ); CountClosedServerClientPortHandles += 1; if (CountClosedServerClientPortHandles == CountServerClientPortHandles) { break; } } else if (Msg.h.u2.s2.Type == LPC_REQUEST) { CheckTlpcMsg( Status, &Msg ); ReplyMsg = &Msg; ReplyPortHandle = ServerClientPortHandles[ PortContext ]; if (TestCallBacks && (Msg.h.u1.s1.DataLength > 30)) { Status = SendRequest( 1, ThreadName, ReplyPortHandle, Context, Msg.h.u1.s1.DataLength >> 1, ReplyMsg, TRUE ); } } } fprintf( stderr, "Exiting %s\n", ThreadName ); return RtlNtStatusToDosError( Status ); } VOID Usage( VOID ) { fprintf( stderr, "usage: USERVER #threads\n" ); ExitProcess( 1 ); } int _cdecl main( int argc, char *argv[] ) { NTSTATUS Status; DWORD rc; ULONG i, NumberOfThreads; OBJECT_ATTRIBUTES ObjectAttributes; Status = STATUS_SUCCESS; fprintf( stderr, "Entering USERVER User Mode LPC Test Program\n" ); TestCallBacks = FALSE; if (argc < 2) { NumberOfThreads = 1; } else { NumberOfThreads = xatoi( argv[ 1 ] ); if (NumberOfThreads >= MAX_REQUEST_THREADS) { Usage(); } if (argc > 2) { TestCallBacks = TRUE; } } RtlInitUnicodeString( &PortName, PORT_NAME ); fprintf( stderr, "Creating %wZ connection port", (PUNICODE_STRING)&PortName ); InitializeObjectAttributes( &ObjectAttributes, &PortName, 0, NULL, NULL ); Status = NtCreatePort( &ServerConnectionPortHandle, &ObjectAttributes, 40, sizeof( TLPC_PORTMSG ), sizeof( TLPC_PORTMSG ) * 32 ); ShowHandleOrStatus( Status, ServerConnectionPortHandle ); rc = RtlNtStatusToDosError( Status ); if (rc == NO_ERROR) { ServerThreadHandles[ 0 ] = GetCurrentThread(); ServerThreadClientIds[ 0 ] = GetCurrentThreadId(); for (i=1; i