📄 openclos.c
字号:
//proceed with the stuff because we know here that the name fits
MRxSmbStuffSMB(StufferState,
BooleanFlagOn(pServer->DialectFlags,DF_UNICODE)?"u!":"z!",
RemainingName);
MRxSmbDumpStufferState (700,"SMB w/ NTOPEN&X after stuffing",StufferState);
FINALLY:
RxDbgTraceUnIndent(-1,Dbg);
return(Status);
}
NTSTATUS
MRxSmbBuildOpenAndX (
PSMBSTUFFER_BUFFER_STATE StufferState,
PMRXSMB_CREATE_PARAMETERS smbcp
)
/*++
Routine Description:
This builds an OpenAndX SMB. we don't have to worry about login id and such
since that is done by the connection engine....pretty neat huh? all we have to do
is to format up the bits
Arguments:
StufferState - the state of the smbbuffer from the stuffer's point of view
Return Value:
RXSTATUS
SUCCESS
NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
Notes:
--*/
{
NTSTATUS Status;
PRX_CONTEXT RxContext = StufferState->RxContext;
PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
PSMB_EXCHANGE Exchange = StufferState->Exchange;
RxCaptureFcb;
PSMBCE_SERVER pServer;
PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
USHORT smbDisposition;
USHORT smbSharingMode;
USHORT smbAttributes;
ULONG smbFileSize;
USHORT smbOpenMode;
USHORT OpenAndXFlags = (SMB_OPEN_QUERY_INFORMATION);
USHORT SearchAttributes = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN;
LARGE_INTEGER CurrentTime;
ULONG SecondsSince1970;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbBuildOpenAndX\n", 0 ));
pServer = SmbCeGetExchangeServer(Exchange);
smbDisposition = MRxSmbMapDisposition(cp->Disposition);
smbSharingMode = MRxSmbMapShareAccess(((USHORT)cp->ShareAccess));
smbAttributes = MRxSmbMapFileAttributes(cp->FileAttributes);
smbFileSize = cp->AllocationSize.LowPart;
smbOpenMode = MRxSmbMapDesiredAccess(cp->DesiredAccess);
smbSharingMode |= smbOpenMode;
if (cp->CreateOptions & FILE_WRITE_THROUGH) {
smbSharingMode |= SMB_DA_WRITE_THROUGH;
}
//lanman10 servers apparently don't like to get the time passed in.......
if (FlagOn(pServer->DialectFlags,DF_LANMAN20)) {
KeQuerySystemTime(&CurrentTime);
MRxSmbTimeToSecondsSince1970(&CurrentTime,
pServer,
&SecondsSince1970);
} else {
SecondsSince1970 = 0;
}
COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_Never,
SMB_COM_OPEN_ANDX, SMB_REQUEST_SIZE(OPEN_ANDX),
NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(4,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
0,0,0,0 STUFFERTRACE(Dbg,'FC'))
);
MRxSmbStuffSMB (StufferState,
"XwwwwdwDddB",
// X UCHAR WordCount; // Count of parameter words = 15
// . UCHAR AndXCommand; // Secondary (X) command; 0xFF = none
// . UCHAR AndXReserved; // Reserved (must be 0)
// . _USHORT( AndXOffset ); // Offset to next command WordCount
OpenAndXFlags, // w _USHORT( Flags ); // Additional information: bit set-
// // 0 - return additional info
// // 1 - set single user total file lock
// // 2 - server notifies consumer of
// // actions which may change file
smbSharingMode, // w _USHORT( DesiredAccess ); // File open mode
SearchAttributes, // w _USHORT( SearchAttributes );
smbAttributes, // w _USHORT( FileAttributes );
SecondsSince1970, // d _ULONG( CreationTimeInSeconds );
smbDisposition, // w _USHORT( OpenFunction );
// D _ULONG( AllocationSize ); // Bytes to reserve on create or truncate
SMB_OFFSET_CHECK(OPEN_ANDX,AllocationSize)
smbFileSize,
0xffffffff, // d _ULONG( Timeout ); // Max milliseconds to wait for resource
0, // d _ULONG( Reserved ); // Reserved (must be 0)
SMB_WCT_CHECK(15) 0 // B _USHORT( ByteCount ); // Count of data bytes; min = 1
// UCHAR Buffer[1]; // File name
);
//proceed with the stuff because we know here that the name fits
MRxSmbStuffSMB (StufferState,"z!", RemainingName);
MRxSmbDumpStufferState (700,"SMB w/ OPEN&X after stuffing",StufferState);
FINALLY:
RxDbgTraceUnIndent(-1,Dbg);
return(Status);
}
typedef enum _SMBPSE_CREATE_METHOD {
CreateAlreadyDone,
CreateUseCore,
CreateUseNT
} SMBPSE_CREATE_METHOD;
NTSTATUS
SmbPseExchangeStart_Create(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
)
/*++
Routine Description:
This is the start routine for net root construction exchanges. This initiates the
construction of the appropriate SMB's if required.
Arguments:
pExchange - the exchange instance
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status = (STATUS_NOT_IMPLEMENTED);
NTSTATUS SetupStatus = STATUS_SUCCESS;
PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
SMBPSE_CREATE_METHOD CreateMethod = CreateAlreadyDone;
PSMBCE_SERVER pServer;
ULONG DialectFlags;
RxCaptureFcb;
PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
PBOOLEAN MustRegainExclusiveResource = &OrdinaryExchange->Create.MustRegainExclusiveResource;
BOOLEAN CreateWithEasSidsOrLongName = OrdinaryExchange->Create.CreateWithEasSidsOrLongName;
BOOLEAN fRetryCore = FALSE;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_Create\n", 0 ));
ASSERT_ORDINARY_EXCHANGE(OrdinaryExchange);
pServer = SmbCeGetExchangeServer(OrdinaryExchange);
DialectFlags = pServer->DialectFlags;
COVERED_CALL(MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0)));
*MustRegainExclusiveResource = TRUE;
if (!FlagOn(DialectFlags,DF_NT_SMBS)) {
OEM_STRING OemString;
PUNICODE_STRING PathName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
if (PathName->Length != 0) {
Status = RtlUnicodeStringToOemString(&OemString, PathName, TRUE);
if (!NT_SUCCESS(Status)) {
goto FINALLY;
}
//
// If we are canonicalizing as FAT, use FAT rules, otherwise use
// HPFS rules.
//
if (!FlagOn(DialectFlags,DF_LANMAN20)) {
if (!FsRtlIsFatDbcsLegal(OemString, FALSE, TRUE, TRUE)) {
RtlFreeOemString(&OemString);
Status = STATUS_OBJECT_NAME_INVALID;
goto FINALLY;
}
} else if (!FsRtlIsHpfsDbcsLegal(OemString, FALSE, TRUE, TRUE)) {
RtlFreeOemString(&OemString);
Status = STATUS_OBJECT_NAME_INVALID;
goto FINALLY;
}
RtlFreeOemString(&OemString);
}
}
if (StufferState->PreviousCommand != SMB_COM_NO_ANDX_COMMAND) {
// we have a latent session setup /tree connect command
//the status of the embedded header commands is passed back in the flags.
SetupStatus = SmbPseOrdinaryExchange(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
SMBPSE_OETYPE_LATENT_HEADEROPS
);
if(SetupStatus != STATUS_SUCCESS) {
Status = SetupStatus;
goto FINALLY;
}
// Turn off reconnect attempts now that we have successfully established
// the session and net root.
OrdinaryExchange->SmbCeFlags &= ~(SMBCE_EXCHANGE_ATTEMPT_RECONNECTS);
COVERED_CALL(MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0)));
}
if (!CreateWithEasSidsOrLongName) {
PUNICODE_STRING AlreadyPrefixedName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
PMRXSMB_CREATE_PARAMETERS SmbCp = &OrdinaryExchange->Create.SmbCp;
PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
USHORT mappedOpenMode;
MRxSmbAdjustCreateParameters(RxContext,SmbCp);
mappedOpenMode = MRxSmbMapDesiredAccess(cp->DesiredAccess);
if ((!MRxSmbForceNoNtCreate)
&& FlagOn(DialectFlags,DF_NT_SMBS)) {
BOOLEAN SecurityIsNULL =
(cp->SecurityContext == NULL) ||
(cp->SecurityContext->AccessState == NULL) ||
(cp->SecurityContext->AccessState->SecurityDescriptor == NULL);
CreateMethod = CreateUseNT;
//now catch the cases where we want to pseudoopen the file
if ( MRxSmbDeferredOpensEnabled &&
!FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MINIRDR_INITIATED) &&
(capFcb->pNetRoot->Type == NET_ROOT_DISK) &&
SecurityIsNULL) {
ASSERT( RxContext->CurrentIrp != 0 );
if ((cp->Disposition==FILE_OPEN) &&
!BooleanFlagOn(cp->CreateOptions, FILE_OPEN_FOR_BACKUP_INTENT) &&
(MustBeDirectory(cp->CreateOptions) ||
!(cp->DesiredAccess & ~(SYNCHRONIZE | DELETE | FILE_READ_ATTRIBUTES)))){
// NT apps expect that you will not succeed the create and then fail the attribs;
// if we had some way of identifying win32 apps then we could defer these (except
// for DFS). since we have no way to get that information (and don't even have
// a good SMB to send..........)
// we don't need to send the open for DELETE and FILE_READ_ATTRIBUTES requests since
// there are path basied SMB operations.
// we can also pseudoopen directories for file_open at the root of the
// share but otherwise we have to at least check that the directory
// exists. we might have to push out the open later. BTW, we wouldn't be
// in here if the name was too long for a GFA or CheckPath
Status = MRxSmbPseudoOpenTailFromFakeGFAResponse(
OrdinaryExchange,
MustBeDirectory(cp->CreateOptions)?FileTypeDirectory:FileTypeFile);
if (Status == STATUS_SUCCESS && AlreadyPrefixedName->Length > 0) {
// send query path information to make sure the file exists on the server
Status = MRxSmbQueryFileInformationFromPseudoOpen(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
if (Status == STATUS_SUCCESS) {
if (MustBeDirectory(cp->CreateOptions) &&
!OrdinaryExchange->Create.FileInfo.Standard.Directory) {
Status = STATUS_NOT_A_DIRECTORY;
}
}
if (Status != STATUS_SUCCESS) {
RxFreePool(smbSrvOpen->DeferredOpenContext);
smbSrvOpen->DeferredOpenContext = NULL;
}
}
CreateMethod = CreateAlreadyDone;
}
}
//if no pseudoopen case was hit, do a real open
if (CreateMethod == CreateUseNT) {
//use NT_CREATE&X
COVERED_CALL(MRxSmbBuildNtCreateAndX(StufferState,SmbCp));
Status = SmbPseOrdinaryExchange(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
SMBPSE_OETYPE_CREATE
);
if (Status == STATUS_SUCCESS && RxContext->pFobx == NULL) {
Status = STATUS_INVALID_NETWORK_RESPONSE;
}
if ((Status == STATUS_SUCCESS) && (cp->Disposition == FILE_OPEN)) {
MRxSmbAdjustReturnedCreateAction(RxContext);
}
}
} else if (FlagOn(DialectFlags, DF_LANMAN10) &&
(mappedOpenMode != ((USHORT)-1)) &&
!MustBeDirectory(cp->CreateOptions)) {
if (MRxSmbDeferredOpensEnabled &&
capFcb->pNetRoot->Type == NET_ROOT_DISK &&
!FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MINIRDR_INITIATED) &&
(cp->Disposition==FILE_OPEN) &&
((cp->DesiredAccess & ~(SYNCHRONIZE | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) == 0) ){
// we don't need to send the open for DELETE and FILE_READ_ATTRIBUTES requests since
// there are path basied SMB operations.
// we should do pseudo open for FILE_WRITE_ATTRIBUTES. Othewise the server will return
// sharing violation
// send query path information to make sure the file exists on the server
Status = MRxSmbPseudoOpenTailFromFakeGFAResponse(
OrdinaryExchange,
MustBeDirectory(cp->CreateOptions)?FileTypeDirectory:FileTypeFile);
if (Status == STATUS_SUCCESS && AlreadyPrefixedName->Length > 0) {
Status = MRxSmbQueryFileInformationFromPseudoOpen(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
if (Status != STATUS_SUCCESS) {
RxFreePool(smbSrvOpen->DeferredOpenContext);
smbSrvOpen->DeferredOpenContext = NULL;
}
}
CreateMethod = CreateAlreadyDone;
} else {
//use OPEN&X
COVERED_CALL(MRxSmbBuildOpenAndX(StufferState,SmbCp));
Status = SmbPseOrdinaryExchange(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
SMBPSE_OETYPE_CREATE
);
if (Status == STATUS_ACCESS_DENIED && !FlagOn(DialectFlags,DF_NT_SMBS)) {
CreateMethod = CreateUseCore;
fRetryCore = TRUE;
}
}
} else {
CreateMethod = CreateUseCore;
}
if (CreateMethod == CreateUseCore) {
Status = MRxSmbDownlevelCreate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
// put back the real error code if we are retrying open&x
if ((Status != STATUS_SUCCESS) && fRetryCore)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -