Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2887 lines
71 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. pnp.c
  5. Abstract:
  6. This file contains RAM disk driver code for processing PnP IRPs.
  7. Author:
  8. Chuck Lenzmeier (ChuckL) 2001
  9. Environment:
  10. Kernel mode only.
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. //
  17. // Registry value format for virtual floppy disks created by textmode setup.
  18. // Should be in a header file, but that's not the way it was done for the
  19. // original virtual floppy driver.
  20. //
  21. typedef struct _VIRTUAL_FLOPPY_DESCRIPTOR {
  22. //
  23. // The structure starts with a system virtual address. On 32-bit systems,
  24. // this is padded to 64 bits.
  25. //
  26. union {
  27. PVOID VirtualAddress;
  28. ULONGLONG Reserved; // align to 64 bits
  29. } ;
  30. //
  31. // The length of the virtual floppy comes next.
  32. //
  33. ULONG Length;
  34. //
  35. // Textmode writes the registry value with 12 bytes of data. In order
  36. // to get the right size for our check, we use of the field offset of
  37. // the following field. We can't use sizeof a struct that just has the
  38. // above fields, because that comes out as 16 bytes due to alignment.
  39. //
  40. ULONG StructSizer;
  41. } VIRTUAL_FLOPPY_DESCRIPTOR, *PVIRTUAL_FLOPPY_DESCRIPTOR;
  42. #if !DBG
  43. #define PRINT_CODE( _code )
  44. #else
  45. #define PRINT_CODE( _code ) \
  46. if ( print ) { \
  47. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("%s", " " #_code "\n") ); \
  48. } \
  49. print = FALSE;
  50. #endif
  51. #if DBG
  52. PSTR StateTable[] = {
  53. "STOPPED",
  54. "WORKING",
  55. "PENDINGSTOP",
  56. "PENDINGREMOVE",
  57. "SURPRISEREMOVED",
  58. "REMOVED",
  59. "UNKNOWN"
  60. };
  61. #endif // DBG
  62. //
  63. // Local functions.
  64. //
  65. NTSTATUS
  66. RamdiskDeleteDiskDevice (
  67. IN PDEVICE_OBJECT DeviceObject,
  68. IN PIRP Irp OPTIONAL
  69. );
  70. NTSTATUS
  71. RamdiskIoCompletionRoutine (
  72. IN PDEVICE_OBJECT DeviceObject,
  73. IN PIRP Irp,
  74. IN PKEVENT Event
  75. );
  76. NTSTATUS
  77. RamdiskQueryBusInformation (
  78. IN PDEVICE_OBJECT DeviceObject,
  79. IN PIRP Irp
  80. );
  81. NTSTATUS
  82. RamdiskQueryCapabilities (
  83. IN PDEVICE_OBJECT DeviceObject,
  84. IN PIRP Irp
  85. );
  86. NTSTATUS
  87. RamdiskQueryId (
  88. IN PDISK_EXTENSION DiskExtension,
  89. IN PIRP Irp
  90. );
  91. NTSTATUS
  92. RamdiskQueryDeviceRelations (
  93. IN DEVICE_RELATION_TYPE RelationsType,
  94. IN PDEVICE_OBJECT DeviceObject,
  95. IN PIRP Irp
  96. );
  97. NTSTATUS
  98. RamdiskQueryDeviceText (
  99. IN PDISK_EXTENSION DiskExtension,
  100. IN PIRP Irp
  101. );
  102. NTSTATUS
  103. RamdiskRemoveBusDevice (
  104. IN PDEVICE_OBJECT DeviceObject,
  105. IN PIRP Irp
  106. );
  107. #if DBG
  108. PSTR
  109. GetPnpIrpName (
  110. IN UCHAR PnpMinorFunction
  111. );
  112. PCHAR
  113. GetDeviceRelationString (
  114. IN DEVICE_RELATION_TYPE Type
  115. );
  116. #endif // DBG
  117. //
  118. // Declare pageable routines.
  119. //
  120. #ifdef ALLOC_PRAGMA
  121. #pragma alloc_text( PAGE, RamdiskPnp )
  122. #pragma alloc_text( PAGE, RamdiskPower )
  123. #pragma alloc_text( PAGE, RamdiskAddDevice )
  124. #pragma alloc_text( PAGE, CreateRegistryDisks )
  125. #pragma alloc_text( PAGE, RamdiskDeleteDiskDevice )
  126. #pragma alloc_text( PAGE, RamdiskQueryBusInformation )
  127. #pragma alloc_text( PAGE, RamdiskQueryCapabilities )
  128. #pragma alloc_text( PAGE, RamdiskQueryId )
  129. #pragma alloc_text( PAGE, RamdiskQueryDeviceRelations )
  130. #pragma alloc_text( PAGE, RamdiskQueryDeviceText )
  131. #pragma alloc_text( PAGE, RamdiskRemoveBusDevice )
  132. #if DBG
  133. #pragma alloc_text( PAGE, GetPnpIrpName )
  134. #pragma alloc_text( PAGE, GetDeviceRelationString )
  135. #endif // DBG
  136. #endif // ALLOC_PRAGMA
  137. NTSTATUS
  138. RamdiskPnp (
  139. IN PDEVICE_OBJECT DeviceObject,
  140. IN PIRP Irp
  141. )
  142. /*++
  143. Routine Description:
  144. This routine is called by the I/O system to perform a PnP function.
  145. Arguments:
  146. DeviceObject - a pointer to the object that represents the device on which
  147. I/O is to be performed
  148. Irp - a pointer to the I/O Request Packet for this request
  149. Return Value:
  150. NTSTATUS - the status of the operation
  151. --*/
  152. {
  153. NTSTATUS status;
  154. PIO_STACK_LOCATION irpSp;
  155. PCOMMON_EXTENSION commonExtension;
  156. PBUS_EXTENSION busExtension;
  157. PDISK_EXTENSION diskExtension;
  158. KEVENT event;
  159. BOOLEAN lockHeld = FALSE;
  160. #if DBG
  161. BOOLEAN print = TRUE;
  162. #endif
  163. PAGED_CODE();
  164. //
  165. // Get pointers the IRP stack location and the device extension.
  166. //
  167. irpSp = IoGetCurrentIrpStackLocation( Irp );
  168. commonExtension = DeviceObject->DeviceExtension;
  169. busExtension = DeviceObject->DeviceExtension;
  170. diskExtension = DeviceObject->DeviceExtension;
  171. ASSERT( commonExtension->DeviceState < RamdiskDeviceStateMaximum );
  172. DBGPRINT( DBG_PNP, DBG_INFO, ("RamdiskPnp: DO=(%p [Type=%d]) Irp=(%p %s) Device State=%s\n",
  173. DeviceObject, commonExtension->DeviceType, Irp,
  174. GetPnpIrpName(irpSp->MinorFunction), StateTable[commonExtension->DeviceState]) );
  175. //
  176. // If the device has been removed, only pass IRP_REMOVE down for cleanup.
  177. //
  178. if ( (commonExtension->DeviceState >= RamdiskDeviceStateRemoved) &&
  179. (irpSp->MinorFunction != IRP_MN_REMOVE_DEVICE) ) {
  180. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("RamdiskPnp: rejecting IRP %d for Removed Device\n",
  181. irpSp->MinorFunction) );
  182. status = STATUS_NO_SUCH_DEVICE;
  183. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  184. return status;
  185. }
  186. //
  187. // Acquire the remove lock. If this fails, fail the I/O.
  188. //
  189. status = IoAcquireRemoveLock( &commonExtension->RemoveLock, Irp );
  190. if ( !NT_SUCCESS(status) ) {
  191. DBGPRINT( DBG_PNP, DBG_ERROR, ("RamdiskPnp: IoAcquireRemoveLock failed: %x\n", status) );
  192. COMPLETE_REQUEST( status, 0, Irp );
  193. return status;
  194. }
  195. //
  196. // Indicate that the remove lock is held.
  197. //
  198. lockHeld = TRUE;
  199. //
  200. // Dispatch based on the minor function.
  201. //
  202. switch ( irpSp->MinorFunction ) {
  203. case IRP_MN_START_DEVICE:
  204. PRINT_CODE( IRP_MN_START_DEVICE );
  205. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  206. //
  207. // Starting the bus device.
  208. //
  209. // Send the IRP down and wait for it to come back.
  210. //
  211. IoCopyCurrentIrpStackLocationToNext( Irp );
  212. KeInitializeEvent( &event, NotificationEvent, FALSE );
  213. IoSetCompletionRoutine(
  214. Irp,
  215. RamdiskIoCompletionRoutine,
  216. &event,
  217. TRUE,
  218. TRUE,
  219. TRUE
  220. );
  221. status = IoCallDriver( commonExtension->LowerDeviceObject, Irp );
  222. if ( status == STATUS_PENDING ) {
  223. KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
  224. status = Irp->IoStatus.Status;
  225. }
  226. if ( NT_SUCCESS(status) ) {
  227. //
  228. // Lower drivers didn't fail the IRP. Start the interface.
  229. //
  230. status = IoSetDeviceInterfaceState( &commonExtension->InterfaceString, TRUE );
  231. if ( !NT_SUCCESS(status) ) {
  232. DBGPRINT( DBG_PNP, DBG_ERROR,
  233. ("IoSetDeviceInterfaceState FAILED Status = 0x%x\n", status) );
  234. }
  235. //
  236. // Device started successfully.
  237. //
  238. commonExtension->DeviceState = RamdiskDeviceStateWorking;
  239. }
  240. } else {
  241. //
  242. // Starting a RAM disk.
  243. //
  244. // Register the device interface. If it's an emulated disk, use the
  245. // private RAM disk interface GUID. If it's an emulated volume, use
  246. // the systemwide volume GUID.
  247. //
  248. if ( commonExtension->InterfaceString.Buffer != NULL ) {
  249. FREE_POOL( commonExtension->InterfaceString.Buffer, FALSE );
  250. }
  251. status = IoRegisterDeviceInterface(
  252. DeviceObject,
  253. diskExtension->DiskType == RAMDISK_TYPE_FILE_BACKED_DISK ?
  254. &RamdiskDiskInterface :
  255. &VolumeClassGuid,
  256. NULL,
  257. &commonExtension->InterfaceString
  258. );
  259. if ( !NT_SUCCESS(status) ) {
  260. DBGPRINT( DBG_PNP, DBG_ERROR,
  261. ("IoRegisterDeviceInterface FAILED Status = 0x%x\n", status) );
  262. }
  263. //
  264. // Start the interface.
  265. //
  266. if ( !diskExtension->Options.Hidden &&
  267. (commonExtension->InterfaceString.Buffer != NULL) ) {
  268. ULONG installState;
  269. ULONG resultLength;
  270. status = IoGetDeviceProperty(
  271. DeviceObject,
  272. DevicePropertyInstallState,
  273. sizeof(installState),
  274. &installState,
  275. &resultLength
  276. );
  277. if ( !NT_SUCCESS(status) ) {
  278. DBGPRINT( DBG_PNP, DBG_ERROR,
  279. ("IoGetDeviceProperty FAILED Status = 0x%x\n", status) );
  280. //
  281. // If we can't get the install state, we set the interface
  282. // state to TRUE anyway, just to be safe.
  283. //
  284. installState = InstallStateInstalled;
  285. }
  286. if ( installState == InstallStateInstalled ) {
  287. DBGPRINT( DBG_PNP, DBG_INFO,
  288. ("%s", "Calling IoSetDeviceInterfaceState(TRUE)\n") );
  289. status = IoSetDeviceInterfaceState( &commonExtension->InterfaceString, TRUE );
  290. if ( !NT_SUCCESS(status) ) {
  291. DBGPRINT( DBG_PNP, DBG_ERROR,
  292. ("IoSetDeviceInterfaceState FAILED Status = 0x%x\n", status) );
  293. }
  294. } else {
  295. DBGPRINT( DBG_PNP, DBG_INFO,
  296. ("Skipping IoSetDeviceInterfaceState; state = 0x%x\n", installState) );
  297. }
  298. }
  299. //
  300. // Device started successfully.
  301. //
  302. commonExtension->DeviceState = RamdiskDeviceStateWorking;
  303. }
  304. //
  305. // Complete the I/O request.
  306. //
  307. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  308. break;
  309. case IRP_MN_QUERY_STOP_DEVICE:
  310. PRINT_CODE( IRP_MN_QUERY_STOP_DEVICE );
  311. //
  312. // Mark that a stop is pending.
  313. //
  314. commonExtension->DeviceState = RamdiskDeviceStatePendingStop;
  315. //
  316. // Indicate success. Send the IRP on down the stack.
  317. //
  318. Irp->IoStatus.Status = STATUS_SUCCESS;
  319. goto send_irp_down;
  320. case IRP_MN_CANCEL_STOP_DEVICE:
  321. PRINT_CODE( IRP_MN_CANCEL_STOP_DEVICE );
  322. //
  323. // Before sending the IRP down make sure we have received
  324. // a IRP_MN_QUERY_STOP_DEVICE. We may get Cancel Stop
  325. // without receiving a Query Stop earlier, if the
  326. // driver on top fails a Query Stop and passes down the
  327. // Cancel Stop.
  328. //
  329. if ( commonExtension->DeviceState == RamdiskDeviceStatePendingStop ) {
  330. //
  331. // Mark that the device is back in the working state, and
  332. // pass the IRP down.
  333. //
  334. commonExtension->DeviceState = RamdiskDeviceStateWorking;
  335. Irp->IoStatus.Status = STATUS_SUCCESS;
  336. goto send_irp_down;
  337. } else {
  338. //
  339. // A spurious Cancel Stop request. Just complete it.
  340. //
  341. status = STATUS_SUCCESS;
  342. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  343. }
  344. break;
  345. case IRP_MN_STOP_DEVICE:
  346. PRINT_CODE( IRP_MN_STOP_DEVICE );
  347. //
  348. // Mark that the device is now stopped. Send the IRP on down the stack.
  349. //
  350. commonExtension->DeviceState = RamdiskDeviceStateStopped;
  351. Irp->IoStatus.Status = STATUS_SUCCESS;
  352. goto send_irp_down;
  353. case IRP_MN_QUERY_REMOVE_DEVICE:
  354. PRINT_CODE( IRP_MN_QUERY_REMOVE_DEVICE );
  355. //
  356. // Mark that the device is pending removal. Send the IRP on down the
  357. // stack.
  358. //
  359. commonExtension->DeviceState = RamdiskDeviceStatePendingRemove;
  360. Irp->IoStatus.Status = STATUS_SUCCESS;
  361. goto send_irp_down;
  362. case IRP_MN_CANCEL_REMOVE_DEVICE:
  363. PRINT_CODE( IRP_MN_CANCEL_REMOVE_DEVICE );
  364. //
  365. // Before sending the IRP down make sure we have received
  366. // a IRP_MN_QUERY_REMOVE_DEVICE. We may get Cancel Remove
  367. // without receiving a Query Remove earlier, if the
  368. // driver on top fails a Query Remove and passes down the
  369. // Cancel Remove.
  370. //
  371. if ( commonExtension->DeviceState == RamdiskDeviceStatePendingRemove ) {
  372. //
  373. // Mark that the device is back in the working state. Send the
  374. // IRP on down the stack.
  375. //
  376. commonExtension->DeviceState = RamdiskDeviceStateWorking;
  377. Irp->IoStatus.Status = STATUS_SUCCESS;
  378. goto send_irp_down;
  379. } else {
  380. //
  381. // A spurious Cancel Remove request. Just complete it.
  382. //
  383. status = STATUS_SUCCESS;
  384. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  385. }
  386. break;
  387. case IRP_MN_SURPRISE_REMOVAL:
  388. PRINT_CODE( IRP_MN_SURPRISE_REMOVAL );
  389. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  390. //
  391. // Mark that the device has been removed, and
  392. // pass the IRP down.
  393. //
  394. commonExtension->DeviceState = RamdiskDeviceStateSurpriseRemoved;
  395. Irp->IoStatus.Status = STATUS_SUCCESS;
  396. goto send_irp_down;
  397. } else {
  398. //
  399. // Ignore surprise removal for disk PDOs.
  400. //
  401. ASSERT( FALSE );
  402. status = STATUS_SUCCESS;
  403. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  404. }
  405. break;
  406. case IRP_MN_REMOVE_DEVICE:
  407. PRINT_CODE( IRP_MN_REMOVE_DEVICE );
  408. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  409. //
  410. // Remove the bus FDO.
  411. //
  412. // Note that RamdiskRemoveBusDevice() sends the IRP down the
  413. // device stack, so we don't complete the IRP here.
  414. //
  415. status = RamdiskRemoveBusDevice( DeviceObject, Irp );
  416. } else {
  417. //
  418. // Remove a disk PDO.
  419. //
  420. status = RamdiskDeleteDiskDevice( DeviceObject, Irp );
  421. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  422. }
  423. //
  424. // The remove lock was released by RamdiskRemoveBusDevice or
  425. // RamdiskDeleteDiskDevice.
  426. //
  427. lockHeld = FALSE;
  428. break;
  429. case IRP_MN_EJECT:
  430. PRINT_CODE( IRP_MN_EJECT );
  431. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  432. //
  433. // Ignore eject for the bus FDO. Just send the IRP down.
  434. //
  435. Irp->IoStatus.Status = STATUS_SUCCESS;
  436. goto send_irp_down;
  437. } else {
  438. //
  439. // Ignore eject for a disk PDO, too. Don't send the IRP down.
  440. //
  441. status = STATUS_SUCCESS;
  442. COMPLETE_REQUEST( status, 0, Irp );
  443. }
  444. break;
  445. case IRP_MN_QUERY_DEVICE_RELATIONS:
  446. //
  447. // Let RamdiskQueryDeviceRelations() do the work. Note that it
  448. // completes the IRP.
  449. //
  450. status = RamdiskQueryDeviceRelations(
  451. irpSp->Parameters.QueryDeviceRelations.Type,
  452. DeviceObject,
  453. Irp
  454. );
  455. break;
  456. case IRP_MN_QUERY_DEVICE_TEXT:
  457. //
  458. // For the bus FDO, just pass the IRP down. For a disk PDO, let
  459. // RamdiskQueryDeviceText() do the work and complete the IRP.
  460. //
  461. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  462. goto send_irp_down;
  463. } else {
  464. status = RamdiskQueryDeviceText( diskExtension, Irp );
  465. }
  466. break;
  467. case IRP_MN_QUERY_BUS_INFORMATION:
  468. //
  469. // Let RamdiskQueryBusInformation() do the work. Note that it
  470. // completes the IRP.
  471. //
  472. status = RamdiskQueryBusInformation( DeviceObject, Irp );
  473. break;
  474. case IRP_MN_QUERY_CAPABILITIES:
  475. //
  476. // For the bus FDO, just pass the IRP down. For a disk PDO, let
  477. // RamdiskQueryCapabilities() do the work and complete the IRP.
  478. //
  479. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  480. goto send_irp_down;
  481. } else {
  482. status = RamdiskQueryCapabilities( DeviceObject, Irp );
  483. }
  484. break;
  485. case IRP_MN_QUERY_RESOURCES:
  486. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  487. //
  488. // We don't have any resources to add to whatever might already be
  489. // there, so just complete the IRP.
  490. //
  491. status = Irp->IoStatus.Status;
  492. COMPLETE_REQUEST( Irp->IoStatus.Status, Irp->IoStatus.Information, Irp );
  493. break;
  494. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  495. //
  496. // For the bus FDO, just pass the IRP down. For a disk PDO, just
  497. // complete the IRP.
  498. //
  499. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  500. goto send_irp_down;
  501. } else {
  502. status = Irp->IoStatus.Status;
  503. COMPLETE_REQUEST( Irp->IoStatus.Status, Irp->IoStatus.Information, Irp );
  504. }
  505. break;
  506. case IRP_MN_QUERY_ID:
  507. //
  508. // For the bus FDO, just pass the IRP down. For a disk PDO, let
  509. // RamdiskQueryId() do the work and complete the IRP.
  510. //
  511. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  512. goto send_irp_down;
  513. } else {
  514. status = RamdiskQueryId( diskExtension, Irp );
  515. }
  516. break;
  517. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  518. case IRP_MN_QUERY_LEGACY_BUS_INFORMATION:
  519. default:
  520. send_irp_down:
  521. //
  522. // If this is the bus FDO, and there is a lower device object,
  523. // send the IRP down to the next device. If this is a disk PDO,
  524. // just complete the IRP.
  525. //
  526. if ( (commonExtension->DeviceType == RamdiskDeviceTypeBusFdo) &&
  527. (commonExtension->LowerDeviceObject != NULL) ) {
  528. IoSkipCurrentIrpStackLocation( Irp );
  529. status = IoCallDriver( commonExtension->LowerDeviceObject, Irp );
  530. } else {
  531. status = Irp->IoStatus.Status;
  532. COMPLETE_REQUEST( Irp->IoStatus.Status, Irp->IoStatus.Information, Irp );
  533. }
  534. break;
  535. } // switch
  536. //
  537. // If the lock is still held, release it now.
  538. //
  539. if ( lockHeld ) {
  540. DBGPRINT( DBG_PNP, DBG_VERBOSE,
  541. ("RamdiskPnp: done; Device State=%s\n",
  542. StateTable[commonExtension->DeviceState]) );
  543. IoReleaseRemoveLock( &commonExtension->RemoveLock, Irp );
  544. }
  545. return status;
  546. } // RamdiskPnp
  547. NTSTATUS
  548. RamdiskPower (
  549. IN PDEVICE_OBJECT DeviceObject,
  550. IN PIRP Irp
  551. )
  552. /*++
  553. Routine Description:
  554. This routine is called by the I/O system to perform a power function.
  555. Arguments:
  556. DeviceObject - a pointer to the object that represents the device on which
  557. I/O is to be performed
  558. Irp - a pointer to the I/O Request Packet for this request
  559. Return Value:
  560. NTSTATUS - the status of the operation
  561. --*/
  562. {
  563. NTSTATUS status = STATUS_SUCCESS;
  564. PCOMMON_EXTENSION commonExtension;
  565. PAGED_CODE();
  566. DBGPRINT( DBG_POWER, DBG_VERBOSE,
  567. ("RamdiskPower: DO=(%p) Irp=(%p)\n", DeviceObject, Irp) );
  568. commonExtension = DeviceObject->DeviceExtension;
  569. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  570. //
  571. // This is the bus FDO. There's not much for us to do here.
  572. //
  573. // Start the next power IRP.
  574. //
  575. PoStartNextPowerIrp( Irp );
  576. //
  577. // If the device has been removed, the driver should not pass
  578. // the IRP down to the next lower driver.
  579. //
  580. if ( commonExtension->DeviceState >= RamdiskDeviceStateRemoved ) {
  581. status = STATUS_DELETE_PENDING;
  582. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  583. return status;
  584. }
  585. //
  586. // Send the IRP on down the stack.
  587. //
  588. IoSkipCurrentIrpStackLocation( Irp );
  589. status = PoCallDriver( commonExtension->LowerDeviceObject, Irp );
  590. } else {
  591. PIO_STACK_LOCATION irpSp;
  592. POWER_STATE powerState;
  593. POWER_STATE_TYPE powerType;
  594. //
  595. // This is a request for a disk PDO.
  596. //
  597. // Get parameters from the IRP.
  598. //
  599. irpSp = IoGetCurrentIrpStackLocation( Irp );
  600. powerType = irpSp->Parameters.Power.Type;
  601. powerState = irpSp->Parameters.Power.State;
  602. //
  603. // Dispatch based on the minor function.
  604. //
  605. switch ( irpSp->MinorFunction ) {
  606. case IRP_MN_SET_POWER:
  607. //
  608. // For SET_POWER, we don't have to do anything but return success.
  609. //
  610. switch ( powerType ) {
  611. case DevicePowerState:
  612. case SystemPowerState:
  613. status = STATUS_SUCCESS;
  614. break;
  615. default:
  616. status = STATUS_NOT_SUPPORTED;
  617. break;
  618. }
  619. break;
  620. case IRP_MN_QUERY_POWER:
  621. //
  622. // For QUERY_POWER, we don't have to do anything but return
  623. // success.
  624. //
  625. status = STATUS_SUCCESS;
  626. break;
  627. case IRP_MN_WAIT_WAKE:
  628. case IRP_MN_POWER_SEQUENCE:
  629. default:
  630. status = STATUS_NOT_SUPPORTED;
  631. break;
  632. }
  633. if ( status != STATUS_NOT_SUPPORTED ) {
  634. Irp->IoStatus.Status = status;
  635. }
  636. PoStartNextPowerIrp( Irp );
  637. status = Irp->IoStatus.Status;
  638. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  639. }
  640. DBGPRINT( DBG_POWER, DBG_VERBOSE, ("RamdiskPower: status = 0x%x\n", status) );
  641. return status;
  642. } // RamdiskPower
  643. NTSTATUS
  644. RamdiskAddDevice (
  645. IN PDRIVER_OBJECT DriverObject,
  646. IN PDEVICE_OBJECT Pdo
  647. )
  648. /*++
  649. Routine Description:
  650. This routine is called by the PnP system to add a device.
  651. We expect to get this call exactly once, to add our bus PDO.
  652. Arguments:
  653. DriverObject - a pointer to our driver object
  654. Pdo - a pointer to the PDO for the FDO that we create
  655. Return Value:
  656. NTSTATUS - the status of the operation
  657. --*/
  658. {
  659. NTSTATUS status;
  660. UNICODE_STRING deviceName;
  661. PDEVICE_OBJECT fdo;
  662. PBUS_EXTENSION busExtension;
  663. PULONG bitmap;
  664. PLOADER_PARAMETER_BLOCK loaderBlock;
  665. PAGED_CODE();
  666. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("%s", "RamdiskAddDevice: entered\n") );
  667. //
  668. // If we've already done this once, fail this call.
  669. //
  670. if ( RamdiskBusFdo != NULL ) {
  671. return STATUS_DEVICE_ALREADY_ATTACHED;
  672. }
  673. #if SUPPORT_DISK_NUMBERS
  674. //
  675. // Allocate space for the disk numbers bitmap.
  676. //
  677. bitmap = ALLOCATE_POOL( PagedPool, DiskNumbersBitmapSize, TRUE );
  678. if ( bitmap == NULL ) {
  679. return STATUS_INSUFFICIENT_RESOURCES;
  680. }
  681. #endif // SUPPORT_DISK_NUMBERS
  682. //
  683. // Create the bus device object.
  684. //
  685. // ISSUE: Apply an ACL to the bus device object. (Or does the next issue obviate this?)
  686. // ISSUE: We're supposed to use autogenerated names for FDOs. What is the
  687. // harm in using our own name? (Benefit is that it's easier to
  688. // find the device when creating/deleting disks.)
  689. //
  690. RtlInitUnicodeString( &deviceName, L"\\Device\\Ramdisk" );
  691. status = IoCreateDevice(
  692. DriverObject, // DriverObject
  693. sizeof(BUS_EXTENSION), // DeviceExtension
  694. &deviceName, // DeviceName
  695. FILE_DEVICE_BUS_EXTENDER, // DeviceType
  696. FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
  697. FALSE, // Exclusive
  698. &fdo // DeviceObject
  699. );
  700. if ( !NT_SUCCESS(status) ) {
  701. DBGPRINT( DBG_PNP, DBG_ERROR, ("RamdiskAddDevice: error %x creating bus FDO\n", status) );
  702. #if SUPPORT_DISK_NUMBERS
  703. FREE_POOL( bitmap, TRUE );
  704. #endif // SUPPORT_DISK_NUMBERS
  705. return status;
  706. }
  707. busExtension = fdo->DeviceExtension;
  708. RtlZeroMemory( busExtension, sizeof(BUS_EXTENSION) );
  709. //
  710. // Initialize device object and extension.
  711. //
  712. //
  713. // Our device does direct I/O and is power pageable.
  714. //
  715. fdo->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
  716. //
  717. // Set the device type and state in the device extension. Initialize the
  718. // fast mutex and the remove lock. Initialize the disk PDO list.
  719. //
  720. busExtension->DeviceType = RamdiskDeviceTypeBusFdo;
  721. busExtension->DeviceState = RamdiskDeviceStateStopped;
  722. ExInitializeFastMutex( &busExtension->Mutex );
  723. IoInitializeRemoveLock( &busExtension->RemoveLock, 'dmaR', 1, 0 );
  724. InitializeListHead( &busExtension->DiskPdoList );
  725. //
  726. // Save object pointers. The PDO for this extension is the PDO that
  727. // was passed in. The FDO is the device object that we just created. The
  728. // lower device object will be set later.
  729. //
  730. busExtension->Pdo = Pdo;
  731. busExtension->Fdo = fdo;
  732. //
  733. // Register the device interface.
  734. //
  735. status = IoRegisterDeviceInterface(
  736. Pdo,
  737. &RamdiskBusInterface,
  738. NULL,
  739. &busExtension->InterfaceString
  740. );
  741. if ( !NT_SUCCESS(status) ) {
  742. DBGPRINT( DBG_PNP, DBG_ERROR,
  743. ("RamdiskAddDevice: error %x registering device interface for bus FDO\n",
  744. status) );
  745. IoDeleteDevice( fdo );
  746. #if SUPPORT_DISK_NUMBERS
  747. FREE_POOL( bitmap, TRUE );
  748. #endif // SUPPORT_DISK_NUMBERS
  749. return status;
  750. }
  751. //
  752. // Attach the FDO to the PDO's device stack. Remember the lower device
  753. // object to which we are to forward PnP IRPs.
  754. //
  755. busExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack( fdo, Pdo );
  756. if ( busExtension->LowerDeviceObject == NULL ) {
  757. DBGPRINT( DBG_PNP, DBG_ERROR,
  758. ("%s", "RamdiskAddDevice: error attaching bus FDO to PDO stack\n") );
  759. //
  760. // Tell PnP that we're not going to be activating the interface that
  761. // we just registered. Free the symbolic link string associated with
  762. // the interface. Delete the device object.
  763. //
  764. IoSetDeviceInterfaceState( &busExtension->InterfaceString, FALSE );
  765. RtlFreeUnicodeString( &busExtension->InterfaceString );
  766. IoDeleteDevice( fdo );
  767. #if SUPPORT_DISK_NUMBERS
  768. FREE_POOL( bitmap, TRUE );
  769. #endif // SUPPORT_DISK_NUMBERS
  770. return STATUS_NO_SUCH_DEVICE;
  771. }
  772. #if SUPPORT_DISK_NUMBERS
  773. //
  774. // Initialize the disk numbers bitmap.
  775. //
  776. busExtension->DiskNumbersBitmapBuffer = bitmap;
  777. RtlInitializeBitMap( &busExtension->DiskNumbersBitmap, bitmap, DiskNumbersBitmapSize );
  778. RtlClearAllBits( &busExtension->DiskNumbersBitmap );
  779. #endif // SUPPORT_DISK_NUMBERS
  780. RamdiskBusFdo = fdo;
  781. //
  782. // If textmode setup is running, create any RAM disks specified in the
  783. // registry.
  784. //
  785. loaderBlock = *(PLOADER_PARAMETER_BLOCK *)KeLoaderBlock;
  786. if ( (loaderBlock != NULL) && (loaderBlock->SetupLoaderBlock != NULL) ) {
  787. CreateRegistryDisks( FALSE );
  788. }
  789. //
  790. // Indicate that we're done initializing the device.
  791. //
  792. fdo->Flags &= ~DO_DEVICE_INITIALIZING;
  793. return STATUS_SUCCESS;
  794. } // RamdiskAddDevice
  795. BOOLEAN
  796. CreateRegistryDisks (
  797. IN BOOLEAN CheckPresenceOnly
  798. )
  799. /*++
  800. Routine Description:
  801. This routine creates virtual floppy disks specified in the registry.
  802. It is called only during textmode setup.
  803. Arguments:
  804. CheckPresenceOnly - indicates whether this routine should just check for
  805. the presence of at least one disk in the registry
  806. Return Value:
  807. BOOLEAN - indicates whether any disks were specified in the registry
  808. --*/
  809. {
  810. NTSTATUS status;
  811. OBJECT_ATTRIBUTES obja;
  812. UNICODE_STRING string;
  813. HANDLE serviceHandle;
  814. HANDLE parametersHandle;
  815. ULONG diskNumber;
  816. WCHAR valueNameBuffer[15];
  817. UNICODE_STRING valueName;
  818. UCHAR valueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(VIRTUAL_FLOPPY_DESCRIPTOR)];
  819. PKEY_VALUE_PARTIAL_INFORMATION value;
  820. PVIRTUAL_FLOPPY_DESCRIPTOR descriptor;
  821. ULONG valueLength;
  822. RAMDISK_CREATE_INPUT createInput;
  823. PDISK_EXTENSION diskExtension;
  824. BOOLEAN disksPresent = FALSE;
  825. HRESULT result;
  826. value = (PKEY_VALUE_PARTIAL_INFORMATION)valueBuffer;
  827. descriptor = (PVIRTUAL_FLOPPY_DESCRIPTOR)value->Data;
  828. //
  829. // Open the driver's key under Services.
  830. //
  831. InitializeObjectAttributes( &obja, &DriverRegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL );
  832. status = ZwOpenKey( &serviceHandle, KEY_READ, &obja );
  833. if ( !NT_SUCCESS(status) ) {
  834. DBGPRINT( DBG_INIT, DBG_ERROR, ("CreateRegistryDisks: ZwOpenKey(1) failed: %x\n", status) );
  835. return FALSE;
  836. }
  837. //
  838. // Open the Parameters subkey.
  839. //
  840. RtlInitUnicodeString( &string, L"Parameters" );
  841. InitializeObjectAttributes( &obja, &string, OBJ_CASE_INSENSITIVE, serviceHandle, NULL );
  842. status = ZwOpenKey( &parametersHandle, KEY_READ, &obja );
  843. NtClose( serviceHandle );
  844. if ( !NT_SUCCESS(status) ) {
  845. DBGPRINT( DBG_INIT, DBG_ERROR, ("CreateRegistryDisks: ZwOpenKey(2) failed: %x\n", status) );
  846. return FALSE;
  847. }
  848. //
  849. // Initialize static fields in the CREATE_INPUT structure that we'll pass
  850. // to RamdiskCreateDiskDevice.
  851. //
  852. RtlZeroMemory( &createInput, sizeof(createInput) );
  853. createInput.DiskType = RAMDISK_TYPE_VIRTUAL_FLOPPY;
  854. createInput.Options.Fixed = TRUE;
  855. createInput.Options.NoDriveLetter = TRUE;
  856. //
  857. // Look for values named DISKn, where n starts at 0 and increases by 1
  858. // each loop. Break out as soon as the expected DISKn is not found.
  859. // (If values named DISK0 and DISK2 are present, only DISK0 will be
  860. // created -- DISK2 will not be found.)
  861. //
  862. diskNumber = 0;
  863. while ( TRUE ) {
  864. // This variable is here to keep PREfast quiet (PREfast warning 209).
  865. size_t size = sizeof(valueNameBuffer);
  866. result = StringCbPrintfW(
  867. valueNameBuffer,
  868. size,
  869. L"DISK%u",
  870. diskNumber
  871. );
  872. ASSERT( result == S_OK );
  873. RtlInitUnicodeString( &valueName, valueNameBuffer );
  874. status = ZwQueryValueKey(
  875. parametersHandle,
  876. &valueName,
  877. KeyValuePartialInformation,
  878. value,
  879. sizeof(valueBuffer),
  880. &valueLength
  881. );
  882. if ( !NT_SUCCESS(status) ) {
  883. if ( status != STATUS_OBJECT_NAME_NOT_FOUND ) {
  884. DBGPRINT( DBG_INIT, DBG_ERROR,
  885. ("CreateRegistryDisks: ZwQueryValueKey failed: %x\n", status) );
  886. }
  887. break;
  888. }
  889. //
  890. // We've found a DISKn value in the registry. For the purposes of
  891. // the CheckPresenceOnly flag, this is enough to know that at least
  892. // one virtual floppy disk is present. We don't care whether the
  893. // data is valid -- we just need to know that it's there.
  894. //
  895. disksPresent = TRUE;
  896. //
  897. // If we're just checking for the presence of at least one disk, we
  898. // can leave now.
  899. //
  900. if ( CheckPresenceOnly ) {
  901. break;
  902. }
  903. //
  904. // We expect the value to be a REG_BINARY with the correct length.
  905. // We don't explicitly check the value type; we assume that the
  906. // length check is sufficient. We also expect the base address
  907. // (which is a system virtual address -- either in KSEG0 or in
  908. // nonpaged pool) and the length to be nonzero.
  909. //
  910. if ( value->DataLength != FIELD_OFFSET(VIRTUAL_FLOPPY_DESCRIPTOR, StructSizer) ) {
  911. DBGPRINT( DBG_INIT, DBG_ERROR,
  912. ("CreateRegistryDisks: key length wrong, wanted 0x%x, got 0x%x\n",
  913. sizeof(VIRTUAL_FLOPPY_DESCRIPTOR), valueLength) );
  914. } else if ( (descriptor->VirtualAddress == NULL) || (descriptor->Length == 0) ) {
  915. DBGPRINT( DBG_INIT, DBG_ERROR,
  916. ("CreateRegistryDisks: address (%x) or length (0x%x) invalid\n",
  917. descriptor->VirtualAddress, descriptor->Length) );
  918. } else {
  919. //
  920. // Create a virtual floppy RAM disk at the specified address and
  921. // with the specified length. Pass the disk number in the GUID.
  922. //
  923. createInput.DiskGuid.Data1 = diskNumber;
  924. createInput.DiskLength = descriptor->Length;
  925. createInput.BaseAddress = descriptor->VirtualAddress;
  926. DBGPRINT( DBG_INIT, DBG_INFO,
  927. ("CreateRegistryDisks: creating virtual floppy #%d at %p for %x\n",
  928. diskNumber, descriptor->VirtualAddress, descriptor->Length) );
  929. ASSERT( RamdiskBusFdo != NULL );
  930. ASSERT( RamdiskBusFdo->DeviceExtension != NULL );
  931. status = RamdiskCreateDiskDevice(
  932. RamdiskBusFdo->DeviceExtension,
  933. &createInput,
  934. FALSE,
  935. &diskExtension
  936. );
  937. if ( !NT_SUCCESS(status) ) {
  938. DBGPRINT( DBG_INIT, DBG_ERROR,
  939. ("CreateRegistryDisks: RamdiskCreateDiskDevice failed: %x\n", status) );
  940. }
  941. }
  942. diskNumber++;
  943. }
  944. //
  945. // Close the Parameters key and return.
  946. //
  947. NtClose( parametersHandle );
  948. return disksPresent;
  949. } // CreateRegistryDisks
  950. NTSTATUS
  951. RamdiskDeleteDiskDevice (
  952. IN PDEVICE_OBJECT DeviceObject,
  953. IN PIRP Irp OPTIONAL
  954. )
  955. /*++
  956. Routine Description:
  957. This routine is called to delete a RAM disk device.
  958. NOTE: The remove lock is held on entry to this routine. It is released on
  959. exit. If Irp == NULL, the bus mutex is held on entry and released on exit.
  960. Arguments:
  961. DeviceObject - a pointer to the object that represents the device on which
  962. the operation is to be performed
  963. Irp - a pointer to the I/O Request Packet for this request. If NULL, this
  964. is a call from RamdiskRemoveBusDevice().
  965. Return Value:
  966. NTSTATUS - the status of the operation
  967. --*/
  968. {
  969. NTSTATUS status;
  970. PDISK_EXTENSION diskExtension;
  971. PDISK_EXTENSION tempDiskExtension;
  972. PBUS_EXTENSION busExtension;
  973. PLIST_ENTRY listEntry;
  974. PAGED_CODE();
  975. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("%s", "RamdiskDeleteDiskDevice\n") );
  976. diskExtension = DeviceObject->DeviceExtension;
  977. busExtension = diskExtension->Fdo->DeviceExtension;
  978. DBGPRINT( DBG_PNP, DBG_INFO,
  979. ("RamdiskDeleteDiskDevice: Deleting device %wZ\n", &diskExtension->DeviceName) );
  980. //
  981. // If no IRP was specified, then we delete the disk device unconditionally.
  982. // (It's a call from RamdiskRemoveBusDevice().) Otherwise, we need to check
  983. // whether we really want to delete the device now.
  984. //
  985. if ( Irp != NULL ) {
  986. Irp->IoStatus.Information = 0;
  987. //
  988. // Check to see if the device has been marked for removal. If not,
  989. // ignore this IRP. We do this because user-mode PnP likes to remove
  990. // and immmediately recreate the devices that we materialize, but we
  991. // don't want to remove the device and lose the information about the
  992. // disk image.
  993. //
  994. if ( !diskExtension->MarkedForDeletion ) {
  995. //
  996. // This device has not really been removed, so ignore this IRP.
  997. // But do mark that the device is no longer claimed.
  998. //
  999. diskExtension->Status &= ~RAMDISK_STATUS_CLAIMED;
  1000. IoReleaseRemoveLock( &diskExtension->RemoveLock, Irp );
  1001. return STATUS_SUCCESS;
  1002. }
  1003. //
  1004. // The device has been marked for deletion, so it's OK for PnP to be
  1005. // trying to remove it. If this is PnP's first attempt at removing the
  1006. // device, just mark it as removed and tell PnP to reenumerate the
  1007. // bus. During reenumeration, we will skip this device, and PnP will
  1008. // come back with another remove IRP.
  1009. //
  1010. if ( diskExtension->DeviceState < RamdiskDeviceStateRemoved ) {
  1011. diskExtension->DeviceState = RamdiskDeviceStateRemoved;
  1012. busExtension = diskExtension->Fdo->DeviceExtension;
  1013. IoInvalidateDeviceRelations( busExtension->Pdo, BusRelations );
  1014. IoReleaseRemoveLock( &diskExtension->RemoveLock, Irp );
  1015. return STATUS_SUCCESS;
  1016. }
  1017. //
  1018. // If the device is marked as removed, but it hasn't yet been skipped
  1019. // in a bus enumeration, don't do anything now.
  1020. //
  1021. if ( diskExtension->DeviceState == RamdiskDeviceStateRemoved ) {
  1022. IoReleaseRemoveLock( &diskExtension->RemoveLock, Irp );
  1023. return STATUS_SUCCESS;
  1024. }
  1025. //
  1026. // If we get here, we have already skipped this device in a bus
  1027. // enumeration, so it's time to delete it. Acquire the bus mutex
  1028. // so that we can do this.
  1029. //
  1030. KeEnterCriticalRegion();
  1031. ExAcquireFastMutex( &busExtension->Mutex );
  1032. }
  1033. //
  1034. // If we get here, we really do want to delete this device. If we've
  1035. // already deleted it, don't do it again.
  1036. //
  1037. if ( diskExtension->DeviceState >= RamdiskDeviceStateDeleted ) {
  1038. DBGPRINT( DBG_PNP, DBG_INFO,
  1039. ("RamdiskDeleteDiskDevice: device %wZ has already been deleted\n",
  1040. &diskExtension->DeviceName) );
  1041. //
  1042. // Release the bus mutex and the remove lock.
  1043. //
  1044. ExReleaseFastMutex( &busExtension->Mutex );
  1045. KeLeaveCriticalRegion();
  1046. IoReleaseRemoveLock( &diskExtension->RemoveLock, Irp );
  1047. return STATUS_SUCCESS;
  1048. }
  1049. //
  1050. // Indicate that the device has been deleted.
  1051. //
  1052. diskExtension->DeviceState = RamdiskDeviceStateDeleted;
  1053. //
  1054. // Remove the disk PDO from the bus FDO's list.
  1055. //
  1056. for ( listEntry = busExtension->DiskPdoList.Flink;
  1057. listEntry != &busExtension->DiskPdoList;
  1058. listEntry = listEntry->Flink ) {
  1059. tempDiskExtension = CONTAINING_RECORD( listEntry, DISK_EXTENSION, DiskPdoListEntry );
  1060. if ( tempDiskExtension == diskExtension ) {
  1061. RemoveEntryList( listEntry );
  1062. #if SUPPORT_DISK_NUMBERS
  1063. RtlClearBit( &busExtension->DiskNumbersBitmap, diskExtension->DiskNumber - 1 );
  1064. #endif // SUPPORT_DISK_NUMBERS
  1065. break;
  1066. }
  1067. }
  1068. //
  1069. // We no longer need to hold the bus mutex and the remove lock.
  1070. //
  1071. ExReleaseFastMutex( &busExtension->Mutex );
  1072. KeLeaveCriticalRegion();
  1073. IoReleaseRemoveLockAndWait( &diskExtension->RemoveLock, Irp );
  1074. //
  1075. // If the interface has been started, stop it now.
  1076. //
  1077. if ( diskExtension->InterfaceString.Buffer != NULL ) {
  1078. if ( !diskExtension->Options.Hidden ) {
  1079. status = IoSetDeviceInterfaceState( &diskExtension->InterfaceString, FALSE );
  1080. }
  1081. RtlFreeUnicodeString( &diskExtension->InterfaceString );
  1082. }
  1083. //
  1084. // Close the file backing the RAM disk, if any.
  1085. //
  1086. if ( diskExtension->SectionObject != NULL ) {
  1087. if ( diskExtension->ViewDescriptors != NULL ) {
  1088. //
  1089. // Clean up the mapped views.
  1090. //
  1091. PVIEW view;
  1092. ASSERT( diskExtension->ViewWaiterCount == 0 );
  1093. while ( !IsListEmpty( &diskExtension->ViewsByOffset ) ) {
  1094. listEntry = RemoveHeadList( &diskExtension->ViewsByOffset );
  1095. view = CONTAINING_RECORD( listEntry, VIEW, ByOffsetListEntry );
  1096. RemoveEntryList( &view->ByMruListEntry );
  1097. ASSERT( view->ReferenceCount == 0 );
  1098. if ( view->Address != NULL ) {
  1099. DBGPRINT( DBG_WINDOW, DBG_VERBOSE,
  1100. ("RamdiskDeleteDiskDevice: unmapping view %p; addr %p\n",
  1101. view, view->Address) );
  1102. MmUnmapViewOfSection( PsGetCurrentProcess(), view->Address );
  1103. }
  1104. }
  1105. ASSERT( IsListEmpty( &diskExtension->ViewsByMru ) );
  1106. FREE_POOL( diskExtension->ViewDescriptors, TRUE );
  1107. }
  1108. ObDereferenceObject( diskExtension->SectionObject );
  1109. }
  1110. if ( !diskExtension->Options.NoDosDevice ) {
  1111. //
  1112. // Delete the DosDevices symbolic link.
  1113. //
  1114. ASSERT( diskExtension->DosSymLink.Buffer != NULL );
  1115. status = IoDeleteSymbolicLink( &diskExtension->DosSymLink );
  1116. if ( !NT_SUCCESS(status) ) {
  1117. DBGPRINT( DBG_PNP, DBG_ERROR,
  1118. ("RamdiskDeleteDiskDevice: IoDeleteSymbolicLink failed: %x\n", status) );
  1119. }
  1120. FREE_POOL( diskExtension->DosSymLink.Buffer, TRUE );
  1121. }
  1122. //
  1123. // Delete the device name string and the GUID string.
  1124. //
  1125. if ( diskExtension->DeviceName.Buffer != NULL ) {
  1126. FREE_POOL( diskExtension->DeviceName.Buffer, TRUE );
  1127. }
  1128. if ( diskExtension->DiskGuidFormatted.Buffer != NULL ) {
  1129. FREE_POOL( diskExtension->DiskGuidFormatted.Buffer, FALSE );
  1130. }
  1131. //
  1132. // Delete the device object.
  1133. //
  1134. IoDeleteDevice( DeviceObject );
  1135. return STATUS_SUCCESS;
  1136. } // RamdiskDeleteDiskDevice
  1137. NTSTATUS
  1138. RamdiskIoCompletionRoutine (
  1139. IN PDEVICE_OBJECT DeviceObject,
  1140. IN PIRP Irp,
  1141. IN PKEVENT Event
  1142. )
  1143. /*++
  1144. Routine Description:
  1145. This internal routine is used as the I/O completion routine when we send
  1146. an IRP down the device stack and want to short-circuit IRP completion so
  1147. that we can do more work.
  1148. Arguments:
  1149. DeviceObject - a pointer to the object that represents the device on which
  1150. the operation is to be performed
  1151. Irp - a pointer to the I/O Request Packet for this request
  1152. Event - a pointer to an event that is to be set to signal the calling code
  1153. that the lower layers have completed the IRP
  1154. Return Value:
  1155. NTSTATUS - the status of the operation
  1156. --*/
  1157. {
  1158. UNREFERENCED_PARAMETER( DeviceObject );
  1159. UNREFERENCED_PARAMETER( Irp );
  1160. //
  1161. // Set the event to signal the IRP issuer that it's time to continue.
  1162. //
  1163. KeSetEvent( Event, 0, FALSE );
  1164. //
  1165. // Tell the I/O system to stop completing the IRP.
  1166. //
  1167. return STATUS_MORE_PROCESSING_REQUIRED;
  1168. } // RamdiskIoCompletionRoutine
  1169. NTSTATUS
  1170. RamdiskQueryBusInformation (
  1171. IN PDEVICE_OBJECT DeviceObject,
  1172. IN PIRP Irp
  1173. )
  1174. /*++
  1175. Routine Description:
  1176. This routine processes the IRP_MN_QUERY_BUS_INFORMATION IRP.
  1177. Arguments:
  1178. DeviceObject - a pointer to the object that represents the device on which
  1179. the operation is to be performed
  1180. Irp - a pointer to the I/O Request Packet for this request
  1181. Return Value:
  1182. NTSTATUS - the status of the operation
  1183. --*/
  1184. {
  1185. NTSTATUS status;
  1186. PPNP_BUS_INFORMATION busInformation;
  1187. PAGED_CODE();
  1188. DBGPRINT( DBG_PNP, DBG_VERBOSE,
  1189. ("RamdiskQueryBusInformation: DO (0x%p) Type 0x%x\n",
  1190. DeviceObject, ((PCOMMON_EXTENSION)DeviceObject->DeviceExtension)->DeviceType) );
  1191. //
  1192. // Allocate a buffer to use for returning the requested information.
  1193. //
  1194. busInformation = ALLOCATE_POOL( PagedPool, sizeof(PNP_BUS_INFORMATION), FALSE );
  1195. if ( busInformation == NULL ) {
  1196. //
  1197. // Fail the IRP.
  1198. //
  1199. status = STATUS_INSUFFICIENT_RESOURCES;
  1200. COMPLETE_REQUEST( status, 0, Irp );
  1201. return status;
  1202. }
  1203. //
  1204. // Fill in the requested information.
  1205. //
  1206. busInformation->BusTypeGuid = GUID_BUS_TYPE_RAMDISK;
  1207. busInformation->LegacyBusType = PNPBus;
  1208. busInformation->BusNumber = 0x00;
  1209. //
  1210. // Complete the IRP.
  1211. //
  1212. status = STATUS_SUCCESS;
  1213. COMPLETE_REQUEST( status, (ULONG_PTR)busInformation, Irp );
  1214. return status;
  1215. } // RamdiskQueryBusInformation
  1216. NTSTATUS
  1217. RamdiskQueryCapabilities (
  1218. IN PDEVICE_OBJECT DeviceObject,
  1219. IN PIRP Irp
  1220. )
  1221. /*++
  1222. Routine Description:
  1223. This routine processes the IRP_MN_QUERY_CAPABILITIES IRP.
  1224. Arguments:
  1225. DeviceObject - a pointer to the object that represents the device on which
  1226. the operation is to be performed
  1227. Irp - a pointer to the I/O Request Packet for this request
  1228. Return Value:
  1229. NTSTATUS - the status of the operation
  1230. --*/
  1231. {
  1232. NTSTATUS status;
  1233. PIO_STACK_LOCATION irpSp;
  1234. PDEVICE_CAPABILITIES deviceCapabilities;
  1235. PDISK_EXTENSION diskExtension;
  1236. PAGED_CODE();
  1237. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("%s", "RamdiskQueryCapabilities\n") );
  1238. //
  1239. // Get a pointer to the device extension and get parameters from the IRP.
  1240. //
  1241. diskExtension = DeviceObject->DeviceExtension;
  1242. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1243. deviceCapabilities = irpSp->Parameters.DeviceCapabilities.Capabilities;
  1244. if ( (deviceCapabilities->Version != 1) ||
  1245. (deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES)) ) {
  1246. //
  1247. // We don't support this version. Fail the request.
  1248. //
  1249. status = STATUS_UNSUCCESSFUL;
  1250. } else {
  1251. status = STATUS_SUCCESS;
  1252. //
  1253. // If this is an emulated volume, we want to allow access to the raw
  1254. // device. (Otherwise PnP won't start the device.)
  1255. //
  1256. // Note that a RAM disk boot disk is an emulated volume.
  1257. //
  1258. deviceCapabilities->RawDeviceOK =
  1259. (BOOLEAN)(diskExtension->DiskType != RAMDISK_TYPE_FILE_BACKED_DISK);
  1260. //
  1261. // Indicate that ejection is not supported.
  1262. //
  1263. deviceCapabilities->EjectSupported = FALSE;
  1264. //
  1265. // This flag specifies whether the device's hardware is disabled.
  1266. // The PnP Manager only checks this bit right after the device is
  1267. // enumerated. Once the device is started, this bit is ignored.
  1268. //
  1269. deviceCapabilities->HardwareDisabled = FALSE;
  1270. //
  1271. // Indicate that the emulated device cannot be physically removed.
  1272. // (Unless the right registry key was specified...)
  1273. //
  1274. deviceCapabilities->Removable = MarkRamdisksAsRemovable;
  1275. //
  1276. // Setting SurpriseRemovalOK to TRUE prevents the warning dialog from
  1277. // appearing whenever the device is surprise removed. Setting it FALSE
  1278. // allows the Hot unplug applet to stop the device.
  1279. //
  1280. // We don't want our disks to show up in the systray, so we set
  1281. // SurpriseRemovalOK to TRUE. There is never really any surprise
  1282. // removal anyway -- removal comes from the user mode control app
  1283. // calling CM_Query_And_Remove_SubTree_Ex().
  1284. //
  1285. deviceCapabilities->SurpriseRemovalOK = TRUE;
  1286. //
  1287. // We support system-wide unique IDs.
  1288. //
  1289. deviceCapabilities->UniqueID = TRUE;
  1290. //
  1291. // Indicate that the Device Manager should suppress all
  1292. // installation pop-ups except required pop-ups such as
  1293. // "no compatible drivers found."
  1294. //
  1295. deviceCapabilities->SilentInstall = TRUE;
  1296. //
  1297. // Indicate that we do not want this device displayed in
  1298. // Device Manager.
  1299. //
  1300. deviceCapabilities->NoDisplayInUI = TRUE;
  1301. }
  1302. //
  1303. // Complete the request.
  1304. //
  1305. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  1306. return status;
  1307. } // RamdiskQueryCapabilities
  1308. NTSTATUS
  1309. RamdiskQueryId (
  1310. IN PDISK_EXTENSION DiskExtension,
  1311. IN PIRP Irp
  1312. )
  1313. /*++
  1314. Routine Description:
  1315. This routine processes the IRP_MN_QUERY_ID IRP for disk devices.
  1316. Arguments:
  1317. DiskExtension - a pointer to the device extension for the device object on
  1318. which the operation is to be performed
  1319. Irp - a pointer to the I/O Request Packet for this request
  1320. Return Value:
  1321. NTSTATUS - the status of the operation
  1322. --*/
  1323. {
  1324. #define MAX_LOCAL_STRING 50
  1325. NTSTATUS status;
  1326. PIO_STACK_LOCATION irpSp;
  1327. PWCHAR buffer;
  1328. PWCHAR p;
  1329. ULONG length;
  1330. PWCHAR deviceType;
  1331. HRESULT result;
  1332. PAGED_CODE();
  1333. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("%s", "RamdiskQueryId\n") );
  1334. //
  1335. // Assume success.
  1336. //
  1337. status = STATUS_SUCCESS;
  1338. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1339. //
  1340. // Dispatch based on the query type.
  1341. //
  1342. switch ( irpSp->Parameters.QueryId.IdType ) {
  1343. case BusQueryDeviceID:
  1344. //
  1345. // DeviceID is a string to identify a device. We return the string
  1346. // "Ramdisk\RamVolume" or "Ramdisk\RamDisk".
  1347. //
  1348. // Allocate pool to hold the string.
  1349. //
  1350. length = sizeof(RAMDISK_ENUMERATOR_TEXT) - sizeof(WCHAR) +
  1351. ((DiskExtension->DiskType == RAMDISK_TYPE_FILE_BACKED_DISK) ?
  1352. sizeof(RAMDISK_DISK_DEVICE_TEXT) : sizeof(RAMDISK_VOLUME_DEVICE_TEXT));
  1353. buffer = ALLOCATE_POOL( PagedPool, length, FALSE );
  1354. if ( buffer == NULL ) {
  1355. status = STATUS_INSUFFICIENT_RESOURCES;
  1356. break;
  1357. }
  1358. //
  1359. // Copy the string into the destination buffer.
  1360. //
  1361. result = StringCbCopyW( buffer, length, RAMDISK_ENUMERATOR_TEXT );
  1362. ASSERT( result == S_OK );
  1363. result = StringCbCatW(
  1364. buffer,
  1365. length,
  1366. (DiskExtension->DiskType == RAMDISK_TYPE_FILE_BACKED_DISK) ?
  1367. RAMDISK_DISK_DEVICE_TEXT : RAMDISK_VOLUME_DEVICE_TEXT
  1368. );
  1369. ASSERT( result == S_OK );
  1370. ASSERT( ((wcslen(buffer) + 1) * sizeof(WCHAR)) == length );
  1371. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("BusQueryDeviceID=%S\n", buffer) );
  1372. break;
  1373. case BusQueryInstanceID:
  1374. //
  1375. // InstanceID is a string to identify the device instance. We return
  1376. // the disk GUID in string form.
  1377. //
  1378. // Allocate pool to hold the string.
  1379. //
  1380. buffer = ALLOCATE_POOL( PagedPool, DiskExtension->DiskGuidFormatted.MaximumLength, FALSE );
  1381. if ( buffer == NULL ) {
  1382. status = STATUS_INSUFFICIENT_RESOURCES;
  1383. break;
  1384. }
  1385. //
  1386. // Copy the string into the destination buffer.
  1387. //
  1388. result = StringCbCopyW(
  1389. buffer,
  1390. DiskExtension->DiskGuidFormatted.MaximumLength,
  1391. DiskExtension->DiskGuidFormatted.Buffer
  1392. );
  1393. ASSERT( result == S_OK );
  1394. ASSERT( ((wcslen(buffer) + 1) * sizeof(WCHAR)) == DiskExtension->DiskGuidFormatted.MaximumLength );
  1395. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("BusQueryInstanceID=%S\n", buffer) );
  1396. break;
  1397. case BusQueryHardwareIDs:
  1398. //
  1399. // HardwareIDs is a multi-sz string to identify a device's hardware
  1400. // type. We return the string "Ramdisk\RamVolume\0" or
  1401. // "Ramdisk\RamDisk\0".
  1402. //
  1403. // Allocate pool to hold the string. Note that we allocate space
  1404. // for two null terminators.
  1405. //
  1406. length = sizeof(RAMDISK_ENUMERATOR_TEXT) - sizeof(WCHAR) +
  1407. ((DiskExtension->DiskType == RAMDISK_TYPE_FILE_BACKED_DISK) ?
  1408. sizeof(RAMDISK_DISK_DEVICE_TEXT) : sizeof(RAMDISK_VOLUME_DEVICE_TEXT)) +
  1409. sizeof(WCHAR);
  1410. buffer = ALLOCATE_POOL( PagedPool, length, FALSE );
  1411. if ( buffer == NULL ) {
  1412. status = STATUS_INSUFFICIENT_RESOURCES;
  1413. break;
  1414. }
  1415. //
  1416. // Copy the string into the destination buffer.
  1417. //
  1418. result = StringCbCopyW( buffer, length, RAMDISK_ENUMERATOR_TEXT );
  1419. ASSERT( result == S_OK );
  1420. result = StringCbCatW(
  1421. buffer,
  1422. length,
  1423. (DiskExtension->DiskType == RAMDISK_TYPE_FILE_BACKED_DISK) ?
  1424. RAMDISK_DISK_DEVICE_TEXT : RAMDISK_VOLUME_DEVICE_TEXT
  1425. );
  1426. ASSERT( result == S_OK );
  1427. ASSERT( ((wcslen(buffer) + 2) * sizeof(WCHAR)) == length );
  1428. buffer[length/sizeof(WCHAR) - 1] = 0;
  1429. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("BusQueryHardwareIDs=%S\n", buffer) );
  1430. break;
  1431. case BusQueryCompatibleIDs:
  1432. //
  1433. // HardwareIDs is a multi-sz string to identify device classes that
  1434. // are compatible with a device. For volume-emulating RAM disks, we
  1435. // return no compatible IDs, so that the device stands on its own at
  1436. // the volume level. For disk-emulating RAM disks, we return the
  1437. // string "Gendisk\0", so that the device gets hooked in below disk.sys.
  1438. //
  1439. if ( DiskExtension->DiskType == RAMDISK_TYPE_FILE_BACKED_DISK ) {
  1440. //
  1441. // Disk emulation. Allocate pool to hold the string.
  1442. //
  1443. length = sizeof(L"GenDisk") + sizeof(WCHAR);
  1444. buffer = ALLOCATE_POOL( PagedPool, length, FALSE );
  1445. if ( buffer == NULL ) {
  1446. status = STATUS_INSUFFICIENT_RESOURCES;
  1447. break;
  1448. }
  1449. //
  1450. // Copy the string into the destination buffer.
  1451. //
  1452. result = StringCbCopyW( buffer, length, L"GenDisk" );
  1453. ASSERT( result == S_OK );
  1454. ASSERT( ((wcslen(buffer) + 2) * sizeof(WCHAR)) == length );
  1455. buffer[length/sizeof(WCHAR) - 1] = 0;
  1456. } else {
  1457. //
  1458. // Volume emulation. Do not return any compatible IDs.
  1459. //
  1460. buffer = NULL;
  1461. status = STATUS_INVALID_DEVICE_REQUEST;
  1462. }
  1463. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("BusQueryCompatibleIDs=%S\n", buffer) );
  1464. break;
  1465. default:
  1466. //
  1467. // Unknown query type. Just leave whatever's already in the IRP there.
  1468. //
  1469. status = Irp->IoStatus.Status;
  1470. buffer = (PWCHAR)Irp->IoStatus.Information;
  1471. }
  1472. //
  1473. // Complete the request.
  1474. //
  1475. COMPLETE_REQUEST( status, (ULONG_PTR)buffer, Irp );
  1476. return status;
  1477. } // RamdiskQueryId
  1478. NTSTATUS
  1479. RamdiskQueryDeviceRelations (
  1480. IN DEVICE_RELATION_TYPE RelationsType,
  1481. IN PDEVICE_OBJECT DeviceObject,
  1482. IN PIRP Irp
  1483. )
  1484. /*++
  1485. Routine Description:
  1486. This routine processes the IRP_MN_QUERY_DEVICE_RELATIONS IRP.
  1487. Arguments:
  1488. DeviceObject - a pointer to the object that represents the device on which
  1489. the operation is to be performed
  1490. Irp - a pointer to the I/O Request Packet for this request
  1491. Return Value:
  1492. NTSTATUS - the status of the operation
  1493. --*/
  1494. {
  1495. NTSTATUS status;
  1496. PCOMMON_EXTENSION commonExtension;
  1497. PBUS_EXTENSION busExtension;
  1498. PDISK_EXTENSION diskExtension;
  1499. RAMDISK_DEVICE_TYPE deviceType;
  1500. PLIST_ENTRY listEntry;
  1501. PDEVICE_RELATIONS deviceRelations;
  1502. PDEVICE_RELATIONS oldRelations;
  1503. ULONG prevCount = 0;
  1504. ULONG length = 0;
  1505. ULONG numPdosPresent = 0;
  1506. PAGED_CODE();
  1507. //
  1508. // Assume success.
  1509. //
  1510. status = STATUS_SUCCESS;
  1511. //
  1512. // Get the device extension pointer and save the device type.
  1513. //
  1514. commonExtension = (PCOMMON_EXTENSION)DeviceObject->DeviceExtension;
  1515. deviceType = commonExtension->DeviceType;
  1516. DBGPRINT( DBG_PNP, DBG_VERBOSE,
  1517. ("RamdiskQueryDeviceRelations: QueryDeviceRelation Type: %s, DeviceType 0x%x\n",
  1518. GetDeviceRelationString(RelationsType), deviceType) );
  1519. //
  1520. // Dispatch based on the device type.
  1521. //
  1522. if ( deviceType == RamdiskDeviceTypeDiskPdo ) {
  1523. //
  1524. // It's a disk PDO. We only handle TargetDeviceRelation for PDOs.
  1525. //
  1526. diskExtension = (PDISK_EXTENSION)commonExtension;
  1527. if ( RelationsType == TargetDeviceRelation ) {
  1528. //
  1529. // Allocate pool to hold the return information. (DEVICE_RELATIONS
  1530. // has space for one entry built-in).
  1531. //
  1532. deviceRelations = ALLOCATE_POOL( PagedPool, sizeof(DEVICE_RELATIONS), FALSE );
  1533. if ( deviceRelations != NULL ) {
  1534. //
  1535. // Return a referenced pointer to the device object for this
  1536. // device.
  1537. //
  1538. ObReferenceObject( DeviceObject );
  1539. deviceRelations->Count = 1;
  1540. deviceRelations->Objects[0] = DeviceObject;
  1541. status = STATUS_SUCCESS;
  1542. } else {
  1543. //
  1544. // Couldn't allocate pool.
  1545. //
  1546. status = STATUS_INSUFFICIENT_RESOURCES;
  1547. }
  1548. //
  1549. // Complete the request.
  1550. //
  1551. COMPLETE_REQUEST( status, (ULONG_PTR)deviceRelations, Irp );
  1552. } else {
  1553. //
  1554. // PDOs just complete enumeration requests without altering
  1555. // the status.
  1556. //
  1557. status = Irp->IoStatus.Status;
  1558. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  1559. }
  1560. return status;
  1561. } else {
  1562. //
  1563. // It's the bus FDO. We only handle BusRelations for the FDO.
  1564. //
  1565. busExtension = (PBUS_EXTENSION)commonExtension;
  1566. if ( RelationsType == BusRelations ) {
  1567. //
  1568. // Re-enumerate the device.
  1569. //
  1570. // Lock the disk PDO list.
  1571. //
  1572. KeEnterCriticalRegion();
  1573. ExAcquireFastMutex( &busExtension->Mutex );
  1574. //
  1575. // There might also be device relations below and above this FDO,
  1576. // so propagate the relations from the upper drivers.
  1577. //
  1578. oldRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
  1579. if (oldRelations != NULL) {
  1580. prevCount = oldRelations->Count;
  1581. } else {
  1582. prevCount = 0;
  1583. }
  1584. //
  1585. // Calculate the number of PDOs actually present on the bus.
  1586. //
  1587. numPdosPresent = 0;
  1588. for ( listEntry = busExtension->DiskPdoList.Flink;
  1589. listEntry != &busExtension->DiskPdoList;
  1590. listEntry = listEntry->Flink ) {
  1591. diskExtension = CONTAINING_RECORD( listEntry, DISK_EXTENSION, DiskPdoListEntry );
  1592. if ( diskExtension->DeviceState < RamdiskDeviceStateRemoved ) {
  1593. numPdosPresent++;
  1594. }
  1595. }
  1596. //
  1597. // Allocate a new relations structure and add our PDOs to it.
  1598. //
  1599. length = sizeof(DEVICE_RELATIONS) +
  1600. ((numPdosPresent + prevCount - 1) * sizeof(PDEVICE_OBJECT));
  1601. deviceRelations = ALLOCATE_POOL( PagedPool, length, FALSE );
  1602. if ( deviceRelations == NULL ) {
  1603. //
  1604. // Fail the IRP.
  1605. //
  1606. ExReleaseFastMutex( &busExtension->Mutex );
  1607. KeLeaveCriticalRegion();
  1608. status = STATUS_INSUFFICIENT_RESOURCES;
  1609. COMPLETE_REQUEST( status, Irp->IoStatus.Information, Irp );
  1610. return status;
  1611. }
  1612. //
  1613. // Copy in the device objects so far.
  1614. //
  1615. if ( prevCount != 0 ) {
  1616. RtlCopyMemory(
  1617. deviceRelations->Objects,
  1618. oldRelations->Objects,
  1619. prevCount * sizeof(PDEVICE_OBJECT)
  1620. );
  1621. }
  1622. deviceRelations->Count = prevCount + numPdosPresent;
  1623. //
  1624. // For each PDO present on this bus, add a pointer to the device
  1625. // relations buffer, being sure to take out a reference to that
  1626. // object. PnP will dereference the object when it is done with it
  1627. // and free the device relations buffer.
  1628. //
  1629. for ( listEntry = busExtension->DiskPdoList.Flink;
  1630. listEntry != &busExtension->DiskPdoList;
  1631. listEntry = listEntry->Flink ) {
  1632. diskExtension = CONTAINING_RECORD( listEntry, DISK_EXTENSION, DiskPdoListEntry );
  1633. if ( diskExtension->DeviceState < RamdiskDeviceStateRemoved ) {
  1634. ObReferenceObject( diskExtension->Pdo );
  1635. deviceRelations->Objects[prevCount] = diskExtension->Pdo;
  1636. DBGPRINT( DBG_PNP, DBG_VERBOSE,
  1637. ("QueryDeviceRelations(BusRelations) PDO = 0x%p\n",
  1638. deviceRelations->Objects[prevCount]) );
  1639. prevCount++;
  1640. } else {
  1641. if ( diskExtension->DeviceState == RamdiskDeviceStateRemoved ) {
  1642. diskExtension->DeviceState = RamdiskDeviceStateRemovedAndNotReported;
  1643. }
  1644. DBGPRINT( DBG_PNP, DBG_VERBOSE,
  1645. ("QueryDeviceRelations(BusRelations) PDO = 0x%p -- SKIPPED\n",
  1646. diskExtension->Pdo) );
  1647. }
  1648. }
  1649. //
  1650. // Release the lock.
  1651. //
  1652. ExReleaseFastMutex( &busExtension->Mutex );
  1653. KeLeaveCriticalRegion();
  1654. DBGPRINT( DBG_PNP, DBG_VERBOSE,
  1655. ("QueryDeviceRelations(BusRelations) Total #PDOs reported = %d, "
  1656. "%d were new\n",
  1657. deviceRelations->Count, numPdosPresent) );
  1658. //
  1659. // Replace the relations structure in the IRP with the new
  1660. // one.
  1661. //
  1662. if ( oldRelations != NULL ) {
  1663. FREE_POOL( oldRelations, FALSE );
  1664. }
  1665. Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
  1666. Irp->IoStatus.Status = STATUS_SUCCESS;
  1667. }
  1668. //
  1669. // Send the IRP down the device stack.
  1670. //
  1671. IoCopyCurrentIrpStackLocationToNext( Irp );
  1672. status = IoCallDriver( busExtension->LowerDeviceObject, Irp );
  1673. }
  1674. return status;
  1675. } // RamdiskQueryDeviceRelations
  1676. NTSTATUS
  1677. RamdiskQueryDeviceText (
  1678. IN PDISK_EXTENSION DiskExtension,
  1679. IN PIRP Irp
  1680. )
  1681. /*++
  1682. Routine Description:
  1683. This routine processes the IRP_MN_QUERY_DEVICE_TEXT IRP.
  1684. Arguments:
  1685. DeviceObject - a pointer to the object that represents the device on which
  1686. the operation is to be performed
  1687. Irp - a pointer to the I/O Request Packet for this request
  1688. Return Value:
  1689. NTSTATUS - the status of the operation
  1690. --*/
  1691. {
  1692. NTSTATUS status;
  1693. PIO_STACK_LOCATION irpSp;
  1694. ULONG length;
  1695. PWCHAR buffer;
  1696. UNICODE_STRING tempString;
  1697. HRESULT result;
  1698. PAGED_CODE();
  1699. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("%s", "RamdiskQueryDeviceText\n") );
  1700. //
  1701. // Assume success.
  1702. //
  1703. status = STATUS_SUCCESS;
  1704. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1705. //
  1706. // Dispatch based on the query type.
  1707. //
  1708. switch ( irpSp->Parameters.QueryDeviceText.DeviceTextType ) {
  1709. case DeviceTextDescription:
  1710. //
  1711. // Description is just "RamDisk".
  1712. //
  1713. // Allocate pool to hold the string.
  1714. //
  1715. length = sizeof( RAMDISK_DISK_DEVICE_TEXT );
  1716. buffer = ALLOCATE_POOL( PagedPool, length, FALSE );
  1717. if ( buffer == NULL ) {
  1718. status = STATUS_INSUFFICIENT_RESOURCES;
  1719. break;
  1720. }
  1721. //
  1722. // Copy the string into the destination buffer.
  1723. //
  1724. result = StringCbCopyW( buffer, length, RAMDISK_DISK_DEVICE_TEXT );
  1725. ASSERT( result == S_OK );
  1726. ASSERT( ((wcslen(buffer) + 1) * sizeof(WCHAR)) == length );
  1727. break;
  1728. case DeviceTextLocationInformation:
  1729. //
  1730. // LocationInformation is just "Ramdisk\\0".
  1731. //
  1732. // Allocate pool to hold the string.
  1733. //
  1734. length = sizeof( RAMDISK_ENUMERATOR_BUS_TEXT );
  1735. buffer = ALLOCATE_POOL( PagedPool, length, FALSE );
  1736. if ( buffer == NULL ) {
  1737. status = STATUS_INSUFFICIENT_RESOURCES;
  1738. break;
  1739. }
  1740. //
  1741. // Copy the string into the destination buffer.
  1742. //
  1743. result = StringCbCopyW( buffer, length, RAMDISK_ENUMERATOR_BUS_TEXT );
  1744. ASSERT( result == S_OK );
  1745. ASSERT( ((wcslen(buffer) + 1) * sizeof(WCHAR)) == length );
  1746. break;
  1747. default:
  1748. //
  1749. // Unknown query type. Just leave whatever's already in the IRP there.
  1750. //
  1751. status = Irp->IoStatus.Status;
  1752. buffer = (PWCHAR)Irp->IoStatus.Information;
  1753. }
  1754. //
  1755. // Complete the request.
  1756. //
  1757. COMPLETE_REQUEST( status, (ULONG_PTR)buffer, Irp );
  1758. return status;
  1759. } // RamdiskQueryDeviceText
  1760. NTSTATUS
  1761. RamdiskRemoveBusDevice (
  1762. IN PDEVICE_OBJECT DeviceObject,
  1763. IN PIRP Irp
  1764. )
  1765. /*++
  1766. Routine Description:
  1767. This routine removes the bus device.
  1768. The remove lock must be held on entry.
  1769. Arguments:
  1770. DeviceObject - a pointer to the object that represents the device on which
  1771. the operation is to be performed
  1772. Irp - a pointer to the I/O Request Packet for this request
  1773. Return Value:
  1774. NTSTATUS - the status of the operation
  1775. --*/
  1776. {
  1777. NTSTATUS status;
  1778. PBUS_EXTENSION busExtension;
  1779. PLIST_ENTRY listEntry;
  1780. PDISK_EXTENSION diskExtension;
  1781. PAGED_CODE();
  1782. DBGPRINT( DBG_PNP, DBG_VERBOSE, ("%s", "RamdiskRemoveBusDevice\n" ) );
  1783. //
  1784. // Get a pointer to the device extension.
  1785. //
  1786. busExtension = DeviceObject->DeviceExtension;
  1787. //
  1788. // Lock the disk PDO list. Walk the list, deleting all remaining devices.
  1789. //
  1790. KeEnterCriticalRegion();
  1791. ExAcquireFastMutex( &busExtension->Mutex );
  1792. while ( !IsListEmpty( &busExtension->DiskPdoList ) ) {
  1793. listEntry = busExtension->DiskPdoList.Flink;
  1794. //
  1795. // Delete the device and clean it up. Acquire the remove lock first.
  1796. // RamdiskDeleteDiskDevice releases it.
  1797. //
  1798. diskExtension = CONTAINING_RECORD( listEntry, DISK_EXTENSION, DiskPdoListEntry );
  1799. status = IoAcquireRemoveLock( &diskExtension->RemoveLock, NULL );
  1800. ASSERT( NT_SUCCESS(status) );
  1801. RamdiskDeleteDiskDevice( diskExtension->Pdo, NULL );
  1802. KeEnterCriticalRegion();
  1803. ExAcquireFastMutex( &busExtension->Mutex );
  1804. }
  1805. //
  1806. // Release the lock.
  1807. //
  1808. ExReleaseFastMutex( &busExtension->Mutex );
  1809. KeLeaveCriticalRegion();
  1810. //
  1811. // Pass the IRP on down to lower levels.
  1812. //
  1813. Irp->IoStatus.Status = STATUS_SUCCESS;
  1814. IoSkipCurrentIrpStackLocation( Irp );
  1815. status = IoCallDriver( busExtension->LowerDeviceObject, Irp );
  1816. //
  1817. // Set the device status to Removed and wait for other drivers
  1818. // to release the lock, then delete the device object.
  1819. //
  1820. busExtension->DeviceState = RamdiskDeviceStateRemoved;
  1821. IoReleaseRemoveLockAndWait( &busExtension->RemoveLock, Irp );
  1822. //
  1823. // Stop the interface and free the interface string.
  1824. //
  1825. if ( busExtension->InterfaceString.Buffer != NULL ) {
  1826. IoSetDeviceInterfaceState( &busExtension->InterfaceString, FALSE );
  1827. RtlFreeUnicodeString( &busExtension->InterfaceString );
  1828. }
  1829. //
  1830. // If attached to a lower device, detach now.
  1831. //
  1832. if ( busExtension->LowerDeviceObject != NULL ) {
  1833. IoDetachDevice( busExtension->LowerDeviceObject );
  1834. }
  1835. #if SUPPORT_DISK_NUMBERS
  1836. //
  1837. // Free the disk numbers bitmap.
  1838. //
  1839. ASSERT( !RtlAreBitsSet( &busExtension->DiskNumbersBitmap, 0, DiskNumbersBitmapSize ) );
  1840. FREE_POOL( busExtension->DiskNumbersBitmapBuffer, TRUE );
  1841. #endif // SUPPORT_DISK_NUMBERS
  1842. //
  1843. // Indicate that we no longer have a bus FDO, and delete the device object.
  1844. //
  1845. RamdiskBusFdo = NULL;
  1846. IoDeleteDevice( DeviceObject );
  1847. DBGPRINT( DBG_PNP, DBG_NOTIFY, ("%s", "Device removed succesfully\n") );
  1848. return status;
  1849. } // RamdiskRemoveBusDevice
  1850. #if DBG
  1851. PSTR
  1852. GetPnpIrpName (
  1853. IN UCHAR PnpMinorFunction
  1854. )
  1855. {
  1856. static char functionName[25];
  1857. HRESULT result;
  1858. PAGED_CODE();
  1859. switch ( PnpMinorFunction ) {
  1860. case IRP_MN_START_DEVICE:
  1861. return "IRP_MN_START_DEVICE";
  1862. case IRP_MN_QUERY_REMOVE_DEVICE:
  1863. return "IRP_MN_QUERY_REMOVE_DEVICE";
  1864. case IRP_MN_REMOVE_DEVICE:
  1865. return "IRP_MN_REMOVE_DEVICE";
  1866. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1867. return "IRP_MN_CANCEL_REMOVE_DEVICE";
  1868. case IRP_MN_STOP_DEVICE:
  1869. return "IRP_MN_STOP_DEVICE";
  1870. case IRP_MN_QUERY_STOP_DEVICE:
  1871. return "IRP_MN_QUERY_STOP_DEVICE";
  1872. case IRP_MN_CANCEL_STOP_DEVICE:
  1873. return "IRP_MN_CANCEL_STOP_DEVICE";
  1874. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1875. return "IRP_MN_QUERY_DEVICE_RELATIONS";
  1876. case IRP_MN_QUERY_INTERFACE:
  1877. return "IRP_MN_QUERY_INTERFACE";
  1878. case IRP_MN_QUERY_CAPABILITIES:
  1879. return "IRP_MN_QUERY_CAPABILITIES";
  1880. case IRP_MN_QUERY_RESOURCES:
  1881. return "IRP_MN_QUERY_RESOURCES";
  1882. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  1883. return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
  1884. case IRP_MN_QUERY_DEVICE_TEXT:
  1885. return "IRP_MN_QUERY_DEVICE_TEXT";
  1886. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  1887. return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
  1888. case IRP_MN_READ_CONFIG:
  1889. return "IRP_MN_READ_CONFIG";
  1890. case IRP_MN_WRITE_CONFIG:
  1891. return "IRP_MN_WRITE_CONFIG";
  1892. case IRP_MN_EJECT:
  1893. return "IRP_MN_EJECT";
  1894. case IRP_MN_SET_LOCK:
  1895. return "IRP_MN_SET_LOCK";
  1896. case IRP_MN_QUERY_ID:
  1897. return "IRP_MN_QUERY_ID";
  1898. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  1899. return "IRP_MN_QUERY_PNP_DEVICE_STATE";
  1900. case IRP_MN_QUERY_BUS_INFORMATION:
  1901. return "IRP_MN_QUERY_BUS_INFORMATION";
  1902. case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  1903. return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
  1904. case IRP_MN_SURPRISE_REMOVAL:
  1905. return "IRP_MN_SURPRISE_REMOVAL";
  1906. case IRP_MN_QUERY_LEGACY_BUS_INFORMATION:
  1907. return "IRP_MN_QUERY_LEGACY_BUS_INFORMATION";
  1908. default:
  1909. result = StringCbPrintfA(
  1910. functionName,
  1911. sizeof( functionName ),
  1912. "Unknown PnP IRP 0x%02x",
  1913. PnpMinorFunction
  1914. );
  1915. ASSERT( result == S_OK );
  1916. return functionName;
  1917. }
  1918. } // GetPnpIrpName
  1919. PCHAR
  1920. GetDeviceRelationString (
  1921. IN DEVICE_RELATION_TYPE Type
  1922. )
  1923. {
  1924. static char relationName[30];
  1925. HRESULT result;
  1926. PAGED_CODE();
  1927. switch ( Type ) {
  1928. case BusRelations:
  1929. return "BusRelations";
  1930. case EjectionRelations:
  1931. return "EjectionRelations";
  1932. case RemovalRelations:
  1933. return "RemovalRelations";
  1934. case TargetDeviceRelation:
  1935. return "TargetDeviceRelation";
  1936. default:
  1937. result = StringCbPrintfA(
  1938. relationName,
  1939. sizeof( relationName ),
  1940. "Unknown relation 0x%02x",
  1941. Type
  1942. );
  1943. ASSERT( result == S_OK );
  1944. return relationName;
  1945. }
  1946. } // GetDeviceRelationString
  1947. #endif // DBG