Exemple #1
0
NTSTATUS
NbfConfigureTransport (
    IN PUNICODE_STRING RegistryPath,
    IN PCONFIG_DATA * ConfigurationInfoPtr
    )
/*++

Routine Description:

    This routine is called by NBF to get information from the configuration
    management routines. We read the registry, starting at RegistryPath,
    to get the parameters. If they don't exist, we use the defaults
    set in nbfcnfg.h file.

Arguments:

    RegistryPath - The name of NBF's node in the registry.

    ConfigurationInfoPtr - A pointer to the configuration information structure.

Return Value:

    Status - STATUS_SUCCESS if everything OK, STATUS_INSUFFICIENT_RESOURCES
            otherwise.

--*/
{

    NTSTATUS OpenStatus;
    HANDLE ParametersHandle;
    HANDLE NbfConfigHandle;
    NTSTATUS Status;
    ULONG Disposition;
    PWSTR RegistryPathBuffer;
    OBJECT_ATTRIBUTES TmpObjectAttributes;
    PCONFIG_DATA ConfigurationInfo;

    DECLARE_STRING(InitRequests);
    DECLARE_STRING(InitLinks);
    DECLARE_STRING(InitConnections);
    DECLARE_STRING(InitAddressFiles);
    DECLARE_STRING(InitAddresses);

    DECLARE_STRING(MaxRequests);
    DECLARE_STRING(MaxLinks);
    DECLARE_STRING(MaxConnections);
    DECLARE_STRING(MaxAddressFiles);
    DECLARE_STRING(MaxAddresses);

    DECLARE_STRING(InitPackets);
    DECLARE_STRING(InitReceivePackets);
    DECLARE_STRING(InitReceiveBuffers);
    DECLARE_STRING(InitUIFrames);

    DECLARE_STRING(SendPacketPoolSize);
    DECLARE_STRING(ReceivePacketPoolSize);
    DECLARE_STRING(MaxMemoryUsage);

    DECLARE_STRING(MinimumT1Timeout);
    DECLARE_STRING(DefaultT1Timeout);
    DECLARE_STRING(DefaultT2Timeout);
    DECLARE_STRING(DefaultTiTimeout);
    DECLARE_STRING(LlcRetries);
    DECLARE_STRING(LlcMaxWindowSize);
    DECLARE_STRING(MaximumIncomingFrames);

    DECLARE_STRING(NameQueryRetries);
    DECLARE_STRING(NameQueryTimeout);
    DECLARE_STRING(AddNameQueryRetries);
    DECLARE_STRING(AddNameQueryTimeout);
    DECLARE_STRING(GeneralRetries);
    DECLARE_STRING(GeneralTimeout);
    DECLARE_STRING(WanNameQueryRetries);

    DECLARE_STRING(UseDixOverEthernet);
    DECLARE_STRING(QueryWithoutSourceRouting);
    DECLARE_STRING(AllRoutesNameRecognized);
    DECLARE_STRING(MinimumSendWindowLimit);

    //
    // Open the registry.
    //

    InitializeObjectAttributes(
        &TmpObjectAttributes,
        RegistryPath,               // name
        OBJ_CASE_INSENSITIVE,       // attributes
        NULL,                       // root
        NULL                        // security descriptor
        );

    Status = ZwCreateKey(
                 &NbfConfigHandle,
                 KEY_WRITE,
                 &TmpObjectAttributes,
                 0,                 // title index
                 NULL,              // class
                 0,                 // create options
                 &Disposition);     // disposition

    if (!NT_SUCCESS(Status)) {
        NbfPrint1("NBF: Could not open/create NBF key: %lx\n", Status);
        return Status;
    }

    IF_NBFDBG (NBF_DEBUG_REGISTRY) {
        NbfPrint2("%s NBF key: %lx\n",
            (Disposition == REG_CREATED_NEW_KEY) ? "created" : "opened",
            NbfConfigHandle);
    }


    OpenStatus = NbfOpenParametersKey (NbfConfigHandle, &ParametersHandle);

    if (OpenStatus != STATUS_SUCCESS) {
        return OpenStatus;
    }

    //
    // Read in the NDIS binding information (if none is present
    // the array will be filled with all known drivers).
    //
    // NbfReadLinkageInformation expects a null-terminated path,
    // so we have to create one from the UNICODE_STRING.
    //

    RegistryPathBuffer = (PWSTR)ExAllocatePoolWithTag(
                                    NonPagedPool,
                                    RegistryPath->Length + sizeof(WCHAR),
                                    NBF_MEM_TAG_REGISTRY_PATH);
    if (RegistryPathBuffer == NULL) {
        NbfCloseParametersKey (ParametersHandle);
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
    *(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';

    NbfReadLinkageInformation (RegistryPathBuffer, ConfigurationInfoPtr);

    if (*ConfigurationInfoPtr == NULL) {
        ExFreePool (RegistryPathBuffer);
        NbfCloseParametersKey (ParametersHandle);
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    ConfigurationInfo = *ConfigurationInfoPtr;


    //
    // Configure the initial values for some NBF resources.
    //

    ConfigurationInfo->InitRequests = 1;
    ConfigurationInfo->InitLinks = 2;
    ConfigurationInfo->InitConnections = 2;
    ConfigurationInfo->InitAddressFiles = 0;
    ConfigurationInfo->InitAddresses = 0;

    //
    // These are the initial values; remember that the
    // resources above also allocate some of these each
    // time they are allocated (shown in the comment).
    //

    ConfigurationInfo->InitPackets = 30;         // + link + 2*conn
    ConfigurationInfo->InitReceivePackets = 10;  // + link + addr
    ConfigurationInfo->InitReceiveBuffers = 5;   // + addr
    ConfigurationInfo->InitUIFrames = 5;         // + addr + conn

    //
    // Set the size of the packet pools and the total
    // allocateable by NBF.
    //

    ConfigurationInfo->SendPacketPoolSize = 100;
    ConfigurationInfo->ReceivePacketPoolSize = 30;
    ConfigurationInfo->MaxMemoryUsage = 0;       // no limit


    //
    // Now initialize the timeout etc. values.
    //
    
    ConfigurationInfo->MinimumT1Timeout = DLC_MINIMUM_T1;
    ConfigurationInfo->DefaultT1Timeout = DLC_DEFAULT_T1;
    ConfigurationInfo->DefaultT2Timeout = DLC_DEFAULT_T2;
    ConfigurationInfo->DefaultTiTimeout = DLC_DEFAULT_TI;
    ConfigurationInfo->LlcRetries = DLC_RETRIES;
    ConfigurationInfo->LlcMaxWindowSize = DLC_WINDOW_LIMIT;
    ConfigurationInfo->MaximumIncomingFrames = 4;
    ConfigurationInfo->NameQueryRetries = NAME_QUERY_RETRIES;
    ConfigurationInfo->NameQueryTimeout = NAME_QUERY_TIMEOUT;
    ConfigurationInfo->AddNameQueryRetries = ADD_NAME_QUERY_RETRIES;
    ConfigurationInfo->AddNameQueryTimeout = ADD_NAME_QUERY_TIMEOUT;
    ConfigurationInfo->GeneralRetries = NAME_QUERY_RETRIES;
    ConfigurationInfo->GeneralTimeout = NAME_QUERY_TIMEOUT;
    ConfigurationInfo->WanNameQueryRetries = WAN_NAME_QUERY_RETRIES;

    ConfigurationInfo->UseDixOverEthernet = 0;
    ConfigurationInfo->QueryWithoutSourceRouting = 0;
    ConfigurationInfo->AllRoutesNameRecognized = 0;
    ConfigurationInfo->MinimumSendWindowLimit = 2;


    //
    // Now read the optional "hidden" parameters; if these do
    // not exist then the current values are used. Note that
    // the current values will be 0 unless they have been
    // explicitly initialized above.
    //
    // NOTE: These macros expect "ConfigurationInfo" and
    // "ParametersHandle" to exist when they are expanded.
    //

    READ_HIDDEN_CONFIG (InitRequests);
    READ_HIDDEN_CONFIG (InitLinks);
    READ_HIDDEN_CONFIG (InitConnections);
    READ_HIDDEN_CONFIG (InitAddressFiles);
    READ_HIDDEN_CONFIG (InitAddresses);

    READ_HIDDEN_CONFIG (MaxRequests);
    READ_HIDDEN_CONFIG (MaxLinks);
    READ_HIDDEN_CONFIG (MaxConnections);
    READ_HIDDEN_CONFIG (MaxAddressFiles);
    READ_HIDDEN_CONFIG (MaxAddresses);

    READ_HIDDEN_CONFIG (InitPackets);
    READ_HIDDEN_CONFIG (InitReceivePackets);
    READ_HIDDEN_CONFIG (InitReceiveBuffers);
    READ_HIDDEN_CONFIG (InitUIFrames);

    READ_HIDDEN_CONFIG (SendPacketPoolSize);
    READ_HIDDEN_CONFIG (ReceivePacketPoolSize);
    READ_HIDDEN_CONFIG (MaxMemoryUsage);

    READ_HIDDEN_CONFIG (MinimumT1Timeout);
    READ_HIDDEN_CONFIG (DefaultT1Timeout);
    READ_HIDDEN_CONFIG (DefaultT2Timeout);
    READ_HIDDEN_CONFIG (DefaultTiTimeout);
    READ_HIDDEN_CONFIG (LlcRetries);
    READ_HIDDEN_CONFIG (LlcMaxWindowSize);
    READ_HIDDEN_CONFIG (MaximumIncomingFrames);

    READ_HIDDEN_CONFIG (NameQueryRetries);
    READ_HIDDEN_CONFIG (NameQueryTimeout);
    READ_HIDDEN_CONFIG (AddNameQueryRetries);
    READ_HIDDEN_CONFIG (AddNameQueryTimeout);
    READ_HIDDEN_CONFIG (GeneralRetries);
    READ_HIDDEN_CONFIG (GeneralTimeout);
    READ_HIDDEN_CONFIG (WanNameQueryRetries);

    READ_HIDDEN_CONFIG (UseDixOverEthernet);
    READ_HIDDEN_CONFIG (QueryWithoutSourceRouting);
    READ_HIDDEN_CONFIG (AllRoutesNameRecognized);
    READ_HIDDEN_CONFIG (MinimumSendWindowLimit);


    //
    // Print out some config info, to make sure it is read right.
    //

    IF_NBFDBG (NBF_DEBUG_REGISTRY) {
       NbfPrint2("Links: init %d, max %d\n",
                     ConfigurationInfo->InitLinks,
                     ConfigurationInfo->MaxLinks);
       NbfPrint3("Timeouts (NBF ticks): T1 %d, T2 %d, Ti %d\n",
                     ConfigurationInfo->DefaultT1Timeout / SHORT_TIMER_DELTA,
                     ConfigurationInfo->DefaultT2Timeout / SHORT_TIMER_DELTA,
                     ConfigurationInfo->DefaultTiTimeout / LONG_TIMER_DELTA);
       NbfPrint2("Pools: send %d, receive %d\n",
                     ConfigurationInfo->SendPacketPoolSize,
                     ConfigurationInfo->ReceivePacketPoolSize);
       NbfPrint1("Max mem %d\n",
                     ConfigurationInfo->MaxMemoryUsage);
       NbfPrint2("NQRetries %d, NQTimeout %d\n",
                     ConfigurationInfo->NameQueryRetries,
                     ConfigurationInfo->NameQueryTimeout / SHORT_TIMER_DELTA);
    }

    //
    // Save the "hidden" parameters, these may not exist in
    // the registry.
    //
    // NOTE: These macros expect "ConfigurationInfo" and
    // "ParametersHandle" to exist when they are expanded.
    //

    //
    // 5/22/92 - don't write the parameters that are set
    // based on Size, since otherwise these will overwrite
    // those values since hidden parameters are set up
    // after the Size-based configuration is done.
    //

    WRITE_HIDDEN_CONFIG (MaxRequests);
    WRITE_HIDDEN_CONFIG (MaxLinks);
    WRITE_HIDDEN_CONFIG (MaxConnections);
    WRITE_HIDDEN_CONFIG (MaxAddressFiles);
    WRITE_HIDDEN_CONFIG (MaxAddresses);

    WRITE_HIDDEN_CONFIG (MinimumT1Timeout);
    WRITE_HIDDEN_CONFIG (DefaultT1Timeout);
    WRITE_HIDDEN_CONFIG (DefaultT2Timeout);
    WRITE_HIDDEN_CONFIG (DefaultTiTimeout);
    WRITE_HIDDEN_CONFIG (LlcRetries);
    WRITE_HIDDEN_CONFIG (LlcMaxWindowSize);
    WRITE_HIDDEN_CONFIG (MaximumIncomingFrames);

    WRITE_HIDDEN_CONFIG (NameQueryRetries);
    WRITE_HIDDEN_CONFIG (NameQueryTimeout);
    WRITE_HIDDEN_CONFIG (AddNameQueryRetries);
    WRITE_HIDDEN_CONFIG (AddNameQueryTimeout);
    WRITE_HIDDEN_CONFIG (GeneralRetries);
    WRITE_HIDDEN_CONFIG (GeneralTimeout);
    WRITE_HIDDEN_CONFIG (WanNameQueryRetries);

    WRITE_HIDDEN_CONFIG (UseDixOverEthernet);
    WRITE_HIDDEN_CONFIG (QueryWithoutSourceRouting);
    WRITE_HIDDEN_CONFIG (AllRoutesNameRecognized);

    // ZwFlushKey (ParametersHandle);

    ExFreePool (RegistryPathBuffer);
    NbfCloseParametersKey (ParametersHandle);
    ZwClose (NbfConfigHandle);

    return STATUS_SUCCESS;

}   /* NbfConfigureTransport */
Exemple #2
0
NTSTATUS
NbfTdiReceive(
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the TdiReceive request for the transport provider.

Arguments:

    Irp - I/O Request Packet for this request.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PTP_CONNECTION connection;
    KIRQL oldirql;
    PIO_STACK_LOCATION irpSp;

    //
    // verify that the operation is taking place on a connection. At the same
    // time we do this, we reference the connection. This ensures it does not
    // get removed out from under us. Note also that we do the connection
    // lookup within a try/except clause, thus protecting ourselves against
    // really bogus handles
    //

    irpSp = IoGetCurrentIrpStackLocation (Irp);
    connection = irpSp->FileObject->FsContext;

    //
    // Check that this is really a connection.
    //

    if ((connection->Size != sizeof (TP_CONNECTION)) ||
        (connection->Type != NBF_CONNECTION_SIGNATURE)) {
#if DBG
        NbfPrint2 ("TdiReceive: Invalid Connection %lx Irp %lx\n", connection, Irp);
#endif
        return STATUS_INVALID_CONNECTION;
    }

    //
    // Initialize bytes transferred here.
    //

    Irp->IoStatus.Information = 0;              // reset byte transfer count.

    // This reference is removed by NbfDestroyRequest.

    KeRaiseIrql (DISPATCH_LEVEL, &oldirql);

    ACQUIRE_DPC_C_SPIN_LOCK (&connection->SpinLock);

    if ((connection->Flags & CONNECTION_FLAGS_READY) == 0) {

        RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock);

        Irp->IoStatus.Status = connection->Status;
        IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);

        status = STATUS_PENDING;

    } else {
        KIRQL cancelIrql;

        //
        // Once the reference is in, LinkSpinLock will be valid.
        //

        NbfReferenceConnection("TdiReceive request", connection, CREF_RECEIVE_IRP);
        RELEASE_DPC_C_SPIN_LOCK (&connection->SpinLock);

        IoAcquireCancelSpinLock(&cancelIrql);
        ACQUIRE_DPC_SPIN_LOCK (connection->LinkSpinLock);

        IRP_RECEIVE_IRP(irpSp) = Irp;
        IRP_RECEIVE_REFCOUNT(irpSp) = 1;

#if DBG
        NbfReceives[NbfReceivesNext].Irp = Irp;
        NbfReceives[NbfReceivesNext].Request = NULL;
        NbfReceives[NbfReceivesNext].Connection = (PVOID)connection;
        NbfReceivesNext = (NbfReceivesNext++) % TRACK_TDI_LIMIT;
#endif

        //
        // If this IRP has been cancelled, complete it now.
        //

        if (Irp->Cancel) {

#if DBG
            NbfCompletedReceives[NbfCompletedReceivesNext].Irp = Irp;
            NbfCompletedReceives[NbfCompletedReceivesNext].Request = NULL;
            NbfCompletedReceives[NbfCompletedReceivesNext].Status = STATUS_CANCELLED;
            {
                ULONG i,j,k;
                PUCHAR va;
                PMDL mdl;

                mdl = Irp->MdlAddress;

                NbfCompletedReceives[NbfCompletedReceivesNext].Contents[0] = (UCHAR)0;

                i = 1;
                while (i<TRACK_TDI_CAPTURE) {
                    if (mdl == NULL) break;
                    va = MmGetSystemAddressForMdl (mdl);
                    j = MmGetMdlByteCount (mdl);

                    for (i=i,k=0;i<TRACK_TDI_CAPTURE&k<j;i++,k++) {
                        NbfCompletedReceives[NbfCompletedReceivesNext].Contents[i] = *va++;
                    }
                    mdl = mdl->Next;
                }
            }

            NbfCompletedReceivesNext = (NbfCompletedReceivesNext++) % TRACK_TDI_LIMIT;
#endif

            //
            // It is safe to do this with locks held.
            //
            NbfCompleteReceiveIrp (Irp, STATUS_CANCELLED, 0);

            RELEASE_DPC_SPIN_LOCK (connection->LinkSpinLock);
            IoReleaseCancelSpinLock(cancelIrql);

        } else {

            //
            // Insert onto the receive queue, and make the IRP
            // cancellable.
            //

            InsertTailList (&connection->ReceiveQueue,&Irp->Tail.Overlay.ListEntry);
            IoSetCancelRoutine(Irp, NbfCancelReceive);

            //
            // Release the cancel spinlock out of order. Since we were
            // already at dpc level when it was acquired, we don't
            // need to swap irqls.
            //
            ASSERT(cancelIrql == DISPATCH_LEVEL);
            IoReleaseCancelSpinLock(cancelIrql);

            //
            // This call releases the link spinlock, and references the
            // connection first if it needs to access it after
            // releasing the lock.
            //

            AwakenReceive (connection);             // awaken if sleeping.

        }

        status = STATUS_PENDING;

    }

    KeLowerIrql (oldirql);

    return status;
} /* TdiReceive */
Exemple #3
0
NTSTATUS
NbfGetExportNameFromRegistry(
    IN  PUNICODE_STRING RegistryPath,
    IN  PUNICODE_STRING BindName,
    OUT PUNICODE_STRING ExportName
    )
{
    NTSTATUS OpenStatus;
    HANDLE ParametersHandle;
    HANDLE NbfConfigHandle;
    NTSTATUS Status;
    PWSTR RegistryPathBuffer;
    OBJECT_ATTRIBUTES TmpObjectAttributes;
    
    RTL_QUERY_REGISTRY_TABLE QueryTable[3];
    PWSTR Subkey = L"Linkage";
    PWSTR Bind = L"Bind";
    PWSTR Export = L"Export";
    LONG BindNumber;

    //
    // Open the registry.
    //

    InitializeObjectAttributes(
        &TmpObjectAttributes,
        RegistryPath,               // name
        OBJ_CASE_INSENSITIVE,       // attributes
        NULL,                       // root
        NULL                        // security descriptor
        );

    OpenStatus = ZwOpenKey(
                     &NbfConfigHandle,
                     KEY_WRITE,
                     &TmpObjectAttributes
                     );

    if (!NT_SUCCESS(OpenStatus)) {
        NbfPrint1("NBF: Could not open NBF key: %lx\n", OpenStatus);
        return OpenStatus;
    }

    Status = NbfOpenParametersKey (NbfConfigHandle, &ParametersHandle);

    if (Status != STATUS_SUCCESS) {
        ZwClose (NbfConfigHandle);
        return Status;
    }

    //
    // NbfReadLinkageInformation expects a null-terminated path,
    // so we have to create one from the UNICODE_STRING.
    //

    RegistryPathBuffer = (PWSTR)ExAllocatePoolWithTag(
                                    NonPagedPool,
                                    RegistryPath->Length + sizeof(WCHAR),
                                    NBF_MEM_TAG_REGISTRY_PATH);
                                    
    if (RegistryPathBuffer == NULL) {
        NbfCloseParametersKey (ParametersHandle);
        ZwClose (NbfConfigHandle);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
    *(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';

    //
    // We have a new device whose binding was absent 
    // at boot - get export name given the bind name
    //

    // First we need to get index of the bind name
    
    // Set up QueryTable to do the following:

    //
    // 1) Switch to the Linkage key below NBF
    //

    QueryTable[0].QueryRoutine = NULL;
    QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
    QueryTable[0].Name = Subkey;

    //
    // 2) Call NbfMatchBindName for each string in "Bind"
    //

    QueryTable[1].QueryRoutine = NbfMatchBindName;
    QueryTable[1].Flags = 0;
    QueryTable[1].Name = Bind;
    QueryTable[1].EntryContext = (PVOID)&BindNumber;
    QueryTable[1].DefaultType = REG_NONE;

    //
    // 3) Stop
    //

    QueryTable[2].QueryRoutine = NULL;
    QueryTable[2].Flags = 0;
    QueryTable[2].Name = NULL;


    BindNumber = -1;

    Status = RtlQueryRegistryValues(
                 RTL_REGISTRY_ABSOLUTE,
                 RegistryPathBuffer,
                 QueryTable,
                 (PVOID)BindName,
                 NULL);

    IF_NBFDBG (NBF_DEBUG_PNP) {
        NbfPrint2 ("Status from NbfMatchBindName's = %08x, Bind Number = %d\n",
                        Status, BindNumber);
    }

    if (Status != STATUS_NO_MORE_MATCHES)
    {
#if DBG
        DbgBreakPoint();
#endif
    
        if (Status == STATUS_SUCCESS) {
        
            // We did not find the device 'bind name'
            Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
            
            IF_NBFDBG (NBF_DEBUG_PNP) {
                NbfPrint1 ("NBF - cannot find dynamic binding %S\n", BindName->Buffer);
            }
        }
Exemple #4
0
VOID
NbfTdiRequestTimeoutHandler(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    )

/*++

Routine Description:

    This routine is executed as a DPC at DISPATCH_LEVEL when a request
    such as TdiSend, TdiReceive, TdiSendDatagram, TdiReceiveDatagram, etc.,
    encounters a timeout.  This routine cleans up the activity and cancels it.

Arguments:

    Dpc - Pointer to a system DPC object.

    DeferredContext - Pointer to the TP_REQUEST block representing the
        request that has timed out.

    SystemArgument1 - Not used.

    SystemArgument2 - Not used.

Return Value:

    none.

--*/

{
    KIRQL oldirql;
    PTP_REQUEST Request;
    PTP_CONNECTION Connection;
#if DBG
    LARGE_INTEGER time, difference;
#endif
    PIO_STACK_LOCATION IrpSp;
    PTDI_REQUEST_KERNEL_QUERY_INFORMATION query;
    PDEVICE_CONTEXT DeviceContext;

    Dpc, SystemArgument1, SystemArgument2; // prevent compiler warnings

    ENTER_NBF;

    Request = (PTP_REQUEST)DeferredContext;

    IF_NBFDBG (NBF_DEBUG_REQUEST) {
        NbfPrint1 ("RequestTimeoutHandler:  Entered, Request %lx\n", Request);
    }

    ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
    Request->Flags &= ~REQUEST_FLAGS_TIMER;
    if ((Request->Flags & REQUEST_FLAGS_STOPPING) == 0) {

#if DBG
        KeQuerySystemTime (&time);
        difference.QuadPart = time.QuadPart - (Request->Time).QuadPart;
        NbfPrint1 ("RequestTimeoutHandler: Request timed out, queued for %ld seconds\n",
                difference.LowPart / SECONDS);
#endif

        //
        // find reason for timeout
        //

        IrpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
        if (IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) {
            switch (IrpSp->MinorFunction) {

                //
                // none of these should time out.
                //

            case TDI_SEND:
            case TDI_ACCEPT:
            case TDI_SET_INFORMATION:
            case TDI_SET_EVENT_HANDLER:
            case TDI_SEND_DATAGRAM:
            case TDI_RECEIVE_DATAGRAM:
            case TDI_RECEIVE:

#if DBG
                NbfPrint1 ("RequestTimeoutHandler: Request: %lx Timed out, and shouldn't have!\n",
                        Request);
#endif
                ASSERT (FALSE);
                RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                NbfCompleteRequest (Request, STATUS_IO_TIMEOUT, 0);
                break;


            case TDI_LISTEN:
            case TDI_CONNECT:

#if DBG
                NbfPrint2 ("RequestTimeoutHandler:  %s Failed, Request: %lx\n",
                            IrpSp->MinorFunction == TDI_LISTEN ?
                                "Listen" :
                                IrpSp->MinorFunction == TDI_CONNECT ?
                                    "Connect" : "Disconnect",
                            Request);
#endif
                Connection = (PTP_CONNECTION)(Request->Context);
                RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);

                //
                // Since these requests are part of the connection
                // itself, we just stop the connection and the
                // request will get torn down then. If we get the
                // situation where the request times out before
                // it is queued to the connection, then the code
                // that is about to queue it will check the STOPPING
                // flag and complete it then.
                //
                // Don't stop the connection if an automatic connection
                // is in progress.
                //

#ifdef RASAUTODIAL

#if DBG
                DbgPrint("RequestTimeoutHandler: AUTOCONNECTING=0x%x\n", Connection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTING);
#endif
                if (!(Connection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTING))
                    NbfStopConnection (Connection, STATUS_IO_TIMEOUT);
                break;

#endif

            case TDI_DISCONNECT:

                //
                // We don't create requests for TDI_DISCONNECT any more.
                //

                ASSERT(FALSE);
                break;

            case TDI_QUERY_INFORMATION:

                DeviceContext = (PDEVICE_CONTEXT)IrpSp->FileObject->DeviceObject;
                query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;

                IF_NBFDBG (NBF_DEBUG_DEVCTX) {
                    NbfPrint1 ("RequestTimeout: %lx:\n", DeviceContext);
                }

                //
                // Determine if the request is done, or if we should
                // requeue it.
                //

                --Request->Retries;

                if (Request->Retries > 0) {

                    RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);

                    //
                    // Send another packet out, and restart the timer.
                    //

                    if (query->QueryType == TDI_QUERY_FIND_NAME) {

                        NbfSendQueryFindName (
                            DeviceContext,
                            Request);

                    } else if (query->QueryType == TDI_QUERY_ADAPTER_STATUS) {

                        PUCHAR SingleSR;
                        UINT SingleSRLength;

                        //
                        // Send the STATUS_QUERY frames out as
                        // single-route source routing.
                        //
                        // On a second status query this should
                        // really be sent directed, but currently we
                        // don't record the address anywhere.
                        //

                        MacReturnSingleRouteSR(
                            &DeviceContext->MacInfo,
                            &SingleSR,
                            &SingleSRLength);

                        NbfSendStatusQuery (
                            DeviceContext,
                            Request,
                            &DeviceContext->NetBIOSAddress,
                            SingleSR,
                            SingleSRLength);

                    } else {

                        ASSERT (FALSE);

                    }

                } else {

                    RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);

                    //
                    // That's it, we retried enough, complete it.
                    //

                    ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
                    RemoveEntryList (&Request->Linkage);
                    RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);

                    if (Request->BytesWritten > 0) {

                        NbfCompleteRequest (Request, STATUS_SUCCESS, Request->BytesWritten);

                    } else {

                        NbfCompleteRequest (Request, STATUS_IO_TIMEOUT, Request->BytesWritten);

                    }


                }

                break;

            default:
#if DBG
                NbfPrint2 ("RequestTimeoutHandler:  Unknown Request Timed out, Request: %lx Type: %x\n",
                            Request, IrpSp->MinorFunction);
#endif
                RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                break;

            }   // end of switch

        } else {