📄 transprt.c
字号:
--*/
{
KIRQL SavedIrql;
PLIST_ENTRY pEntry;
PSMBCE_TRANSPORT pTransport;
BOOLEAN Found = FALSE;
PSMBCE_TRANSPORT_ARRAY pTransportArray;
PAGED_CODE();
pTransportArray = SmbCeReferenceTransportArray();
if (pTransportArray == NULL) {
RxDbgTrace(0, Dbg, ("SmbCeFindTransport : Transport not available.\n"));
return NULL;
}
if (pTransportArray != NULL) {
ULONG i;
for (i=0;i<pTransportArray->Count;i++) {
pTransport = pTransportArray->SmbCeTransports[i];
if (RtlEqualUnicodeString(
&pTransport->RxCeTransport.Name,
pTransportName,
TRUE)) {
SmbCeReferenceTransport(pTransport);
Found = TRUE;
break;
}
}
}
if (!Found) {
pTransport = NULL;
}
SmbCeDereferenceTransportArray(pTransportArray);
return pTransport;
}
VOID
SmbCepTearDownServerTransport(
PSMBCEDB_SERVER_ENTRY pServerEntry)
/*++
Routine Description:
This routine uninitializes the transport information corresponding to a server
Arguments:
pServerEntry - the server entry instance in the database
Notes:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
SMBCEDB_SERVER_TYPE ServerType = SmbCeGetServerType(pServerEntry);
BOOLEAN WaitForTransportRundown = FALSE;
BOOLEAN TearDown = FALSE;
SmbCeAcquireSpinLock();
if (!pServerEntry->IsTransportDereferenced) {
// ServerEntry takes only one reference count of transport, which should only be
// dereferenced once when it comes to tear down transport. Multiple dereference called
// from construct server transport and PNP unbind transport needs to be prevented.
pServerEntry->IsTransportDereferenced = TRUE;
TearDown = TRUE;
KeInitializeEvent(&pServerEntry->TransportRundownEvent,NotificationEvent,FALSE);
if (pServerEntry->pTransport != NULL) {
pServerEntry->pTransport->State = SMBCEDB_MARKED_FOR_DELETION;
pServerEntry->pTransport->pRundownEvent = &pServerEntry->TransportRundownEvent;
WaitForTransportRundown = TRUE;
}
} else {
if (pServerEntry->pTransport != NULL) {
WaitForTransportRundown = TRUE;
}
}
SmbCeReleaseSpinLock();
if (TearDown) {
if (pServerEntry->pTransport != NULL) {
SmbCeDereferenceServerTransport(&pServerEntry->pTransport);
}
}
if (WaitForTransportRundown) {
KeWaitForSingleObject(
&pServerEntry->TransportRundownEvent,
Executive,
KernelMode,
FALSE,
NULL );
}
}
VOID
SmbCeTearDownServerTransport(
IN OUT PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext)
/*++
Routine Description:
This routine tears down the server transport instance
Arguments:
pContext - the server transport construction context
Notes:
--*/
{
SmbCepTearDownServerTransport(pContext->pServerEntry);
if (pContext->pCompletionEvent != NULL) {
ASSERT(pContext->pCallbackContext == NULL);
ASSERT(pContext->pCompletionRoutine == NULL);
KeSetEvent(
pContext->pCompletionEvent,
0,
FALSE );
} else if (pContext->pCallbackContext != NULL) {
ASSERT(pContext->pCompletionEvent == NULL);
(pContext->pCompletionRoutine)(pContext->pCallbackContext);
}
RxFreePool(pContext);
}
VOID
SmbCepUpdateTransportConstructionState(
IN OUT PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext)
{
SMBCE_SERVER_TRANSPORT_CONSTRUCTION_STATE State;
if (pContext->Status == STATUS_SUCCESS) {
if (pContext->TransportsToBeConstructed & SMBCE_STT_VC) {
pContext->TransportsToBeConstructed &= ~SMBCE_STT_VC;
State = SmbCeServerVcTransportConstructionBegin;
} else {
State = SmbCeServerTransportConstructionEnd;
}
} else {
State = SmbCeServerTransportConstructionEnd;
}
pContext->State = State;
}
VOID
SmbCeConstructServerTransport(
IN OUT PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext)
/*++
Routine Description:
This routine constructs the server transport instance
Arguments:
pContext - the server transport construction context
Notes:
--*/
{
NTSTATUS Status;
PSMBCEDB_SERVER_ENTRY pServerEntry;
SMBCEDB_SERVER_TYPE ServerType;
BOOLEAN ContinueConstruction = TRUE;
BOOLEAN UpdateUnavailableServerlist = TRUE;
PAGED_CODE();
ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
pServerEntry = pContext->pServerEntry;
ServerType = SmbCeGetServerType(pServerEntry);
do {
switch (pContext->State) {
case SmbCeServerTransportConstructionBegin :
{
if (pServerEntry->pTransport != NULL) {
SmbCepTearDownServerTransport(pServerEntry);
}
ASSERT(pServerEntry->pTransport == NULL);
pContext->Status = STATUS_SUCCESS;
// See if we have any reason to believe this server is unavailable
pContext->Status = SmbCeIsServerAvailable( &pServerEntry->Name );
if (pContext->Status != STATUS_SUCCESS) {
UpdateUnavailableServerlist = FALSE;
}
SmbCepUpdateTransportConstructionState(pContext);
}
break;
case SmbCeServerVcTransportConstructionBegin:
{
Status = VctInstantiateServerTransport(
pContext);
if (Status == STATUS_PENDING) {
ContinueConstruction = FALSE;
break;
}
ASSERT(pContext->State == SmbCeServerVcTransportConstructionEnd);
}
// lack of break intentional
case SmbCeServerVcTransportConstructionEnd:
{
SmbCepUpdateTransportConstructionState(pContext);
}
break;
case SmbCeServerTransportConstructionEnd:
{
pServerEntry->ServerStatus = pContext->Status;
if (pServerEntry->ServerStatus == STATUS_SUCCESS) {
SmbCeAcquireSpinLock();
if (pContext->pTransport != NULL) {
pContext->pTransport->SwizzleCount = 1;
}
pServerEntry->pTransport = pContext->pTransport;
pContext->pTransport = NULL;
if (pContext->pCallbackContext != NULL) {
pContext->pCallbackContext->Status = STATUS_SUCCESS;
}
pServerEntry->IsTransportDereferenced = FALSE;
SmbCeReleaseSpinLock();
} else {
PRX_CONTEXT pRxContext = NULL;
if (UpdateUnavailableServerlist) {
SmbCeServerIsUnavailable( &pServerEntry->Name, pServerEntry->ServerStatus );
}
if (pContext->pTransport != NULL) {
pContext->pTransport->pDispatchVector->TearDown(
pContext->pTransport);
}
pContext->pTransport = NULL;
pServerEntry->pTransport = NULL;
if ((pContext->pCallbackContext) &&
(pContext->pCallbackContext->SrvCalldownStructure)) {
pRxContext =
pContext->pCallbackContext->SrvCalldownStructure->RxContext;
}
if (pContext->pCallbackContext != NULL) {
pContext->pCallbackContext->Status = pServerEntry->ServerStatus;
}
}
if (pContext->pCompletionEvent != NULL) {
ASSERT(pContext->pCallbackContext == NULL);
ASSERT(pContext->pCompletionRoutine == NULL);
KeSetEvent(
pContext->pCompletionEvent,
0,
FALSE );
} else if (pContext->pCallbackContext != NULL) {
ASSERT(pContext->pCompletionEvent == NULL);
(pContext->pCompletionRoutine)(pContext->pCallbackContext);
} else {
ASSERT(!"ill formed transport initialization context");
}
// pServerEntry->ConstructionContext = NULL;
RxFreePool(pContext);
ContinueConstruction = FALSE;
}
}
} while (ContinueConstruction);
}
NTSTATUS
SmbCepInitializeServerTransport(
PSMBCEDB_SERVER_ENTRY pServerEntry,
PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CALLBACK pCallbackRoutine,
PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext,
ULONG TransportsToBeConstructed)
/*++
Routine Description:
This routine initializes the transport information corresponding to a server
Arguments:
pServerEntry - the server entry instance in the database
pCallbackRoutine - the callback routine
pCallbackContext - the callback context
TransportsToBeConstructed -- the transports to be constructed
Return Value:
STATUS_SUCCESS - the server transport construction has been finalized.
Other Status codes correspond to error situations.
Notes:
Currently, only connection oriented transports are handled.
--*/
{
NTSTATUS Status;
BOOLEAN CompleteConstruction;
PAGED_CODE();
if ((pServerEntry->ServerStatus == STATUS_SUCCESS) &&
(pServerEntry->pTransport != NULL)) {
Status = STATUS_SUCCESS;
CompleteConstruction = TRUE;
} else {
PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext;
pContext = RxAllocatePoolWithTag(
NonPagedPool,
sizeof(SMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT),
MRXSMB_TRANSPORT_POOLTAG);
CompleteConstruction = (pContext == NULL);
if (pContext != NULL) {
KEVENT CompletionEvent;
RtlZeroMemory(
pContext,
sizeof(SMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT));
pContext->Status = STATUS_SUCCESS;
pContext->pServerEntry = pServerEntry;
pContext->State = SmbCeServerTransportConstructionBegin;
pContext->TransportsToBeConstructed = TransportsToBeConstructed;
if (pCallbackContext == NULL) {
KeInitializeEvent(
&CompletionEvent,
NotificationEvent,
FALSE);
pContext->pCompletionEvent = &CompletionEvent;
} else {
pContext->pCallbackContext = pCallbackContext;
pContext->pCompletionRoutine = pCallbackRoutine;
}
pServerEntry->ConstructionContext = (PVOID)pContext;
Status = STATUS_PENDING;
if (IoGetCurrentProcess() == RxGetRDBSSProcess()) {
SmbCeConstructServerTransport(pContext);
} else {
Status = RxPostToWorkerThread(
MRxSmbDeviceObject,
CriticalWorkQueue,
&pContext->WorkQueueItem,
SmbCeConstructServerTransport,
pContext);
if (Status == STATUS_SUCCESS) {
Status = STATUS_PENDING;
} else {
pServerEntry->ConstructionContext = NULL;
RxFreePool(pContext);
CompleteConstruction = TRUE;
}
}
if ((Status == STATUS_PENDING) && (pCallbackContext == NULL)) {
KeWaitForSingleObject(
&CompletionEvent,
Executive,
KernelMode,
FALSE,
NULL );
Status = pServerEntry->ServerStatus;
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
if (CompleteConstruction) {
pServerEntry->ServerStatus = Status;
if (pCallbackRoutine != NULL && pCallbackContext != NULL) {
pCallbackContext->Status = Status;
(pCallbackRoutine)(pCallbackContext);
Status = STATUS_PENDING;
}
}
return Status;
}
NTSTATUS
SmbCeUninitializeServerTransport(
PSMBCEDB_SERVER_ENTRY pServerEntry,
PSMBCE_SERVER_TRANSPORT_DESTRUCTION_CALLBACK pCallbackRoutine,
PVOID pCallbackContext)
/*++
Routine Description:
This routine uninitializes the transport information corresponding to a server
Arguments:
pServerEntry - the server entry instance in the database
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -