diff options
Diffstat (limited to 'private/net/srvtest/subs.c')
-rw-r--r-- | private/net/srvtest/subs.c | 2417 |
1 files changed, 2417 insertions, 0 deletions
diff --git a/private/net/srvtest/subs.c b/private/net/srvtest/subs.c new file mode 100644 index 000000000..fea02cacd --- /dev/null +++ b/private/net/srvtest/subs.c @@ -0,0 +1,2417 @@ +/*++ + +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; +} |