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

📄 transprt.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
                                               PagedPool,
                                               sizeof(TRANSPORT_BIND_CONTEXT) + pTransportName->Length,
                                               MRXSMB_TRANSPORT_POOLTAG);

                    if (pNewTransportContext != NULL) {
                        pNewTransportContext->Priority = Priority;
                        pNewTransportContext->TransportName.MaximumLength = pTransportName->MaximumLength;
                        pNewTransportContext->TransportName.Length = pTransportName->Length;
                        pNewTransportContext->TransportName.Buffer = (PWCHAR)((PBYTE)pNewTransportContext +
                                                                      sizeof(TRANSPORT_BIND_CONTEXT));

                        RtlCopyMemory(
                            pNewTransportContext->TransportName.Buffer,
                            pTransportName->Buffer,
                            pTransportName->Length);

                        Status = RxDispatchToWorkerThread(
                                     MRxSmbDeviceObject,
                                     CriticalWorkQueue,
                                     MRxSmbpBindTransportWorkerThreadRoutine,
                                     pNewTransportContext);
                    } else {
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                    }

                    if (Status != STATUS_SUCCESS) {
                        InterlockedDecrement(&TdiBindRequestsActive);
                        SmbCeSignalNetReadyEvent();
                    }
                }
            }
        }
        break;

    case TDI_PNP_OP_DEL:
        {
            PSMBCE_TRANSPORT pTransport;


            pTransport = SmbCeFindTransport(pTransportName);

            if (pTransport != NULL) {
                if (IoGetCurrentProcess() == RxGetRDBSSProcess()) {
                    MRxSmbpUnbindTransportCallback(pTransport);
                } else {

                    Status = RxDispatchToWorkerThread(
                                 MRxSmbDeviceObject,
                                 CriticalWorkQueue,
                                 MRxSmbpUnbindTransportCallback,
                                 pTransport);
                }
            }
        }
        break;

    case TDI_PNP_OP_UPDATE:
        {
        }
        break;

    case  TDI_PNP_OP_NETREADY:
        {
            TdiPnpNetReadyEventReceived = TRUE;
            SmbCeSignalNetReadyEvent();
        }
        break;

    default:
        break;
    }
}

NTSTATUS
MRxSmbPnPPowerHandler(
    IN PUNICODE_STRING  DeviceName,
    IN PNET_PNP_EVENT   PowerEvent,
    IN PTDI_PNP_CONTEXT Context1,
    IN PTDI_PNP_CONTEXT Context2
)
/*++

Routine Description:

    This routine deals with power changes

Notes:

    The implementation needs to be completed

--*/
{
    NTSTATUS Status;
    LONG     NumberOfActiveOpens;

    Status = STATUS_SUCCESS;

    FsRtlEnterFileSystem();

    RxPurgeAllFobxs(MRxSmbDeviceObject);

    RxScavengeAllFobxs(MRxSmbDeviceObject);
    NumberOfActiveOpens = MRxSmbNumberOfSrvOpens;

    switch (PowerEvent->NetEvent) {
    case NetEventQueryPower:
        {
            // If the redirector were to return an error on this request there
            // is no underlying support to tell the user about the files that
            // are open. There are two approaches to doing this.. either the RDR
            // rolls its own UI or the PNP manager provides the infra structure.
            // The problem with the former is that hibernation becomes a painstaking
            // process wherein the user has to contend with a variety of UI.
            // Till this is resolved the decision was to use the power mgmt. API
            // to manage system initiated hibernate requests and succeed user
            // initiated requests after appropriate purging/scavenging.

            if (MRxSmbNumberOfSrvOpens > 0) {
                DbgPrint(
                    "RDR: PNP Hibernate Request Status %lx Number of Opens %lx\n",
                    Status,
                    MRxSmbNumberOfSrvOpens);
            }

            Status = STATUS_SUCCESS;
        }
        break;

    case NetEventQueryRemoveDevice:
        {
            PSMBCEDB_SERVER_ENTRY pServerEntry;
            ULONG                 NumberOfFilesOpen = 0;
            PSMBCE_TRANSPORT      pTransport = NULL;

            pTransport = SmbCeFindTransport(DeviceName);

            if (pTransport != NULL) {
                SmbCeAcquireSpinLock();

                pServerEntry = SmbCeGetFirstServerEntry();

                while (pServerEntry != NULL) {
                    if ((pServerEntry->pTransport != NULL) &&
                        (pTransport == pServerEntry->pTransport->pTransport)) {
                        NumberOfFilesOpen += pServerEntry->Server.NumberOfSrvOpens;
                    }

                    pServerEntry = SmbCeGetNextServerEntry(pServerEntry);
                }

                SmbCeReleaseSpinLock();

                SmbCeDereferenceTransport(pTransport);
            }
        }
        break;

    default:
        break;
    }

    FsRtlExitFileSystem();

    return Status;
}

NTSTATUS
MRxSmbRegisterForPnpNotifications()
/*++

Routine Description:

    This routine registers with TDI for receiving transport notifications

--*/
{
    NTSTATUS Status = STATUS_SUCCESS;

    PAGED_CODE();

    if(MRxSmbTdiNotificationHandle == NULL ) {
        UNICODE_STRING ClientName;

        TDI_CLIENT_INTERFACE_INFO ClientInterfaceInfo;

        RtlInitUnicodeString(&ClientName,L"LanmanWorkStation");

        ClientInterfaceInfo.MajorTdiVersion = 2;
        ClientInterfaceInfo.MinorTdiVersion = 0;

        ClientInterfaceInfo.Unused = 0;
        ClientInterfaceInfo.ClientName = &ClientName;

        ClientInterfaceInfo.BindingHandler = MRxSmbPnPBindingHandler;
        ClientInterfaceInfo.AddAddressHandler = NULL;
        ClientInterfaceInfo.DelAddressHandler = NULL;
        ClientInterfaceInfo.PnPPowerHandler = MRxSmbPnPPowerHandler;

        KeInitializeEvent(
            &TdiNetStartupCompletionEvent,
            NotificationEvent,
            FALSE);

        Status = TdiRegisterPnPHandlers (
                     &ClientInterfaceInfo,
                     sizeof(ClientInterfaceInfo),
                     &MRxSmbTdiNotificationHandle );

        if (Status == STATUS_SUCCESS) {
            LARGE_INTEGER WaitInterval;

            WaitInterval.QuadPart = -( 10000 * 2 * 60 * 1000 );

            Status = KeWaitForSingleObject(
                         &TdiNetStartupCompletionEvent,
                         Executive,
                         KernelMode,
                         TRUE,
                         &WaitInterval);
        }
    }

    return Status;
}

NTSTATUS
MRxSmbDeregisterForPnpNotifications()
/*++

Routine Description:

    This routine deregisters the TDI notification mechanism

Notes:

--*/
{
    NTSTATUS Status = STATUS_SUCCESS;

    PAGED_CODE();

    if( MRxSmbTdiNotificationHandle != NULL ) {
        Status = TdiDeregisterPnPHandlers( MRxSmbTdiNotificationHandle );

        if( NT_SUCCESS( Status ) ) {
            MRxSmbTdiNotificationHandle = NULL;
        }
    }

    return Status;
}



PSMBCE_TRANSPORT_ARRAY
SmbCeReferenceTransportArray(VOID)
/*++

Routine Description:

    This routine references and returns the current transport array instance

Return Value:

    PSMBCE_TRANSPORT_ARRAY - the pointer of the current transport array instance

Notes:

--*/
{
    KIRQL                  SavedIrql;
    PSMBCE_TRANSPORT_ARRAY pTransportArray;

    KeAcquireSpinLock(&MRxSmbTransports.Lock,&SavedIrql);

    pTransportArray = MRxSmbTransports.pTransportArray;

    if (pTransportArray != NULL) {
        InterlockedIncrement(&pTransportArray->ReferenceCount);
    }

    KeReleaseSpinLock(&MRxSmbTransports.Lock,SavedIrql);

    return pTransportArray;
}

NTSTATUS
SmbCeDereferenceTransportArray(
    PSMBCE_TRANSPORT_ARRAY pTransportArray)
/*++

Routine Description:

    This routine dereferences the transport array instance

Arguments:

    pTransportArray - the transport array instance

Return Value:

    STATUS_SUCCESS - the server transport was successfully dereferenced

    Other Status codes correspond to error situations.

Notes:

--*/
{
    KIRQL    SavedIrql;
    NTSTATUS Status = STATUS_SUCCESS;

    PAGED_CODE();

    if (pTransportArray != NULL) {
        ASSERT( pTransportArray->ReferenceCount > 0 );

        if(InterlockedDecrement(&pTransportArray->ReferenceCount)==0) {
            ULONG i;

            for(i=0;i<pTransportArray->Count;i++) {
                SmbCeDereferenceTransport(pTransportArray->SmbCeTransports[i]);
            }

            RxFreePool(pTransportArray->SmbCeTransports);
            RxFreePool(pTransportArray->LocalAddresses);
            RxFreePool(pTransportArray);
        }
    } else {
        Status = STATUS_INVALID_PARAMETER;
    }

    return Status;
}

NTSTATUS
SmbCeIsServerAvailable(
    PUNICODE_STRING Name
)
/*++

Routine Description:

    This routine scans the list of "unreachable" servers and returns the status
    of the last failed connection attempt.

Return:
    STATUS_SUCCESS -> we have no reason to believe this server is unreachable
    other -> server is unreachable for this reason
--*/
{
    PUNAVAILABLE_SERVER server;
    LARGE_INTEGER now;
    NTSTATUS status = STATUS_SUCCESS;

    PAGED_CODE();

    KeQueryTickCount( &now );

    ExAcquireResourceExclusive( &UnavailableServerListResource, TRUE );

    for( server  = (PUNAVAILABLE_SERVER)UnavailableServerList.Flink;
         server != (PUNAVAILABLE_SERVER)&UnavailableServerList;
         server  = (PUNAVAILABLE_SERVER)server->ListEntry.Flink ) {

        //
        // If this entry has timed out, remove it.
        //
        if( now.QuadPart > server->Time.QuadPart ) {
            PUNAVAILABLE_SERVER tmp;
            //
            // Unlink this entry from the list and discard it
            //
            tmp = (PUNAVAILABLE_SERVER)(server->ListEntry.Blink);
            RemoveEntryList( &server->ListEntry );
            RxFreePool( server );
            server = tmp;
            continue;
        }

        //
        // See if this entry is the one we want
        //
        if( RtlCompareUnicodeString( &server->Name, Name, TRUE ) == 0 ) {

            status = server->Status;

            RxDbgTrace(0, Dbg, ("SmbCeIsServerAvailable: Found %wZ %X\n",
                        &server->Name, status ));
        }
    }

    ExReleaseResource( &UnavailableServerListResource );

    return status;
}

VOID
SmbCeServerIsUnavailable(
    PUNICODE_STRING Name,
    NTSTATUS Status
)
{
    PUNAVAILABLE_SERVER server;

    LARGE_INTEGER CurrentTime;
    LARGE_INTEGER ExpiryTimeInTicks;

    PAGED_CODE();

    server = (PUNAVAILABLE_SERVER)RxAllocatePoolWithTag(
                                        PagedPool,
                                        sizeof( *server ) + Name->Length,
                                        MRXSMB_TRANSPORT_POOLTAG
                                        );

    if( server == NULL ) {
        return;
    }

    RxDbgTrace(0, Dbg, ("SmbCeServerIsUnavailable: Add %wZ %X\n", Name, Status ));

    server->Name.Buffer = (PUSHORT)(server + 1);
    server->Name.MaximumLength = Name->Length;
    RtlCopyUnicodeString( &server->Name, Name );

    KeQueryTickCount( &CurrentTime );

    ExpiryTimeInTicks.QuadPart = (1000 * 1000 * 10) / KeQueryTimeIncrement();

    ExpiryTimeInTicks.QuadPart = UNAVAILABLE_SERVER_TIME * ExpiryTimeInTicks.QuadPart;

    server->Time.QuadPart = CurrentTime.QuadPart + ExpiryTimeInTicks.QuadPart;

    server->Status = Status;

    ExAcquireResourceExclusive( &UnavailableServerListResource, TRUE );
    InsertHeadList( &UnavailableServerList, &server->ListEntry );
    ExReleaseResource( &UnavailableServerListResource );
}

VOID
SmbCeDiscardUnavailableServerList(
)
{
    PUNAVAILABLE_SERVER server;

    PAGED_CODE();

    RxDbgTrace(0, Dbg, ("SmbCeDiscardUnavailableServerList\n" ));

    FsRtlEnterFileSystem( );
    ExAcquireResourceExclusive( &UnavailableServerListResource, TRUE );

    while( UnavailableServerList.Flink != &UnavailableServerList ) {
        server  = (PUNAVAILABLE_SERVER)Unav

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -