📄 netroot.c
字号:
This routine signals the completion of a reconnect attempt
Arguments:
pCreateNetRootContext - the net root context
Return Value:
RXSTATUS - The return status for the operation
--*/
{
KeSetEvent(&pCreateNetRootContext->FinishEvent, IO_NETWORK_INCREMENT, FALSE );
}
NTSTATUS
SmbCeReconnect(
IN PMRX_V_NET_ROOT pVNetRoot)
/*++
Routine Description:
This routine reconnects, i.e, establishes a new session and tree connect to a previously
connected serverb share
Arguments:
pVNetRoot - the virtual net root instance.
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PSMBCEDB_SESSION_ENTRY pSessionEntry;
PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)pVNetRoot->Context;
PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext;
PAGED_CODE();
if ((pVNetRootContext != NULL) &&
(pVNetRootContext->Header.State == SMBCEDB_ACTIVE)) {
pServerEntry = pVNetRootContext->pServerEntry;
pSessionEntry = pVNetRootContext->pSessionEntry;
pNetRootEntry = pVNetRootContext->pNetRootEntry;
if ((pServerEntry->Header.State == SMBCEDB_ACTIVE) &&
(pSessionEntry->Header.State == SMBCEDB_ACTIVE) &&
(pNetRootEntry->Header.State == SMBCEDB_ACTIVE)) {
return STATUS_SUCCESS;
}
}
pCreateNetRootContext = (PMRX_CREATENETROOT_CONTEXT)
RxAllocatePoolWithTag(
NonPagedPool,
sizeof(MRX_CREATENETROOT_CONTEXT),
MRXSMB_NETROOT_POOLTAG);
if (pCreateNetRootContext != NULL) {
for (;;) {
pCreateNetRootContext->pVNetRoot = (PV_NET_ROOT)pVNetRoot;
pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
pCreateNetRootContext->Callback = SmbCeReconnectCallback;
pCreateNetRootContext->RxContext = NULL;
KeInitializeEvent(
&pCreateNetRootContext->FinishEvent,
SynchronizationEvent,
FALSE );
// Since this is a reconnect instance the net root initialization is not required
Status = SmbCeEstablishConnection(
pVNetRoot,
pCreateNetRootContext,
FALSE);
if (Status == STATUS_PENDING) {
// Wait for the construction to be completed.
KeWaitForSingleObject(
&pCreateNetRootContext->FinishEvent,
Executive,
KernelMode,
FALSE,
NULL);
Status = pCreateNetRootContext->VirtualNetRootStatus;
}
if (Status != STATUS_LINK_FAILED) {
break;
}
}
RxFreePool(pCreateNetRootContext);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return Status;
}
NTSTATUS
SmbCeEstablishConnection(
IN OUT PMRX_V_NET_ROOT pVNetRoot,
IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext,
IN BOOLEAN fInitializeNetRoot
)
/*++
Routine Description:
This routine triggers off the connection attempt for initial establishment of a
connection as well as subsequent reconnect attempts.
Arguments:
pVNetRoot - the virtual net root instance.
pCreateNetRootContext - the net root context for calling back
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PSMBCEDB_SESSION_ENTRY pSessionEntry;
PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
PAGED_CODE();
pVNetRootContext = SmbCeGetAssociatedVNetRootContext(pVNetRoot);
if (pVNetRootContext == NULL) {
Status = STATUS_BAD_NETWORK_PATH;
} else {
pServerEntry = pVNetRootContext->pServerEntry;
pSessionEntry = pVNetRootContext->pSessionEntry;
pNetRootEntry = pVNetRootContext->pNetRootEntry;
Status = STATUS_SUCCESS;
}
if (Status == STATUS_SUCCESS) {
//
// The following code initializes the NetRootEntry, VNetRootContext and
// the session entry under certain cases.
//
// The session entry to a doenlevel server needs to be initialized. This
// is not handled by the previous code since the session entry and the
// net root entry initialization can be combined into one exchange.
//
// The net root entry has not been initialized, i.e., this corresponds to
// the construction of the first SMBCE_V_NET_ROOT_CONTEXT instance for a
// given NetRootEntry.
//
// Subsequent SMBCE_V_NET_ROOT context constructions. In these cases the
// construction of each context must obtain a new TID
//
BOOLEAN fNetRootExchangeRequired;
fNetRootExchangeRequired = (
(pSessionEntry->Header.State != SMBCEDB_ACTIVE) ||
!BooleanFlagOn(
pVNetRootContext->Flags,
SMBCE_V_NET_ROOT_CONTEXT_FLAG_VALID_TID)
);
if (fNetRootExchangeRequired) {
// This is a tree connect open which needs to be triggered immediately.
PSMB_EXCHANGE pSmbExchange;
PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
pSmbExchange = SmbMmAllocateExchange(CONSTRUCT_NETROOT_EXCHANGE,NULL);
if (pSmbExchange != NULL) {
Status = SmbCeInitializeExchange(
&pSmbExchange,
NULL,
pVNetRoot,
CONSTRUCT_NETROOT_EXCHANGE,
&ConstructNetRootExchangeDispatch);
if (Status == STATUS_SUCCESS) {
pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pSmbExchange;
// Attempt to reconnect( In this case it amounts to establishing the
// connection/session)
pNetRootExchange->SmbCeFlags |= (SMBCE_EXCHANGE_ATTEMPT_RECONNECTS |
SMBCE_EXCHANGE_TIMED_RECEIVE_OPERATION);
// Initialize the continuation for resumption upon completion of the
// tree connetcion.
pNetRootExchange->NetRootCallback = pCreateNetRootContext->Callback;
pNetRootExchange->pCreateNetRootContext = pCreateNetRootContext;
pNetRootExchange->fInitializeNetRoot = fInitializeNetRoot;
// Initiate the exchange.
Status = SmbCeInitiateExchange(pSmbExchange);
if (Status != STATUS_PENDING) {
SmbCeDiscardExchangeWorkerThreadRoutine(pSmbExchange);
}
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
}
return Status;
}
//
// The net roots are normally constructed as part of some other exchange, i.e., the SMB for
// Tree connect is compounded with other operations. However, there is one situation in which
// the tree connect SMB needs to be sent by itself. This case refers to the prefix claim
// situation ( net use command ). This is handled by the construct net root exchange.
//
#define CONSTRUCT_NETROOT_BUFFER_SIZE (4096)
NTSTATUS
SmbConstructNetRootExchangeStart(
PSMB_EXCHANGE pExchange)
/*++
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:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
NTSTATUS RequestLockStatus = STATUS_UNSUCCESSFUL;
NTSTATUS ResponseLockStatus = STATUS_UNSUCCESSFUL;
PVOID pSmbActualBuffer;
PVOID pSmbBuffer;
UCHAR SmbCommand,LastCommandInHeader;
ULONG SmbLength;
PUCHAR pCommand;
PMDL pSmbRequestMdl,pSmbResponseMdl;
ULONG SmbMdlSize;
PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
PMRX_NET_ROOT pNetRoot = pExchange->SmbCeContext.pVNetRoot->pNetRoot;
PAGED_CODE();
pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pExchange;
ASSERT(pNetRootExchange->Type == CONSTRUCT_NETROOT_EXCHANGE);
if (pNetRoot->Type == NET_ROOT_PIPE) {
RxDbgTrace( 0, Dbg, ("pipe open to core server\n"));
return STATUS_NOT_SUPPORTED;
}
pSmbRequestMdl = pSmbResponseMdl = NULL;
pSmbActualBuffer = RxAllocatePoolWithTag(
PagedPool,
(CONSTRUCT_NETROOT_BUFFER_SIZE + TRANSPORT_HEADER_SIZE),
MRXSMB_NETROOT_POOLTAG);
if (pSmbActualBuffer != NULL) {
PSMBCE_SERVER pServer = SmbCeGetExchangeServer(pExchange);
(PCHAR) pSmbBuffer = (PCHAR) pSmbActualBuffer + TRANSPORT_HEADER_SIZE;
Status = SmbCeBuildSmbHeader(
pExchange,
pSmbBuffer,
CONSTRUCT_NETROOT_BUFFER_SIZE,
&SmbLength,
&LastCommandInHeader,
&pCommand);
// Ensure that the NET_ROOT/SESSION still needs to be constructed before
// sending it. It is likely that they were costructed by an earlier exchange
if (NT_SUCCESS(Status) &&
(SmbLength > sizeof(SMB_HEADER))) {
if (LastCommandInHeader != SMB_COM_TREE_CONNECT){
*pCommand = SMB_COM_NO_ANDX_COMMAND;
}
RxAllocateHeaderMdl(
pSmbBuffer,
SmbLength,
pSmbRequestMdl
);
pSmbResponseMdl = RxAllocateMdl(pSmbBuffer,CONSTRUCT_NETROOT_BUFFER_SIZE);
if ((pSmbRequestMdl != NULL) &&
(pSmbResponseMdl != NULL)) {
RxProbeAndLockHeaderPages(
pSmbRequestMdl,
KernelMode,
IoModifyAccess,
RequestLockStatus);
RxProbeAndLockPages(
pSmbResponseMdl,
KernelMode,
IoModifyAccess,
ResponseLockStatus);
if ((Status == STATUS_SUCCESS) &&
((Status = RequestLockStatus) == STATUS_SUCCESS) &&
((Status = ResponseLockStatus) == STATUS_SUCCESS)) {
pNetRootExchange->pSmbResponseMdl = pSmbResponseMdl;
pNetRootExchange->pSmbRequestMdl = pSmbRequestMdl;
pNetRootExchange->pSmbActualBuffer = pSmbActualBuffer;
pNetRootExchange->pSmbBuffer = pSmbBuffer;
Status = SmbCeTranceive(
pExchange,
(RXCE_SEND_PARTIAL | RXCE_SEND_SYNCHRONOUS),
pNetRootExchange->pSmbRequestMdl,
SmbLength);
RxDbgTrace( 0, Dbg, ("Net Root SmbCeTranceive returned %lx\n",Status));
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if ((Status != STATUS_PENDING) &&
(Status != STATUS_SUCCESS)) {
pNetRootExchange->pSmbResponseMdl = NULL;
pNetRootExchange->pSmbRequestMdl = NULL;
pNetRootExchange->pSmbActualBuffer = NULL;
pNetRootExchange->pSmbBuffer = NULL;
if (pSmbResponseMdl != NULL) {
if (ResponseLockStatus == STATUS_SUCCESS) {
MmUnlockPages(pSmbResponseMdl);
}
IoFreeMdl(pSmbResponseMdl);
}
if (pSmbRequestMdl != NULL) {
if (RequestLockStatus == STATUS_SUCCESS) {
RxUnlockHeaderPages(pSmbRequestMdl);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -