singrdk/base/Windows/Benchmarks/Lpc/userver.c

339 lines
11 KiB
C

//++
//
//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<NumberOfThreads; i++) {
fprintf( stderr, "Creating Server Request Thread %ld\n", i+1 );
rc = NO_ERROR;
ServerThreadHandles[ i ] = CreateThread( NULL,
0,
(LPTHREAD_START_ROUTINE)ServerThread,
(LPVOID)(i+1),
CREATE_SUSPENDED,
&ServerThreadClientIds[ i ]
);
if (ServerThreadHandles[ i ] == NULL) {
rc = GetLastError();
break;
}
}
if (rc == NO_ERROR) {
for (i=1; i<NumberOfThreads; i++) {
ResumeThread( ServerThreadHandles[ i ] );
}
ServerThread( 0 );
}
}
if (rc != NO_ERROR) {
fprintf( stderr, "USERVER: Initialization Failed - %u\n", rc );
}
ExitProcess( rc );
return( rc );
}