summaryrefslogtreecommitdiffstats
path: root/private/net/srvtest/rdwrtsub.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/net/srvtest/rdwrtsub.c
downloadNT4.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.c1925
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