/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
subs.c
Abstract:
Common subroutines for USRV.
Author:
David Treadwell (davidtr) 20-Oct-1989
Chuck Lenzmeier (chuckl)
Revision History:
--*/
#define INCLUDE_SMB_FILE_CONTROL
#define INCLUDE_SMB_OPEN_CLOSE
#define INCLUDE_SMB_READ_WRITE
#define INCLUDE_SMB_TRANSACTION
#include "usrv.h"
NTSTATUS
DoOpen(
IN PSZ Title,
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN CLONG Session,
IN USHORT Pid,
IN PSTRING File,
IN USHORT DesiredAccess,
IN USHORT OpenFunction,
OUT PUSHORT Fid,
#ifdef DOSERROR
IN UCHAR ExpectedClass,
IN USHORT ExpectedError
#else
IN NTSTATUS ExpectedStatus
#endif
)
{
NTSTATUS status;
CLONG smbSize;
PSMB_HEADER header;
PREQ_OPEN_ANDX request;
PRESP_OPEN_ANDX response;
#ifdef DOSERROR
UCHAR class;
USHORT error;
#endif
IF_DEBUG(3) printf( "'%s' start\n", Title );
header = (PSMB_HEADER)Redir->Data[0];
request = (PREQ_OPEN_ANDX)(header + 1);
IdSelections->Uid += Session;
(VOID)MakeSmbHeader(
Redir,
header,
SMB_COM_OPEN_ANDX,
IdSelections,
IdValues
);
SmbPutAlignedUshort( &header->Pid, Pid );
IdSelections->Uid -= Session;
request->WordCount = 15;
SmbPutUshort( &request->Flags, 0 );
SmbPutUshort( &request->DesiredAccess, DesiredAccess );
SmbPutUshort( &request->SearchAttributes, 0 );
SmbPutUshort( &request->FileAttributes, 0 );
SmbPutUshort( &request->OpenFunction, OpenFunction );
SmbPutUlong( &request->AllocationSize, 0 );
SmbPutUlong( &request->Timeout, 0 );
SmbPutUlong( &request->Reserved, 0 );
SmbPutUshort( &request->ByteCount, (USHORT)(File->Length+1) );
RtlMoveMemory( request->Buffer, File->Buffer, File->Length+1 );
request->AndXCommand = SMB_COM_NO_ANDX_COMMAND;
SmbPutUshort(
&request->AndXOffset,
GET_ANDX_OFFSET( header, request, REQ_OPEN_ANDX, File->Length+1 )
);
smbSize = SmbGetUshort( &request->AndXOffset );
status = SendAndReceiveSmb(
Redir,
DebugString,
smbSize,
0,
1
);
CHECK_STATUS( Title );
header = (PSMB_HEADER)Redir->Data[1];
response = (PRESP_OPEN_ANDX)(header + 1);
#ifdef DOSERROR
class = header->ErrorClass;
error = SmbGetUshort( &header->Error );
CHECK_ERROR( Title, ExpectedClass, ExpectedError );
#else
status = SmbGetUlong( (PULONG)&header->ErrorClass );
CHECK_ERROR( Title, status, ExpectedStatus );
#endif
*Fid = SmbGetUshort( &response->Fid );
#ifdef DOS_ERROR
IF_DEBUG(3) {
printf( "'%s' complete. Fid 0x%lx, Class %ld, Error %ld\n",
Title, *Fid, class, error );
}
#else
IF_DEBUG(3) {
printf( "'%s' complete. Fid 0x%lx, Status %lx\n",
Title, *Fid, status);
}
#endif
return STATUS_SUCCESS;
} // DoOpen
NTSTATUS
DoClose(
IN PSZ Title,
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN CLONG Session,
IN USHORT Fid,
#ifdef DOSERROR
IN UCHAR ExpectedClass,
IN USHORT ExpectedError
#else
IN NTSTATUS ExpectedStatus
#endif
)
{
NTSTATUS status;
CLONG smbSize;
PSMB_HEADER header;
PREQ_CLOSE request;
#ifdef DOSERROR
UCHAR class;
USHORT error;
#else
NTSTATUS smbStatus;
#endif
IF_DEBUG(3) printf( "'%s' start\n", Title );
header = (PSMB_HEADER)Redir->Data[0];
request = (PREQ_CLOSE)(header + 1);
IdSelections->Uid += Session;
(VOID)MakeSmbHeader(
Redir,
header,
SMB_COM_CLOSE,
IdSelections,
IdValues
);
IdSelections->Uid -= Session;
request->WordCount = 3;
SmbPutUshort( &request->Fid, Fid );
SmbPutUlong( &request->LastWriteTimeInSeconds, 0 );
SmbPutUshort( &request->ByteCount, 0 );
smbSize = GET_ANDX_OFFSET( header, request, REQ_CLOSE, 0 );
status = SendAndReceiveSmb(
Redir,
DebugString,
smbSize,
0,
1
);
CHECK_STATUS( Title );
header = (PSMB_HEADER)Redir->Data[1];
#ifdef DOSERROR
class = header->ErrorClass;
error = SmbGetUshort( &header->Error );
CHECK_ERROR( Title, ExpectedClass, ExpectedError );
IF_DEBUG(3) {
printf( "'%s' complete. Class %ld, Error %ld\n",
Title, class, error );
}
#else
smbStatus = SmbGetUlong( (PULONG)&header->ErrorClass );
CHECK_ERROR( Title, smbStatus, ExpectedStatus );
IF_DEBUG(3) {
printf( "'%s' complete. Status %lx\n",
Title, smbStatus );
}
#endif
return STATUS_SUCCESS;
} // DoClose
NTSTATUS
DoDelete(
IN PSZ Title,
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN CLONG Session,
IN PSTRING File,
#ifdef DOSERROR
IN UCHAR ExpectedClass,
IN USHORT ExpectedError
#else
IN NTSTATUS ExpectedStatus
#endif
)
{
NTSTATUS status;
CLONG smbSize;
PSMB_HEADER header;
PREQ_DELETE request;
#ifdef DOSERROR
UCHAR class;
USHORT error;
#else
NTSTATUS smbStatus;
#endif
IF_DEBUG(3) printf( "'%s' start\n", Title );
header = (PSMB_HEADER)Redir->Data[0];
request = (PREQ_DELETE)(header + 1);
IdSelections->Uid += Session;
(VOID)MakeSmbHeader(
Redir,
header,
SMB_COM_DELETE,
IdSelections,
IdValues
);
IdSelections->Uid -= Session;
request->WordCount = 1;
SmbPutUshort( &request->SearchAttributes, 0 );
SmbPutUshort( &request->ByteCount, (USHORT)(File->Length + 2) );
request->Buffer[0] = SMB_FORMAT_ASCII;
RtlMoveMemory( request->Buffer+1, File->Buffer, File->Length+1 );
smbSize = GET_ANDX_OFFSET( header, request, REQ_DELETE, File->Length+2 );
status = SendAndReceiveSmb(
Redir,
DebugString,
smbSize,
0,
1
);
CHECK_STATUS( Title );
header = (PSMB_HEADER)Redir->Data[1];
#ifdef DOSERROR
class = header->ErrorClass;
error = SmbGetUshort( &header->Error );
CHECK_ERROR( Title, ExpectedClass, ExpectedError );
IF_DEBUG(3) {
printf( "'%s' complete. Class %ld, Error %ld\n",
Title, class, error );
}
#else
smbStatus = SmbGetUlong( (PULONG)&header->ErrorClass );
CHECK_ERROR( Title, smbStatus, ExpectedStatus );
IF_DEBUG(3) {
printf( "'%s' complete. Status %lx\n", Title, smbStatus );
}
#endif
return STATUS_SUCCESS;
} // DoDelete
long
atolx(
const char *String
)
{
LONG result = 0;
CHAR c;
while ( (c = *String++) != 0 ) {
result = result * 16;
if ( c < '0' ) {
return 0;
}
if ( c <= '9' ) {
result += c - '0';
continue;
}
if ( c < 'A' ) {
return 0;
}
if ( c <= 'F' ) {
result += c - 'A' + 10;
continue;
}
if ( c < 'a' ) {
return 0;
}
if ( c > 'f' ) {
return 0;
}
result += c - 'a' + 10;
}
return result;
} // atolx
CCHAR
GetTreeConnectIndex (
IN PSZ InputString
)
{
if ( *(InputString+1) != ':' ) {
return 0;
}
if ( *InputString >= '0' && *InputString <= '9' ) {
return (CCHAR)( *InputString - '0' );
}
if ( *InputString >= 'a' && *InputString <= 'f' ) {
return (CCHAR)( *InputString - 'a' + 0xA );
}
if ( *InputString >= 'A' && *InputString <= 'F' ) {
return (CCHAR)( *InputString - 'F' + 0xA );
}
return 0;
}
NTSTATUS
MakeSmbHeader(
IN OUT PDESCRIPTOR Redir,
IN PSMB_HEADER Header,
IN USHORT Command,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues
)
{
Redir; // prevent compiler warnings
if ( Header == NULL ) {
return STATUS_SUCCESS;
}
Header->Protocol[0] = 0xFF;
Header->Protocol[1] = 'S';
Header->Protocol[2] = 'M';
Header->Protocol[3] = 'B';
Header->Command = (UCHAR)Command;
Header->ErrorClass = 0;
Header->Reserved = 0;
SmbPutUshort( &Header->Error, 0 );
Header->Flags = SMB_FLAGS_CASE_INSENSITIVE;
SmbPutAlignedUshort( &Header->Flags2, 0 );
RtlZeroMemory( &Header->Reserved2[0], sizeof(Header->Reserved2) );
if ( IdSelections->Tid == 0xF && Redir->argc > 1 ) {
SHORT i;
USHORT tid = 0;
//
// Find the first argument that starts with "X:". Use that to
// find the TID.
//
for ( i = 1; i < Redir->argc; i++ ) {
CHAR c = *Redir->argv[i];
CHAR d = *(Redir->argv[i]+1);
if ( d == ':' && ( (c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ) ) {
break;
}
}
if ( i != Redir->argc ) {
tid = IdValues->Tid[GetTreeConnectIndex( Redir->argv[i] )];
}
if ( (i == Redir->argc || tid == 0) &&
(Command != SMB_COM_NEGOTIATE &&
Command != SMB_COM_SESSION_SETUP_ANDX &&
Command != SMB_COM_TREE_CONNECT &&
Command != SMB_COM_TREE_CONNECT_ANDX) ) {
printf( "Bad virtual drive letter.\n" );
return STATUS_INVALID_PARAMETER;
}
SmbPutUshort( &Header->Tid, tid );
} else if ( IdSelections->Tid == 0xF ) {
SmbPutUshort( &Header->Tid, IdValues->Tid[0xA] );
} else {
SmbPutUshort( &Header->Tid, IdValues->Tid[IdSelections->Tid] );
}
SmbPutUshort( &Header->Pid, (USHORT)0xdead );
SmbPutUshort( &Header->Uid, IdValues->Uid[IdSelections->Uid] );
SmbPutUshort( &Header->Mid, 0 );
return STATUS_SUCCESS;
} // MakeSmbHeader
NTSTATUS
VerifySmbHeader(
IN OUT PDESCRIPTOR Redir,
IN PID_SELECTIONS IdSelections,
IN OUT PID_VALUES IdValues,
IN PSMB_HEADER Header,
IN USHORT Command
)
{
NTSTATUS status;
Redir, IdSelections, IdValues; // prevent compiler warnings
if ( Header->Command != (UCHAR)Command &&
Command != SMB_COM_NO_ANDX_COMMAND ) {
IF_SMB_ERROR_PRINT {
printf( "SMB Header error.\n" );
printf( "Expected command: 0x%lx; Received command: %lx\n",
Command, Header->Command );
}
SMB_ERROR_BREAK;
return STATUS_UNSUCCESSFUL;
}
#ifdef DOSERROR
if ( Header->ErrorClass == SMB_ERR_CLASS_DOS &&
SmbGetUshort( &Header->Error ) == SMB_ERR_NO_FILES ) {
return STATUS_NO_MORE_FILES;
}
if ( Header->ErrorClass == SMB_ERR_CLASS_DOS &&
( SmbGetUshort( &Header->Error ) == ERROR_EA_ACCESS_DENIED ||
SmbGetUshort( &Header->Error ) == ERROR_EAS_DIDNT_FIT ) ) {
return (NTSTATUS)(SRV_OS2_STATUS | SmbGetUshort( &Header->Error ));
}
if (Header->ErrorClass == SMB_ERR_CLASS_DOS &&
SmbGetUshort( &Header->Error ) == SMB_ERR_MORE_DATA ) {
return STATUS_BUFFER_OVERFLOW;
}
if ( (Header->ErrorClass != 0) || (SmbGetUshort( &Header->Error ) != 0) ) {
IF_SMB_ERROR_PRINT {
printf( "SMB header error, command = 0x%lx\n", Header->Command );
PrintError( Header->ErrorClass, SmbGetUshort( &Header->Error ) );
}
SMB_ERROR_BREAK;
if ( StopOnSmbError ) {
return STATUS_UNSUCCESSFUL;
} else {
return STATUS_SUCCESS;
}
}
#else
status = SmbGetUlong( (PULONG)&Header->ErrorClass );
if ( status == STATUS_NO_MORE_FILES
|| status == STATUS_OS2_EA_ACCESS_DENIED
|| status == STATUS_OS2_EAS_DIDNT_FIT
|| status == STATUS_BUFFER_OVERFLOW ) {
return status;
}
if ( status != STATUS_SUCCESS ) {
IF_SMB_ERROR_PRINT {
printf( "SMB header error, command = 0x%lx\n", Header->Command );
printf( "Status = 0x%lx\n", status );
}
SMB_ERROR_BREAK;
if ( StopOnSmbError ) {
return STATUS_UNSUCCESSFUL;
} else {
return STATUS_SUCCESS;
}
}
#endif
return STATUS_SUCCESS;
} // VerifySmbHeader
NTSTATUS
MakeAndXChain(
IN OUT PDESCRIPTOR Redir,
IN OUT PVOID Buffer,
IN PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
OUT PULONG SmbSize
)
{
NTSTATUS status;
CSHORT i;
UCHAR currentChain = AndXCommand;
IdSelections; // prevent compiler warnings
*SmbSize = 0;
ForcedParams = NULL;
for ( i = 0; AndXChains[currentChain][i].SmbMaker != NULL; i++ ) {
status = AndXChains[currentChain][i].SmbMaker(
Redir,
Buffer,
ForcedParams,
AndXChains[currentChain][i+1].Command,
&AndXChains[currentChain][i].IdSelections,
IdValues,
SmbSize
);
if ( !NT_SUCCESS(status) ) {
return status;
}
ForcedParams = (PVOID)( (PUCHAR)Buffer + *SmbSize);
}
return STATUS_SUCCESS;
} // MakeAndXChain
NTSTATUS
VerifyAndXChain(
IN OUT PDESCRIPTOR Redir,
IN OUT PVOID ForcedParams OPTIONAL,
IN UCHAR AndXCommand,
IN PID_SELECTIONS IdSelections,
IN OUT PID_VALUES IdValues,
OUT PULONG SmbSize,
IN PVOID Buffer
)
{
PSMB_HEADER Header;
NTSTATUS status;
SHORT i;
UCHAR currentChain = AndXCommand;
Header = (PSMB_HEADER)(Buffer);
*SmbSize = 0;
status = VerifySmbHeader(
Redir,
IdSelections,
IdValues,
Header,
AndXChains[currentChain][0].Command
);
if ( !NT_SUCCESS(status) ) {
return status;
}
for ( i = 0; AndXChains[currentChain][i].SmbVerifier != NULL; i++ ) {
status = AndXChains[currentChain][i].SmbVerifier(
Redir,
&ForcedParams,
AndXChains[currentChain][i+1].Command,
&AndXChains[currentChain][i].IdSelections,
IdValues,
SmbSize,
Buffer
);
if ( !NT_SUCCESS(status) ) {
return status;
}
ForcedParams = (PVOID)( (PUCHAR)Buffer + *SmbSize);
}
return STATUS_SUCCESS;
} // VerifyAndXChain
LONG
MatchTestName(
IN PSZ GivenName
)
{
ULONG i;
LONG foundIndex = -1;
CHAR redirName[64];
PSZ s,t;
LONG givenNameLength = strlen( GivenName );
for ( i = 0; i < NumberOfRedirs; i++ ) {
for ( s = redirName, t = RedirTests[i].RedirName;
*t != '\0';
s++, t++) {
*s = *t;
if ( *s >= 'a' && *s <= 'z' ) {
*s -= 'a' - 'A';
}
}
for ( s = GivenName; *s != '\0'; s++ ) {
if ( *s >= 'a' && *s <= 'z' ) {
*s -= 'a' - 'A';
}
}
if ( strncmp( redirName, GivenName, givenNameLength ) == 0) {
if ( foundIndex != -1 ) {
return -2;
}
foundIndex = (LONG)i;
}
}
return foundIndex;
} // MatchTestName
VOID
PutNtDateAndTime(
IN PSZ Prefix,
IN LARGE_INTEGER Time
)
{
TIME_FIELDS timeFields;
RtlTimeToTimeFields( &Time, &timeFields );
printf( "%s date %ld/%ld/%ld, time %ld:%ld:%ld\n",
Prefix,
timeFields.Month,
timeFields.Day,
timeFields.Year,
timeFields.Hour,
timeFields.Minute,
timeFields.Second
);
return;
} // PutDateAndTime
VOID
PutDateAndTime(
IN PSZ Prefix,
IN SMB_DATE Date,
IN SMB_TIME Time
)
{
printf( "%s date %ld/%ld/%ld, time %ld:%ld:%ld\n",
Prefix,
Date.Struct.Month,
Date.Struct.Day,
Date.Struct.Year + 80,
Time.Struct.Hours,
Time.Struct.Minutes,
Time.Struct.TwoSeconds*2
);
return;
} // PutDateAndTime
VOID
PutDateAndTime2(
IN SMB_DATE Date,
IN SMB_TIME Time
)
{
switch ( Date.Struct.Month ) {
case 1:
printf( "Jan " );
break;
case 2:
printf( "Feb " );
break;
case 3:
printf( "Mar " );
break;
case 4:
printf( "Apr " );
break;
case 5:
printf( "May " );
break;
case 6:
printf( "Jun " );
break;
case 7:
printf( "Jul " );
break;
case 8:
printf( "Aug " );
break;
case 9:
printf( "Sep " );
break;
case 10:
printf( "Oct " );
break;
case 11:
printf( "Nov " );
break;
case 12:
printf( "Dec " );
break;
default:
printf( "xxx " );
}
if ( Date.Struct.Day < 10 ) {
printf( "0%ld ", Date.Struct.Day );
} else {
printf( "%ld ", Date.Struct.Day );
}
if ( Time.Struct.Hours < 10 ) {
printf( "0%ld:", Time.Struct.Hours );
} else if ( Time.Struct.Hours < 100 ) {
printf( "%ld:", Time.Struct.Hours );
} else {
printf( "%ldx", Time.Struct.Hours % 100 );
}
if ( Time.Struct.Minutes < 10 ) {
printf( "0%ld:", Time.Struct.Minutes );
} else {
printf( "%ld:", Time.Struct.Minutes );
}
if ( Time.Struct.TwoSeconds*2 < 10 ) {
printf( "0%ld ", Time.Struct.TwoSeconds*2 );
} else {
printf( "%ld ", Time.Struct.TwoSeconds*2 );
}
printf( "%ld", Date.Struct.Year + 1980 );
return;
} // PutDateAndTime2
NTSTATUS
ReceiveSmb(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN UCHAR ReceiveBuffer
)
{
NTSTATUS status;
status = StartReceive(
DebugString,
Redir->FileHandle,
Redir->EventHandle[ReceiveBuffer],
&Redir->Iosb[ReceiveBuffer],
Redir->Data[ReceiveBuffer],
Redir->MaxBufferSize
);
if ( !NT_SUCCESS(status) ) {
return status;
}
status = WaitForSendOrReceive(
DebugString,
Redir,
ReceiveBuffer,
"receive"
);
if ( !NT_SUCCESS(status) ) {
return status;
}
return STATUS_SUCCESS;
} // ReceiveSmb
NTSTATUS
SendAndReceiveSmb(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN ULONG SmbSize,
IN UCHAR SendBuffer,
IN UCHAR ReceiveBuffer
)
{
NTSTATUS status;
if ( ( (DebugParameter & 0x80000000) >> 31) == 0 ) {
status = StartReceive(
DebugString,
Redir->FileHandle,
Redir->EventHandle[ReceiveBuffer],
&Redir->Iosb[ReceiveBuffer],
Redir->Data[ReceiveBuffer],
Redir->MaxBufferSize
);
if ( !NT_SUCCESS(status) ) {
return status;
}
}
status = StartSend(
DebugString,
Redir->FileHandle,
Redir->EventHandle[SendBuffer],
&Redir->Iosb[SendBuffer],
Redir->Data[SendBuffer],
SmbSize
);
if ( !NT_SUCCESS(status) ) {
return status;
}
if ( ( (DebugParameter & 0xc0000000) >> 30) == 2 ) {
status = StartReceive(
DebugString,
Redir->FileHandle,
Redir->EventHandle[ReceiveBuffer],
&Redir->Iosb[ReceiveBuffer],
Redir->Data[ReceiveBuffer],
Redir->MaxBufferSize
);
if ( !NT_SUCCESS(status) ) {
return status;
}
}
status = WaitForSendOrReceive(
DebugString,
Redir,
SendBuffer,
"send"
);
if ( !NT_SUCCESS(status) ) {
return status;
}
if ( ( (DebugParameter & 0xc0000000) >> 30) == 3 ) {
status = StartReceive(
DebugString,
Redir->FileHandle,
Redir->EventHandle[ReceiveBuffer],
&Redir->Iosb[ReceiveBuffer],
Redir->Data[ReceiveBuffer],
Redir->MaxBufferSize
);
if ( !NT_SUCCESS(status) ) {
return status;
}
}
status = WaitForSendOrReceive(
DebugString,
Redir,
ReceiveBuffer,
"receive"
);
if ( !NT_SUCCESS(status) ) {
return status;
}
return STATUS_SUCCESS;
} // SendAndReceiveSmb
NTSTATUS
SendAndReceiveTransaction(
IN OUT PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN UCHAR Command,
IN OUT PVOID Setup,
IN CLONG InSetupCount,
IN OUT PCLONG OutSetupCount,
IN PUCHAR Name,
IN USHORT Function,
IN OUT PVOID Parameters,
IN CLONG InParameterCount,
IN OUT PCLONG OutParameterCount,
IN OUT PVOID Data,
IN CLONG InDataCount,
IN OUT PCLONG OutDataCount
)
{
PSMB_HEADER header;
PREQ_TRANSACTION request;
PREQ_NT_TRANSACTION ntRequest;
NTSTATUS status;
NTSTATUS initStatus;
CLONG smbSize;
PUSHORT pSetup;
PUSHORT pBcc;
PUCHAR pParam, pData, pName; // pointer to field
CLONG lParam, lData, lName; // length of field
CLONG oParam, oData; // offset of field in SMB
CLONG dParam, dData; // displacement of these bytes
CLONG rParam, rData; // remaining bytes to be sent
//
// Build the primary request.
//
header = (PSMB_HEADER)Redir->Data[0];
status = MakeSmbHeader(
Redir,
header,
Command,
IdSelections,
IdValues
);
if ( !NT_SUCCESS(status) ) {
return status;
}
request = (PREQ_TRANSACTION)(header + 1);
ntRequest = (PREQ_NT_TRANSACTION)(header + 1);
RtlZeroMemory(
request,
MAX( sizeof(REQ_TRANSACTION), sizeof(REQ_NT_TRANSACTION) )
);
if ( Command == SMB_COM_NT_TRANSACT ) {
ntRequest->WordCount = (UCHAR)(19 + InSetupCount);
SmbPutUshort( &ntRequest->TotalParameterCount, (USHORT)InParameterCount );
SmbPutUshort( &ntRequest->TotalDataCount, (USHORT)InDataCount );
SmbPutUshort( &ntRequest->MaxParameterCount, *(PUSHORT)OutParameterCount );
SmbPutUshort( &ntRequest->MaxDataCount, *(PUSHORT)OutDataCount );
ntRequest->MaxSetupCount = *(PUCHAR)OutSetupCount;
ntRequest->SetupCount = (UCHAR)InSetupCount;
ntRequest->Function = Function;
pSetup = (PUSHORT)ntRequest->Buffer;
} else {
request->WordCount = (UCHAR)(14 + InSetupCount);
SmbPutUshort( &request->TotalParameterCount, (USHORT)InParameterCount );
SmbPutUshort( &request->TotalDataCount, (USHORT)InDataCount );
SmbPutUshort( &request->MaxParameterCount, *(PUSHORT)OutParameterCount );
SmbPutUshort( &request->MaxDataCount, *(PUSHORT)OutDataCount );
request->MaxSetupCount = *(PUCHAR)OutSetupCount;
request->SetupCount = (UCHAR)InSetupCount;
pSetup = (PUSHORT)request->Buffer;
}
RtlMoveMemory( pSetup, Setup, InSetupCount * sizeof(USHORT) );
pBcc = pSetup + InSetupCount;
// *(PUCHAR)(pBcc+1) = 0; // null transaction name
pName = (PUCHAR)(pBcc + 1);
lName = strlen(Name) + 1;
pParam = (PUCHAR)(pName + lName + 1);
oParam = (pParam - (PUCHAR)header + 3) & ~3;
pParam = (PUCHAR)header + oParam;
lParam = InParameterCount;
if ( oParam + lParam > (CLONG)Redir->MaxBufferSize ) {
lParam = (Redir->MaxBufferSize - oParam) & ~3;
pData = pParam + lParam;
oData = 0;
lData = 0;
} else {
pData = pParam + lParam;
oData = (pData - (PUCHAR)header + 3) & ~3;
pData = (PUCHAR)header + oData;
lData = InDataCount;
if ( oData + lData > (CLONG)Redir->MaxBufferSize ) {
lData = (Redir->MaxBufferSize - oData) & ~3;
}
}
if ( Command == SMB_COM_NT_TRANSACT ) {
SmbPutUlong( &ntRequest->ParameterCount, lParam );
SmbPutUlong( &ntRequest->ParameterOffset, oParam );
SmbPutUlong( &ntRequest->DataCount, lData );
SmbPutUlong( &ntRequest->DataOffset, oData );
} else {
SmbPutUshort( &request->ParameterCount, (USHORT)lParam );
SmbPutUshort( &request->ParameterOffset, (USHORT)oParam );
SmbPutUshort( &request->DataCount, (USHORT)lData );
SmbPutUshort( &request->DataOffset, (USHORT)oData );
}
SmbPutUshort( pBcc, (USHORT)(pData - (PUCHAR)(pBcc+1) + lData) );
if ( lName > 0 ) {
RtlMoveMemory( pName, Name, lName );
}
if ( lParam > 0 ) {
RtlMoveMemory( pParam, Parameters, lParam );
}
if ( lData > 0 ) {
RtlMoveMemory( pData, Data, lData );
}
dParam = lParam;
rParam = InParameterCount - lParam;
dData = lData;
rData = InDataCount - lData;
smbSize = pData - (PUCHAR)header + lData;
//
// Send the primary request, and receive either the interim response
// or the first (possibly only) secondary response.
//
status = SendAndReceiveSmb(
Redir,
DebugString,
smbSize,
0,
1
);
if ( !NT_SUCCESS(status) ) {
return status;
}
//
// If there's more data to send, then interpret the response as an
// interim one, and send the remaining request messages.
//
while ( rParam + rData > 0 ) {
PREQ_TRANSACTION_SECONDARY request; // overrides outer declaration
PREQ_NT_TRANSACTION_SECONDARY ntRequest; // overrides outer declaration
status = VerifySmbHeader(
Redir,
IdSelections,
IdValues,
(PSMB_HEADER)Redir->Data[1],
Command
);
if ( !NT_SUCCESS(status) ) {
return status;
}
//
// Build the secondary request.
//
if ( Command == SMB_COM_NT_TRANSACT ) {
header->Command = SMB_COM_NT_TRANSACT_SECONDARY;
} else {
header->Command = SMB_COM_TRANSACTION2_SECONDARY;
}
request = (PREQ_TRANSACTION_SECONDARY)(header + 1);
ntRequest = (PREQ_NT_TRANSACTION_SECONDARY)(header + 1);
RtlZeroMemory(
request,
MAX(
sizeof(REQ_TRANSACTION_SECONDARY),
sizeof(REQ_NT_TRANSACTION_SECONDARY)
)
);
if ( Command == SMB_COM_NT_TRANSACT ) {
ntRequest->WordCount = (UCHAR)18;
SmbPutUlong(
&ntRequest->TotalParameterCount,
InParameterCount
);
SmbPutUlong( &ntRequest->TotalDataCount, InDataCount );
pParam = request->Buffer;
} else {
request->WordCount = (UCHAR)9;
SmbPutUshort(
&request->TotalParameterCount,
(USHORT)InParameterCount
);
SmbPutUshort( &request->TotalDataCount, (USHORT)InDataCount );
pParam = request->Buffer + 2; // Leave space for 9th word (fid)
}
oParam = (pParam - (PUCHAR)header + 3) & ~3;
pParam = (PUCHAR)header + oParam;
lParam = rParam;
if ( oParam + lParam > (CLONG)Redir->MaxBufferSize ) {
lParam = (Redir->MaxBufferSize - oParam) & ~3;
pData = pParam + lParam;
oData = 0;
lData = 0;
} else {
pData = pParam + lParam;
oData = (pData - (PUCHAR)header + 3) & ~3;
pData = (PUCHAR)header + oData;
lData = rData;
if ( oData + lData > (CLONG)Redir->MaxBufferSize ) {
lData = (Redir->MaxBufferSize - oData) & ~3;
}
}
if ( Command == SMB_COM_NT_TRANSACT ) {
SmbPutUlong( &ntRequest->ParameterCount, lParam );
SmbPutUlong( &ntRequest->ParameterOffset, oParam );
SmbPutUlong( &ntRequest->ParameterDisplacement, dParam );
SmbPutUlong( &ntRequest->DataCount, lData );
SmbPutUlong( &ntRequest->DataOffset, oData );
SmbPutUlong( &ntRequest->DataDisplacement, dData );
SmbPutUshort(
&request->ByteCount,
(USHORT)(pData - (request->Buffer+2) + lData)
);
} else {
SmbPutUshort( &request->ParameterCount, (USHORT)lParam );
SmbPutUshort( &request->ParameterOffset, (USHORT)oParam );
SmbPutUshort( &request->ParameterDisplacement, (USHORT)dParam );
SmbPutUshort( &request->DataCount, (USHORT)lData );
SmbPutUshort( &request->DataOffset, (USHORT)oData );
SmbPutUshort( &request->DataDisplacement, (USHORT)dData );
//
// Since we are using the transaction response description,
// but this is a transaction2, put the ByteCount 2 bytes
// back so that it is in the right place.
//
SmbPutUshort(
&(request->ByteCount) + 1,
(USHORT)(pData - (request->Buffer+2) + lData)
);
}
if ( lParam > 0 ) {
RtlMoveMemory( pParam, (PUCHAR)Parameters+dParam, lParam );
}
if ( lData > 0 ) {
RtlMoveMemory( pData, (PUCHAR)Data+dData, lData );
}
dParam = lParam;
rParam = rParam - lParam;
dData = lData;
rData = rData - lData;
smbSize = pData - (PUCHAR)header + lData;
//
// If this isn't the last request message, just send it.
// Otherwise, send it and receive the first response.
//
if ( rParam + rData > 0 ) {
status = SendSmb(
Redir,
DebugString,
smbSize,
0
);
} else {
status = SendAndReceiveSmb(
Redir,
DebugString,
smbSize,
0,
1
);
}
if ( !NT_SUCCESS(status) ) {
return status;
}
}
//
// All request messages have been sent, and the first response has
// been received.
//
lParam = 0;
lData = 0;
while ( TRUE ) {
PRESP_TRANSACTION response;
PRESP_NT_TRANSACTION ntResponse;
header = (PSMB_HEADER)Redir->Data[1];
status = VerifySmbHeader(
Redir,
IdSelections,
IdValues,
header,
Command
);
if ( !NT_SUCCESS(status) &&
status != STATUS_OS2_EA_ACCESS_DENIED &&
status != STATUS_OS2_EAS_DIDNT_FIT &&
status != STATUS_BUFFER_OVERFLOW ) {
return status;
}
initStatus = status;
response = (PRESP_TRANSACTION)(header + 1);
ntResponse = (PRESP_NT_TRANSACTION)(header + 1);
//
// Copy data from the response into output buffers.
//
if ( Command == SMB_COM_NT_TRANSACT ) {
if ( ntResponse->SetupCount != 0 ) {
RtlMoveMemory(
Setup,
ntResponse->Buffer,
ntResponse->SetupCount
);
*OutSetupCount = ntResponse->SetupCount;
}
if ( SmbGetUshort( &ntResponse->ParameterCount ) != 0 ) {
RtlMoveMemory(
(PUCHAR)Parameters +
SmbGetUshort( &ntResponse->ParameterDisplacement ),
(PUCHAR)header + SmbGetUshort( &ntResponse->ParameterOffset ),
SmbGetUshort( &ntResponse->ParameterCount )
);
lParam = lParam + SmbGetUshort( &ntResponse->ParameterCount );
}
if ( SmbGetUshort( &ntResponse->DataCount ) != 0 ) {
RtlMoveMemory(
(PUCHAR)Data + SmbGetUshort( &ntResponse->DataDisplacement ),
(PUCHAR)header + SmbGetUshort( &ntResponse->DataOffset ),
SmbGetUshort( &ntResponse->DataCount )
);
lData = lData + SmbGetUshort( &ntResponse->DataCount );
}
//
// If all data has been received, jump out.
//
if ( (lParam ==
SmbGetUlong( &ntResponse->TotalParameterCount )) &&
(lData == SmbGetUlong( &ntResponse->TotalDataCount )) ) {
*OutParameterCount = lParam;
*OutDataCount = lData;
return initStatus;
}
} else {
if ( response->SetupCount != 0 ) {
RtlMoveMemory(
Setup,
response->Buffer,
response->SetupCount
);
*OutSetupCount = response->SetupCount;
}
if ( SmbGetUshort( &response->ParameterCount ) != 0 ) {
RtlMoveMemory(
(PUCHAR)Parameters +
SmbGetUshort( &response->ParameterDisplacement ),
(PUCHAR)header + SmbGetUshort( &response->ParameterOffset ),
SmbGetUshort( &response->ParameterCount )
);
lParam = lParam + SmbGetUshort( &response->ParameterCount );
}
if ( SmbGetUshort( &response->DataCount ) != 0 ) {
RtlMoveMemory(
(PUCHAR)Data + SmbGetUshort( &response->DataDisplacement ),
(PUCHAR)header + SmbGetUshort( &response->DataOffset ),
SmbGetUshort( &response->DataCount )
);
lData = lData + SmbGetUshort( &response->DataCount );
}
//
// If all data has been received, jump out.
//
if ( ((USHORT)lParam ==
SmbGetUshort( &response->TotalParameterCount )) &&
((USHORT)lData == SmbGetUshort( &response->TotalDataCount )) ) {
*OutParameterCount = lParam;
*OutDataCount = lData;
return initStatus;
}
}
//
// Receive another response message.
//
status = ReceiveSmb(
Redir,
DebugString,
1
);
}
} // SendAndReceiveTransaction
NTSTATUS
SendSmb(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN ULONG SmbSize,
IN UCHAR SendBuffer
)
{
NTSTATUS status;
status = StartSend(
DebugString,
Redir->FileHandle,
Redir->EventHandle[SendBuffer],
&Redir->Iosb[SendBuffer],
Redir->Data[SendBuffer],
SmbSize
);
if ( !NT_SUCCESS(status) ) {
return status;
}
status = WaitForSendOrReceive(
DebugString,
Redir,
SendBuffer,
"send"
);
if ( !NT_SUCCESS(status) ) {
return status;
}
return STATUS_SUCCESS;
} // SendSmb
NTSTATUS
StartReceive (
IN PSZ Operation,
IN HANDLE FileHandle,
IN HANDLE EventHandle,
IN PIO_STATUS_BLOCK Iosb,
IN PVOID Buffer,
IN ULONG BufferLength
)
{
NTSTATUS status;
IF_DEBUG(2) printf( "Starting %s receive\n", Operation );
status = NtDeviceIoControlFile(
FileHandle,
EventHandle,
NULL,
NULL,
Iosb,
IOCTL_TDI_RECEIVE,
NULL,
0,
(PVOID)Buffer,
BufferLength
);
if ( !NT_SUCCESS(status) ) {
printf( "NtDeviceIoControlFile (%s) service failed: %X\n",
Operation, status );
return status;
}
return STATUS_SUCCESS;
} // StartReceive
NTSTATUS
StartSend (
IN PSZ Operation,
IN HANDLE FileHandle,
IN HANDLE EventHandle,
IN PIO_STATUS_BLOCK Iosb,
IN PVOID Buffer,
IN ULONG BufferLength
)
{
NTSTATUS status;
IF_DEBUG(2) printf( "Starting %s send\n", Operation );
status = NtDeviceIoControlFile(
FileHandle,
EventHandle,
NULL,
NULL,
Iosb,
IOCTL_TDI_SEND,
NULL,
0,
(PVOID)Buffer,
BufferLength
);
if ( !NT_SUCCESS(status) ) {
printf( "NtDeviceIoControlFile (%s) service failed: %X\n",
Operation, status );
DbgBreakPoint( );
return status;
}
return STATUS_SUCCESS;
} // StartSend
NTSTATUS
WaitForSendOrReceive (
IN PSZ Operation,
IN PDESCRIPTOR Redir,
IN UCHAR EventNumber,
IN PSZ SendOrReceive
)
{
NTSTATUS status;
IF_DEBUG(2) printf( "Waiting for %s %s\n", Operation, SendOrReceive );
status = NtWaitForSingleObject(
Redir->EventHandle[EventNumber],
FALSE,
NULL
);
IF_DEBUG(2) printf( "%s %s complete\n", Operation, SendOrReceive );
if ( !NT_SUCCESS(status) ) {
printf( "KeWaitForSingleObject (%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;
} // WaitForSendOrReceive
VOID
AllocateAndBuildFeaList (
IN PVOID *Information,
IN PULONG InformationLength,
IN PSZ argv[],
IN SHORT argc
)
{
LONG i;
PFEA fea;
*InformationLength = 4;
for ( i = 1; i < argc-1; i++ ) {
if ( *argv[i+1] == '~' ) {
*argv[i+1] = '\0';
}
*InformationLength += sizeof(FEA) + strlen( argv[i++] ) + 1 +
strlen( argv[i] );
}
*Information = malloc( *InformationLength );
for ( i = 1, fea = (PFEA)((PCHAR)*Information + 4); i < argc-1; i++ ) {
//
// Set the flags field. If the first character is '!', then
// set FILE_NEED_EA.
//
fea->fEA = (UCHAR)( (*argv[i] == '!') ? FILE_NEED_EA : 0 );
fea->cbName = (UCHAR)strlen( argv[i] );
SmbPutUshort( &fea->cbValue, (USHORT)strlen( argv[i+1] ) );
RtlMoveMemory( fea+1, argv[i], fea->cbName+1 );
RtlMoveMemory(
(PCHAR)(fea+1) + fea->cbName + 1,
argv[++i],
SmbGetUshort( &fea->cbValue )
);
(PCHAR)fea += sizeof(FEA) + fea->cbName + 1 +
SmbGetUshort( &fea->cbValue );
}
SmbPutUlong( (PULONG)*Information, *InformationLength );
return;
} // AllocateAndBuildFeaList
VOID
BuildGeaList (
IN PVOID Information,
IN PULONG InformationLength,
IN PSZ argv[],
IN SHORT argc
)
{
SHORT i;
PGEA gea;
*InformationLength = 4;
for ( i = 1; i < argc; i++ ) {
*InformationLength += sizeof(GEA) + strlen( argv[i] );
}
for ( i = 1, gea = (PGEA)((PCHAR)Information + 4); i < argc; i++ ) {
gea->cbName = (UCHAR)strlen( argv[i] );
RtlMoveMemory( gea->szName, argv[i], gea->cbName+1 );
gea = (PGEA)((PCHAR)gea + sizeof(GEA) + gea->cbName);
}
SmbPutUlong( (PULONG)Information, *InformationLength );
return;
} // BuildGeaList
#ifdef DOSERROR
VOID
PrintError (
IN USHORT ErrorClass,
IN USHORT ErrorCode
)
{
CSHORT i;
switch ( ErrorClass ) {
case SMB_ERR_CLASS_DOS:
printf( "Error Class: DOS " );
break;
case SMB_ERR_CLASS_SERVER:
printf( "Error Class: Server " );
break;
case SMB_ERR_CLASS_HARDWARE:
printf( "Error Class: Hardware " );
break;
default:
printf( "Unknown error class: %ld, error code %ld\n",
ErrorClass, ErrorCode );
return;
}
for ( i = 0; Errors[ErrorClass][i].ErrorValue != 0; i++ ) {
if ( Errors[ErrorClass][i].ErrorValue == ErrorCode ) {
printf( "Error Code: %s\n", Errors[ErrorClass][i].ErrorName );
return;
}
}
printf( "Unknown error code: %ld\n", ErrorCode );
return;
}
#else
VOID
PrintError (
IN NTSTATUS Status
)
{
printf ("Status: %lx\n", Status );
return;
}
#endif
VOID
PrintFeaList (
IN PFEALIST FeaList
)
{
PFEA fea, lastFeaStartLocation;
lastFeaStartLocation = (PFEA)( (PCHAR)FeaList +
SmbGetUlong( &FeaList->cbList ) - sizeof(FEA) );
if ( SmbGetUlong( &FeaList->cbList ) < sizeof(FEA) + 4) {
printf( "No EAs.\n" );
return;
}
for ( fea = FeaList->list;
fea <= lastFeaStartLocation;
(PCHAR)fea += sizeof(FEA) + fea->cbName + 1 +
SmbGetUshort( &fea->cbValue ) ) {
STRING eaValue;
eaValue.Length = SmbGetUshort( &fea->cbValue );
eaValue.Buffer = ((PCHAR)(fea+1) + fea->cbName + 1);
printf( "EA name: %s, ", fea+1 );
printf( "value length: %ld, ", SmbGetUshort( &fea->cbValue ) );
if ( eaValue.Length == 0 ) {
printf( "(no value)\n" );
} else {
printf( "Value: %Z\n", &eaValue );
}
}
return;
} // PrintFeaList
#if SMBDBG
//
// The following functions are defined in smbgtpt.h. When debug mode is
// disabled (!DBG), these functions are instead defined as macros.
//
USHORT
SmbGetUshort (
IN PUSHORT SrcAddress
)
{
return (USHORT)(
( ( (PUCHAR)(SrcAddress) )[0] ) |
( ( (PUCHAR)(SrcAddress) )[1] << 8 )
);
}
USHORT
SmbGetAlignedUshort (
IN PUSHORT SrcAddress
)
{
return *(SrcAddress);
}
VOID
SmbPutUshort (
OUT PUSHORT DestAddress,
IN USHORT Value
)
{
( (PUCHAR)(DestAddress) )[0] = BYTE_0(Value);
( (PUCHAR)(DestAddress) )[1] = BYTE_1(Value);
return;
}
VOID
SmbPutAlignedUshort (
OUT PUSHORT DestAddress,
IN USHORT Value
)
{
*(DestAddress) = (Value);
return;
}
VOID
SmbMoveUshort (
OUT PUSHORT DestAddress,
IN PUSHORT SrcAddress
)
{
( (PUCHAR)(DestAddress) )[0] = ( (PUCHAR)(SrcAddress) )[0];
( (PUCHAR)(DestAddress) )[1] = ( (PUCHAR)(SrcAddress) )[1];
return;
}
ULONG
SmbGetUlong (
IN PULONG SrcAddress
)
{
return (ULONG)(
( ( (PUCHAR)(SrcAddress) )[0] ) |
( ( (PUCHAR)(SrcAddress) )[1] << 8 ) |
( ( (PUCHAR)(SrcAddress) )[2] << 16 ) |
( ( (PUCHAR)(SrcAddress) )[3] << 24 )
);
}
ULONG
SmbGetAlignedUlong (
IN PULONG SrcAddress
)
{
return *(SrcAddress);
}
VOID
SmbPutUlong (
OUT PULONG DestAddress,
IN ULONG Value
)
{
( (PUCHAR)(DestAddress) )[0] = BYTE_0(Value);
( (PUCHAR)(DestAddress) )[1] = BYTE_1(Value);
( (PUCHAR)(DestAddress) )[2] = BYTE_2(Value);
( (PUCHAR)(DestAddress) )[3] = BYTE_3(Value);
return;
}
VOID
SmbPutAlignedUlong (
OUT PULONG DestAddress,
IN ULONG Value
)
{
*(DestAddress) = Value;
return;
}
VOID
SmbMoveUlong (
OUT PULONG DestAddress,
IN PULONG SrcAddress
)
{
( (PUCHAR)(DestAddress) )[0] = ( (PUCHAR)(SrcAddress) )[0];
( (PUCHAR)(DestAddress) )[1] = ( (PUCHAR)(SrcAddress) )[1];
( (PUCHAR)(DestAddress) )[2] = ( (PUCHAR)(SrcAddress) )[2];
( (PUCHAR)(DestAddress) )[3] = ( (PUCHAR)(SrcAddress) )[3];
return;
}
VOID
SmbPutDate (
OUT PSMB_DATE DestAddress,
IN SMB_DATE Value
)
{
( (PUCHAR)&(DestAddress)->Ushort )[0] = BYTE_0(Value.Ushort);
( (PUCHAR)&(DestAddress)->Ushort )[1] = BYTE_1(Value.Ushort);
return;
}
VOID
SmbMoveDate (
OUT PSMB_DATE DestAddress,
IN PSMB_DATE SrcAddress
)
{
(DestAddress)->Ushort = (USHORT)(
( ( (PUCHAR)&(SrcAddress)->Ushort )[0] ) |
( ( (PUCHAR)&(SrcAddress)->Ushort )[1] << 8 ) );
return;
}
VOID
SmbZeroDate (
IN PSMB_DATE Date
)
{
(Date)->Ushort = 0;
}
BOOLEAN
SmbIsDateZero (
IN PSMB_DATE Date
)
{
return (BOOLEAN)( (Date)->Ushort == 0 );
}
VOID
SmbPutTime (
OUT PSMB_TIME DestAddress,
IN SMB_TIME Value
)
{
( (PUCHAR)&(DestAddress)->Ushort )[0] = BYTE_0(Value.Ushort);
( (PUCHAR)&(DestAddress)->Ushort )[1] = BYTE_1(Value.Ushort);
return;
}
VOID
SmbMoveTime (
OUT PSMB_TIME DestAddress,
IN PSMB_TIME SrcAddress
)
{
(DestAddress)->Ushort = (USHORT)(
( ( (PUCHAR)&(SrcAddress)->Ushort )[0] ) |
( ( (PUCHAR)&(SrcAddress)->Ushort )[1] << 8 ) );
return;
}
VOID
SmbZeroTime (
IN PSMB_TIME Time
)
{
(Time)->Ushort = 0;
}
BOOLEAN
SmbIsTimeZero (
IN PSMB_TIME Time
)
{
return (BOOLEAN)( (Time)->Ushort == 0 );
}
#endif // SMBDBG
//
// Named pipe functions
//
NTSTATUS
WaitNamedPipe(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues
)
{
NTSTATUS status;
SHORT setup[] = { 0x53, 0 };
CLONG outSetupCount = 0;
PUCHAR parameters = NULL;
CLONG outParameterCount = 0;
PUCHAR data = NULL;
CLONG outDataCount = 0;
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
0, // sizeof (parameters)
&outParameterCount,
data,
0, // sizeof (data)
&outDataCount
);
return status;
}
NTSTATUS
QueryNamedPipeHandle(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues
)
{
NTSTATUS status;
SHORT setup[] = { 0x21, 0 };
CLONG outSetupCount = 0;
UCHAR parameters[2];
CLONG outParameterCount = 2;
PUCHAR data;
CLONG outDataCount = 0;
setup[1] = IdValues->Fid[IdSelections->Fid]; // Put fid in setup2
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
0, // inParameterCount
&outParameterCount,
data,
0, // inParamterCount
&outDataCount
);
printf ("Named pipe handle state is %x\n", *((PUSHORT)parameters));
return status;
}
NTSTATUS
SetNamedPipeHandle(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN USHORT HandleState
)
{
NTSTATUS status;
SHORT setup[] = { 0x01, 0 };
CLONG outSetupCount = 0;
UCHAR parameters[2];
CLONG outParameterCount = 0;
PUCHAR data;
CLONG outDataCount = 0;
setup[1] = IdValues->Fid[IdSelections->Fid]; // Put fid in setup2
parameters[0] = (UCHAR) (HandleState & 0xFF);
parameters[1] = (UCHAR) (HandleState >> 8);
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
sizeof (parameters),
&outParameterCount,
data,
0, // inDataCount
&outDataCount
);
return status;
}
NTSTATUS
QueryNamedPipeInfo(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN USHORT Level
)
{
NTSTATUS status;
SHORT setup[2] = { 0x22, 0 };
CLONG outSetupCount = 0;
UCHAR parameters[2];
CLONG outParameterCount = 0;
PUCHAR data;
CLONG outDataCount = 0x100;
setup[1] = IdValues->Fid[IdSelections->Fid]; // Put fid in setup2
parameters[0] = (UCHAR) (Level & 0xFF);
parameters[1] = (UCHAR) (Level >> 8);
data = malloc( outDataCount );
if (data == NULL)
return STATUS_NO_MEMORY;
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
sizeof(parameters), // inParameterCount
&outParameterCount,
data,
0, // inDataCount
&outDataCount
);
if (NT_SUCCESS(status)) {
printf ("Pipe status:\n");
printf ("\tOutput quota %d, input quota %d\n",
*((PUSHORT)&data[0]), *((PUSHORT)&data[2]));
printf ("\tMaximum instances %d, current instances %d\n",
(USHORT)data[4], (USHORT)data[5]);
printf ("\tPipe name (%d bytes) ""%s""\n", data[6], &data[7]);
}
free( data );
return status;
}
NTSTATUS
CallNamedPipe(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN USHORT OutputDataLength
)
{
NTSTATUS status;
SHORT setup[] = { 0x54, 0 };
CLONG outSetupCount = 0;
PUCHAR parameters;
CLONG outParameterCount = 0;
PUCHAR data;
CLONG outDataCount = OutputDataLength;
USHORT i;
setup[1] = IdValues->Fid[IdSelections->Fid]; // Put fid in setup2
data = malloc( outDataCount );
if (data == NULL)
return STATUS_NO_MEMORY;
for (i=0; i < OutputDataLength; i++) {
data[i] = '$';
}
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
0, // sizeof (parameters)
&outParameterCount,
data,
OutputDataLength,
&outDataCount
);
free( data );
return status;
}
NTSTATUS
PeekNamedPipe(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN USHORT BytesToRead
)
{
NTSTATUS status;
SHORT setup[] = { 0x23, 0 };
CLONG outSetupCount = 0;
UCHAR parameters[6];
CLONG outParameterCount = 6;
PUCHAR data;
CLONG outDataCount = BytesToRead;
CLONG pipeState;
PSZ pipeStateString[] = { "Unknown",
"Disconnected",
"Listening",
"Connected",
"Closing"
};
setup[1] = IdValues->Fid[IdSelections->Fid]; // Put fid in setup2
data = malloc( outDataCount );
if (data == NULL)
return STATUS_NO_MEMORY;
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
0, // sizeof (parameters)
&outParameterCount,
data,
0, // sizeof (data)
&outDataCount
);
if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) {
printf ("Pipe info:\n");
printf ("\tBytes remaining in pipe %d\n", *(PUSHORT)¶meters[0]);
printf ("\tBytes remaining in message %d\n",
*(PUSHORT)¶meters[2]);
pipeState = *(PUSHORT)¶meters[4];
printf ("\tPipe state %s\n",
pipeState <= 4 ? pipeStateString[pipeState] : "Unknown");
}
free( data );
return status;
}
NTSTATUS
TransactNamedPipe(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues,
IN PUCHAR OutputData,
IN USHORT OutputDataLength
)
{
NTSTATUS status;
SHORT setup[] = { 0x26, 0 };
CLONG outSetupCount = 0;
PUCHAR parameters;
CLONG outParameterCount = 0;
PUCHAR data;
CLONG outDataCount = OutputDataLength;
setup[1] = IdValues->Fid[IdSelections->Fid]; // Put fid in setup2
data = malloc( outDataCount );
if (data == NULL)
return STATUS_NO_MEMORY;
RtlMoveMemory( data, OutputData, OutputDataLength );
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
0, // sizeof (parameters)
&outParameterCount,
data,
OutputDataLength,
&outDataCount
);
free( data );
return status;
}
NTSTATUS
RawReadNamedPipe(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues
)
{
NTSTATUS status;
SHORT setup[] = { 0x11, 0 };
CLONG outSetupCount = 0;
PUCHAR parameters;
CLONG outParameterCount = 2;
PUCHAR data;
CLONG outDataCount = 0;
setup[1] = IdValues->Fid[IdSelections->Fid]; // Put fid in setup2
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
0, // sizeof (parameters)
&outParameterCount,
data,
0, // sizeof (data)
&outDataCount
);
return status;
}
NTSTATUS
RawWriteNamedPipe(
IN PDESCRIPTOR Redir,
IN PSZ DebugString,
IN PID_SELECTIONS IdSelections,
IN PID_VALUES IdValues
)
{
NTSTATUS status;
SHORT setup[] = { 0x31, 0 };
CLONG outSetupCount = 0;
UCHAR parameters[2];
CLONG outParameterCount = 2;
UCHAR data[] = { 0, 0 };
CLONG outDataCount = 0;
setup[1] = IdValues->Fid[IdSelections->Fid]; // Put fid in setup2
status = SendAndReceiveTransaction(
Redir,
DebugString,
IdSelections,
IdValues,
SMB_COM_TRANSACTION,
setup,
sizeof (setup) / sizeof (SHORT),
&outSetupCount,
TestPipeName,
0,
parameters,
0, // sizeof (parameters)
&outParameterCount,
data,
sizeof (data),
&outDataCount
);
if (NT_SUCCESS(status) && *((PUSHORT)parameters) != 2) {
printf( "RawWriteNamedPipe returned %d bytes written\n",
*((PUSHORT)parameters));
}
return status;
}