📄 openclos.c
字号:
BOOLEAN CreateWithEasSidsOrLongName = FALSE;
ULONG DialectFlags;
PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
PNT_CREATE_PARAMETERS CreateParameters = &RxContext->Create.NtCreateParameters;
ULONG Disposition = CreateParameters->Disposition;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbCreate\n", 0 ));
ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
RxDbgTrace( 0, Dbg, (" Attempt to open %wZ\n", RemainingName ));
if (FlagOn( capFcb->FcbState, FCB_STATE_PAGING_FILE )) {
return STATUS_NOT_IMPLEMENTED;
}
if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_STATUS) &&
MRxSmbIsStreamFile(RemainingName,NULL)) {
// The Samba server return file system type NTFS but doesn't support stream
return STATUS_OBJECT_PATH_NOT_FOUND;
}
RxContext->Create.NtCreateParameters.CreateOptions &= 0xfffff;
if( NetRoot->Type == NET_ROOT_PRINT ) {
return STATUS_OBJECT_NAME_NOT_FOUND;
}
// we cannot have a file cached on a write only handle. so we have to behave a little
// differently if this is a write-only open. remember this in the smbsrvopen
if ( ((CreateParameters->DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA)) == 0) &&
((CreateParameters->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0)
) {
SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_WRITE_ONLY_HANDLE);
SrvOpen->Flags |= SRVOPEN_FLAG_DONTUSE_WRITE_CACHING;
}
//the way that SMBs work, there is no buffering effect if we open for attributes-only
//so set that up immediately.
if ((CreateParameters->DesiredAccess
& ~(FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE))
== 0 ){
SetFlag(SrvOpen->Flags,SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE);
}
if (NetRoot->Type == NET_ROOT_MAILSLOT) {
return STATUS_NOT_SUPPORTED;
}
if (NetRoot->Type == NET_ROOT_PIPE) {
return STATUS_NOT_SUPPORTED;
}
// Get the control struct for the file not found name cache.
//
pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
// assume Reconnection to be trivially successful
Status = STATUS_SUCCESS;
CreateWithEasSidsOrLongName = MRxSmbIsCreateWithEasSidsOrLongName(RxContext,&DialectFlags);
if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
CreateWithEasSidsOrLongName = FALSE;
}
ReconnectRequired = IsReconnectRequired((PMRX_SRV_CALL)SrvCall);
//get rid of nonEA guys right now
if (RxContext->Create.EaLength && !FlagOn(DialectFlags,DF_SUPPORTEA)) {
RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
Status = STATUS_NOT_SUPPORTED;
goto FINALLY;
}
if (ReconnectRequired || !CreateWithEasSidsOrLongName) {
Status = __SmbPseCreateOrdinaryExchange(
RxContext,
SrvOpen->pVNetRoot,
SMBPSE_OE_FROM_CREATE,
SmbPseExchangeStart_Create,
&OrdinaryExchange);
if (Status != STATUS_SUCCESS) {
RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
goto FINALLY;
}
OrdinaryExchange->Create.CreateWithEasSidsOrLongName = CreateWithEasSidsOrLongName;
// For Creates, the resources need to be reacquired after sending an
// SMB; so, do not hold onto the MIDS till finalization; instead give the MID back
// right away
OrdinaryExchange->SmbCeFlags &= ~SMBCE_EXCHANGE_REUSE_MID;
OrdinaryExchange->SmbCeFlags |= (SMBCE_EXCHANGE_ATTEMPT_RECONNECTS |
SMBCE_EXCHANGE_TIMED_RECEIVE_OPERATION);
OrdinaryExchange->pSmbCeSynchronizationEvent = &RxContext->SyncEvent;
// drop the resource before you go in!
// the start routine will reacquire it on the way out.....
RxReleaseFcbResourceInMRx( capFcb );
Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
ASSERT((Status != STATUS_SUCCESS) || RxIsFcbAcquiredExclusive( capFcb ));
OrdinaryExchange->pSmbCeSynchronizationEvent = NULL;
SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
if (!RxIsFcbAcquiredExclusive(capFcb)) {
ASSERT(!RxIsFcbAcquiredShared(capFcb));
RxAcquireExclusiveFcbResourceInMRx( capFcb );
}
}
if (CreateWithEasSidsOrLongName && (Status == STATUS_SUCCESS)) {
Status = MRxSmbCreateWithEasSidsOrLongName(RxContext);
}
// There are certain downlevel servers(OS/2 servers) that return the error
// STATUS_OPEN_FAILED. This is a context sensitive error code that needs to
// be interpreted in conjunction with the disposition specified for the OPEN.
if (Status == STATUS_OPEN_FAILED) {
switch (Disposition) {
//
// If we were asked to create the file, and got OPEN_FAILED,
// this implies that the file already exists.
//
case FILE_CREATE:
Status = STATUS_OBJECT_NAME_COLLISION;
break;
//
// If we were asked to open the file, and got OPEN_FAILED,
// this implies that the file doesn't exist.
//
case FILE_OPEN:
case FILE_SUPERSEDE:
case FILE_OVERWRITE:
Status = STATUS_OBJECT_NAME_NOT_FOUND;
break;
//
// If there is an error from either FILE_OPEN_IF or
// FILE_OVERWRITE_IF, it indicates the user is trying to
// open a file on a read-only share, so return the
// correct error for that.
//
case FILE_OPEN_IF:
case FILE_OVERWRITE_IF:
Status = STATUS_NETWORK_ACCESS_DENIED;
break;
default:
break;
}
}
FINALLY:
ASSERT(Status != (STATUS_PENDING));
if (Status == STATUS_SUCCESS) {
SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SUCCESSFUL_OPEN);
}
RxDbgTrace(-1, Dbg, ("MRxSmbCreate exit with status=%08lx\n", Status ));
RxLog(("MRxSmbCreate exits %lx\n", Status));
return(Status);
}
NTSTATUS
MRxSmbDeferredCreate (
IN OUT PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine constructs a rxcontext from saved information and then calls
MRxSmbCreate.
Arguments:
RxContext - the RDBSS context
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
RxCaptureFcb;
RxCaptureFobx;
PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
PMRX_SMB_DEFERRED_OPEN_CONTEXT DeferredOpenContext = smbSrvOpen->DeferredOpenContext;
PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
PRX_CONTEXT OpenRxContext,oc;
PAGED_CODE();
if ((!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)
|| !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN))) {
Status = STATUS_SUCCESS;
goto FINALLY;
}
if (DeferredOpenContext == NULL) {
if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_CLOSED)) {
Status = STATUS_FILE_CLOSED;
goto FINALLY;
} else {
DbgBreakPoint();
}
}
ASSERT(RxIsFcbAcquiredExclusive(capFcb));
SmbCeAcquireResource();
if (!smbSrvOpen->DeferredOpenInProgress) {
PLIST_ENTRY pListHead;
PLIST_ENTRY pListEntry;
smbSrvOpen->DeferredOpenInProgress = TRUE;
InitializeListHead(&smbSrvOpen->DeferredOpenSyncContexts);
SmbCeReleaseResource();
OpenRxContext = RxAllocatePoolWithTag(NonPagedPool,
sizeof(RX_CONTEXT),
MRXSMB_RXCONTEXT_POOLTAG);
if (OpenRxContext==NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
} else {
RtlZeroMemory(
OpenRxContext,
sizeof(RX_CONTEXT));
RxInitializeContext(
NULL,
RxContext->RxDeviceObject,
0,
OpenRxContext );
oc = OpenRxContext;
oc->pFcb = capFcb;
oc->pFobx = capFobx;
oc->NonPagedFcb = RxContext->NonPagedFcb;
oc->MajorFunction = IRP_MJ_CREATE;
oc->pRelevantSrvOpen = SrvOpen;
oc->Create.pVNetRoot = SrvOpen->pVNetRoot;
oc->Create.pNetRoot = oc->Create.pVNetRoot->pNetRoot;
oc->Create.pSrvCall = oc->Create.pNetRoot->pSrvCall;
oc->Flags = DeferredOpenContext->RxContextFlags;
oc->Flags |= RX_CONTEXT_FLAG_MINIRDR_INITIATED|RX_CONTEXT_FLAG_WAIT|RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK;
oc->Create.Flags = DeferredOpenContext->RxContextCreateFlags;
oc->Create.NtCreateParameters = DeferredOpenContext->NtCreateParameters;
Status = MRxSmbCreate(oc);
if (Status==STATUS_SUCCESS) {
if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
MRxSmbIncrementSrvOpenCount(pServerEntry,SrvOpen);
} else {
ASSERT(smbSrvOpen->NumOfSrvOpenAdded);
}
ClearFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
}
RxLog(("DeferredOpen %lx %lx %lx %lx\n", capFcb, capFobx, RxContext, Status));
ASSERT(oc->ReferenceCount==1);
RxFreePool(oc);
}
if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_CLOSED) ||
FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_ORPHANED)) {
RxFreePool(smbSrvOpen->DeferredOpenContext);
smbSrvOpen->DeferredOpenContext = NULL;
RxDbgTrace(0, Dbg, ("Free deferred open context for file %wZ %lX\n",GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),smbSrvOpen));
}
SmbCeAcquireResource();
smbSrvOpen->DeferredOpenInProgress = FALSE;
pListHead = &smbSrvOpen->DeferredOpenSyncContexts;
pListEntry = pListHead->Flink;
while (pListEntry != pListHead) {
PDEFERRED_OPEN_SYNC_CONTEXT pWaitingContext;
pWaitingContext = (PDEFERRED_OPEN_SYNC_CONTEXT)CONTAINING_RECORD(
pListEntry,
DEFERRED_OPEN_SYNC_CONTEXT,
ListHead);
pListEntry = pListEntry->Flink;
RemoveHeadList(&pWaitingContext->ListHead);
pWaitingContext->Status = Status;
//DbgPrint("Signal RxContext %x after deferred open\n",pWaitingContext->RxContext);
RxSignalSynchronousWaiter(pWaitingContext->RxContext);
}
SmbCeReleaseResource();
} else {
DEFERRED_OPEN_SYNC_CONTEXT WaitingContext;
BOOLEAN AcquireExclusive = RxIsFcbAcquiredExclusive(capFcb);
BOOLEAN AcquireShare = RxIsFcbAcquiredShared(capFcb) > 0;
// put the RxContext on the waiting list
WaitingContext.RxContext = RxContext;
InitializeListHead(&WaitingContext.ListHead);
InsertTailList(
&smbSrvOpen->DeferredOpenSyncContexts,
&WaitingContext.ListHead);
SmbCeReleaseResource();
if (AcquireExclusive || AcquireShare) {
RxReleaseFcbResourceInMRx( capFcb );
}
RxWaitSync(RxContext);
Status = WaitingContext.Status;
KeInitializeEvent(
&RxContext->SyncEvent,
SynchronizationEvent,
FALSE);
if (AcquireExclusive) {
RxAcquireExclusiveFcbResourceInMRx( capFcb );
} else if (AcquireShare) {
RxAcquireSharedFcbResourceInMRx( capFcb );
}
}
FINALLY:
return Status;
}
NTSTATUS
MRxSmbCollapseOpen(
IN OUT PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine collapses a open locally
Arguments:
RxContext - the RDBSS context
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
RxCaptureFcb;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -