diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/net/srvtest/rdwrtsub.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/net/srvtest/rdwrtsub.c')
-rw-r--r-- | private/net/srvtest/rdwrtsub.c | 1925 |
1 files changed, 1925 insertions, 0 deletions
diff --git a/private/net/srvtest/rdwrtsub.c b/private/net/srvtest/rdwrtsub.c new file mode 100644 index 000000000..886f2593c --- /dev/null +++ b/private/net/srvtest/rdwrtsub.c @@ -0,0 +1,1925 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + rdwrtsub.c + +Abstract: + + Subroutines (etc.) for the _read, _write, and copy tests. (See + rdwrt.c for "main" routines for these tests.) + +Author: + + Chuck Lenzmeier (chuckl) 24-Jan-1990 + +Revision History: + +--*/ + +#define INCLUDE_SMB_LOCK +#define INCLUDE_SMB_RAW +#define INCLUDE_SMB_READ_WRITE + +#include "usrv.h" +#include "rdwrt.h" + + +NTSTATUS +DoNormalRead( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN CLONG MaxLength, + IN ULONG Offset, + OUT CLONG *ActualLength, + OUT PUCHAR *ActualData + ) +{ + PSMB_HEADER header; + PREQ_READ request; + PRESP_READ response; + + NTSTATUS status; + CLONG smbSize; + + Mode; + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_READ)(header + 1); + + status = MakeSmbHeader( + Redir, + header, + SMB_COM_READ, + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + request->WordCount = 5; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUshort( &request->Count, (USHORT)MaxLength ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUshort( &request->Remaining, 0 ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( header, request, REQ_READ, 0 ); + + IF_DEBUG(4) printf( "reading %ld bytes at offset %ld\n", + MaxLength, Offset ); + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[1]; + response = (PRESP_READ)(header + 1); + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_READ + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + *ActualLength = (CLONG)SmbGetUshort( &response->Count ); + *ActualData = (PUCHAR)response->Buffer; + + if ( *ActualLength > MaxLength ) { + printf( "Too much read data returned. Expected %ld, received %ld\n", + MaxLength, *ActualLength ); + SMB_ERROR_BREAK; + return STATUS_UNSUCCESSFUL; + } + + IF_DEBUG(4) printf( "%ld bytes read\n", *ActualLength ); + + return STATUS_SUCCESS; + +} // DoNormalRead + + +NTSTATUS +DoAndXRead( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN CLONG MaxLength, + IN ULONG Offset, + OUT CLONG *ActualLength, + OUT PUCHAR *ActualData + ) +{ + PSMB_HEADER header; + PREQ_READ_ANDX request; + PRESP_READ_ANDX response; + + NTSTATUS status; + CLONG smbSize; + + Mode; + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_READ_ANDX)(header + 1); + + status = MakeSmbHeader( + Redir, + header, + SMB_COM_READ_ANDX, + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + request->WordCount = 10; + request->AndXCommand = SMB_COM_NO_ANDX_COMMAND; + request->AndXReserved = 0; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUshort( &request->MaxCount, (USHORT)MaxLength ); + SmbPutUshort( &request->MinCount, (USHORT)MaxLength ); + SmbPutUlong( &request->Timeout, 0 ); + SmbPutUshort( &request->Remaining, 0 ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( header, request, REQ_READ_ANDX, 0 ); + + IF_DEBUG(4) printf( "reading %ld bytes at offset %ld\n", + MaxLength, Offset ); + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[1]; + response = (PRESP_READ_ANDX)(header + 1); + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_READ_ANDX + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + *ActualLength = (CLONG)SmbGetUshort( &response->DataLength ); + *ActualData = (PUCHAR)header + SmbGetUshort( &response->DataOffset ); + + if ( *ActualLength > MaxLength ) { + printf( "Too much read data returned. Expected %ld, received %ld\n", + MaxLength, *ActualLength ); + SMB_ERROR_BREAK; + return STATUS_UNSUCCESSFUL; + } + + IF_DEBUG(4) printf( "%ld bytes read\n", *ActualLength ); + + return STATUS_SUCCESS; + +} // DoAndXRead + + +NTSTATUS +DoRawRead( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN CLONG MaxLength, + IN ULONG Offset, + OUT CLONG *ActualLength, + OUT PUCHAR *ActualData + ) +{ + PSMB_HEADER header; + PREQ_READ_RAW request; + + NTSTATUS status; + CLONG smbSize; + PUCHAR destination; + CLONG lengthRead; + CLONG readLength; + + Mode; + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_READ_RAW)(header + 1); + + lengthRead = 0; + destination = Redir->RawBuffer; + + while ( MaxLength != 0 ) { + + status = MakeSmbHeader( + Redir, + header, + SMB_COM_READ_RAW, + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + request->WordCount = 8; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUshort( &request->MaxCount, (USHORT)MaxLength ); + SmbPutUshort( &request->MinCount, 0 ); + SmbPutUlong( &request->Timeout, 0 ); + SmbPutUshort( &request->Reserved, 0 ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( header, request, REQ_READ_RAW, 0 ); + + IF_DEBUG(4) { + printf( "requesting raw read of %ld bytes at offset %ld\n", + MaxLength, Offset ); + } + + // + // Start a receive for the raw read data before sending the + // request. + // + + status = StartReceive( + DebugString, + Redir->FileHandle, + Redir->EventHandle[1], + &Redir->Iosb[1], + destination, + MaxLength + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + // + // Send the request for raw data. + // + // *** If there is an error, the receive remains posted! + + status = SendSmb( Redir, DebugString, smbSize, 0 ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + // + // Wait for the raw data to arrive. + // + + status = WaitForSendOrReceive( DebugString, Redir, 1, "receive" ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + // + // If any data was received, then the raw read succeeded. + // + + if ( Redir->Iosb[1].Information != 0 ) { + + IF_DEBUG(4) { + printf( "Raw read succeeded; %ld bytes received\n", + Redir->Iosb[1].Information ); + } + + *ActualLength = lengthRead + Redir->Iosb[1].Information; + *ActualData = Redir->RawBuffer; + + return STATUS_SUCCESS; + + } + + // + // A zero-length message was received. Either 1) the server + // didn't have resources to process the request; 2) the read + // failed; or 3) we tried to read at or beyond EOF. Retry with + // a normal Read. + // + + IF_DEBUG(4) { + printf( "Raw read returned 0 bytes; trying normal read\n" ); + } + + readLength = MIN( + MaxLength, + (CLONG)((Redir->MaxBufferSize - 100) & ~1023) + ); + + status = DoNormalRead( + Redir, + DebugString, + IdSelections, + IdValues, + Normal, + readLength, + Offset, + ActualLength, + ActualData + ); + + if ( !NT_SUCCESS(status) ) { + + // + // The normal read failed, so things are really screwed up. + // + + IF_DEBUG(4) printf( "Normal read failed: %X\n", status ); + return status; + + } + + if ( *ActualLength == 0 ) { + + // + // The normal read succeeded, but we didn't get any data, so + // we must be at EOF. + // + + IF_DEBUG(4) printf( "Normal read returned 0 bytes; at EOF\n" ); + *ActualLength = lengthRead; + *ActualData = Redir->RawBuffer; + return STATUS_SUCCESS; + + } + + // + // The normal read succeeded, and we got some data back. Copy + // the data into the output buffer and update counters. + // + + RtlMoveMemory( destination, *ActualData, *ActualLength ); + + lengthRead += *ActualLength; + MaxLength -= *ActualLength; + destination += *ActualLength; + Offset += *ActualLength; + + if ( *ActualLength != readLength ) { + + // + // We didn't read as much as we asked for, so we must have + // hit EOF. + // + + IF_DEBUG(4) { + printf( "Normal read didn't return full-length; at EOF\n" ); + } + *ActualLength = lengthRead; + *ActualData = Redir->RawBuffer; + return STATUS_SUCCESS; + + } + + // + // The normal read returned as much as we asked for. Keep going. + // + + IF_DEBUG(4) { + printf( "Normal read returned full-length; continuing\n" ); + } + + } // while ( MaxLength != 0 ) + + *ActualLength = lengthRead; + *ActualData = Redir->RawBuffer; + return STATUS_SUCCESS; + +} // DoRawRead + + +NTSTATUS +DoMultiplexedRead( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN CLONG MaxLength, + IN ULONG Offset, + OUT CLONG *ActualLength, + OUT PUCHAR *ActualData + ) +{ + Redir, DebugString, IdSelections, IdValues, Mode, MaxLength, Offset; + ActualLength, ActualData; + + printf( "DoMultiplexedRead: not implemented\n" ); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +DoBulkRead( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN CLONG MaxLength, + IN ULONG Offset, + OUT CLONG *ActualLength, + OUT PUCHAR *ActualData + ) +{ +#if 1 + Redir, DebugString, IdSelections, IdValues, Mode, MaxLength, Offset; + ActualLength, ActualData; + + printf( "DoBulkRead: not implemented\n" ); + return STATUS_NOT_IMPLEMENTED; +#else + PSMB_HEADER header; + PREQ_READ2 request; + PRESP_READ2 response; + + PCHAR tempBuffer; + ULONG bytesReceivedSoFar; + ULONG totalBytesToReceive; + + NTSTATUS status; + CLONG smbSize; + + Mode; + + // + // Allocate a buffer to hold responses. + // + + tempBuffer = malloc( 65536 ); + if ( tempBuffer == NULL ) { + return STATUS_NO_MEMORY; + } + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_READ2)(header + 1); + + status = MakeSmbHeader( + Redir, + header, + SMB_COM_READ2, + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + free( tempBuffer ); + return status; + } + + request->WordCount = 5; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUlong( &request->Count, (ULONG)MaxLength ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUlong( &request->Remaining, 0 ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( header, request, REQ_READ2, 0 ); + + IF_DEBUG(4) printf( "reading %ld bytes at offset %ld\n", + MaxLength, Offset ); + + // + // Start a receive for the first response data before sending the + // request. + // + + status = StartReceive( + DebugString, + Redir->FileHandle, + Redir->EventHandle[1], + &Redir->Iosb[1], + tempBuffer, + 65536 + ); + if ( !NT_SUCCESS(status) ) { + free( tempBuffer ); + return status; + } + + // + // Send the request for bulk data. + // + // *** If there is an error, the receive remains posted! + + status = SendSmb( Redir, DebugString, smbSize, 0 ); + if ( !NT_SUCCESS(status) ) { + free( tempBuffer ); + return status; + } + + // + // Wait for the first response to arrive. + // + + status = WaitForSendOrReceive( DebugString, Redir, 1, "receive" ); + if ( !NT_SUCCESS(status) ) { + free( tempBuffer ); + return status; + } + + IF_DEBUG(4) { + printf( "Bulk read succeeded; %ld bytes received\n", + Redir->Iosb[1].Information ); + } + + *ActualLength = totalBytesToReceive; + *ActualData = Redir->RawBuffer; + + header = (PSMB_HEADER)tempBuffer; + response = (PRESP_READ2)(header + 1); + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_READ2 + ); + if ( !NT_SUCCESS(status) ) { + free( tempBuffer ); + return status; + } + + totalBytesToReceive = SmbGetUlong( &response->Count ); + bytesReceivedSoFar = SmbGetUshort( &response->ByteCount ); + + IF_DEBUG(4) { + printf( "%ld bytes total, %ld in first message\n", + totalBytesToReceive, bytesReceivedSoFar ); + } + + // + // Copy the read data into the real buffer. + // + + RtlMoveMemory( + Redir->RawBuffer, + response->Buffer, + bytesReceivedSoFar + ); + + // + // Loop receiving the rest of the data. + // + + while ( bytesReceivedSoFar < totalBytesToReceive ) { + + PBULK_DATA_MESSAGE bulkResponse = (PBULK_DATA_MESSAGE)response; + ULONG bulkOffset; + ULONG bulkLength; + + status = StartReceive( + DebugString, + Redir->FileHandle, + Redir->EventHandle[1], + &Redir->Iosb[1], + tempBuffer, + 65536 + ); + if ( !NT_SUCCESS(status) ) { + free( tempBuffer ); + return status; + } + + status = WaitForSendOrReceive( DebugString, Redir, 1, "receive" ); + if ( !NT_SUCCESS(status) ) { + free( tempBuffer ); + return status; + } + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_READ2 + ); + if ( !NT_SUCCESS(status) ) { + free( tempBuffer ); + return status; + } + + bulkOffset = SmbGetUlong( &bulkResponse->Data1MessageOffset ); + bulkLength = SmbGetUlong( &bulkResponse->Data1Length ); + + bytesReceivedSoFar += bulkLength; + + IF_DEBUG(4) { + printf( "received %ld data bytes, %ld so far, offset %ld\n", + bulkLength, bytesReceivedSoFar, bulkOffset ); + } + + RtlMoveMemory( + (PCHAR)Redir->RawBuffer + + SmbGetUlong( &bulkResponse->Data1BlockOffset ), + (PCHAR)bulkResponse + bulkOffset, + bulkLength + ); + + } + + ASSERT( bytesReceivedSoFar == totalBytesToReceive ); + + *ActualLength = (CLONG)totalBytesToReceive; + *ActualData = Redir->RawBuffer; + + if ( *ActualLength > MaxLength ) { + printf( "Too much read data returned. Expected %ld, received %ld\n", + MaxLength, *ActualLength ); + SMB_ERROR_BREAK; + free( tempBuffer ); + return STATUS_UNSUCCESSFUL; + } + + IF_DEBUG(4) printf( "%ld bytes read\n", *ActualLength ); + + free( tempBuffer ); + + return STATUS_SUCCESS; +#endif + +} // DoBulkRead + + +NTSTATUS +DoNormalWrite( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN BOOLEAN UseClose, + IN CLONG WriteLength, + IN ULONG Offset, + IN PUCHAR WriteData + ) +{ + PSMB_HEADER header; + + NTSTATUS status; + CLONG smbSize; + + Mode; + + header = (PSMB_HEADER)Redir->Data[1]; + + if ( WriteLength == 0 ) { + + if ( !UseClose ) { + IF_DEBUG(4) printf( "skipping zero-length write\n" ); + return STATUS_SUCCESS; + } + + status = MakeCloseSmb( + Redir, + header, + NULL, + SMB_COM_NO_ANDX_COMMAND, + IdSelections, + IdValues, + &smbSize + ); + + } else { + + status = MakeSmbHeader( + Redir, + header, + (UCHAR)(UseClose ? + SMB_COM_WRITE_AND_CLOSE : SMB_COM_WRITE), + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + if ( !UseClose ) { + + PREQ_WRITE request = (PREQ_WRITE)(header + 1); + + request->WordCount = 5; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUshort( &request->Count, (USHORT)WriteLength ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUshort( &request->Remaining, 0 ); + + SmbPutUshort( + &request->ByteCount, + (USHORT)(WriteLength + FIELD_OFFSET(REQ_WRITE,Buffer[0]) - + FIELD_OFFSET(REQ_WRITE,BufferFormat)) + ); + + request->BufferFormat = SMB_FORMAT_DATA; + SmbPutUshort( &request->DataLength, (USHORT)WriteLength ); + if ( (WriteData != NULL) && + (WriteData != (PUCHAR)request->Buffer) ) { + printf( "DoNormalWrite copying data from 0x%lx to 0x%lx\n", + WriteData, request->Buffer ); + RtlMoveMemory( request->Buffer, WriteData, WriteLength ); + } + + smbSize = GET_ANDX_OFFSET( + header, + request, + REQ_WRITE, + SmbGetUshort( &request->ByteCount ) + ); + + } else { + + PREQ_WRITE_AND_CLOSE request = (PREQ_WRITE_AND_CLOSE)(header + 1); + + request->WordCount = 6; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUshort( &request->Count, (USHORT)WriteLength ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUlong( &request->LastWriteTimeInSeconds, 0 ); + + SmbPutUshort( + &request->ByteCount, + (USHORT)(WriteLength + + FIELD_OFFSET(REQ_WRITE_AND_CLOSE,Buffer[0]) - + FIELD_OFFSET(REQ_WRITE_AND_CLOSE,Pad)) + ); + + request->Pad = 0; + if ( (WriteData != NULL) && + (WriteData != (PUCHAR)request->Buffer) ) { + printf( "DoNormalWrite copying data from 0x%lx to 0x%lx\n", + WriteData, request->Buffer ); + RtlMoveMemory( request->Buffer, WriteData, WriteLength ); + } + + smbSize = GET_ANDX_OFFSET( + header, + request, + REQ_WRITE_AND_CLOSE, + SmbGetUshort( &request->ByteCount ) + ); + + } + + } + + IF_DEBUG(4) { + if ( WriteLength == 0 ) { + printf( "skipping zero-length write; sending close\n" ); + } else { + printf( "writing %ld bytes at offset %ld\n", + WriteLength, Offset ); + } + } + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 1, + 0 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[0]; + + if ( WriteLength == 0 ) { + + status = VerifyClose( + Redir, + NULL, + SMB_COM_NO_ANDX_COMMAND, + IdSelections, + IdValues, + &smbSize, + header + ); + + } else { + + PRESP_WRITE response = (PRESP_WRITE)(header + 1); + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + (UCHAR)(UseClose ? SMB_COM_WRITE_AND_CLOSE : SMB_COM_WRITE) + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + if ( (CLONG)SmbGetUshort( &response->Count ) != WriteLength ) { + printf( "Length written incorrect. Sent %ld, wrote %ld\n", + WriteLength, SmbGetUshort( &response->Count ) ); + SMB_ERROR_BREAK; + return STATUS_UNSUCCESSFUL; + } + + } + + IF_DEBUG(4) { + if ( WriteLength == 0 ) { + printf( "output file closed\n" ); + } else { + printf( "%ld bytes written\n", WriteLength ); + } + } + + return STATUS_SUCCESS; + +} // DoNormalWrite + + +NTSTATUS +DoAndXWrite( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN BOOLEAN UseClose, + IN CLONG WriteLength, + IN ULONG Offset, + IN PUCHAR WriteData + ) +{ + PSMB_HEADER header; + + NTSTATUS status; + CLONG smbSize; + + Mode; + + header = (PSMB_HEADER)Redir->Data[1]; + + if ( WriteLength == 0 ) { + + if ( !UseClose ) { + IF_DEBUG(4) printf( "skipping zero-length write\n" ); + return STATUS_SUCCESS; + } + + status = MakeCloseSmb( + Redir, + header, + NULL, + SMB_COM_NO_ANDX_COMMAND, + IdSelections, + IdValues, + &smbSize + ); + + } else { + + status = MakeSmbHeader( + Redir, + header, + (UCHAR)(UseClose ? + SMB_COM_WRITE_AND_CLOSE : SMB_COM_WRITE_ANDX), + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + if ( !UseClose ) { + + PREQ_WRITE_ANDX request = (PREQ_WRITE_ANDX)(header + 1); + CLONG dataOffset, pad; + + request->WordCount = 12; + request->AndXCommand = SMB_COM_NO_ANDX_COMMAND; + request->AndXReserved = 0; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUlong( &request->Timeout, 0 ); + SmbPutUshort( &request->WriteMode, 0 ); + SmbPutUshort( &request->Remaining, 0 ); + SmbPutUshort( &request->Reserved, 0 ); + SmbPutUshort( &request->DataLength, (USHORT)WriteLength ); + + dataOffset = request->Buffer - (PUCHAR)header; + pad = (4 - (dataOffset & 3)) & 3; + dataOffset += pad; + + SmbPutUshort( &request->DataOffset, (USHORT)dataOffset ); + SmbPutUshort( &request->ByteCount, (USHORT)(pad + WriteLength) ); + + if ( (WriteData != NULL) && (WriteData != request->Buffer+pad) ) { + printf( "DoAndXWrite copying data from 0x%lx to 0x%lx\n", + WriteData, request->Buffer+pad ); + RtlMoveMemory( request->Buffer + pad, WriteData, WriteLength ); + } + + smbSize = GET_ANDX_OFFSET( + header, + request, + REQ_WRITE_ANDX, + WriteLength + pad + ); + + SmbPutUshort( &request->AndXOffset, (USHORT)smbSize ); + + } else { + + PREQ_WRITE_AND_CLOSE_LONG request = + (PREQ_WRITE_AND_CLOSE_LONG)(header + 1); + + request->WordCount = 12; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUshort( &request->Count, (USHORT)WriteLength ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUlong( &request->LastWriteTimeInSeconds, 0 ); + RtlZeroMemory( &request->Reserved[0], sizeof(request->Reserved) ); + + SmbPutUshort( + &request->ByteCount, + (USHORT)(WriteLength + + FIELD_OFFSET(REQ_WRITE_AND_CLOSE_LONG,Buffer[0]) - + FIELD_OFFSET(REQ_WRITE_AND_CLOSE_LONG,Pad)) + ); + + request->Pad = 0; + if ( (WriteData != NULL) && + (WriteData != (PUCHAR)request->Buffer) ) { + printf( "DoAndXWrite copying data from 0x%lx to 0x%lx\n", + WriteData, request->Buffer ); + RtlMoveMemory( request->Buffer, WriteData, WriteLength ); + } + + smbSize = GET_ANDX_OFFSET( + header, + request, + REQ_WRITE_AND_CLOSE_LONG, + SmbGetUshort( &request->ByteCount ) + ); + + } + + } + + IF_DEBUG(4) { + if ( WriteLength == 0 ) { + printf( "skipping zero-length write; sending close\n" ); + } else { + printf( "writing %ld bytes at offset %ld\n", + WriteLength, Offset ); + } + } + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 1, + 0 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[0]; + + if ( WriteLength == 0 ) { + + status = VerifyClose( + Redir, + NULL, + SMB_COM_NO_ANDX_COMMAND, + IdSelections, + IdValues, + &smbSize, + header + ); + + } else { + + CLONG lengthWritten; + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + (UCHAR)(UseClose ? + SMB_COM_WRITE_AND_CLOSE : SMB_COM_WRITE_ANDX ) + ); + if( !NT_SUCCESS(status) ) { + return status; + } + + if ( !UseClose ) { + + PRESP_WRITE_ANDX response = (PRESP_WRITE_ANDX)(header + 1); + + lengthWritten = (CLONG)SmbGetUshort( &response->Count ); + + } else { + + PRESP_WRITE_AND_CLOSE response = + (PRESP_WRITE_AND_CLOSE)(header + 1); + + lengthWritten = (CLONG)SmbGetUshort( &response->Count ); + + } + + if ( lengthWritten != WriteLength ) { + printf( "Length written incorrect. Sent %ld, wrote %ld\n", + WriteLength, lengthWritten ); + SMB_ERROR_BREAK; + return STATUS_UNSUCCESSFUL; + } + + } + + IF_DEBUG(4) { + if ( WriteLength == 0 ) { + printf( "output file closed\n" ); + } else { + printf( "%ld bytes written\n", WriteLength ); + } + } + + return STATUS_SUCCESS; + +} // DoAndXWrite + + +NTSTATUS +DoRawWrite( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN BOOLEAN UseClose, + IN CLONG WriteLength, + IN ULONG Offset, + IN PUCHAR WriteData + ) + +{ + PSMB_HEADER header; + PREQ_WRITE_RAW request; + PRESP_WRITE_COMPLETE finalResponse; + + NTSTATUS status; + CLONG smbSize; + PVOID savedDataPointer; + PUCHAR source; + CLONG lengthWritten; + CLONG immediateLength; + USHORT smbStatus; + + source = WriteData; + lengthWritten = 0; + immediateLength = 0; + + while ( TRUE ) { + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_WRITE_RAW)(header + 1); + + status = MakeSmbHeader( + Redir, + header, + SMB_COM_WRITE_RAW, + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + request->WordCount = 12; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUshort( &request->Count, (USHORT)WriteLength ); + SmbPutUshort( &request->Reserved, 0 ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUlong( &request->Timeout, 0 ); + SmbPutUshort( + &request->WriteMode, + (USHORT)(Mode == Raw ? 0 : SMB_WMODE_WRITE_THROUGH) + ); + SmbPutUlong( &request->Reserved2, 0 ); + + if ( immediateLength == 0 ) { + + SmbPutUshort( &request->DataLength, 0 ); + SmbPutUshort( &request->DataOffset, 0 ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( header, request, REQ_WRITE_RAW, 0 ); + + } else { + + CLONG pad; + CLONG dataOffset; + + dataOffset = request->Buffer - (PUCHAR)header; + pad = (4 - (dataOffset & 3)) & 3; + dataOffset += pad; + + SmbPutUshort( &request->DataLength, (USHORT)immediateLength ); + SmbPutUshort( &request->DataOffset, (USHORT)dataOffset ); + SmbPutUshort( + &request->ByteCount, + (USHORT)(pad + immediateLength) + ); + + RtlMoveMemory( request->Buffer + pad, source, immediateLength ); + + smbSize = GET_ANDX_OFFSET( + header, + request, + REQ_WRITE_RAW, + pad + immediateLength + ); + } + + IF_DEBUG(4) { + printf( "requesting raw write of %ld bytes (%ld immediate) " + "at offset %ld\n", + WriteLength, immediateLength, Offset ); + } + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[1]; + + smbStatus = SmbGetUshort( &header->Error ); + + if ( smbStatus == SMB_ERR_SUCCESS ) { + + // + // The request to send raw write data was accepted. Go do it. + // + + break; + + } else if ( (smbStatus == SMB_ERR_USE_STANDARD) || + (smbStatus == SMB_ERR_USE_MPX) ) { + + // + // The server isn't accepting raw writes just now. Try it + // again, this time sending immediate data. The immediate + // data will be written, even if the server can't do the + // raw part at the moment. + // + + source += immediateLength; + lengthWritten += immediateLength; + Offset += immediateLength; + WriteLength -= immediateLength; + + if ( WriteLength == 0 ) { + IF_DEBUG(4) { + printf( "Raw write rejected, but immediate write " + "sent all remaining data\n" ); + } + return STATUS_SUCCESS; + } + + immediateLength = MIN( + WriteLength, + (CLONG)((Redir->MaxBufferSize - 100) & ~1023) + ); + + IF_DEBUG(4) { + printf( "Server rejected raw write. Retrying " + "with immediate data.\n" ); + } + + continue; + + } else { + + // + // Fatal error. + // + + (VOID)VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_NO_ANDX_COMMAND + ); + return STATUS_UNSUCCESSFUL; + + } + + } // while ( TRUE ) + + // + // The request to send raw write data was accepted. Send the rest + // of data, minus immediate data sent in the request. (Note that + // we may have sent _all_ of the remaining data as immediate data.) + // + + if ( WriteLength - immediateLength != 0 ) { + + IF_DEBUG(4) printf( "sending raw write data\n" ); + + savedDataPointer = Redir->Data[0]; + Redir->Data[0] = source + immediateLength; + + if ( Mode == Raw ) { + + status = SendSmb( + Redir, + DebugString, + WriteLength - immediateLength, + 0 + ); + + Redir->Data[0] = savedDataPointer; + + if ( !NT_SUCCESS(status) ) { + return status; + } + + } else { + + status = SendAndReceiveSmb( + Redir, + DebugString, + WriteLength - immediateLength, + 0, + 1 + ); + + Redir->Data[0] = savedDataPointer; + + if ( !NT_SUCCESS(status) ) { + return status; + } + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_WRITE_COMPLETE + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + finalResponse = (PRESP_WRITE_COMPLETE)(header + 1); + + if ( (CLONG)SmbGetUshort( &finalResponse->Count ) != WriteLength ) { + printf( "Write length incorrect. Sent %ld, wrote %ld\n", + WriteLength, SmbGetUshort( &finalResponse->Count ) ); + SMB_ERROR_BREAK; + return STATUS_UNSUCCESSFUL; + } + + } + + } + + if ( UseClose ) { + return DoRemoteClose( + Redir, + DebugString, + IdSelections, + IdValues + ); + } + + return STATUS_SUCCESS; + +} // DoRawWrite + + +NTSTATUS +DoMultiplexedWrite( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN BOOLEAN UseClose, + IN CLONG WriteLength, + IN ULONG Offset, + IN PUCHAR WriteData + ) +{ + Redir, DebugString, IdSelections, IdValues, Mode, UseClose; + WriteLength, Offset, WriteData; + + printf( "DoMultiplexedWrite: not implemented\n" ); + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +DoBulkWrite ( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN RWC_MODE Mode, + IN BOOLEAN UseClose, + IN CLONG WriteLength, + IN ULONG Offset, + IN PUCHAR WriteData + ) +{ + Redir, DebugString, IdSelections, IdValues, Mode, UseClose; + WriteLength, Offset, WriteData; + + printf( "DoBulkWrite: not implemented\n" ); + return STATUS_NOT_IMPLEMENTED; +} + + + +NTSTATUS +RwcDoLock( + IN PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN PID_VALUES IdValues, + IN ULONG Offset, + IN CLONG Length + ) + +{ + NTSTATUS status; + CLONG smbSize; + + PSMB_HEADER header; + PREQ_LOCK_BYTE_RANGE request; + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_LOCK_BYTE_RANGE)(header + 1); + + (VOID)MakeSmbHeader( + Redir, + header, + SMB_COM_LOCK_BYTE_RANGE, + IdSelections, + IdValues + ); + + request->WordCount = 5; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUlong( &request->Count, Length ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( header, request, REQ_LOCK_BYTE_RANGE, 0 ); + IF_DEBUG(4) printf( "locking %ld bytes at offset %ld\n", + Length, Offset ); + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[1]; + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_LOCK_BYTE_RANGE + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + return STATUS_SUCCESS; + +} // RwcDoLock + + +NTSTATUS +RwcDoUnlock( + IN PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN ULONG Offset, + IN CLONG Length + ) + +{ + NTSTATUS status; + CLONG smbSize; + + PSMB_HEADER header; + PREQ_UNLOCK_BYTE_RANGE request; + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_UNLOCK_BYTE_RANGE)(header + 1); + + (VOID)MakeSmbHeader( + Redir, + header, + SMB_COM_UNLOCK_BYTE_RANGE, + IdSelections, + IdValues + ); + + request->WordCount = 5; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUlong( &request->Count, Length ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( header, request, REQ_UNLOCK_BYTE_RANGE, 0 ); + IF_DEBUG(4) printf( "unlocking %ld bytes at offset %ld\n", + Length, Offset ); + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[1]; + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_UNLOCK_BYTE_RANGE + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + return STATUS_SUCCESS; + +} // RwcDoUnlock + + +NTSTATUS +RwcDoLockAndRead( + IN PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN ULONG Offset, + IN CLONG MaxLength, + IN OUT PCLONG ActualLength, + IN PUCHAR *ActualData + ) + +{ + NTSTATUS status; + CLONG smbSize; + + PSMB_HEADER header; + PREQ_READ request; + PRESP_READ response; + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_READ)(header + 1); + + status = MakeSmbHeader( + Redir, + header, + SMB_COM_LOCK_AND_READ, + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + request->WordCount = 5; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUshort( &request->Count, (USHORT)MaxLength ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUshort( &request->Remaining, 0 ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( + header, + request, + REQ_READ, + 0 + ); + IF_DEBUG(4) printf( "locking and reading %ld bytes at offset %ld\n", + MaxLength, Offset ); + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[1]; + response = (PRESP_READ)(header + 1); + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_LOCK_AND_READ + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + if ( (CLONG)SmbGetUshort( &response->Count ) > MaxLength ) { + printf( "Read size too large. Expected %ld, received %ld\n", + MaxLength, SmbGetUshort( &response->Count ) ); + SMB_ERROR_BREAK; + return STATUS_UNSUCCESSFUL; + } + + *ActualLength = SmbGetUshort( &response->Count ); + + *ActualData = (PUCHAR)response->Buffer; + + IF_DEBUG(4) printf( "%ld bytes locked and read\n", *ActualLength ); + + return STATUS_SUCCESS; + +} // DoLockAndRead + + +NTSTATUS +RwcDoWriteAndUnlock( + IN PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN ULONG Offset, + IN CLONG WriteLength, + IN PUCHAR WriteData OPTIONAL + ) + +{ + NTSTATUS status; + CLONG smbSize; + + PSMB_HEADER header; + PREQ_WRITE request; + PRESP_WRITE response; + + header = (PSMB_HEADER)Redir->Data[1]; + request = (PREQ_WRITE)(header + 1); + + status = MakeSmbHeader( + Redir, + header, + SMB_COM_WRITE_AND_UNLOCK, + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + request->WordCount = 5; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUshort( &request->Count, (USHORT)WriteLength ); + SmbPutUlong( &request->Offset, Offset ); + SmbPutUshort( &request->Remaining, 0 ); + + SmbPutUshort( + &request->ByteCount, + (USHORT)(WriteLength + FIELD_OFFSET(REQ_WRITE,Buffer[0]) - + FIELD_OFFSET(REQ_WRITE,BufferFormat)) + ); + + request->BufferFormat = SMB_FORMAT_DATA; + SmbPutUshort( &request->DataLength, (USHORT)WriteLength ); + if ( (WriteData != NULL) && + (WriteData != (PUCHAR)request->Buffer) ) { + printf( "RwcDoWriteAndUnlock copying data from 0x%lx to 0x%lx\n", + WriteData, request->Buffer ); + RtlMoveMemory( request->Buffer, WriteData, WriteLength ); + } + + smbSize = GET_ANDX_OFFSET( + header, + request, + REQ_WRITE, + SmbGetUshort( &request->ByteCount ) + ); + IF_DEBUG(4) printf( "writing and unlocking %ld bytes at offset %ld\n", + WriteLength, Offset ); + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 1, + 0 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[0]; + response = (PRESP_WRITE)(header + 1); + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_WRITE_AND_UNLOCK + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + if ( (CLONG)SmbGetUshort( &response->Count ) != WriteLength ) { + printf( "Write size incorrect. Sent %ld, wrote %ld\n", + WriteLength, SmbGetUshort( &response->Count ) ); + SMB_ERROR_BREAK; + return STATUS_UNSUCCESSFUL; + } + + IF_DEBUG(4) printf( "%ld bytes written and unlocked\n", WriteLength ); + + return STATUS_SUCCESS; + +} // RwcDoWriteAndUnlock + +NTSTATUS +DoSeek ( + IN OUT PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN OUT PID_VALUES IdValues, + IN USHORT Mode, + IN LONG Offset, + IN PLONG ResultingOffset + ) +{ + PSMB_HEADER header; + PREQ_SEEK request; + PRESP_SEEK response; + + CLONG smbSize; + + NTSTATUS status; + + header = (PSMB_HEADER)Redir->Data[0]; + request = (PREQ_SEEK)(header + 1); + + status = MakeSmbHeader( + Redir, + header, + SMB_COM_SEEK, + IdSelections, + IdValues + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + request->WordCount = 4; + SmbPutUshort( &request->Fid, IdValues->Fid[IdSelections->Fid] ); + SmbPutUshort( &request->Mode, Mode ); + SmbPutUlong( &request->Offset, (ULONG)Offset ); + SmbPutUshort( &request->ByteCount, 0 ); + + smbSize = GET_ANDX_OFFSET( header, request, REQ_SEEK, 0 ); + + IF_DEBUG(4) { + printf( "Setting offset to %s%s%ld\n", + (Mode == 0) ? "BOF" : (Mode == 1) ? "current" : "EOF", + (Offset < 0) ? "" : "+", Offset ); + } + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + header = (PSMB_HEADER)Redir->Data[1]; + response = (PRESP_SEEK)(header + 1); + + status = VerifySmbHeader( + Redir, + IdSelections, + IdValues, + header, + SMB_COM_SEEK + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + *ResultingOffset = (LONG)SmbGetUlong( &response->Offset ); + IF_DEBUG(4) printf( "Resulting offset is %ld\n", *ResultingOffset ); + + return STATUS_SUCCESS; + +} // DoSeek + + +NTSTATUS +DoRemoteOpen( + IN PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN PID_VALUES IdValues, + IN BOOLEAN UseAndX + ) + +{ + NTSTATUS status; + ULONG smbSize = 0; + + if ( UseAndX ) { + status = MakeOpenAndXSmb( + Redir, + Redir->Data[0], + NULL, + 0xFF, + IdSelections, + IdValues, + &smbSize + ); + } else { + status = MakeOpenSmb( + Redir, + Redir->Data[0], + NULL, + 0xFF, + IdSelections, + IdValues, + &smbSize + ); + } + + if ( !NT_SUCCESS(status) ) { + return status; + } + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + if ( UseAndX ) { + status = VerifyOpenAndX( + Redir, + NULL, + 0, + IdSelections, + IdValues, + &smbSize, + Redir->Data[1] + ); + } else { + status = VerifyOpen( + Redir, + NULL, + 0, + IdSelections, + IdValues, + &smbSize, + Redir->Data[1] + ); + } + + if ( !NT_SUCCESS(status) ) { + printf( "Open failed: %X\n", status ); + } + + return status; + +} // DoRemoteOpen + + +NTSTATUS +DoRemoteClose( + IN PDESCRIPTOR Redir, + IN PSZ DebugString, + IN PID_SELECTIONS IdSelections, + IN PID_VALUES IdValues + ) + +{ + NTSTATUS status; + ULONG smbSize; + + status = MakeCloseSmb( + Redir, + Redir->Data[0], + NULL, + 0, + IdSelections, + IdValues, + &smbSize + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + status = SendAndReceiveSmb( + Redir, + DebugString, + smbSize, + 0, + 1 + ); + if ( !NT_SUCCESS(status) ) { + return status; + } + + status = VerifyClose( + Redir, + NULL, + 0, + IdSelections, + IdValues, + &smbSize, + Redir->Data[1] + ); + if ( !NT_SUCCESS(status) ) { + printf( "Close failed: %X\n", status ); + } + + return status; + +} // DoRemoteClose |