passthru.c
上传用户:sabrinaco
上传日期:2016-01-19
资源大小:3177k
文件大小:22k
开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 1992-2000  Microsoft Corporation
  3.  
  4. Module Name:
  5.  
  6.     passthru.c
  7. Abstract:
  8.     Ndis Intermediate Miniport driver sample. This is a passthru driver.
  9. Author:
  10. Environment:
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #pragma NDIS_INIT_FUNCTION(DriverEntry)
  16. #define START CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS )
  17. #define RUN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS )
  18. #define USERNUM CTL_CODE(FILE_DEVICE_UNKNOWN, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS )
  19. #define CUT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS )
  20. #define CONNECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x905, METHOD_BUFFERED, FILE_ANY_ACCESS )
  21. #define IP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x906, METHOD_BUFFERED, FILE_ANY_ACCESS )
  22. #define LOOKADAPT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x907, METHOD_BUFFERED, FILE_ANY_ACCESS )
  23. #define SETADAPT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x908, METHOD_BUFFERED, FILE_ANY_ACCESS )
  24. #define OPENADAPT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x909, METHOD_BUFFERED, FILE_ANY_ACCESS )
  25. #define QUERYOID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x90a, METHOD_BUFFERED, FILE_ANY_ACCESS )
  26. #define SETOID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x90b, METHOD_BUFFERED, FILE_ANY_ACCESS )
  27. NDIS_HANDLE                     ProtHandle = NULL;
  28. NDIS_HANDLE                     DriverHandle = NULL;
  29. NDIS_MEDIUM                     MediumArray[4] =
  30.                                     {
  31.                                         NdisMedium802_3,    // Ethernet
  32.                                         NdisMedium802_5,    // Token-ring
  33.                                         NdisMediumFddi,     // Fddi
  34.                                         NdisMediumWan       // NDISWAN
  35.                                     };
  36. NDIS_SPIN_LOCK  GlobalLock;
  37. PADAPT          pAdaptList = NULL;
  38. LONG            MiniportCount = 0;
  39. NDIS_HANDLE     NdisWrapperHandle;
  40. //
  41. // To support ioctls from user-mode:
  42. //
  43. #define LINKNAME_STRING     L"\DosDevices\Passthru"
  44. #define NTDEVICE_STRING     L"\Device\Passthru"
  45. NDIS_HANDLE     NdisDeviceHandle = NULL;
  46. PDEVICE_OBJECT  ControlDeviceObject = NULL;
  47. enum _DEVICE_STATE
  48. {
  49.     PS_DEVICE_STATE_READY = 0,  // ready for create/delete
  50.     PS_DEVICE_STATE_CREATING,   // create operation in progress
  51.     PS_DEVICE_STATE_DELETING    // delete operation in progress
  52. }               ControlDeviceState = PS_DEVICE_STATE_READY;
  53. NTSTATUS
  54. DriverEntry(
  55.     IN  PDRIVER_OBJECT      DriverObject,
  56.     IN  PUNICODE_STRING     RegistryPath
  57.     )
  58. /*++
  59. Routine Description:
  60.     First entry point to be called, when this driver is loaded.
  61.     Register with NDIS as an intermediate driver.
  62. Arguments:
  63.     DriverObject - pointer to the system's driver object structure
  64.         for this driver
  65.     
  66.     RegistryPath - system's registry path for this driver
  67.     
  68. Return Value:
  69.     STATUS_SUCCESS if all initialization is successful, STATUS_XXX
  70.     error code if not.
  71. --*/
  72. {
  73.     NDIS_STATUS                     Status;
  74.     NDIS_PROTOCOL_CHARACTERISTICS   PChars;
  75.     NDIS_MINIPORT_CHARACTERISTICS   MChars;
  76.     PNDIS_CONFIGURATION_PARAMETER   Param;
  77.     NDIS_STRING                     Name;
  78.     int i,j;
  79.     usernum=0;
  80.     for(i=0;i<60;i++)
  81.     {
  82.         for(j=0;j<4;j++)
  83.             ip[i][j]=0;
  84.         packetnum[i]=0;
  85.         num[i]=1;
  86.     }
  87.     NdisAllocateMemoryWithTag(&selectpAdapt, sizeof(ADAPT), TAG);
  88.     NdisInitializeString(&selectpAdapt->DeviceName,"a");
  89.     Status = NDIS_STATUS_SUCCESS;
  90.     NdisAllocateSpinLock(&GlobalLock);
  91.     DbgPrint("hi,stating");
  92.     NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);
  93.     do
  94.     {
  95.         //
  96.         // Register the miniport with NDIS. Note that it is the miniport
  97.         // which was started as a driver and not the protocol. Also the miniport
  98.         // must be registered prior to the protocol since the protocol's BindAdapter
  99.         // handler can be initiated anytime and when it is, it must be ready to
  100.         // start driver instances.
  101.         //
  102.         NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
  103.         MChars.MajorNdisVersion = PASSTHRU_MAJOR_NDIS_VERSION;
  104.         MChars.MinorNdisVersion = PASSTHRU_MINOR_NDIS_VERSION;
  105.         MChars.InitializeHandler = MPInitialize;
  106.         MChars.QueryInformationHandler = MPQueryInformation;
  107.         MChars.SetInformationHandler = MPSetInformation;
  108.         MChars.ResetHandler = MPReset;
  109.         MChars.TransferDataHandler = MPTransferData;
  110.         MChars.HaltHandler = MPHalt;
  111. #ifdef NDIS51_MINIPORT
  112.         MChars.CancelSendPacketsHandler = MPCancelSendPackets;
  113.         MChars.PnPEventNotifyHandler = MPDevicePnPEvent;
  114.         MChars.AdapterShutdownHandler = MPAdapterShutdown;
  115. #endif // NDIS51_MINIPORT
  116.         //
  117.         // We will disable the check for hang timeout so we do not
  118.         // need a check for hang handler!
  119.         //
  120.         MChars.CheckForHangHandler = NULL;
  121.         MChars.ReturnPacketHandler = MPReturnPacket;
  122.         //
  123.         // Either the Send or the SendPackets handler should be specified.
  124.         // If SendPackets handler is specified, SendHandler is ignored
  125.         //
  126.         MChars.SendHandler = NULL;  // MPSend;
  127.         MChars.SendPacketsHandler = MPSendPackets;
  128.         Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle,
  129.                                                &MChars,
  130.                                                sizeof(MChars),
  131.                                                &DriverHandle);
  132.         if (Status != NDIS_STATUS_SUCCESS)
  133.         {
  134.             break;
  135.         }
  136. #ifndef WIN9X
  137.         NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);
  138. #endif
  139.         //
  140.         // Now register the protocol.
  141.         //
  142.         NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  143.         PChars.MajorNdisVersion = PASSTHRU_PROT_MAJOR_NDIS_VERSION;
  144.         PChars.MinorNdisVersion = PASSTHRU_PROT_MINOR_NDIS_VERSION;
  145.         //
  146.         // Make sure the protocol-name matches the service-name
  147.         // (from the INF) under which this protocol is installed.
  148.         // This is needed to ensure that NDIS can correctly determine
  149.         // the binding and call us to bind to miniports below.
  150.         //
  151.         NdisInitUnicodeString(&Name, L"Passthru");  // Protocol name
  152.         PChars.Name = Name;
  153.         PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
  154.         PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
  155.         PChars.SendCompleteHandler = PtSendComplete;
  156.         PChars.TransferDataCompleteHandler = PtTransferDataComplete;
  157.     
  158.         PChars.ResetCompleteHandler = PtResetComplete;
  159.         PChars.RequestCompleteHandler = PtRequestComplete;
  160.         PChars.ReceiveHandler = PtReceive;
  161.         PChars.ReceiveCompleteHandler = PtReceiveComplete;
  162.         PChars.StatusHandler = PtStatus;
  163.         PChars.StatusCompleteHandler = PtStatusComplete;
  164.         PChars.BindAdapterHandler = PtBindAdapter;
  165.         PChars.UnbindAdapterHandler = PtUnbindAdapter;
  166.         PChars.UnloadHandler = PtUnloadProtocol;
  167.         PChars.ReceivePacketHandler = PtReceivePacket;
  168.         PChars.PnPEventHandler= PtPNPHandler;
  169.         NdisRegisterProtocol(&Status,
  170.                             &ProtHandle,
  171.                             &PChars,
  172.                             sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  173.         if (Status != NDIS_STATUS_SUCCESS)
  174.         {
  175.             NdisIMDeregisterLayeredMiniport(DriverHandle);
  176.             break;
  177.         }
  178.         NdisIMAssociateMiniport(DriverHandle, ProtHandle);
  179.     }
  180.     while (FALSE);
  181.     if (Status != NDIS_STATUS_SUCCESS)
  182.     {
  183.         NdisTerminateWrapper(NdisWrapperHandle, NULL);
  184.     }
  185.     return(Status);
  186. }
  187. NDIS_STATUS
  188. PtRegisterDevice(
  189.     VOID
  190.     )
  191. /*++
  192. Routine Description:
  193.     Register an ioctl interface - a device object to be used for this
  194.     purpose is created by NDIS when we call NdisMRegisterDevice.
  195.     This routine is called whenever a new miniport instance is
  196.     initialized. However, we only create one global device object,
  197.     when the first miniport instance is initialized. This routine
  198.     handles potential race conditions with PtDeregisterDevice via
  199.     the ControlDeviceState and MiniportCount variables.
  200.     NOTE: do not call this from DriverEntry; it will prevent the driver
  201.     from being unloaded (e.g. on uninstall).
  202. Arguments:
  203.     None
  204. Return Value:
  205.     NDIS_STATUS_SUCCESS if we successfully register a device object.
  206. --*/
  207. {
  208.     NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;
  209.     UNICODE_STRING      DeviceName;
  210.     UNICODE_STRING      DeviceLinkUnicodeString;
  211.     PDRIVER_DISPATCH    DispatchTable[IRP_MJ_MAXIMUM_FUNCTION];
  212.     UINT                i;
  213.     DBGPRINT(("==>PtRegisterDevicen"));
  214.     NdisAcquireSpinLock(&GlobalLock);
  215.     ++MiniportCount;
  216.     
  217.     if (1 == MiniportCount)
  218.     {
  219.         ASSERT(ControlDeviceState != PS_DEVICE_STATE_CREATING);
  220.         //
  221.         // Another thread could be running PtDeregisterDevice on
  222.         // behalf of another miniport instance. If so, wait for
  223.         // it to exit.
  224.         //
  225.         while (ControlDeviceState != PS_DEVICE_STATE_READY)
  226.         {
  227.             NdisReleaseSpinLock(&GlobalLock);
  228.             NdisMSleep(1);
  229.             NdisAcquireSpinLock(&GlobalLock);
  230.         }
  231.         ControlDeviceState = PS_DEVICE_STATE_CREATING;
  232.         NdisReleaseSpinLock(&GlobalLock);
  233.         for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
  234.         {
  235.             DispatchTable[i] = PtDispatch;
  236.         }
  237.         NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING);
  238.         NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);
  239.         //
  240.         // Create a device object and register our dispatch handlers
  241.         //
  242.         
  243.         Status = NdisMRegisterDevice(
  244.                     NdisWrapperHandle, 
  245.                     &DeviceName,
  246.                     &DeviceLinkUnicodeString,
  247.                     &DispatchTable[0],
  248.                     &ControlDeviceObject,
  249.                     &NdisDeviceHandle
  250.                     );
  251.         NdisAcquireSpinLock(&GlobalLock);
  252.         ControlDeviceState = PS_DEVICE_STATE_READY;
  253.     }
  254.     NdisReleaseSpinLock(&GlobalLock);
  255.     DBGPRINT(("<==PtRegisterDevice: %xn", Status));
  256.     return (Status);
  257. }
  258. NTSTATUS
  259. PtDispatch(
  260.     IN PDEVICE_OBJECT   DeviceObject,
  261.     IN PIRP             Irp
  262.     )
  263. /*++
  264. Routine Description:
  265.     Process IRPs sent to this device.
  266. Arguments:
  267.     DeviceObject - pointer to a device object
  268.     Irp   - pointer to an I/O Request Packet
  269. Return Value:
  270.     NTSTATUS - STATUS_SUCCESS always - change this when adding
  271.     real code to handle ioctls.
  272. --*/
  273. {
  274.     NTSTATUS            status = STATUS_SUCCESS;
  275.     int i;
  276.     PVOID pNext;
  277.     ULONG id;
  278.     ULONG tran=0;
  279.     PADAPT pAdapt;
  280.     POPEN_CONTEXT pOpenContext;
  281.     PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
  282.     PPTUSERIO_OID_DATA pOidData = (PPTUSERIO_OID_DATA)Irp->AssociatedIrp.SystemBuffer;
  283.     // 取得I/O控制代码
  284.     ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  285.     // 取得I/O缓冲区指针和它的长度
  286.     PVOID pIoBuffer = Irp->AssociatedIrp.SystemBuffer;
  287.     ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  288.     ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  289.     pNext=pIoBuffer;
  290.     DBGPRINT(("==>Pt Dispatchn"));
  291.     switch (pIrpStack->MajorFunction)
  292.     {
  293.         case IRP_MJ_CREATE:
  294.             pIrpStack->FileObject->FsContext = NULL;
  295.             pIrpStack->FileObject->FsContext2 = NULL;
  296.             tran=0;
  297.             break;
  298.         case IRP_MJ_CLOSE:
  299.             pOpenContext = (POPEN_CONTEXT)pIrpStack->FileObject->FsContext;
  300.             pIrpStack->FileObject->FsContext = NULL;
  301.             pIrpStack->FileObject->FsContext2 = NULL;
  302.             if(pOpenContext != NULL) // 关闭的是一个适配器句柄
  303.             {
  304.                 if(pOpenContext->pAdapt != NULL)
  305.                 {
  306.                     NdisAcquireSpinLock(&(pOpenContext->pAdapt)->Lock);
  307.                     (pOpenContext->pAdapt)->pOpenContext = NULL;
  308.                     NdisReleaseSpinLock(&(pOpenContext->pAdapt)->Lock);
  309.                  }
  310.                 DevDerefOpenContext(pOpenContext);
  311.             }
  312.             tran=0;
  313.             break;        
  314.         case IRP_MJ_DEVICE_CONTROL:
  315.         switch(uIoControlCode)
  316.         {
  317.             case START:
  318.                 NdisMoveMemory(mac[usernum],(unsigned char*)pIoBuffer,6);
  319.                 usernum++;
  320.                 tran=0;
  321.                 break;
  322.             case RUN:
  323.                 NdisMoveMemory((ULONG *)pIoBuffer,packetnum,240);
  324.                 tran=240;
  325.                 for(i=0;i<60;i++)
  326.                 packetnum[i]=0;
  327.                 break;
  328.             case USERNUM:
  329.                 NdisMoveMemory(&usernum,(ULONG *)pIoBuffer,4);
  330.                 tran=0;
  331.                 break;
  332.             case CUT:
  333.                 NdisMoveMemory(&id,(ULONG *)pIoBuffer,4);
  334.                 num[id]=0;
  335.                 tran=0;
  336.                 break;
  337.             case CONNECT:
  338.                 NdisMoveMemory(&id,(ULONG *)pIoBuffer,4);
  339.                 num[id]=1;
  340.                 tran=0;
  341.                 break;
  342.             case IP:
  343.                 for(i=0;i<60;i++)
  344.                 NdisMoveMemory((UCHAR *)pNext+i*4,ip[i],4);
  345.                 tran=240;
  346.                 break;
  347.             case LOOKADAPT:
  348.                 GetBindingList(pIoBuffer,uOutSize,&tran);
  349.                 break;
  350.             case SETADAPT:
  351.                 break;
  352.             case OPENADAPT:
  353.                 pAdapt=LookupAdaptByName((PUCHAR)pIoBuffer,uInSize);
  354.                 if(pAdapt==NULL)
  355.                 {
  356.                     status= STATUS_OBJECT_NAME_NOT_FOUND;
  357.                     break;
  358.                 }
  359.                  // 如果正在Unbind,则失败
  360.                 NdisAcquireSpinLock(&pAdapt->Lock);
  361.                 if(pAdapt->UnbindingInProcess)
  362.                 {
  363.                     NdisReleaseSpinLock(&pAdapt->Lock);
  364.                     PtDerefAdapter(pAdapt);
  365.                     status = STATUS_INVALID_DEVICE_STATE;
  366.                     break;
  367.                 }
  368.                 NdisReleaseSpinLock(&pAdapt->Lock);
  369.                  // 如果适配器已经打开,则失败
  370.                 if(pAdapt->pOpenContext != NULL)
  371.                 {
  372.                     PtDerefAdapter(pAdapt);
  373.                     status = STATUS_DEVICE_BUSY;
  374.                     break;
  375.                 }
  376.                 pOpenContext = DevAllocateOpenContext(pAdapt);
  377.                 if(pOpenContext == NULL)
  378.                 {
  379.                     PtDerefAdapter(pAdapt);
  380.                     status = STATUS_INSUFFICIENT_RESOURCES;
  381.                     break;
  382.                 }
  383.                 if(InterlockedCompareExchangePointer(&(pAdapt->pOpenContext),
  384.                                                     pOpenContext, NULL) != NULL)
  385.                 {
  386.                     PtDerefAdapter(pAdapt);
  387.                     status = STATUS_DEVICE_BUSY;
  388.                     break;
  389.                 }
  390.                 selectpAdapt=pAdapt;
  391.             // 将打开环境与句柄关联
  392.                 pIrpStack->FileObject->FsContext = pOpenContext;
  393.                 status = STATUS_SUCCESS;
  394.                 tran=0;
  395.                 break;
  396.             case SETOID:
  397.             case QUERYOID:
  398.                 status = STATUS_INVALID_DEVICE_REQUEST;
  399.                 do
  400.                 {
  401.                     // 取得与此句柄关联的OPEN_CONTEXT结构的指针 // 首先检查此句柄是否打开适配器
  402.                     pOpenContext = (POPEN_CONTEXT)pIrpStack->FileObject->FsContext;
  403.                     if(pOpenContext == NULL)
  404.                     {
  405.                         status = STATUS_INVALID_HANDLE;
  406.                         break;
  407.                     }
  408.                     pAdapt = pOpenContext->pAdapt;
  409.                     if(pAdapt == NULL)
  410.                     {
  411.                         status = STATUS_INVALID_HANDLE;
  412.                         break;
  413.                     }
  414.         
  415.                      // 检查缓冲区
  416.                     if(uOutSize != uInSize || uOutSize < sizeof(PTUSERIO_OID_DATA) ||
  417.                     uOutSize < sizeof(PTUSERIO_OID_DATA) - 1 + pOidData->Length)
  418.                     {
  419.                         status = STATUS_INVALID_PARAMETER;
  420.                         break;
  421.                     }
  422.                      // 如果Unbind正在进行,则失败
  423.                     NdisAcquireSpinLock(&pAdapt->Lock);
  424.                     if( pAdapt->UnbindingInProcess )
  425.                     {
  426.                          NdisReleaseSpinLock(&pAdapt->Lock);
  427.                          DBGPRINT(( "      Unbind In Processn" ));
  428.                          status = STATUS_INVALID_DEVICE_STATE;
  429.                          break;
  430.                     }
  431.                     // All other queries are failed, if the miniport is not at D0,
  432.                     if (pAdapt->MPDeviceState > NdisDeviceStateD0)
  433.                     {
  434.                         NdisReleaseSpinLock(&pAdapt->Lock);
  435.                         DBGPRINT(( "      Invalid Miniport Device Staten" ));
  436.                         status = STATUS_INVALID_DEVICE_STATE;
  437.                         break;
  438.                     }
  439.                     // This is in the process of powering down the system, always fail the request
  440.                    if (pAdapt->StandingBy == TRUE)
  441.                    {
  442.                         NdisReleaseSpinLock(&pAdapt->Lock);
  443.                         DBGPRINT(( "      Miniport Powering Downn" ));
  444.                         status = STATUS_INVALID_DEVICE_STATE;
  445.                         break;
  446.                     }
  447.                     NdisReleaseSpinLock(&pAdapt->Lock);
  448.                     // 检查完毕,最后,进行这个请求
  449.                     DevRefOpenContext(pOpenContext);
  450.                     // 初始化NDIS_REQUEST结构
  451.                     NdisZeroMemory(&pOpenContext->Request, sizeof(pOpenContext->Request));
  452.                     if(uIoControlCode == SETOID)
  453.                     { 
  454.                          pOpenContext->Request.RequestType = NdisRequestSetInformation;
  455.                          pOpenContext->Request.DATA.SET_INFORMATION.Oid = pOidData->Oid;
  456.                          pOpenContext->Request.DATA.SET_INFORMATION.InformationBuffer = pOidData->Data;
  457.                          pOpenContext->Request.DATA.SET_INFORMATION.InformationBufferLength = pOidData->Length;
  458.                     }
  459.                     else
  460.                     {
  461.                          pOpenContext->Request.RequestType = NdisRequestQueryInformation;
  462.                          pOpenContext->Request.DATA.QUERY_INFORMATION.Oid = pOidData->Oid;
  463.                          pOpenContext->Request.DATA.QUERY_INFORMATION.InformationBuffer = pOidData->Data;
  464.                          pOpenContext->Request.DATA.QUERY_INFORMATION.InformationBufferLength = pOidData->Length;
  465.                     }
  466.                     NdisResetEvent( &pOpenContext->RequestEvent);
  467.                     NdisRequest(&status, pAdapt->BindingHandle, &pOpenContext->Request);
  468.                     if(status != NDIS_STATUS_PENDING)
  469.                     {
  470.                          DevRequestComplete(pAdapt, &pOpenContext->Request, status);
  471.                     }
  472.                     // 等待请求的完成,即等待Ndis调用DevRequestComplete例程
  473.                     NdisWaitEvent(&pOpenContext->RequestEvent, 0);
  474.                     if(pOpenContext->RequestStatus == NDIS_STATUS_SUCCESS)
  475.                     {
  476.                          if(uIoControlCode == SETOID)
  477.                          {
  478.                              pOidData->Length = pOpenContext->Request.DATA.SET_INFORMATION.BytesRead;
  479.                          }
  480.                         else if(uIoControlCode == QUERYOID)
  481.                          {
  482.                              pOidData->Length = pOpenContext->Request.DATA.QUERY_INFORMATION.BytesWritten;
  483.                          }
  484.                         // 设置返回给I/O管理器的信息
  485.                         tran = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  486.                         status = STATUS_SUCCESS;
  487.                     }
  488.                     else
  489.                     {
  490.                         status = STATUS_UNSUCCESSFUL;
  491.                     }
  492.                     DevDerefOpenContext(pOpenContext);
  493.                 }while(FALSE);
  494.                 break;
  495.         default:
  496.             break;
  497.         }
  498.     }
  499.     Irp->IoStatus.Information = tran;
  500.     Irp->IoStatus.Status = status;
  501.     IoCompleteRequest(Irp, IO_NO_INCREMENT);
  502.     DBGPRINT(("<== Pt Dispatchn"));
  503.     return status;
  504. NDIS_STATUS
  505. PtDeregisterDevice(
  506.     VOID
  507.     )
  508. /*++
  509. Routine Description:
  510.     Deregister the ioctl interface. This is called whenever a miniport
  511.     instance is halted. When the last miniport instance is halted, we
  512.     request NDIS to delete the device object
  513. Arguments:
  514.     NdisDeviceHandle - Handle returned by NdisMRegisterDevice
  515. Return Value:
  516.     NDIS_STATUS_SUCCESS if everything worked ok
  517. --*/
  518. {
  519.     NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  520.     DBGPRINT(("==>PassthruDeregisterDevicen"));
  521.     NdisAcquireSpinLock(&GlobalLock);
  522.     ASSERT(MiniportCount > 0);
  523.     --MiniportCount;
  524.     
  525.     if (0 == MiniportCount)
  526.     {
  527.         //
  528.         // All miniport instances have been halted. Deregister
  529.         // the control device.
  530.         //
  531.         ASSERT(ControlDeviceState == PS_DEVICE_STATE_READY);
  532.         //
  533.         // Block PtRegisterDevice() while we release the control
  534.         // device lock and deregister the device.
  535.         // 
  536.         ControlDeviceState = PS_DEVICE_STATE_DELETING;
  537.         NdisReleaseSpinLock(&GlobalLock);
  538.         if (NdisDeviceHandle != NULL)
  539.         {
  540.             Status = NdisMDeregisterDevice(NdisDeviceHandle);
  541.             NdisDeviceHandle = NULL;
  542.         }
  543.         NdisAcquireSpinLock(&GlobalLock);
  544.         ControlDeviceState = PS_DEVICE_STATE_READY;
  545.     }
  546.     NdisReleaseSpinLock(&GlobalLock);
  547.     DBGPRINT(("<== PassthruDeregisterDevice: %xn", Status));
  548.     return Status;
  549.     
  550. }
  551. VOID
  552. PtUnloadProtocol(
  553.     VOID
  554. )
  555. {
  556.     NDIS_STATUS Status;
  557.     if (ProtHandle != NULL)
  558.     {
  559.         NdisDeregisterProtocol(&Status, ProtHandle);
  560.         ProtHandle = NULL;
  561.     }
  562.     DBGPRINT(("PtUnloadProtocol: done!n"));
  563. }