⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transprt.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
--*/
{
    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 + -