476 lines
11 KiB
C
476 lines
11 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
tmsserv.c
|
||
|
||
Abstract:
|
||
|
||
This module contains a user mode mailslot server test program.
|
||
|
||
This test program can be built from the command line using the
|
||
command 'nmake UMTEST=tmsserv'.
|
||
|
||
Author:
|
||
|
||
Manny Weiser (mannyw) 11-Jan-91
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <ntioapi.h>
|
||
|
||
//
|
||
// Local definitions
|
||
//
|
||
|
||
BOOLEAN
|
||
CreateMailslot(
|
||
PSZ Name,
|
||
PHANDLE Handle
|
||
);
|
||
|
||
BOOLEAN
|
||
QueryDirectoryTest(
|
||
VOID
|
||
);
|
||
|
||
|
||
BOOLEAN
|
||
QueryInfoTest(
|
||
HANDLE Handle
|
||
);
|
||
|
||
BOOLEAN
|
||
PeekTest(
|
||
HANDLE Handle
|
||
);
|
||
|
||
BOOLEAN
|
||
ReadTest(
|
||
HANDLE Handle
|
||
);
|
||
|
||
VOID
|
||
DisplayUsage(
|
||
PSZ ProgramName
|
||
);
|
||
|
||
VOID
|
||
DisplayTime(
|
||
IN PLARGE_INTEGER
|
||
);
|
||
|
||
DisplayUnicode(
|
||
IN WCHAR *UnicodeString,
|
||
IN ULONG Length
|
||
);
|
||
|
||
#define MESSAGE_SIZE 100L
|
||
#define MAILSLOT_SIZE (10 * MESSAGE_SIZE)
|
||
|
||
#define PEEK_PARAMETER_BYTES 16
|
||
#define READ_PARAMETER_BYTES 16
|
||
#define MAILSLOT_PARAMETER_BYTES 16 // Max of peek and read param bytes
|
||
|
||
char Buffer[1000];
|
||
|
||
|
||
int
|
||
main(argc, argv)
|
||
|
||
int argc;
|
||
char **argv;
|
||
|
||
{
|
||
HANDLE handle;
|
||
ULONG ms, time;
|
||
LARGE_INTEGER delayTime;
|
||
int i;
|
||
|
||
if (argc < 2) {
|
||
DisplayUsage(argv[0]);
|
||
return 1;
|
||
}
|
||
|
||
if ( !CreateMailslot( argv[1], &handle ) ) {
|
||
return 2;
|
||
}
|
||
|
||
for (i = 2; i < argc; i++) {
|
||
|
||
switch ( *argv[i] ) {
|
||
|
||
case 'r':
|
||
if ( !ReadTest( handle ) ) {
|
||
return 3;
|
||
}
|
||
break;
|
||
|
||
case 'd':
|
||
if ( !QueryDirectoryTest() ) {
|
||
return 3;
|
||
}
|
||
break;
|
||
|
||
case 'p':
|
||
if ( !PeekTest( handle ) ) {
|
||
return 3;
|
||
}
|
||
break;
|
||
|
||
case 'q':
|
||
if ( !QueryInfoTest( handle ) ) {
|
||
return 3;
|
||
}
|
||
break;
|
||
|
||
case 's':
|
||
time = atoi( argv[i] + 1);
|
||
|
||
printf( "%s: sleeping for %lu tenths of a second\n",
|
||
argv[0],
|
||
time );
|
||
|
||
ms = time * 100;
|
||
delayTime = LiNMul( ms, -10000 );
|
||
NtDelayExecution( TRUE, (PLARGE_INTEGER)&delayTime );
|
||
|
||
printf ("%s: awake\n", argv[0] );
|
||
break;
|
||
|
||
default:
|
||
printf ("Unknown test ""%s""\n", argv[i] );
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
printf( "Closing file\n" );
|
||
NtClose( handle );
|
||
|
||
printf( "%s exiting\n", argv[0] );
|
||
return 0;
|
||
}
|
||
|
||
|
||
VOID
|
||
DisplayUsage(
|
||
PSZ ProgramName
|
||
)
|
||
{
|
||
printf( "Usage: %s \\Device\\Mailslot\\Msname\n", ProgramName);
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
CreateMailslot(
|
||
PSZ Name,
|
||
PHANDLE Handle
|
||
)
|
||
{
|
||
NTSTATUS status;
|
||
STRING ansiString;
|
||
UNICODE_STRING nameString;
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
LARGE_INTEGER readTimeout = { -1, -1 }; // Infinite read timeout
|
||
|
||
RtlInitString(&ansiString, Name );
|
||
RtlOemStringToUnicodeString(&nameString, &ansiString, TRUE);
|
||
|
||
InitializeObjectAttributes(
|
||
&objectAttributes,
|
||
&nameString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
printf( "Attempting to create mailslot \"%wZ\"\n", &nameString );
|
||
|
||
status = NtCreateMailslotFile (
|
||
Handle,
|
||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
||
&objectAttributes,
|
||
&ioStatusBlock,
|
||
0,
|
||
0,
|
||
MESSAGE_SIZE,
|
||
&readTimeout
|
||
);
|
||
|
||
printf( "Open Status = %lx\n", status );
|
||
RtlFreeUnicodeString(&nameString);
|
||
|
||
return ( (BOOLEAN) NT_SUCCESS(status));
|
||
}
|
||
|
||
BOOLEAN
|
||
QueryDirectoryTest(
|
||
VOID
|
||
)
|
||
{
|
||
HANDLE rootDirHandle;
|
||
BOOLEAN done;
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
UNICODE_STRING nameString;
|
||
NTSTATUS status;
|
||
PFILE_FULL_DIR_INFORMATION dirInfo;
|
||
|
||
RtlInitUnicodeString(&nameString, L"\\Device\\Mailslot\\" );
|
||
|
||
InitializeObjectAttributes(
|
||
&objectAttributes,
|
||
&nameString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
printf( "Attempting to open mailslot directory \"%wZ\"\n", &nameString );
|
||
|
||
status = NtOpenFile (
|
||
&rootDirHandle,
|
||
GENERIC_READ,
|
||
&objectAttributes,
|
||
&ioStatusBlock,
|
||
0,
|
||
0L
|
||
);
|
||
|
||
RtlFreeUnicodeString(&nameString);
|
||
printf( "MSFS root dir open status = %lx\n", status );
|
||
|
||
status = NtQueryDirectoryFile(
|
||
rootDirHandle,
|
||
0,
|
||
NULL,
|
||
NULL,
|
||
&ioStatusBlock,
|
||
(PVOID)Buffer,
|
||
sizeof(Buffer),
|
||
FileFullDirectoryInformation,
|
||
FALSE,
|
||
NULL,
|
||
FALSE );
|
||
|
||
printf("Query directory status = %lx\n", status );
|
||
printf("Query directory information %d\n", ioStatusBlock.Information );
|
||
|
||
if ( NT_SUCCESS( status )) {
|
||
done = FALSE;
|
||
dirInfo = (PFILE_FULL_DIR_INFORMATION)Buffer;
|
||
} else {
|
||
done = TRUE;
|
||
}
|
||
|
||
|
||
while (!done) {
|
||
printf ("NextEntry = %d\n", dirInfo->NextEntryOffset);
|
||
printf ("FileIndex = %ld\n", dirInfo->FileIndex );
|
||
printf ("CreationTime = ");
|
||
DisplayTime( &dirInfo->CreationTime );
|
||
printf ("\nLastAccessTime = ");
|
||
DisplayTime( &dirInfo->LastAccessTime );
|
||
printf ("\nLastWriteTime = ");
|
||
DisplayTime( &dirInfo->LastWriteTime );
|
||
printf ("\nChangeTime = ");
|
||
DisplayTime( &dirInfo->ChangeTime );
|
||
printf ("\nEnd of file = %lx%08lx\n",
|
||
dirInfo->EndOfFile.HighPart,
|
||
dirInfo->EndOfFile.LowPart );
|
||
printf ("Allocation size = %lx%08lx\n",
|
||
dirInfo->AllocationSize.HighPart,
|
||
dirInfo->AllocationSize.LowPart );
|
||
printf ("File attributes = %x\n", dirInfo->FileAttributes );
|
||
printf ("File name length = %x\n", dirInfo->FileNameLength );
|
||
printf ("EA size = %x\n", dirInfo->EaSize );
|
||
printf ("File Name = ");
|
||
DisplayUnicode( dirInfo->FileName, dirInfo->FileNameLength );
|
||
printf ("\n\n");
|
||
|
||
if (dirInfo->NextEntryOffset == 0) {
|
||
done = TRUE;
|
||
}
|
||
|
||
dirInfo = (PFILE_FULL_DIR_INFORMATION)
|
||
((PCHAR)dirInfo + dirInfo->NextEntryOffset);
|
||
}
|
||
|
||
return( (BOOLEAN)NT_SUCCESS( status ));
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
QueryInfoTest(
|
||
HANDLE Handle
|
||
)
|
||
{
|
||
PFILE_BASIC_INFORMATION basicInfo;
|
||
PFILE_STANDARD_INFORMATION standardInfo;
|
||
PFILE_INTERNAL_INFORMATION internalInfo;
|
||
PFILE_EA_INFORMATION eaInfo;
|
||
PFILE_POSITION_INFORMATION positionInfo;
|
||
PFILE_NAME_INFORMATION nameInfo;
|
||
NTSTATUS status;
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
|
||
status = NtQueryInformationFile( Handle,
|
||
&ioStatusBlock,
|
||
Buffer,
|
||
MESSAGE_SIZE,
|
||
FileAllInformation );
|
||
|
||
printf ("\nBasic Information:\n");
|
||
|
||
basicInfo = (PFILE_BASIC_INFORMATION)Buffer;
|
||
printf (" Creation time: " );
|
||
DisplayTime( &basicInfo->CreationTime );
|
||
printf ("\n Last access time: " );
|
||
DisplayTime( &basicInfo->LastAccessTime );
|
||
printf ("\n Last write time: " );
|
||
DisplayTime( &basicInfo->LastWriteTime );
|
||
printf ("\n Change time: " );
|
||
DisplayTime( &basicInfo->ChangeTime );
|
||
printf ("\n");
|
||
|
||
printf ("\nStandard Information:\n");
|
||
|
||
standardInfo = (PFILE_STANDARD_INFORMATION)(basicInfo + 1);
|
||
printf (" Number of links: %ld\n", standardInfo->NumberOfLinks );
|
||
printf (" Delete pending : %ld\n", standardInfo->DeletePending );
|
||
printf (" Directory : %ld\n", standardInfo->Directory );
|
||
|
||
printf ("\nInternal Information:\n");
|
||
|
||
internalInfo = (PFILE_INTERNAL_INFORMATION)(standardInfo + 1);
|
||
printf (" Index Number : %ld\n", internalInfo->IndexNumber );
|
||
|
||
printf ("\nEa Information:\n");
|
||
|
||
eaInfo = (PFILE_EA_INFORMATION)(internalInfo + 1);
|
||
printf (" No ea info\n" );
|
||
|
||
printf ("\nPosition Information:\n");
|
||
|
||
positionInfo = (PFILE_POSITION_INFORMATION)(eaInfo+1);
|
||
printf (" Current offset: %ld\n", positionInfo->CurrentByteOffset );
|
||
|
||
printf ("\nName Information:\n");
|
||
|
||
nameInfo = (PFILE_NAME_INFORMATION)(positionInfo + 1);
|
||
printf (" File name length: %ld\n", nameInfo->FileNameLength );
|
||
printf (" File name : ");
|
||
DisplayUnicode( nameInfo->FileName, nameInfo->FileNameLength );
|
||
putchar ('\n');
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN
|
||
PeekTest(
|
||
HANDLE Handle
|
||
)
|
||
{
|
||
FILE_MAILSLOT_PEEK_BUFFER mailslotPeekBuffer;
|
||
NTSTATUS status;
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
|
||
status = NtFsControlFile (
|
||
Handle,
|
||
0L,
|
||
NULL,
|
||
NULL,
|
||
&ioStatusBlock,
|
||
FSCTL_MAILSLOT_PEEK,
|
||
&mailslotPeekBuffer,
|
||
sizeof(mailslotPeekBuffer),
|
||
Buffer,
|
||
MESSAGE_SIZE );
|
||
|
||
printf( " ReadDataAvailable = %lx\n", mailslotPeekBuffer.ReadDataAvailable );
|
||
printf( " NumberOfMessages = %lx\n", mailslotPeekBuffer.NumberOfMessages);
|
||
printf( " MessageLength = %lx\n", mailslotPeekBuffer.MessageLength);
|
||
return ( (BOOLEAN) NT_SUCCESS( status ) );
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
ReadTest(
|
||
HANDLE Handle
|
||
)
|
||
{
|
||
IO_STATUS_BLOCK ioStatusBlock;
|
||
NTSTATUS status;
|
||
|
||
status = NtReadFile(
|
||
Handle,
|
||
0L,
|
||
NULL,
|
||
NULL,
|
||
&ioStatusBlock,
|
||
Buffer,
|
||
MESSAGE_SIZE,
|
||
NULL,
|
||
NULL);
|
||
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
status = NtWaitForSingleObject( Handle, TRUE, NULL );
|
||
printf( "NtWaitForSingleObject returns %lx\n", status );
|
||
status = ioStatusBlock.Status;
|
||
}
|
||
|
||
printf( "NtReadFileFinalStatus returns %lx\n", status );
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
printf ("message is ""%s""\n", Buffer );
|
||
}
|
||
|
||
return ( (BOOLEAN)NT_SUCCESS( status ) );
|
||
}
|
||
VOID
|
||
DisplayTime(
|
||
IN PLARGE_INTEGER Time
|
||
)
|
||
|
||
{
|
||
TIME_FIELDS timeFields;
|
||
|
||
RtlTimeToTimeFields( Time, &timeFields );
|
||
|
||
printf("%02d/%02d/%04d @ %02d:%02d:%02d.%d",
|
||
timeFields.Month,
|
||
timeFields.Day,
|
||
timeFields.Year,
|
||
timeFields.Hour,
|
||
timeFields.Minute,
|
||
timeFields.Second,
|
||
timeFields.Milliseconds );
|
||
|
||
}
|
||
|
||
DisplayUnicode(
|
||
IN WCHAR *UnicodeString,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
while (Length > 0) {
|
||
putchar( (CHAR)*UnicodeString );
|
||
UnicodeString++;
|
||
Length -= 2;
|
||
}
|
||
|
||
return 0;
|
||
}
|