Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1276 lines
31 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
redir.c
Abstract:
Redirector thread for USRV.
Author:
David Treadwell (davidtr) 20-Oct-1989
Chuck Lenzmeier (chuckl)
Revision History:
--*/
#include "usrv.h"
//
// Forward declarations
//
STATIC
NTSTATUS
CreateEndpoint (
IN OUT PDESCRIPTOR Redir,
IN CLONG RedirNumber,
IN PSZ DebugName
);
STATIC
NTSTATUS
CreateEvents (
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugName
);
STATIC
NTSTATUS
ExecuteBatchFile(
IN PSZ Name,
IN PDESCRIPTOR Redir,
IN PSZ Prompt
);
STATIC
NTSTATUS
ExecuteCommand(
IN PSZ Command,
IN PDESCRIPTOR Redir,
IN PSZ Prompt
);
STATIC
NTSTATUS
Negotiate (
IN OUT PDESCRIPTOR Redir
);
STATIC
VOID
ParseCommand(
IN PSZ CommandLine,
OUT PSZ Argv[],
OUT PSHORT Argc,
IN SHORT MaxArgc
);
STATIC
NTSTATUS
StartAssociate (
IN HANDLE ConnectionFileHandle,
IN HANDLE AddressFileHandle,
IN HANDLE EventHandle,
IN PIO_STATUS_BLOCK Iosb,
IN PSZ DebugString
);
STATIC
NTSTATUS
StartConnect (
IN PSTRING RemoteAddress,
IN PVOID Buffer,
IN HANDLE FileHandle,
IN HANDLE EventHandle,
IN PIO_STATUS_BLOCK Iosb,
IN PSZ DebugString
);
STATIC
NTSTATUS
WaitForAssociate (
IN PSZ Operation,
IN PDESCRIPTOR Redir,
IN UCHAR EventNumber
);
STATIC
NTSTATUS
WaitForConnect (
IN PSZ Operation,
IN PDESCRIPTOR Redir,
IN UCHAR EventNumber
);
NTSTATUS
RedirThreadWrapper(
IN PVOID Dummy
)
{
NTSTATUS status;
status = RedirThread( (PDESCRIPTOR)Dummy );
NtTerminateThread( NtCurrentThread(), status );
return status; // shouldn't get here
} // RedirThreadWrapper
NTSTATUS
RedirThread(
IN PDESCRIPTOR Redir
)
{
#define MAX_ARGC 20
NTSTATUS status;
UCHAR i;
STRING remoteAddress;
CLONG redirNumber;
CHAR prompt[11];
redirNumber = Redir->RedirNumber;
IF_DEBUG(1) printf( "****Entered redir thread %ld.\n", redirNumber );
//
// Allocate data buffers.
//
for( i = 0; i < NUMBER_OF_EVENTS; i++ ) {
Redir->Data[i] = malloc( Redir->MaxBufferSize );
if ( Redir->Data[i] == NULL ) {
printf( "malloc (redir data buffer) failed\n" );
DbgBreakPoint( );
return STATUS_UNSUCCESSFUL;
}
IF_DEBUG(2) printf( "Redir data buffer address: 0x%lx\n", Redir->Data[i] );
}
Redir->RawBuffer = NULL;
//
// Create redir events.
//
status = CreateEvents(
Redir,
"Redir"
);
if ( !NT_SUCCESS(status) ) {
return status;
}
//
// Create endpoint for Redir.
//
status = CreateEndpoint(
Redir,
redirNumber,
"Redir"
);
if ( !NT_SUCCESS(status) ) {
return status;
}
//
// Connect redir to server (must be started after server listen).
//
RtlInitString( &remoteAddress, ServerName+1 ); // skip comma in server name
IF_DEBUG(2) printf( "Server name \"%Z\"\n", &remoteAddress );
status = StartConnect(
&remoteAddress,
Redir->Data[0],
Redir->FileHandle,
Redir->EventHandle[0],
&Redir->Iosb[0],
"Connect"
);
if ( !NT_SUCCESS(status) ) {
return status;
}
status = WaitForConnect(
"Connect",
Redir,
0
);
if ( !NT_SUCCESS(status) ) {
return status;
}
if ( DefaultNegotiate ) {
status = Negotiate( Redir );
if ( !NT_SUCCESS(status) ) {
return status;
}
}
IF_DEBUG(1) {
printf( "****Redir thread %ld initialization complete.\n",
redirNumber );
}
RtlMoveMemory( prompt, "Redir_", 6 );
prompt[6] = (CHAR)( redirNumber / 10 + '0' );
prompt[7] = (CHAR)( redirNumber % 10 + '0' );
prompt[8] = '>';
prompt[9] = ' ';
prompt[10] = 0;
if ( !NoUsrvInit ) {
ExecuteBatchFile( "usrvinit", Redir, prompt );
}
ExecuteCommand( NULL, Redir, prompt );
printf( "****Redir thread %ld exiting: %X\n",
redirNumber, STATUS_SUCCESS );
return STATUS_SUCCESS;
} // RedirThread
NTSTATUS
CreateEndpoint (
PDESCRIPTOR Redir,
CLONG RedirNumber,
PSZ DebugName
)
{
NTSTATUS status;
CHAR transportName[128];
CHAR redirName[17];
CLONG baseNameLength;
STRING nameString;
UNICODE_STRING unicodeNameString;
OBJECT_ATTRIBUTES objectAttributes;
LARGE_INTEGER allocationSize = { 0, 0 };
CHAR eaBuffer[sizeof(FILE_FULL_EA_INFORMATION) - 1 +
TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
sizeof(TA_NETBIOS_ADDRESS)];
PFILE_FULL_EA_INFORMATION ea;
CONNECTION_CONTEXT ctx;
CONNECTION_CONTEXT *pctx;
//
// Create the transport and redir names.
//
baseNameLength = strlen( REDIR_ADDRESS_PART1 );
RtlMoveMemory(
transportName,
REDIR_ADDRESS_PART1,
baseNameLength
);
RtlMoveMemory(
transportName + baseNameLength,
Transport,
strlen( Transport ) + 1
);
IF_DEBUG(1) printf( "Using transport name %s\n", transportName );
RtlMoveMemory( redirName, "Redir_", 6 );
redirName[6] = (CHAR)( RedirNumber / 10 + '0' );
redirName[7] = (CHAR)( RedirNumber % 10 + '0' );
RtlMoveMemory( redirName+8, " ", 7 );
redirName[15] = 0;
redirName[16] = 0;
IF_DEBUG(1) printf( "Using redir name \"%s\"\n", redirName );
//
// Open the address.
//
RtlInitString( &nameString, transportName );
status = RtlAnsiStringToUnicodeString(
&unicodeNameString,
&nameString,
TRUE
);
ASSERT( NT_SUCCESS(status) );
IF_DEBUG(2) printf( "Creating %s endpoint\n", DebugName );
status = TdiOpenNetbiosAddress(
&Redir->EndpointFileHandle,
eaBuffer,
&unicodeNameString,
redirName
);
RtlFreeUnicodeString( &unicodeNameString );
if ( !NT_SUCCESS(status) ) {
printf( "TdiOpenNetbiosAddress (%s) failed: %X\n",
DebugName, status );
DbgBreakPoint( );
return status;
}
IF_DEBUG(2) printf( " %s Address file handle 0x%lx\n",
DebugName, Redir->EndpointFileHandle );
//
// Create a connection.
//
// Create the EA for the connection context.
//
ASSERT( TDI_CONNECTION_CONTEXT_LENGTH + sizeof(CONNECTION_CONTEXT) <=
TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_NETBIOS_ADDRESS) );
ea = (PFILE_FULL_EA_INFORMATION)eaBuffer;
ea->NextEntryOffset = 0;
ea->Flags = 0;
ea->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
ea->EaValueLength = sizeof( CONNECTION_CONTEXT );
RtlMoveMemory( ea->EaName, TdiConnectionContext, ea->EaNameLength + 1 );
ctx = (PVOID)0x22222222;
pctx = (CONNECTION_CONTEXT *)&ea->EaName[ea->EaNameLength + 1];
RtlMoveMemory( pctx, &ctx, sizeof(CONNECTION_CONTEXT) );
//
// Create the connection file object.
//
RtlInitString( &nameString, transportName );
status = RtlAnsiStringToUnicodeString(
&unicodeNameString,
&nameString,
TRUE
);
ASSERT( NT_SUCCESS(status) );
InitializeObjectAttributes(
&objectAttributes,
&unicodeNameString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = NtCreateFile(
&Redir->FileHandle,
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
&objectAttributes,
&Redir->Iosb[0],
&allocationSize,
0,
0,
0,
0,
eaBuffer,
FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0] ) +
ea->EaNameLength + 1 + ea->EaValueLength
);
RtlFreeUnicodeString( &unicodeNameString );
if ( !NT_SUCCESS(status) ) {
printf( "NtCreateFile (%s) service failed: %X\n", DebugName, status );
DbgBreakPoint( );
NtClose( Redir->EndpointFileHandle );
return status;
}
status = Redir->Iosb[0].Status;
if ( !NT_SUCCESS(status) ) {
printf( "NtCreateFile (%s) I/O failed: %X\n", DebugName, status );
DbgBreakPoint( );
NtClose( Redir->EndpointFileHandle );
return status;
}
IF_DEBUG(2) printf( " %s Connection File handle 0x%lx\n",
DebugName, Redir->FileHandle );
//
// Associate the connection with the address.
//
status = StartAssociate(
Redir->FileHandle,
Redir->EndpointFileHandle,
Redir->EventHandle[0],
&Redir->Iosb[0],
DebugName
);
if ( !NT_SUCCESS(status) ) {
NtClose( Redir->FileHandle );
NtClose( Redir->EndpointFileHandle );
return status;
}
status = WaitForAssociate(
DebugName,
Redir,
0
);
if ( !NT_SUCCESS(status) ) {
NtClose( Redir->FileHandle );
NtClose( Redir->EndpointFileHandle );
return status;
}
IF_DEBUG(2) printf( " connection 0x%lx associated with address 0x%lx\n",
Redir->FileHandle, Redir->EndpointFileHandle );
return STATUS_SUCCESS;
} // CreateEndpoint
NTSTATUS
CreateEvents (
PDESCRIPTOR Redir,
PSZ DebugName
)
{
NTSTATUS status;
UCHAR i;
//
// Create redir events.
//
for( i = 0; i < NUMBER_OF_EVENTS; i++ ) {
status = NtCreateEvent(
&Redir->EventHandle[i],
EVENT_ALL_ACCESS,
NULL,
NotificationEvent,
FALSE
);
if ( !NT_SUCCESS(status) ) {
printf( "NtCreateEvent (%s) failed: %X\n", DebugName, status );
DbgBreakPoint( );
return status;
}
IF_DEBUG(2) printf( " %s Event handle 0x%lx\n",
DebugName, Redir->EventHandle[i] );
} // loop on NUMBER_OF_EVENTS
return STATUS_SUCCESS;
} // CreateEvents
NTSTATUS
Negotiate(
IN OUT PDESCRIPTOR Redir
)
{
NTSTATUS status;
ID_SELECTIONS idSelections;
ULONG smbSize;
//
// Create dummy IdSelections. Required to be present, but not used
// by Negotiate request/response.
//
idSelections.Uid = 0;
idSelections.Tid = 0;
idSelections.Fid = 0;
//
// Format the Negotiate request.
//
status = MakeNegotiateSmb(
Redir,
Redir->Data[0],
NULL,
SMB_COM_NO_ANDX_COMMAND,
&idSelections,
&Redir->IdValues,
&smbSize
);
if ( !NT_SUCCESS(status) ) {
return status;
}
//
// Send the request and receive a response.
//
status = SendAndReceiveSmb( Redir, "Negotiate", smbSize, 0, 1 );
if ( !NT_SUCCESS(status) ) {
return status;
}
//
// Verify the response.
//
status = VerifyNegotiate(
Redir,
NULL,
SMB_COM_NEGOTIATE,
&idSelections,
&Redir->IdValues,
&smbSize,
Redir->Data[1]
);
if ( !NT_SUCCESS(status) ) {
return status;
}
return STATUS_SUCCESS;
} // Negotiate
VOID
ParseCommand(
IN PSZ CommandLine,
OUT PSZ Argv[],
OUT PSHORT Argc,
IN SHORT MaxArgc
)
{
PSZ cl = CommandLine;
SHORT ac = 0;
while ( *cl && (ac < MaxArgc) ) {
while ( *cl && (*cl <= ' ') ) { // ignore leading blanks
cl++;
}
if ( !*cl ) break;
*Argv++ = cl;
++ac;
while (*cl > ' ') {
cl++;
}
if ( *cl ) {
*cl++ = '\0';
}
}
if ( ac < MaxArgc ) {
*Argv++ = NULL;
} else if ( *cl ) {
printf( "Too many tokens in command; \"%s\" ignored\n", cl );
}
*Argc = ac;
return;
} // ParseCommand
NTSTATUS
StartConnect (
IN PSTRING RemoteAddress,
IN PVOID Buffer,
IN HANDLE FileHandle,
IN HANDLE EventHandle,
IN PIO_STATUS_BLOCK Iosb,
IN PSZ DebugString
)
{
NTSTATUS status;
PTDI_REQUEST_CONNECT request;
PTDI_CONNECTION_INFORMATION conninfo;
PTA_NETBIOS_ADDRESS address;
ULONG i;
SHORT length;
PSZ remoteAddress;
remoteAddress = RemoteAddress->Buffer;
length = RemoteAddress->Length;
//
// Inside of Buffer, initialize the TDI_REQUEST_CONNECT,
// followed immediately by the TDI_CONNECTION_INFORMATION,
// followed by the TA_NETBIOS_ADDRESS.
//
request = (PTDI_REQUEST_CONNECT)Buffer;
request->RequestConnectionInformation = (PTDI_CONNECTION_INFORMATION)(request + 1);
conninfo = request->RequestConnectionInformation;
conninfo->UserDataLength = 0;
conninfo->OptionsLength = 0;
conninfo->RemoteAddressLength = sizeof(TA_NETBIOS_ADDRESS);
conninfo->RemoteAddress = (PTA_NETBIOS_ADDRESS)(conninfo + 1);
address = conninfo->RemoteAddress;
address->TAAddressCount = 1;
address->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
address->Address[0].AddressLength = sizeof(TDI_ADDRESS_NETBIOS);
address->Address[0].Address[0].NetbiosNameType =
TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
RtlMoveMemory(
address->Address[0].Address[0].NetbiosName,
remoteAddress,
MIN( length, 16 )
);
for ( i = length; i < 16; i++ ) {
address->Address[0].Address[0].NetbiosName[i] = 0;
}
IF_DEBUG(2) printf( "Starting %s\n", DebugString );
status = NtDeviceIoControlFile(
FileHandle,
EventHandle,
NULL,
NULL,
Iosb,
IOCTL_TDI_CONNECT,
(PVOID)Buffer,
sizeof(*request) + sizeof(*conninfo) + sizeof(*address),
NULL,
0
);
if ( !NT_SUCCESS(status) ) {
printf( "NtDeviceIoControlFile (%s) service failed: %X\n",
DebugString, status );
DbgBreakPoint( );
return status;
}
return STATUS_SUCCESS;
} // StartConnect
NTSTATUS
WaitForConnect(
IN PSZ Operation,
IN PDESCRIPTOR Redir,
IN UCHAR EventNumber
)
{
NTSTATUS status;
IF_DEBUG(2) printf( "Waiting for %s\n", Operation );
status = NtWaitForSingleObject(
Redir->EventHandle[EventNumber],
FALSE,
NULL
);
IF_DEBUG(2) printf( "%s complete\n", Operation );
if ( !NT_SUCCESS(status) ) {
printf( "NtWaitForSingleObject (%s) failed: %X\n", Operation, status );
DbgBreakPoint( );
return status;
}
status = Redir->Iosb[EventNumber].Status;
if ( !NT_SUCCESS(status) ) {
printf( "%s I/O failed: %X\n", Operation, status );
DbgBreakPoint( );
return status;
}
return STATUS_SUCCESS;
} // WaitForConnect
NTSTATUS
StartAssociate (
IN HANDLE ConnectionFileHandle,
IN HANDLE AddressFileHandle,
IN HANDLE EventHandle,
IN PIO_STATUS_BLOCK Iosb,
IN PSZ DebugString
)
{
NTSTATUS status;
TDI_REQUEST_ASSOCIATE_ADDRESS request;
request.AddressHandle = AddressFileHandle;
IF_DEBUG(2) printf( "Starting %s Associate\n", DebugString );
status = NtDeviceIoControlFile(
ConnectionFileHandle,
EventHandle,
NULL,
NULL,
Iosb,
IOCTL_TDI_ASSOCIATE_ADDRESS,
(PVOID)&request,
sizeof(request),
NULL,
0
);
if ( !NT_SUCCESS(status) ) {
printf( "NtDeviceIoControlFile (%s Associate) service failed: %X\n",
DebugString, status );
DbgBreakPoint( );
return status;
}
return STATUS_SUCCESS;
} // StartAssociate
NTSTATUS
WaitForAssociate(
IN PSZ Operation,
IN PDESCRIPTOR Redir,
IN UCHAR EventNumber
)
{
NTSTATUS status;
IF_DEBUG(2) printf( "Waiting for %s Associate\n", Operation );
status = NtWaitForSingleObject(
Redir->EventHandle[EventNumber],
FALSE,
NULL
);
IF_DEBUG(2) printf( "%s Associate complete\n", Operation );
if ( !NT_SUCCESS(status) ) {
printf( "NtWaitForSingleObject (%s Associate) failed: %X\n",
Operation, status );
DbgBreakPoint( );
return status;
}
status = Redir->Iosb[EventNumber].Status;
if ( !NT_SUCCESS(status) ) {
printf( "%s Associate I/O failed: %X\n", Operation, status );
DbgBreakPoint( );
return status;
}
return STATUS_SUCCESS;
} // WaitForAssociate
STATIC
BOOLEAN
ReadWithPrompt(
PSZ Prompt,
PSZ Buffer,
ULONG BufferLength
)
{
ULONG length;
CHAR c;
PSZ dest;
ASSERT( BufferLength > 0 );
printf( Prompt );
c = 0;
length = 0;
dest = Buffer;
while ( length < BufferLength ) {
c = (CHAR)getchar( );
if ( c == EOF ) break;
if ( c == '\n' ) break;
*dest++ = c;
length++;
}
*dest = 0;
return (BOOLEAN)(c == EOF);
} // ReadWithPrompt
STATIC
NTSTATUS
ExecuteCommand(
IN PSZ Command OPTIONAL,
IN PDESCRIPTOR Redir,
IN PSZ Prompt
)
{
BOOLEAN done = FALSE;
NTSTATUS status = STATUS_SUCCESS;
UCHAR i;
ULONG SmbSize;
PREDIR_TEST LocalRedirTest;
PSMB_TEST smbTest;
CLONG redirNumber;
LONG testNumber;
CHAR debugString[128];
CLONG testNameLength;
BOOLEAN again = TRUE;
#define COMMAND_LINE_LENGTH 128
CHAR commandLineBuffer[COMMAND_LINE_LENGTH];
PSZ commandLine;
PSZ localArgv[MAX_ARGC];
while ( !done ) {
testNumber = Redir->TestNumber;
if ( (testNumber < 0) && again ) {
while ( !done ) {
if ( Command == NULL ) {
done = ReadWithPrompt(
Prompt,
commandLineBuffer,
COMMAND_LINE_LENGTH
);
commandLine = (PSZ)commandLineBuffer;
} else {
done = TRUE;
printf( "%s%s\n", Prompt, Command );
commandLine = Command;
}
ParseCommand(
commandLine,
localArgv,
&Redir->argc,
MAX_ARGC
);
if ( Redir->argc <= 0 ) {
continue;
}
if ( *localArgv[0] == '@' ) {
ExecuteBatchFile( localArgv[0]+1, Redir, Prompt );
continue;
}
if ( _stricmp( localArgv[0], "break" ) == 0 ) {
DbgBreakPoint( );
continue;
}
if ( _stricmp( localArgv[0], "exit" ) == 0 ) {
break;
}
if ( _stricmp( localArgv[0], "debug" ) == 0 ) {
if ( Redir->argc > 1 ) {
DebugParameter = atolx( localArgv[1] );
} else {
printf( "USRV: Missing argument\n" );
}
continue;
}
#if 0
if ( _stricmp( localArgv[0], "dbg" ) == 0 ) {
NTSTATUS netStatus;
netStatus = NetLocalSetServerDebug(
(SHORT)(Redir->argc - 1),
&localArgv[1],
NULL,
NULL
);
if ( NT_SUCCESS(status) ) {
printf( "The command completed successfully\n" );
}
continue;
}
#endif
if ( _stricmp( localArgv[0], "delay" ) == 0 ) {
ULONG ms = 1000;
LARGE_INTEGER delayTime;
if ( Redir->argc > 1 ) {
ms = atol( localArgv[1] );
}
printf( "Delaying for %lu milliseconds\n", ms );
delayTime.QuadPart = Int32x32To64( ms, -10000 );
NtDelayExecution( TRUE, (PLARGE_INTEGER)&delayTime );
continue;
}
Redir->argv = localArgv;
testNumber = MatchTestName( localArgv[0] );
switch( testNumber ) {
case (LONG)-1:
printf( "Unknown test specified: %s\n", localArgv[0] );
continue;
case (LONG)-2:
printf( "Test name ambiguous: %s\n", localArgv[0] );
continue;
}
Redir->TestNumber = testNumber;
break;
}
}
if ( testNumber < 0 ) {
break;
}
LocalRedirTest = &RedirTests[testNumber];
testNameLength = strlen( LocalRedirTest->RedirName );
RtlMoveMemory( debugString, LocalRedirTest->RedirName, testNameLength );
debugString[testNameLength] = ' ';
for( i = 0, smbTest = LocalRedirTest->SmbTests;
smbTest->SmbMaker != NULL;
i++, smbTest++ ) {
RtlMoveMemory(
debugString + testNameLength + 1,
smbTest->DebugString,
strlen( smbTest->DebugString ) + 1
);
IF_DEBUG(1) printf( "Starting test #%ld.%ld.%ld - %s\n",
redirNumber, testNumber, i, debugString );
Redir->ErrorInhibit = smbTest->ErrorInhibit;
if ( smbTest->SmbVerifier == NULL ) {
status = smbTest->SmbMaker(
Redir,
debugString,
NULL,
smbTest->Command,
&smbTest->IdSelections,
&Redir->IdValues,
NULL
);
} else {
status = smbTest->SmbMaker(
Redir,
Redir->Data[0],
NULL,
(UCHAR)(smbTest->SmbMaker == MakeAndXChain ?
smbTest->Command : 0xFF),
&smbTest->IdSelections,
&Redir->IdValues,
&SmbSize
);
if ( NT_SUCCESS(status) && (status != STATUS_PENDING) ) {
status = SendAndReceiveSmb(
Redir,
debugString,
SmbSize,
0,
1
);
if ( NT_SUCCESS(status) ) {
status = smbTest->SmbVerifier(
Redir,
NULL,
smbTest->Command,
&smbTest->IdSelections,
&Redir->IdValues,
&SmbSize,
Redir->Data[1]
);
}
}
} // if ( smbTest->SmbVerifier == NULL )
if ( !NT_SUCCESS(status) ) {
IF_SMB_ERROR_QUIT_TEST {
break;
}
}
} // for( i = 0, smbTest = LocalRedirTest->SmbTests; ...
Redir->TestNumber = -4;
again = PromptForNextTest;
} // while ( TRUE )
return status;
} // ExecuteCommand
STATIC
NTSTATUS
ExecuteBatchFile(
IN PSZ Name,
IN PDESCRIPTOR Redir,
IN PSZ Prompt
)
{
NTSTATUS status;
CHAR nameBuffer[32];
CHAR commandBuffer[128];
PCHAR commandBufferPtr;
STRING fileName;
UNICODE_STRING unicodeFileName;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE fileHandle;
IO_STATUS_BLOCK ioStatusBlock;
PCHAR readBuffer;
ULONG readBufferIndex;
RtlMoveMemory( nameBuffer, "\\SystemRoot\\", 12 );
RtlMoveMemory( nameBuffer + 15, Name, strlen( Name ) );
RtlMoveMemory( nameBuffer + 15 + strlen( Name ), ".CMD", 5 );
fileName.Buffer = nameBuffer;
fileName.Length = (SHORT)strlen( nameBuffer );
status = RtlAnsiStringToUnicodeString(
&unicodeFileName,
&fileName,
TRUE
);
ASSERT( NT_SUCCESS(status) );
InitializeObjectAttributes(
&objectAttributes,
&unicodeFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = NtOpenFile(
&fileHandle,
FILE_READ_DATA | SYNCHRONIZE,
&objectAttributes,
&ioStatusBlock,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT
);
RtlFreeUnicodeString( &unicodeFileName );
if ( !NT_SUCCESS(status) ) {
if ( status == STATUS_OBJECT_NAME_NOT_FOUND ) {
printf( "Batch file %Z not found\n", &fileName );
} else {
printf( "Error opening batch file %Z: %X\n",
&fileName, status );
}
return status;
}
readBuffer = malloc( 4096 );
if ( readBuffer == NULL ) {
NtClose( fileHandle );
return STATUS_INSUFFICIENT_RESOURCES;
}
status = NtReadFile(
fileHandle,
NULL,
NULL,
NULL,
&ioStatusBlock,
readBuffer,
4096,
NULL,
NULL
);
if ( !NT_SUCCESS(status) ) {
printf( "Error reading batch file %Z: %X\n", &fileName, status );
ioStatusBlock.Information = 0;
}
for ( readBufferIndex = 0, commandBufferPtr = commandBuffer;
readBufferIndex < ioStatusBlock.Information;
readBufferIndex++ ) {
if ( readBuffer[readBufferIndex] == '\n' ) {
*commandBufferPtr = '\0';
(VOID)ExecuteCommand( commandBuffer, Redir, Prompt );
commandBufferPtr = commandBuffer;
continue;
}
*commandBufferPtr++ = readBuffer[readBufferIndex];
}
NtClose( fileHandle );
free( readBuffer );
return STATUS_SUCCESS;
} // ExecuteBatchFile
NTSTATUS
TdiOpenNetbiosAddress (
IN OUT PHANDLE FileHandle,
IN PUCHAR Buffer,
IN PVOID DeviceName,
IN PVOID Address)
/*++
Routine Description:
Opens an address on the given file handle and device.
Arguments:
FileHandle - the returned handle to the file object that is opened.
Buffer - pointer to a buffer that the ea is to be built in. This buffer
must be at least 40 bytes long.
DeviceName - the Unicode string that points to the device object.
Name - the address to be registered. If this pointer is NULL, the routine
will attempt to open a "control channel" to the device; that is, it
will attempt to open the file object with a null ea pointer, and if the
transport provider allows for that, will return that handle.
Return Value:
An informative error code if something goes wrong. STATUS_SUCCESS if the
returned file handle is valid.
--*/
{
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
PFILE_FULL_EA_INFORMATION EaBuffer;
TA_NETBIOS_ADDRESS NetbiosAddress;
PSZ Name;
ULONG Length;
if (Address != NULL) {
Name = (PSZ)Address;
try {
Length = FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0] ) +
TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
sizeof(TA_NETBIOS_ADDRESS);
EaBuffer = (PFILE_FULL_EA_INFORMATION)Buffer;
if (EaBuffer == NULL) {
return STATUS_UNSUCCESSFUL;
}
EaBuffer->NextEntryOffset = 0;
EaBuffer->Flags = 0;
EaBuffer->EaNameLength = (UCHAR)TDI_TRANSPORT_ADDRESS_LENGTH;
EaBuffer->EaValueLength = sizeof (TA_NETBIOS_ADDRESS);
RtlMoveMemory(
EaBuffer->EaName,
TdiTransportAddress,
EaBuffer->EaNameLength + 1
);
//
// Create a copy of the NETBIOS address descriptor in a local
// first, in order to avoid alignment problems.
//
NetbiosAddress.TAAddressCount = 1;
NetbiosAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
NetbiosAddress.Address[0].AddressLength =
sizeof (TDI_ADDRESS_NETBIOS);
NetbiosAddress.Address[0].Address[0].NetbiosNameType =
TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
RtlMoveMemory(
NetbiosAddress.Address[0].Address[0].NetbiosName,
Name,
16
);
RtlMoveMemory (
&EaBuffer->EaName[EaBuffer->EaNameLength + 1],
&NetbiosAddress,
sizeof(TA_NETBIOS_ADDRESS)
);
} except(EXCEPTION_EXECUTE_HANDLER) {
//
// Couldn't touch the passed parameters; just return an error
// status.
//
return GetExceptionCode();
}
} else {
EaBuffer = NULL;
Length = 0;
}
InitializeObjectAttributes (
&ObjectAttributes,
DeviceName,
0,
NULL,
NULL);
Status = NtCreateFile (
FileHandle,
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, // desired access.
&ObjectAttributes, // object attributes.
&IoStatusBlock, // returned status information.
0, // block size (unused).
0, // file attributes.
FILE_SHARE_READ | FILE_SHARE_WRITE, // share access.
FILE_CREATE, // create disposition.
0, // create options.
EaBuffer, // EA buffer.
Length); // EA length.
if (!NT_SUCCESS( Status )) {
return Status;
}
Status = IoStatusBlock.Status;
return Status;
} // TdiOpenNetbiosAddress