2020-09-30 17:12:29 +02:00

741 lines
17 KiB
C

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
tex.c
Abstract:
User mode test program for the Microsoft Netware redir file system.
This test program can be built from the command line using the
command 'nmake UMTEST=tex'.
Author:
Manny Weiser (mannyw) 7-Jun-1993
Revision History:
--*/
#include <stdio.h>
#include <string.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntddnwfs.h>
#include <ntddnwp.h>
#include <STDARG.H>
//
// Local definitions
//
VOID
DisplayUsage(
PSZ ProgramName
);
SendMessage(
IN char* Format,
...
);
VOID
SetLock(
PCHAR FileHandle,
BOOLEAN Exclusive,
ULONG ByteOffset,
ULONG Length,
ULONG Timeout
);
NTSTATUS
FormatRequest(
PCHAR SendBuffer,
PULONG SendBufferLength,
char* Format,
va_list a
);
BOOLEAN
OpenServer(
PHANDLE Handle,
PWCH ServerName
);
NTSTATUS
_cdecl
ParseResponse(
char* FormatString,
... // format specific parameters
);
#define BUFFER_SIZE 200
WCHAR *ServerName = L"NETWARE311";
UCHAR Pid = 255;
HANDLE ServerHandle;
_cdecl
main(
int argc,
char *argv[],
)
{
BOOLEAN success;
UCHAR DirectoryHandle;
UCHAR FileHandle1[6];
UCHAR FileHandle2[6];
success = OpenServer( &ServerHandle, ServerName );
if ( !success) {
return 1;
}
printf("Opened server, %S\n", ServerName );
// Get directory handle for SYS:
SendMessage( "Sbbp", 0x16, 0x12, 0, 0, "SYS:" );
ParseResponse( "b", &DirectoryHandle );
// Open FILE1
Pid = 100;
SendMessage( "Fbbbp", 0x4C, DirectoryHandle, 0x07, 01, "File1" );
ParseResponse( "r", FileHandle1, 6 );
// Open FILE1
Pid = 101;
SendMessage( "Fbbbp", 0x4C, DirectoryHandle, 0x07, 01, "File1" );
ParseResponse( "r", FileHandle2, 6 );
// Lock test
Pid = 100;
SetLock( FileHandle1, TRUE, 0, 10, 0xFFFF );
SetLock( FileHandle1, TRUE, 10, 10, 0xFFFF );
SetLock( FileHandle1, TRUE, 5, 10, 0xFFFF );
SetLock( FileHandle1, TRUE, 10, 10, 0xFFFF );
Pid = 101;
SetLock( FileHandle2, TRUE, 6, 10, 0xFFFF );
SetLock( FileHandle2, TRUE, 7, 10, 0xFFFF );
SetLock( FileHandle2, TRUE, 0, 10, 0xFFFF );
Sleep( 10 * 1000 );
// Close FILE1
SendMessage( "F-r", 0x42, FileHandle1, 6 );
ParseResponse( "" );
// Close FILE1
SendMessage( "F-r", 0x42, FileHandle2, 6 );
ParseResponse( "" );
// End Job
Pid = 100;
SendMessage( "F-", 0x18 );
Pid = 101;
SendMessage( "F-", 0x18 );
// Close the directory
SendMessage( "Sb", 0x16, 0x14, DirectoryHandle );
ParseResponse( "" );
printf( "%s exiting\n", argv[0]);
return 0;
}
VOID
SetLock(
PCHAR FileHandle,
BOOLEAN Exclusive,
ULONG ByteOffset,
ULONG Length,
ULONG Timeout
)
{
USHORT Flags;
if ( Exclusive ) {
Flags = 1;
} else {
Flags = 3;
}
SendMessage( "Fbrddw", 0x1A, Flags, FileHandle, 6, ByteOffset, Length, Timeout );
ParseResponse( "" );
}
BOOLEAN
OpenServer(
PHANDLE Handle,
PWCH ServerName
)
{
NTSTATUS status;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
WCHAR FileNameBuffer[100];
UNICODE_STRING FileName;
FileName.Buffer = FileNameBuffer;
FileName.Length = 0;
FileName.MaximumLength = 100;
status = RtlAppendUnicodeToString( &FileName, DD_NWFS_DEVICE_NAME_U );
ASSERT( status == STATUS_SUCCESS );
status = RtlAppendUnicodeToString( &FileName, L"\\" );
ASSERT( status == STATUS_SUCCESS );
status = RtlAppendUnicodeToString( &FileName, ServerName );
ASSERT( status == STATUS_SUCCESS );
//
// Open the file
//
InitializeObjectAttributes(
&objectAttributes,
&FileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = NtOpenFile (
Handle,
FILE_GENERIC_READ | SYNCHRONIZE,
&objectAttributes,
&ioStatusBlock,
FILE_SHARE_WRITE | FILE_SHARE_READ,
0L
);
if (!NT_SUCCESS(status) ) {
printf( "Open status = %x for file %Z\n", status, &FileName );
}
return ( (BOOLEAN) NT_SUCCESS( status ) );
}
CHAR Buffer1[100];
CHAR Buffer2[100];
SendMessage(
IN char* Format,
...
)
{
NTSTATUS status;
IO_STATUS_BLOCK IoStatusBlock;
va_list Arguments;
NTSTATUS Status;
ULONG ReceiveBufferSize = 100;
ULONG SendBufferSize = 100;
va_start( Arguments, Format );
Buffer1[0] = Pid;
Status = FormatRequest( &Buffer1[1], &SendBufferSize, Format, Arguments );
if ( !NT_SUCCESS( Status ) ) {
return( Status );
}
printf("Sending message\n" );
status = NtFsControlFile(
ServerHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
FSCTL_NWR_ANY_NCP,
Buffer1,
SendBufferSize + 1,
Buffer2,
ReceiveBufferSize
);
if ( NT_SUCCESS( status ) ) {
status = NtWaitForSingleObject( ServerHandle, FALSE, NULL );
if ( NT_SUCCESS( status )) {
status = IoStatusBlock.Status;
}
}
if ( !NT_SUCCESS( status ) ) {
printf("NtFsControlFile returns %08lx\n", status );
return( status );
} else {
printf("Message received\n" );
}
return( status );
}
NTSTATUS
FormatRequest(
PCHAR SendBuffer,
PULONG SendBufferLength,
char* Format,
va_list a
)
/*++
Routine Description:
Send the packet described by Format and the additional parameters.
Arguments:
Format - the information needed to create the request to the
server. The first byte indicates the packet type and the
following bytes contain field types.
Packet types:
'A' SAP broadcast ( void )
'C' NCP connect ( void )
'F' NCP function ( byte )
'S' NCP subfunction ( byte, byte )
'D' NCP disconnect ( void )
Field types, request/response:
'b' byte ( byte / byte* )
'w' hi-lo word ( word / word* )
'd' hi-lo dword ( dword / dword* )
'-' zero/skip byte ( void )
'=' zero/skip word ( void )
._. zero/skip string ( word )
'p' pstring ( char* )
'u' p unicode string ( UNICODE_STRING * )
'c' cstring ( char* )
'r' raw bytes ( byte*, word )
'u' p unicode string ( UNICODE_STRING * )
'U' p uppercase string( UNICODE_STRING * )
'f' separate fragment ( PMDL )
An 'f' field must be last, and in a response it cannot be
preceeded by 'p' or 'c' fields.
Return Value:
Normally returns STATUS_PENDING.
--*/
{
NTSTATUS status;
char* pFormatCharacter;
USHORT t = 1;
ULONG data_size;
ULONG length;
data_size = 1;
SendBuffer[ 0 ] = va_arg( a, UCHAR );
if ( *Format == 'S' ) {
data_size += 2;
SendBuffer[data_size++] = va_arg( a, UCHAR );
}
pFormatCharacter = Format;
while ( *++pFormatCharacter && *pFormatCharacter != 'f' )
{
switch ( *pFormatCharacter ) {
case '=':
SendBuffer[data_size++] = 0;
case '-':
SendBuffer[data_size++] = 0;
break;
case '_':
length = va_arg ( a, USHORT );
if ( data_size + length > *SendBufferLength ) {
printf("***exch:!0!\n");
return( FALSE );
}
while ( length-- ) {
SendBuffer[data_size++] = 0;
}
break;
case 'b':
SendBuffer[data_size++] = va_arg ( a, UCHAR );
break;
case 'w':
{
USHORT w = va_arg ( a, USHORT );
SendBuffer[data_size++] = (UCHAR) (w >> 8);
SendBuffer[data_size++] = (UCHAR) (w >> 0);
break;
}
case 'd':
{
ULONG d = va_arg ( a, ULONG );
SendBuffer[data_size++] = (UCHAR) (d >> 24);
SendBuffer[data_size++] = (UCHAR) (d >> 16);
SendBuffer[data_size++] = (UCHAR) (d >> 8);
SendBuffer[data_size++] = (UCHAR) (d >> 0);
break;
}
case 'c':
{
char* c = va_arg ( a, char* );
length = strlen( c );
if ( data_size + length > *SendBufferLength ) {
printf("***exch:!1!\n");
return( FALSE );
}
RtlCopyMemory( &SendBuffer[data_size], c, length + 1 );
data_size += length + 1;
break;
}
case 'p':
{
char* c = va_arg ( a, char* );
length = strlen( c );
if ( data_size + length > *SendBufferLength ) {
printf("***exch:!2!\n");
return FALSE;
}
SendBuffer[data_size++] = (UCHAR)length;
RtlCopyMemory( &SendBuffer[data_size], c, length );
data_size += length;
break;
}
case 'u':
{
PUNICODE_STRING pUString = va_arg ( a, PUNICODE_STRING );
OEM_STRING OemString;
//
// Calculate required string length, excluding trailing NUL.
//
length = (USHORT)RtlUnicodeStringToOemSize( pUString ) - 1;
ASSERT( length < 0x100 );
if ( data_size + length > *SendBufferLength ) {
printf("***exch:!4!\n");
return( FALSE );
}
SendBuffer[data_size++] = (UCHAR)length;
OemString.Buffer = &SendBuffer[data_size];
OemString.MaximumLength = (USHORT)length + 1;
status = RtlUnicodeStringToCountedOemString( &OemString, pUString, FALSE );
ASSERT( NT_SUCCESS( status ));
data_size += (USHORT)length;
break;
}
case 'U':
{
USHORT i;
//
// UPPERCASE the string, copy it from unicode to the packet
//
PUNICODE_STRING pUString = va_arg ( a, PUNICODE_STRING );
UNICODE_STRING UUppercaseString;
OEM_STRING OemString;
if ( pUString->Length > 0 ) {
RtlUpcaseUnicodeString( &UUppercaseString, pUString, TRUE );
//
// Change all '\' to '/'
//
for ( i = 0 ; i < UUppercaseString.Length ; i++ ) {
if ( UUppercaseString.Buffer[i] == L'\\' ) {
UUppercaseString.Buffer[i] = L'/';
}
}
//
// Calculate required string length, excluding trailing NUL.
//
length = (USHORT)RtlUnicodeStringToOemSize( &UUppercaseString ) - 1;
ASSERT( length < 0x100 );
} else {
UUppercaseString = *pUString;
length = 0;
}
if ( data_size + length > *SendBufferLength ) {
printf("***exch:!5!\n");
return( FALSE );
}
SendBuffer[data_size++] = (UCHAR)length;
OemString.Buffer = &SendBuffer[data_size];
OemString.MaximumLength = (USHORT)length + 1;
status = RtlUnicodeStringToCountedOemString( &OemString,
&UUppercaseString,
FALSE );
ASSERT( NT_SUCCESS( status ));
if ( pUString->Length > 0 ) {
RtlFreeUnicodeString( &UUppercaseString );
}
data_size += (USHORT)length;
break;
}
case 'r':
{
UCHAR* b = va_arg ( a, UCHAR* );
length = va_arg ( a, USHORT );
if ( data_size + length > *SendBufferLength ) {
printf("***exch:!6!\n");
return( FALSE );
}
RtlCopyMemory( &SendBuffer[data_size], b, length );
data_size += length;
break;
}
default:
printf ( "*****exchange: invalid request field, %x\n", *pFormatCharacter);
return( FALSE );
}
if ( data_size > *SendBufferLength ) {
printf( "*****exchange: CORRUPT, too much request data\n" );
va_end( a );
return FALSE;
}
}
if ( *Format == 'S' )
{
SendBuffer[1] = (UCHAR)((data_size-3) >> 8);
SendBuffer[2] = (UCHAR)(data_size-3);
}
va_end( a );
*SendBufferLength = data_size;
return TRUE;
}
NTSTATUS
_cdecl
ParseResponse(
char* FormatString,
... // format specific parameters
)
/*++
Routine Description:
This routine parse an NCP response.
Arguments:
FormatString - supplies the information needed to create the request to the
server. The first byte indicates the packet type and the
following bytes contain field types.
Field types, request/response:
'b' byte ( byte* )
'w' hi-lo word ( word* )
'd' hi-lo dword ( dword* )
'-' zero/skip byte ( void )
'=' zero/skip word ( void )
._. zero/skip string ( word )
'p' pstring ( char* )
'c' cstring ( char* )
'r' raw bytes ( byte*, word )
'R' ASCIIZ to Unicode ( UNICODE_STRING *, word )
Return Value:
STATUS - The converted error code from the NCP response.
--*/
{
PCHAR FormatByte;
va_list Arguments;
int Length = 0;
va_start( Arguments, FormatString );
FormatByte = FormatString;
while ( *FormatByte ) {
switch ( *FormatByte ) {
case '-':
Length += 1;
break;
case '=':
Length += 2;
break;
case '_':
{
USHORT l = va_arg ( Arguments, USHORT );
Length += l;
break;
}
case 'b':
{
UCHAR* b = va_arg ( Arguments, UCHAR* );
*b = Buffer2[Length++];
break;
}
case 'w':
{
UCHAR* b = va_arg ( Arguments, UCHAR* );
b[1] = Buffer2[Length++];
b[0] = Buffer2[Length++];
break;
}
case 'd':
{
UCHAR* b = va_arg ( Arguments, UCHAR* );
b[3] = Buffer2[Length++];
b[2] = Buffer2[Length++];
b[1] = Buffer2[Length++];
b[0] = Buffer2[Length++];
break;
}
case 'c':
{
char* c = va_arg ( Arguments, char* );
USHORT l = strlen( &Buffer2[Length] );
memcpy ( c, &Buffer2[Length], l+1 );
Length += l+1;
break;
}
case 'p':
{
char* c = va_arg ( Arguments, char* );
UCHAR l = Buffer2[Length++];
memcpy ( c, &Buffer2[Length], l );
c[l+1] = 0;
break;
}
#if 0
case 'P':
{
PUNICODE_STRING pUString = va_arg ( Arguments, PUNICODE_STRING );
OEM_STRING OemString;
OemString.Length = Buffer2[Length++];
OemString.Buffer = &Buffer2[Length];
Status = RtlOemStringToCountedUnicodeString( pUString, &OemString, FALSE );
ASSERT( NT_SUCCESS( Status ));
break;
}
#endif
case 'r':
{
UCHAR* b = va_arg ( Arguments, UCHAR* );
USHORT l = va_arg ( Arguments, USHORT );
RtlCopyMemory( b, &Buffer2[Length], l );
Length += l;
break;
}
#if 0
case 'R':
{
//
// Interpret the buffer as an ASCIIZ string. Convert
// it to unicode in the preallocated buffer.
//
PUNICODE_STRING pUString = va_arg ( Arguments, PUNICODE_STRING );
OEM_STRING OemString;
USHORT len = va_arg ( Arguments, USHORT );
OemString.Buffer = &Buffer2[Length];
OemString.Length = strlen( OemString.Buffer );
OemString.MaximumLength = OemString.Length;
Status = RtlOemStringToCountedUnicodeString( pUString, &OemString, FALSE );
ASSERT( NT_SUCCESS( Status ));
Length += len;
break;
}
#endif
default:
printf ( "*****exchange: invalid response field, %x\n", *FormatByte );
return( FALSE );
}
#if 0
if ( Length > PacketLength )
{
printf ( "*****exchange: not enough response data, %d\n", i );
}
#endif
FormatByte++;
}
va_end( Arguments );
}