pnp.c
上传用户:zanmei2
上传日期:2010-03-06
资源大小:775k
文件大小:17k
源码类别:

通讯编程文档

开发平台:

C/C++

  1. /*++
  2. Copyright (c) 2005  Changzhi Zhou All Rights Reserved
  3. Module Name:
  4.     pnp.c
  5. Abstract:
  6.     This module works for the handles Plug&Play dispatch.
  7. Environment:
  8.     Kernel mode
  9. Revision History:
  10. Changzhi Zhou Dec 20  2004
  11. --*/
  12. #include <ntddk.h>
  13. #include <initguid.h>
  14. #include "main.h"
  15. #include "tdiclient.h"
  16. #include "..incwdmioctl.h"
  17. NTSTATUS
  18. SamplePnpDispatch (
  19.     IN PDEVICE_OBJECT DeviceObject,
  20.     IN PIRP Irp
  21.     )
  22. /*++
  23. Routine Description:
  24.     The plug and play dispatch routines.
  25.     Most of these the driver will completely ignore.
  26.     In all cases it must pass on the IRP to the lower driver.
  27. Arguments:
  28.    DeviceObject - pointer to a device object.
  29.    Irp - pointer to an I/O Request Packet.
  30. Return Value:
  31.       NT status code
  32. --*/
  33. {
  34.     PDEVICE_EXTENSION   deviceExtension;
  35.     PIO_STACK_LOCATION  irpStack;
  36.     NTSTATUS            status;
  37.     KEVENT              event;
  38. KIRQL oldIrql;
  39.     PAGED_CODE();
  40.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  41. irpStack = IoGetCurrentIrpStackLocation(Irp);
  42.     DebugPrint(("Sample %s IRP:0x%x n", PnPMinorFunctionString(irpStack->MinorFunction), Irp));
  43. if ( Removed == deviceExtension->DevicePnPState) {
  44.         status = STATUS_DELETE_PENDING;
  45. return CompleteRequest(Irp, status, 0 );
  46.     }
  47. status = STATUS_SUCCESS;
  48. SampleIoIncrement( deviceExtension );
  49.     
  50.     switch (irpStack->MinorFunction) {
  51.     case IRP_MN_START_DEVICE:
  52. status = PnpStartDevice( DeviceObject, Irp);
  53. break;
  54.     case IRP_MN_QUERY_STOP_DEVICE:
  55. status = PnpQueryStopDevice( DeviceObject, Irp );
  56. return status;
  57.     case IRP_MN_CANCEL_STOP_DEVICE:
  58. status = PnpCancelStopDevice( DeviceObject, Irp );
  59. break;
  60.     case IRP_MN_STOP_DEVICE:
  61.         SET_NEW_PNP_STATE(deviceExtension, Stopped);
  62. SampleIoDecrement( deviceExtension );
  63.   status = DefaultPnpHandler( DeviceObject, Irp );
  64. return status;
  65.     case IRP_MN_QUERY_REMOVE_DEVICE:
  66. status = PnpQueryRemoveDevice( DeviceObject, Irp );
  67. return status;
  68.     case IRP_MN_CANCEL_REMOVE_DEVICE:
  69. status = PnpCancelRemoveDevice( DeviceObject, Irp );
  70. break;
  71.     case IRP_MN_REMOVE_DEVICE:
  72. status = PnpRemoveDevice( DeviceObject, Irp );        
  73.         return status;
  74.     case IRP_MN_SURPRISE_REMOVAL:
  75. status = PnpSurpriseRemoval( DeviceObject, Irp );
  76. SampleIoDecrement( deviceExtension );
  77.         return status;
  78. case IRP_MN_QUERY_CAPABILITIES:
  79. return PnpQueryCapabilities( DeviceObject, Irp );
  80.     default:
  81.         IoSkipCurrentIrpStackLocation(Irp);
  82.         status = IoCallDriver(deviceExtension->NextLowerDriver, Irp);
  83. SampleIoDecrement(deviceExtension);
  84. return status;
  85.     }
  86. CompleteRequest( Irp, status, 0 );
  87.     SampleIoDecrement(deviceExtension);
  88. return status;
  89. }
  90. NTSTATUS PnpStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  91. /*++
  92. Routine Description:
  93. Pnp handler to IRP_MN_START_DEVICE.
  94. Arguments:
  95.     deviceExtension - pointer to a device object extension.
  96. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  97. Return Value:
  98.     NT status code.
  99. --*/
  100. {
  101.     NTSTATUS status;
  102. PDEVICE_EXTENSION deviceExtension;
  103.     PIO_STACK_LOCATION irpStack;
  104. KIRQL oldIrql;
  105. deviceExtension = DeviceObject->DeviceExtension;
  106. status = ForwardAndWait( DeviceObject, Irp);
  107.     if ( !NT_SUCCESS( status ) )
  108.         return CompleteRequest(Irp, status, Irp->IoStatus.Information);
  109. irpStack = IoGetCurrentIrpStackLocation( Irp );
  110. //status = CreateWorkThread( deviceExtension );
  111. // Open transport address, set clienteventhandler and initialize recvContext.
  112. status = InitializeConnection( deviceExtension );
  113. if( NT_SUCCESS( status ) && NT_SUCCESS( Irp->IoStatus.Status ) ){
  114. status = IoSetDeviceInterfaceState( &deviceExtension->InterfaceName, TRUE );
  115. if( !NT_SUCCESS( status )){
  116. DebugPrint(( "StartDevice:  IoSetDeviceInterfaceState failed (%x)n", status ));
  117. }
  118. SET_NEW_PNP_STATE( deviceExtension, Working );
  119. }
  120.     return status;
  121. }
  122. NTSTATUS
  123. PnpQueryStopDevice(
  124.     IN PDEVICE_OBJECT DeviceObject,
  125.     IN PIRP           Irp
  126.     )
  127. /*++
  128. Routine Description:
  129. Pnp handler to IRP_MN_QUERY_STOP_DEVICE.
  130. Arguments:
  131.     deviceExtension - pointer to a device object extension.
  132. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  133. Return Value:
  134.     NT status code.
  135. --*/
  136. {
  137.     KIRQL             oldIrql;
  138.     NTSTATUS          status;
  139.     PDEVICE_EXTENSION deviceExtension;
  140.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  141.     //
  142.     // If we can stop the device, we need to set the QueueState to 
  143.     // PendingStop so further requests will be queued.
  144.     //
  145.     SET_NEW_PNP_STATE(deviceExtension, PendingStop);
  146.     SampleIoDecrement( deviceExtension );
  147.     KeWaitForSingleObject(&deviceExtension->StopEvent,
  148.                           Executive,
  149.                           KernelMode,
  150.                           FALSE,
  151.                           NULL);
  152. status = DefaultPnpHandler( DeviceObject, Irp );
  153.     return status;
  154. }
  155. NTSTATUS
  156. PnpCancelStopDevice(
  157.     IN PDEVICE_OBJECT DeviceObject,
  158.     IN PIRP           Irp
  159.     )
  160. /*++
  161. Routine Description:
  162. Pnp handler to IRP_MN_CANCEL_STOP_DEVICE.
  163. Arguments:
  164.     deviceExtension - pointer to a device object extension.
  165. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  166. Return Value:
  167.     NT status code.
  168. --*/
  169. {
  170.     KIRQL             oldIrql;    
  171.     KEVENT            event;
  172.     NTSTATUS          status;
  173.     PDEVICE_EXTENSION deviceExtension;
  174.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  175.     //
  176.     // Send this IRP down and wait for it to come back.
  177.     // Set the QueueState flag to AllowRequests, 
  178.     // and process all the previously queued up IRPs.
  179.     //
  180.     //
  181.     // First check to see whether you have received cancel-stop
  182.     // without first receiving a query-stop. This could happen if someone
  183.     // above us fails a query-stop and passes down the subsequent
  184.     // cancel-stop.
  185.     //
  186.     if(PendingStop == deviceExtension->DevicePnPState) {
  187. status = ForwardAndWait( DeviceObject, Irp );
  188.         if(NT_SUCCESS( status )) {
  189.             RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
  190.         }
  191.     }
  192.     else {
  193.         status = STATUS_SUCCESS;
  194.     }
  195.     return status;
  196. }
  197. NTSTATUS
  198. PnpQueryRemoveDevice(
  199.     IN PDEVICE_OBJECT DeviceObject,
  200.     IN PIRP           Irp
  201.     )
  202. /*++
  203. Routine Description:
  204. Pnp handler to IRP_MN_QUERY_REMOVE_DEVICE.
  205. Arguments:
  206.     deviceExtension - pointer to a device object extension.
  207. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  208. Return Value:
  209.     NT status code.
  210. --*/
  211. {
  212. #define WDM_DELAY_VALUE            (ULONG)(-1 * 20000 * 1000)     // 2s
  213.     KIRQL             oldIrql;
  214.     NTSTATUS          status;
  215.     PDEVICE_EXTENSION deviceExtension;
  216.     LARGE_INTEGER deltaTime;
  217.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  218.     SampleIoDecrement( deviceExtension );
  219. deltaTime.LowPart = WDM_DELAY_VALUE;
  220. deltaTime.HighPart = -1;
  221.     //
  222.     // Wait deltaTime for all the requests to be completed.
  223.     // If timeout, that means some Irps haven't be completed.
  224. // So we will simply return Device_Busy and not pass down to lower driver.
  225. //
  226.     status = KeWaitForSingleObject(&deviceExtension->StopEvent, 
  227.                           Executive,
  228.                           KernelMode,
  229.                           FALSE,
  230.                           &deltaTime);
  231. if( STATUS_TIMEOUT == status )
  232. return CompleteRequest( Irp, STATUS_DEVICE_BUSY, 0 );
  233.     //
  234.     // If we can allow removal of the device, we should set the QueueState
  235.     // to HoldRequests so further requests will be queued. This is required
  236.     // so that we can process queued up requests in cancel-remove just in 
  237.     // case somebody else in the stack fails the query-remove. 
  238.     //
  239.     SET_NEW_PNP_STATE(deviceExtension, PendingRemove );
  240. status = DefaultPnpHandler( DeviceObject, Irp );
  241.     return status;
  242. }
  243. NTSTATUS
  244. PnpCancelRemoveDevice(
  245.     IN PDEVICE_OBJECT DeviceObject,
  246.     IN PIRP           Irp
  247.     )
  248. /*++
  249. Routine Description:
  250. Pnp handler to IRP_MN_CANEL_REMOVE_DEVICE.
  251. Arguments:
  252.     deviceExtension - pointer to a device object extension.
  253. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  254. Return Value:
  255.     NT status code.
  256. --*/
  257. {
  258.     NTSTATUS          status;
  259.     PDEVICE_EXTENSION deviceExtension;
  260. KIRQL oldIrql;
  261.     //
  262.     // initialize variables
  263.     //
  264.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  265.     //
  266.     // We need to reset the QueueState flag to ProcessRequest, 
  267.     // since the device resume its normal activities.
  268.     //
  269.     //
  270.     // First check to see whether you have received cancel-remove
  271.     // without first receiving a query-remove. This could happen if 
  272.     // someone above us fails a query-remove and passes down the 
  273.     // subsequent cancel-remove.
  274.     //
  275.     if(PendingRemove == deviceExtension->DevicePnPState) {
  276. status = ForwardAndWait( DeviceObject, Irp );
  277.         if(NT_SUCCESS( status )) {
  278.             RESTORE_PREVIOUS_PNP_STATE( deviceExtension );
  279.         }
  280. // Re-start workthread. omit now.
  281. //
  282.     }
  283.     else {
  284.         // 
  285.         // spurious cancel-remove
  286.         //
  287.         status = STATUS_SUCCESS;
  288.     }
  289.     return status;
  290. }
  291. NTSTATUS PnpRemoveDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  292. /*++
  293. Routine Description:
  294. Pnp handler to IRP_MN_REMOVE_DEVICE.
  295. Arguments:
  296.     deviceExtension - pointer to a device object extension.
  297. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  298. Return Value:
  299.     NT status code.
  300. --*/
  301. {
  302. NTSTATUS status;
  303. PDEVICE_EXTENSION deviceExtension;
  304. KIRQL oldIrql;
  305. ULONG requestCount;
  306. DebugPrint(("+Enter RemoveDevice routinen" ));
  307. deviceExtension = DeviceObject->DeviceExtension;
  308. //  TODO: handle our remove work at first
  309. if ( SurpriseRemoved != deviceExtension->DevicePnPState )
  310. {
  311. //
  312. // If the device is not surprise removed, we should call set interface to FALSE.
  313. // If surprise removed, This step has been called in SurprisedRemoved handle.
  314. //
  315. status = IoSetDeviceInterfaceState( &deviceExtension->InterfaceName, FALSE );
  316. if( !NT_SUCCESS( status ) ){
  317. DebugPrint(( "RemoveDevice: IoSetDeviceInterfaceState failed (%x)n", status ));
  318. }
  319. }
  320. // set new PNP state
  321. SET_NEW_PNP_STATE(deviceExtension, Removed );
  322.     requestCount = SampleIoDecrement( deviceExtension );
  323.     ASSERT(requestCount > 0);
  324.     requestCount = SampleIoDecrement( deviceExtension );
  325.     KeWaitForSingleObject(&deviceExtension->RemoveEvent, 
  326.                           Executive, 
  327.                           KernelMode, 
  328.                           FALSE, 
  329.                           NULL);
  330. Disconnection( deviceExtension );
  331. // Unregister serial DosName and delete register
  332. SerialUndoExternalNaming( deviceExtension );
  333. // delete buffer pool used for device name , dos name and others.
  334. SerialRemoveDevObj( DeviceObject );
  335. RtlFreeUnicodeString( &deviceExtension->InterfaceName );
  336. Disconnection( deviceExtension );
  337. if ( deviceExtension->RxBuffer )
  338. ExFreePool ( deviceExtension->RxBuffer );
  339. if ( deviceExtension->recvContext.RemainderBuffer )
  340. ExFreePool ( deviceExtension->recvContext.RemainderBuffer );
  341. // Pass down the IRP
  342. status = DefaultPnpHandler( DeviceObject, Irp );
  343. IoDetachDevice( deviceExtension->NextLowerDriver );
  344. //
  345. // Free up interface memory
  346. //
  347. IoDeleteDevice( DeviceObject );
  348. DebugPrint(("-Exit RemoveDevice routinen"));
  349. return status;
  350. }
  351. NTSTATUS
  352. PnpSurpriseRemoval(
  353.     IN PDEVICE_OBJECT DeviceObject,
  354.     IN PIRP           Irp
  355. )
  356. /*++
  357. Routine Description:
  358. Pnp handler to IRP_MN_SURPRISE_REMOVAL.
  359. Arguments:
  360.     deviceExtension - pointer to a device object extension.
  361. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  362. Return Value:
  363.     NT status code.
  364. --*/
  365. {
  366. KIRQL             oldIrql;
  367.     NTSTATUS          status;
  368.     PDEVICE_EXTENSION deviceExtension;
  369.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  370. // set new PNP state
  371. SET_NEW_PNP_STATE(deviceExtension, SurpriseRemoved );
  372. status = IoSetDeviceInterfaceState( &deviceExtension->InterfaceName, FALSE );
  373. if( !NT_SUCCESS( status ) ){
  374. DebugPrint(( "RemoveDevice: IoSetDeviceInterfaceState failed (%x)n", status ));
  375. }
  376. status = DefaultPnpHandler( DeviceObject, Irp );
  377. return status;
  378. }
  379. NTSTATUS PnpQueryCapabilities( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  380. /*++
  381. Routine Description:
  382. Pnp handler to IRP_MN_QUERY_CAPABILITIES.
  383. Arguments:
  384.     deviceExtension - pointer to a device object extension.
  385. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  386. Return Value:
  387.     NT status code.
  388. --*/
  389. {
  390.     NTSTATUS status;
  391. PIO_STACK_LOCATION      stack;
  392.     PDEVICE_CAPABILITIES    deviceCapabilities;
  393.     PAGED_CODE ();
  394. status = ForwardAndWait( DeviceObject, Irp );
  395.     stack = IoGetCurrentIrpStackLocation (Irp);
  396.     //
  397.     // add our device's capabilities.
  398.     //
  399.     deviceCapabilities = stack->Parameters.DeviceCapabilities.Capabilities;
  400. //
  401. // thess mean the device is Removeable and NOT surprise removed.
  402. // If user force to surprise remove the device, "Unsafe remove device" dialog will appear.
  403. //
  404. deviceCapabilities->SurpriseRemovalOK = FALSE;
  405. //deviceCapabilities->Removable = TRUE;
  406. status = CompleteRequest( Irp, status, Irp->IoStatus.Information );
  407.     SampleIoDecrement( DeviceObject->DeviceExtension );
  408. return status;
  409. }
  410. NTSTATUS DefaultPnpHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  411. {
  412. PDEVICE_EXTENSION deviceExtension;
  413.     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  414.     IoSkipCurrentIrpStackLocation( Irp );
  415.     return IoCallDriver( deviceExtension->NextLowerDriver, Irp);
  416. }
  417. NTSTATUS ForwardAndWait(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  418. /*++
  419. Routine Description:
  420. pass down Irp to lower driver and wait for its completion.
  421. Arguments:
  422.     deviceExtension - pointer to a device object extension.
  423. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  424. Return Value:
  425.     NT status code.
  426. --*/
  427. {
  428.     KEVENT event;
  429.     NTSTATUS status;
  430. PDEVICE_EXTENSION deviceExtension;
  431. deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
  432.     
  433. KeInitializeEvent(&event, NotificationEvent, FALSE);
  434.     IoCopyCurrentIrpStackLocationToNext( Irp );
  435.     IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) 
  436.         OnRequestComplete, (PVOID) &event, TRUE, TRUE, TRUE);
  437. status = IoCallDriver( deviceExtension->NextLowerDriver, Irp);
  438.     if (status == STATUS_PENDING)
  439.     {                       // wait for completion
  440.         KeWaitForSingleObject(
  441. &event,
  442. Executive, // Waiting for reasion of a driver
  443. KernelMode, // Waiting in kernel mode
  444. FALSE, // No alert
  445. NULL); // No timeout
  446.         status = Irp->IoStatus.Status;
  447.     }                       // wait for completion
  448.     return status;
  449. }
  450. NTSTATUS OnRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
  451.     IN PKEVENT event)
  452. {
  453.     KeSetEvent( event, 0, FALSE);
  454.     return STATUS_MORE_PROCESSING_REQUIRED;
  455. }
  456. #if DBG
  457. PCHAR
  458. PnPMinorFunctionString (
  459.     UCHAR MinorFunction
  460. )
  461. /*++
  462. Routine Description:
  463. Print PnP Irp's minor function informaion.
  464. Arguments:
  465.     deviceExtension - pointer to a device object extension.
  466. Irp - the pointer to PnP IRP_MN_START_DEVICE Irp.
  467. Return Value:
  468.     NT status code.
  469. --*/
  470. {
  471.     switch (MinorFunction)
  472.     {
  473.         case IRP_MN_START_DEVICE:
  474.             return "IRP_MN_START_DEVICE";
  475.         case IRP_MN_QUERY_REMOVE_DEVICE:
  476.             return "IRP_MN_QUERY_REMOVE_DEVICE";
  477.         case IRP_MN_REMOVE_DEVICE:
  478.             return "IRP_MN_REMOVE_DEVICE";
  479.         case IRP_MN_CANCEL_REMOVE_DEVICE:
  480.             return "IRP_MN_CANCEL_REMOVE_DEVICE";
  481.         case IRP_MN_STOP_DEVICE:
  482.             return "IRP_MN_STOP_DEVICE";
  483.         case IRP_MN_QUERY_STOP_DEVICE:
  484.             return "IRP_MN_QUERY_STOP_DEVICE";
  485.         case IRP_MN_CANCEL_STOP_DEVICE:
  486.             return "IRP_MN_CANCEL_STOP_DEVICE";
  487.         case IRP_MN_QUERY_DEVICE_RELATIONS:
  488.             return "IRP_MN_QUERY_DEVICE_RELATIONS";
  489.         case IRP_MN_QUERY_INTERFACE:
  490.             return "IRP_MN_QUERY_INTERFACE";
  491.         case IRP_MN_QUERY_CAPABILITIES:
  492.             return "IRP_MN_QUERY_CAPABILITIES";
  493.         case IRP_MN_QUERY_RESOURCES:
  494.             return "IRP_MN_QUERY_RESOURCES";
  495.         case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  496.             return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
  497.         case IRP_MN_QUERY_DEVICE_TEXT:
  498.             return "IRP_MN_QUERY_DEVICE_TEXT";
  499.         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  500.             return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
  501.         case IRP_MN_READ_CONFIG:
  502.             return "IRP_MN_READ_CONFIG";
  503.         case IRP_MN_WRITE_CONFIG:
  504.             return "IRP_MN_WRITE_CONFIG";
  505.         case IRP_MN_EJECT:
  506.             return "IRP_MN_EJECT";
  507.         case IRP_MN_SET_LOCK:
  508.             return "IRP_MN_SET_LOCK";
  509.         case IRP_MN_QUERY_ID:
  510.             return "IRP_MN_QUERY_ID";
  511.         case IRP_MN_QUERY_PNP_DEVICE_STATE:
  512.             return "IRP_MN_QUERY_PNP_DEVICE_STATE";
  513.         case IRP_MN_QUERY_BUS_INFORMATION:
  514.             return "IRP_MN_QUERY_BUS_INFORMATION";
  515.         case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  516.             return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
  517.         case IRP_MN_SURPRISE_REMOVAL:
  518.             return "IRP_MN_SURPRISE_REMOVAL";
  519.             
  520.         default:
  521.             return "IRP_MN_?????";
  522.     }
  523. }
  524. #endif