📄 transprt.c
字号:
Returns:
STATUS_SUCCESS if successful
Notes:
Currently, only connection oriented transports are handled.
In order to handle async. operations the uninitialization has to be coordinated
with the referencing mechanism. It is for this reason that this routine sets up
a rundown event and waits for it to be set.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
if (pCallbackRoutine == NULL &&
IoGetCurrentProcess() == RxGetRDBSSProcess()) {
SmbCepTearDownServerTransport(pServerEntry);
} else {
PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext;
pContext = RxAllocatePoolWithTag(
NonPagedPool,
sizeof(SMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT),
MRXSMB_TRANSPORT_POOLTAG);
if (pContext != NULL) {
KEVENT CompletionEvent;
RtlZeroMemory(
pContext,
sizeof(SMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT));
pContext->Status = STATUS_SUCCESS;
pContext->pServerEntry = pServerEntry;
if (pCallbackRoutine == NULL) {
KeInitializeEvent(
&CompletionEvent,
NotificationEvent,
FALSE);
pContext->pCompletionEvent = &CompletionEvent;
} else {
pContext->pCallbackContext = pCallbackContext;
pContext->pCompletionRoutine = pCallbackRoutine;
}
if (IoGetCurrentProcess() == RxGetRDBSSProcess()) {
SmbCeTearDownServerTransport(pContext);
} else {
Status = RxPostToWorkerThread(
MRxSmbDeviceObject,
CriticalWorkQueue,
&pContext->WorkQueueItem,
SmbCeTearDownServerTransport,
pContext);
}
if (Status == STATUS_SUCCESS) {
if (pCallbackRoutine == NULL) {
KeWaitForSingleObject(
&CompletionEvent,
Executive,
KernelMode,
FALSE,
NULL );
} else {
Status = STATUS_PENDING;
}
} else {
RxFreePool(pContext);
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
return Status;
}
VOID
SmbCeCompleteUninitializeServerTransport(
PSMBCEDB_SERVER_ENTRY pServerEntry)
{
// in case of async uninitialize server transport, an additional reference count of
// server entry should be taken so that uninitialize server transport will not be
// called once again from tear down server entry if its reference count comes to 0
// before uninitialize server transport is done.
SmbCeDereferenceServerEntry(pServerEntry);
}
NTSTATUS
SmbCeInitiateDisconnect(
PSMBCEDB_SERVER_ENTRY pServerEntry)
/*++
Routine Description:
This routine initiates the TDI disconnect
Arguments:
pServerEntry - the server entry instance in the database
Return Value:
STATUS_SUCCESS - the server transport construction has been finalized.
Other Status codes correspond to error situations.
Notes:
--*/
{
NTSTATUS Status;
PSMBCE_SERVER_TRANSPORT pTransport;
ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
Status = SmbCeReferenceServerTransport(&pServerEntry->pTransport);
if (Status == STATUS_SUCCESS) {
Status = (pServerEntry->pTransport->pDispatchVector->InitiateDisconnect)(
pServerEntry->pTransport);
if (Status != STATUS_SUCCESS) {
RxDbgTrace(0, Dbg, ("SmbCeInitiateDisconnect : Status %lx\n",Status));
}
SmbCeDereferenceServerTransport(&pServerEntry->pTransport);
}
return STATUS_SUCCESS;
}
LONG Initializes[SENTINEL_EXCHANGE] = {0,0,0,0};
LONG Uninitializes[SENTINEL_EXCHANGE] = {0,0,0,0};
NTSTATUS
SmbCeInitializeExchangeTransport(
PSMB_EXCHANGE pExchange)
/*++
Routine Description:
This routine initializes the transport associated with the exchange
Arguments:
pExchange - the exchange to be initialized
Return Value:
STATUS_SUCCESS - the exchange transport initialization has been finalized.
Other Status codes correspond to error situations.
Notes:
--*/
{
NTSTATUS Status;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PAGED_CODE();
pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
Status = pExchange->SmbStatus;
if (Status == STATUS_SUCCESS) {
PSMBCE_SERVER_TRANSPORT *pTransportPointer;
pTransportPointer = &pServerEntry->pTransport;
if (*pTransportPointer != NULL) {
Status = SmbCeReferenceServerTransport(pTransportPointer);
if (Status == STATUS_SUCCESS) {
Status = ((*pTransportPointer)->pDispatchVector->InitializeExchange)(
*pTransportPointer,
pExchange);
if (Status == STATUS_SUCCESS) {
ULONG TransportInitialized;
InterlockedIncrement(&Initializes[pExchange->Type]);
TransportInitialized = InterlockedExchange(&pExchange->ExchangeTransportInitialized,1);
ASSERT(TransportInitialized == 0);
} else {
SmbCeDereferenceServerTransport(pTransportPointer);
}
}
} else {
Status = STATUS_CONNECTION_DISCONNECTED;
}
}
return Status;
}
NTSTATUS
SmbCeUninitializeExchangeTransport(
PSMB_EXCHANGE pExchange)
/*++
Routine Description:
This routine uniinitializes the transport associated with the exchange
Arguments:
pExchange - the exchange to be initialized
Return Value:
STATUS_SUCCESS - the exchange transport initialization has been finalized.
Other Status codes correspond to error situations.
Notes:
--*/
{
NTSTATUS Status;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PAGED_CODE();
pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
if (InterlockedExchange(&pExchange->ExchangeTransportInitialized,0)==1) {
PSMBCE_SERVER_TRANSPORT *pTransportPointer;
pTransportPointer = &pServerEntry->pTransport;
if (*pTransportPointer != NULL) {
Status = ((*pTransportPointer)->pDispatchVector->UninitializeExchange)(
*pTransportPointer,
pExchange);
SmbCeDereferenceServerTransport(pTransportPointer);
InterlockedIncrement(&Uninitializes[pExchange->Type]);
return Status;
} else {
return STATUS_CONNECTION_DISCONNECTED;
}
} else {
return pExchange->SmbStatus;
}
}
NTSTATUS
SmbCepReferenceServerTransport(
PSMBCE_SERVER_TRANSPORT *pServerTransportPointer)
/*++
Routine Description:
This routine references the transport associated with a server entry
Arguments:
pServerEntry - the server entry instance in the database
Return Value:
STATUS_SUCCESS - the server transport was successfully referenced
Other Status codes correspond to error situations.
Notes:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
SmbCeAcquireSpinLock();
if (*pServerTransportPointer != NULL &&
(*pServerTransportPointer)->State == SMBCEDB_ACTIVE) {
InterlockedIncrement(&(*pServerTransportPointer)->SwizzleCount);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_CONNECTION_DISCONNECTED;
}
SmbCeReleaseSpinLock();
return Status;
}
NTSTATUS
SmbCepDereferenceServerTransport(
PSMBCE_SERVER_TRANSPORT *pServerTransportPointer)
/*++
Routine Description:
This routine dereferences the transport associated with a server entry
Arguments:
pServerTransportPointer - the server entry transport instance pointer
Return Value:
STATUS_SUCCESS - the server transport was successfully dereferenced
Other Status codes correspond to error situations.
Notes:
On finalization this routine sets the event to enable the process awaiting
tear down to restart. It also tears down the associated server transport
instance.
As a side effect the pointer value is set to NULL under the protection of a
spin lock.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
SmbCeAcquireSpinLock();
if (*pServerTransportPointer != NULL) {
LONG FinalRefCount;
PKEVENT pRundownEvent;
PSMBCE_SERVER_TRANSPORT pServerTransport;
pServerTransport = *pServerTransportPointer;
FinalRefCount = InterlockedDecrement(&pServerTransport->SwizzleCount);
if (FinalRefCount == 0) {
pServerTransport->State = SMBCEDB_INVALID;
// transport is set to NULL before the spinlock is release so that no
// exchange should reference it after it's been torn down
*pServerTransportPointer = NULL;
pRundownEvent = pServerTransport->pRundownEvent;
}
SmbCeReleaseSpinLock();
if (FinalRefCount == 0) {
if (IoGetCurrentProcess() == RxGetRDBSSProcess()) {
pServerTransport->pDispatchVector->TearDown(pServerTransport);
} else {
Status = RxDispatchToWorkerThread(
MRxSmbDeviceObject,
CriticalWorkQueue,
pServerTransport->pDispatchVector->TearDown,
pServerTransport);
}
}
} else {
SmbCeReleaseSpinLock();
Status = STATUS_CONNECTION_DISCONNECTED;
}
return Status;
}
NTSTATUS
SmbCepReferenceTransport(
PSMBCE_TRANSPORT pTransport)
/*++
Routine Description:
This routine references the transport instance
Arguments:
pTransport - the transport instance
Return Value:
STATUS_SUCCESS - the server transport was successfully referenced
Other Status codes correspond to error situations.
Notes:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
if (pTransport != NULL) {
SmbCeAcquireSpinLock();
if (pTransport->Active) {
InterlockedIncrement(&pTransport->SwizzleCount);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_UNSUCCESSFUL;
}
SmbCeReleaseSpinLock();
} else {
Status = STATUS_INVALID_PARAMETER;
}
return Status;
}
NTSTATUS
SmbCepDereferenceTransport(
PSMBCE_TRANSPORT pTransport)
/*++
Routine Description:
This routine dereferences the transport
Arguments:
pTransport - the transport instance
Return Value:
STATUS_SUCCESS - the server transport was successfully dereferenced
Other Status codes correspond to error situations.
Notes:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN AttachToSystemProcess = FALSE;
KAPC_STATE ApcState;
PAGED_CODE();
if (pTransport != NULL) {
LONG FinalRefCount;
FinalRefCount = InterlockedDecrement(&pTransport->SwizzleCount);
if (FinalRefCount == 0) {
SmbCeRemoveTransport(pTransport);
if (IoGetCurrentProcess() != RxGetRDBSSProcess()) {
KeStackAttachProcess(RxGetRDBSSProcess(),&ApcState);
AttachToSystemProcess = TRUE;
}
RxCeTearDownAddress(&pTransport->RxCeAddress);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -