📄 write.c
字号:
/*++
Copyright (c) 1989 - 1999 Microsoft Corporation
Module Name:
write.c
Abstract:
This module implements the mini redirector call down routines pertaining
to write of file system objects.
--*/
#include "precomp.h"
#pragma hdrstop
#pragma warning(error:4101) // Unreferenced local variable
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, MRxSmbWrite)
#pragma alloc_text(PAGE, MRxSmbBuildWriteRequest)
#pragma alloc_text(PAGE, SmbPseExchangeStart_Write)
#pragma alloc_text(PAGE, MRxSmbFinishWrite)
#endif
#define MAX(a,b) ((a) > (b) ? (a) : (b))
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_WRITE)
#ifndef FORCE_NO_NTWRITEANDX
#define MRxSmbForceNoNtWriteAndX FALSE
#else
BOOLEAN MRxSmbForceNoNtWriteAndX = TRUE;
#endif
#define WRITE_COPY_THRESHOLD 64
#define FORCECOPYMODE FALSE
#ifdef SETFORCECOPYMODE
#undef FORCECOPYMODE
#define FORCECOPYMODE MRxSmbForceCopyMode
ULONG MRxSmbForceCopyMode = TRUE;
#endif
NTSTATUS
SmbPseExchangeStart_Write(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
);
ULONG MRxSmbWriteSendOptions = 0;
NTSTATUS
MRxSmbWrite (
IN PRX_CONTEXT RxContext)
/*++
Routine Description:
This routine opens a file across the network.
Arguments:
RxContext - the RDBSS context
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
RxCaptureFcb;
RxCaptureFobx;
PMRX_SRV_OPEN SrvOpen;
PMRX_SMB_SRV_OPEN smbSrvOpen;
PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbWrite\n", 0 ));
if (RxContext->pFcb->pNetRoot->Type == NET_ROOT_PIPE) {
Status = STATUS_NOT_SUPPORTED;
RxDbgTrace(-1, Dbg, ("MRxSmbWrite: Pipe write returned %lx\n",Status));
return Status;
}
if ( NodeType(capFcb) == RDBSS_NTC_MAILSLOT ) {
Status = STATUS_NOT_SUPPORTED;
RxDbgTrace(-1, Dbg, ("MRxSmbWrite: Mailslot write returned %lx\n",Status));
return Status;
}
if(NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE) {
PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
smbFcb->MFlags |= SMB_FCB_FLAG_WRITES_PERFORMED;
}
ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN );
SrvOpen = capFobx->pSrvOpen;
smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
if (smbSrvOpen->OplockLevel == SMB_OPLOCK_LEVEL_II &&
!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
LOWIO_READWRITEFLAG_PAGING_IO)) {
PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
PMRX_SRV_CALL pSrvCall;
pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)SrvOpen->pVNetRoot->Context;
pSrvCall = SrvOpen->pVNetRoot->pNetRoot->pSrvCall;
RxIndicateChangeOfBufferingStateForSrvOpen(
pSrvCall,
SrvOpen,
MRxSmbMakeSrvOpenKey(pVNetRootContext->TreeId,smbSrvOpen->Fid),
ULongToPtr(SMB_OPLOCK_LEVEL_NONE));
SmbCeLog(("Breaking oplock to None in Write SO %lx\n",SrvOpen));
}
do {
Status = __SmbPseCreateOrdinaryExchange(
RxContext,
capFobx->pSrvOpen->pVNetRoot,
SMBPSE_OE_FROM_WRITE,
SmbPseExchangeStart_Write,
&OrdinaryExchange);
if (Status != STATUS_SUCCESS) {
RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
return Status;
}
Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
if ( Status != STATUS_PENDING ) {
BOOLEAN FinalizationComplete = SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
ASSERT( FinalizationComplete );
} else {
ASSERT(BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION));
}
if ((Status == STATUS_RETRY) &&
BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION)) {
MRxSmbResumeAsyncReadWriteRequests(RxContext);
Status = STATUS_PENDING;
}
} while (Status == STATUS_RETRY);
RxDbgTrace(-1, Dbg, ("MRxSmbWrite exit with status=%08lx\n", Status ));
return(Status);
} // MRxSmbWrite
NTSTATUS
MRxSmbBuildWriteRequest(
PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
BOOLEAN IsPagingIo,
UCHAR WriteCommand,
ULONG ByteCount,
PLARGE_INTEGER ByteOffsetAsLI,
PBYTE Buffer,
PMDL BufferAsMdl)
/*++
Routine Description:
This is the start routine for write.
Arguments:
pExchange - the exchange instance
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
PRX_CONTEXT RxContext = StufferState->RxContext;
RxCaptureFcb;
RxCaptureFobx;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
PNT_SMB_HEADER NtSmbHeader = (PNT_SMB_HEADER)(StufferState->BufferBase);
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
ULONG OffsetLow,OffsetHigh;
PSMB_PSE_OE_READWRITE rw = &OrdinaryExchange->ReadWrite;
USHORT WriteMode = 0;
ULONG DataLengthLow,DataLengthHigh;
ULONG BytesRemaining = 0;
BOOLEAN AddLengthBytes = FALSE;
ULONG WriteCommandSize;
PSMBCE_SERVER pServer = SmbCeGetExchangeServer((PSMB_EXCHANGE)OrdinaryExchange);
BOOLEAN UseNtVersion;
UseNtVersion = BooleanFlagOn(pServer->DialectFlags,DF_NT_SMBS) &&
!MRxSmbForceNoNtWriteAndX;
// The data length field in SMB is a USHORT, and hence the data length given
// needs to be split up into two parts -- DataLengthHigh and DataLengthLow
DataLengthLow = (ByteCount & 0xffff);
DataLengthHigh = ((ByteCount & 0xffff0000) >> 16);
OffsetLow = ByteOffsetAsLI->LowPart;
OffsetHigh = ByteOffsetAsLI->HighPart;
switch (WriteCommand) {
case SMB_COM_WRITE_ANDX:
WriteCommandSize = SMB_REQUEST_SIZE(NT_WRITE_ANDX);
break;
case SMB_COM_WRITE:
WriteCommandSize = SMB_REQUEST_SIZE(WRITE);
break;
case SMB_COM_WRITE_PRINT_FILE:
WriteCommandSize = SMB_REQUEST_SIZE(WRITE_PRINT_FILE);
break;
}
Status = MRxSmbStartSMBCommand(
StufferState,
SetInitialSMB_Never,
WriteCommand,
WriteCommandSize,
NO_EXTRA_DATA,
NO_SPECIAL_ALIGNMENT,
RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
0,0,0,0 STUFFERTRACE(Dbg,'FC'));
MRxSmbDumpStufferState(
1000,
"SMB Write Request before stuffing",
StufferState);
switch (WriteCommand) {
case SMB_COM_WRITE_ANDX :
{
if ( UseNtVersion && IsPagingIo ) {
SmbPutAlignedUshort(
&NtSmbHeader->Flags2,
SmbGetAlignedUshort(&NtSmbHeader->Flags2)|SMB_FLAGS2_PAGING_IO );
}
//
// If the file object was opened in write through mode, set write
// through on the write operation.
if (FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_WRITE_THROUGH)) {
WriteMode |= SMB_WMODE_WRITE_THROUGH;
}
MRxSmbStuffSMB (
StufferState,
"XwddwwwwQ",
// X UCHAR WordCount;
// UCHAR AndXCommand;
// UCHAR AndXReserved;
// _USHORT( AndXOffset );
smbSrvOpen->Fid, // w _USHORT( Fid );
OffsetLow, // d _ULONG( Offset );
-1, // d _ULONG( Timeout );
WriteMode, // w _USHORT( WriteMode );
BytesRemaining, // w _USHORT( Remaining );
DataLengthHigh, // w _USHORT( DataLengthHigh );
DataLengthLow, // w _USHORT( DataLength );
// Q _USHORT( DataOffset );
SMB_OFFSET_CHECK(WRITE_ANDX,DataOffset)
StufferCondition(UseNtVersion), "D",
SMB_OFFSET_CHECK(NT_WRITE_ANDX,OffsetHigh)
OffsetHigh, // D NTonly _ULONG( OffsetHigh );
//
STUFFER_CTL_NORMAL, "BS5",
// B _USHORT( ByteCount );
SMB_WCT_CHECK(((UseNtVersion)?14:12))
// UCHAR Buffer[1];
// S //UCHAR Pad[];
// 5 //UCHAR Data[];
StufferCondition(AddLengthBytes), "w", LowIoContext->ParamsFor.ReadWrite.ByteCount,
StufferCondition(Buffer!=NULL), "c!",
ByteCount,
Buffer, // c the actual data
0
);
}
break;
case SMB_COM_WRITE :
{
MRxSmbStuffSMB (
StufferState,
"0wwdwByw",
// 0 UCHAR WordCount; // Count of parameter words = 5
smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
DataLengthLow, // w _USHORT( Count ); // Number of bytes to be written
OffsetLow, // d _ULONG( Offset ); // Offset in file to begin write
BytesRemaining, // w _USHORT( Remaining ); // Bytes remaining to satisfy request
SMB_WCT_CHECK(5) // B _USHORT( ByteCount ); // Count of data bytes
// //UCHAR Buffer[1]; // Buffer containing:
0x01, // y UCHAR BufferFormat; // 0x01 -- Data block
DataLengthLow, // w _USHORT( DataLength ); // Length of data
// ULONG Buffer[1]; // Data
StufferCondition(Buffer!=NULL), "c!",
ByteCount,
Buffer, // c the actual data
0
);
}
break;
case SMB_COM_WRITE_PRINT_FILE:
{
MRxSmbStuffSMB (
StufferState,
"0wByw",
// 0 UCHAR WordCount; // Count of parameter words = 1
smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
SMB_WCT_CHECK(1) // B _USHORT( ByteCount ); // Count of data bytes; min = 4
// UCHAR Buffer[1]; // Buffer containing:
0x01, // y //UCHAR BufferFormat; // 0x01 -- Data block
DataLengthLow, // w //USHORT DataLength; // Length of data
// //UCHAR Data[]; // Data
StufferCondition(Buffer!=NULL), "c!",
ByteCount,
Buffer, // c the actual data
0
);
}
break;
default:
Status = STATUS_UNSUCCESSFUL ;
break;
}
if ( BufferAsMdl ) {
MRxSmbStuffAppendRawData( StufferState, BufferAsMdl );
MRxSmbStuffSetByteCount( StufferState );
}
MRxSmbDumpStufferState(
700,
"SMB Write Request after stuffing",
StufferState);
if (Status==STATUS_SUCCESS) {
InterlockedIncrement(&MRxSmbStatistics.SmallWriteSmbs);
}
return Status;
}
BOOLEAN DisableLargeWrites = 0;
NTSTATUS
SmbPseExchangeStart_Write (
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
)
/*++
Routine Description:
This is the start routine for write.
Arguments:
pExchange - the exchange instance
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
ULONG StartEntryCount;
PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
PSMB_PSE_OE_READWRITE rw = &OrdinaryExchange->ReadWrite;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
PMDL OriginalDataMdl = LowIoContext->ParamsFor.ReadWrite.Buffer;
RxCaptureFcb;
RxCaptureFobx;
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
PMRX_SMB_FCB SmbFcb = MRxSmbGetFcbExtension(capFcb);
BOOLEAN SynchronousIo, IsPagingIo;
BOOLEAN WriteToTheEnd = FALSE;
UCHAR WriteCommand;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_Write\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -