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.

1256 lines
30 KiB

  1. /*++
  2. Copyright (c) 1993-2001 Microsoft Corporation
  3. Module Name:
  4. ramdisk.c
  5. Abstract:
  6. This is the RAM disk driver for Windows.
  7. Author:
  8. Chuck Lenzmeier (ChuckL) 2001
  9. based on prototype XIP driver by DavePr
  10. based on NT4 DDK ramdisk by RobertN
  11. Environment:
  12. Kernel mode only.
  13. Notes:
  14. Revision History:
  15. --*/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include <initguid.h>
  19. #include <ntddstor.h>
  20. #include <ntddramd.h>
  21. //
  22. // ISSUE: 2000/10/11-DavePr -- haven't decided how to define DO_XIP appropriately.
  23. //
  24. #ifndef DO_XIP
  25. #define DO_XIP 0x00020000
  26. #endif
  27. //
  28. // Data declarations.
  29. //
  30. PDEVICE_OBJECT RamdiskBusFdo = NULL;
  31. BOOLEAN ReportDetectedDevice;
  32. ULONG MinimumViewCount;
  33. ULONG DefaultViewCount;
  34. ULONG MaximumViewCount;
  35. ULONG MinimumViewLength;
  36. ULONG DefaultViewLength;
  37. ULONG MaximumViewLength;
  38. ULONG MaximumPerDiskViewLength;
  39. UNICODE_STRING DriverRegistryPath;
  40. BOOLEAN MarkRamdisksAsRemovable;
  41. #if SUPPORT_DISK_NUMBERS
  42. ULONG DiskNumbersBitmapSize;
  43. #endif // SUPPORT_DISK_NUMBERS
  44. #if DBG
  45. ULONG BreakOnEntry = DEFAULT_BREAK_ON_ENTRY;
  46. ULONG DebugComponents = DEFAULT_DEBUG_COMPONENTS;
  47. ULONG DebugLevel = DEFAULT_DEBUG_LEVEL;
  48. BOOLEAN DontLoad = FALSE;
  49. #endif
  50. //
  51. // Local functions.
  52. //
  53. NTSTATUS
  54. DriverEntry (
  55. IN OUT PDRIVER_OBJECT DriverObject,
  56. IN PUNICODE_STRING RegistryPath
  57. );
  58. NTSTATUS
  59. RamdiskCreateClose (
  60. IN PDEVICE_OBJECT DeviceObject,
  61. IN PIRP Irp
  62. );
  63. NTSTATUS
  64. RamdiskFlushBuffers (
  65. IN PDEVICE_OBJECT DeviceObject,
  66. IN PIRP Irp
  67. );
  68. NTSTATUS
  69. RamdiskFlushBuffersReal (
  70. IN PDISK_EXTENSION DiskExtension
  71. );
  72. NTSTATUS
  73. RamdiskSystemControl (
  74. IN PDEVICE_OBJECT DeviceObject,
  75. IN PIRP Irp
  76. );
  77. VOID
  78. RamdiskUnload (
  79. IN PDRIVER_OBJECT DriverObject
  80. );
  81. VOID
  82. QueryParameters (
  83. IN PUNICODE_STRING RegistryPath
  84. );
  85. #if DBG
  86. NTSTATUS
  87. RamdiskInvalidDeviceRequest (
  88. IN PDEVICE_OBJECT DeviceObject,
  89. IN PIRP Irp
  90. );
  91. VOID
  92. QueryDebugParameters (
  93. IN PUNICODE_STRING RegistryPath
  94. );
  95. #endif
  96. //
  97. // Declare pageable routines.
  98. //
  99. #ifdef ALLOC_PRAGMA
  100. #pragma alloc_text( INIT, DriverEntry )
  101. #pragma alloc_text( INIT, QueryParameters )
  102. #pragma alloc_text( PAGE, RamdiskCreateClose )
  103. #pragma alloc_text( PAGE, RamdiskFlushBuffers )
  104. #pragma alloc_text( PAGE, RamdiskFlushBuffersReal )
  105. #pragma alloc_text( PAGE, RamdiskSystemControl )
  106. #pragma alloc_text( PAGE, RamdiskUnload )
  107. #pragma alloc_text( PAGE, RamdiskWorkerThread )
  108. #if DBG
  109. #pragma alloc_text( INIT, QueryDebugParameters )
  110. #endif // DBG
  111. #endif // ALLOC_PRAGMA
  112. NTSTATUS
  113. DriverEntry (
  114. IN OUT PDRIVER_OBJECT DriverObject,
  115. IN PUNICODE_STRING RegistryPath
  116. )
  117. /*++
  118. Routine Description:
  119. This routine is called by the operating system to initialize the driver.
  120. Arguments:
  121. DriverObject - a pointer to a driver object for the driver
  122. RegistryPath - a pointer to our Services key in the registry
  123. Return Value:
  124. NTSTATUS
  125. --*/
  126. {
  127. NTSTATUS status;
  128. HANDLE handle;
  129. ULONG i;
  130. PDEVICE_OBJECT pdo = NULL;
  131. PLOADER_PARAMETER_BLOCK loaderBlock;
  132. //
  133. // Initialize pool debugging, if enabled.
  134. //
  135. #if defined(POOL_DBG)
  136. RamdiskInitializePoolDebug();
  137. #endif
  138. //
  139. // Get debugging parameters from the registry.
  140. //
  141. #if DBG
  142. QueryDebugParameters( RegistryPath );
  143. #endif
  144. DBGPRINT( DBG_INIT, DBG_VERBOSE,
  145. ("DriverEntry: DriverObject = %x, RegistryPath = %ws\n",
  146. DriverObject, RegistryPath->Buffer) );
  147. //
  148. // If requested, break into the debugger.
  149. //
  150. #if DBG
  151. if ( BreakOnEntry ) {
  152. KdBreakPoint();
  153. }
  154. #endif
  155. //
  156. // If requested, fail the driver load.
  157. //
  158. #if DBG
  159. if ( DontLoad ) {
  160. return STATUS_INVALID_DEVICE_REQUEST;
  161. }
  162. #endif
  163. //
  164. // Get non-debug parameters from the registry.
  165. //
  166. QueryParameters( RegistryPath );
  167. //
  168. // Save the path to the driver's registry key.
  169. //
  170. DriverRegistryPath.Length = RegistryPath->Length;
  171. DriverRegistryPath.MaximumLength = (USHORT)(RegistryPath->Length + sizeof(WCHAR));
  172. DriverRegistryPath.Buffer = ALLOCATE_POOL( PagedPool, DriverRegistryPath.MaximumLength, TRUE );
  173. if ( DriverRegistryPath.Buffer == NULL ) {
  174. return STATUS_INSUFFICIENT_RESOURCES;
  175. }
  176. RtlCopyUnicodeString( &DriverRegistryPath, RegistryPath );
  177. ASSERT( DriverRegistryPath.Length == RegistryPath->Length );
  178. //
  179. // Initialize the driver object with this driver's entry points.
  180. //
  181. #if DBG
  182. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  183. DriverObject->MajorFunction[i] = RamdiskInvalidDeviceRequest;
  184. }
  185. #endif
  186. DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskCreateClose;
  187. DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskCreateClose;
  188. DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
  189. DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
  190. DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
  191. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
  192. DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
  193. DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
  194. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
  195. DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
  196. DriverObject->DriverUnload = RamdiskUnload;
  197. DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
  198. //
  199. // If the registry tells us to do so, or if textmode setup is running and
  200. // virtual floppy RAM disks are specified in the registry, call
  201. // IoReportDetectedDevice to hook us up to PnP, then call RamdiskAddDevice
  202. // directly. This is necessary during textmode in order to get any virtual
  203. // floppy RAM disks created -- our AddDevice routine is not normally called
  204. // during textmode. Calling IoReportDetectedDevice is also necessary during
  205. // a boot from a RAM disk in order to get the device plumbed early enough.
  206. //
  207. // We don't want to call IoReportDetectedDevice during textmode setup if
  208. // no virtual floppies exist, because calling IoReportDetectedDevice
  209. // causes a devnode for the controller device to be written to the
  210. // registry, and textmode setup only deletes the devnode if virtual
  211. // floppies exist. If we leave the devnode in the registry, then GUI setup
  212. // installs ramdisk.sys on the machine, even though we don't really want
  213. // it to.
  214. //
  215. loaderBlock = *(PLOADER_PARAMETER_BLOCK *)KeLoaderBlock;
  216. if ( ReportDetectedDevice ||
  217. ( (loaderBlock != NULL) &&
  218. (loaderBlock->SetupLoaderBlock != NULL) &&
  219. CreateRegistryDisks( TRUE ) ) ) {
  220. //
  221. // Inform PnP that we have detected the bus enumerator device and will be
  222. // doing the AddDevice ourselves.
  223. //
  224. status = IoReportDetectedDevice(
  225. DriverObject,
  226. InterfaceTypeUndefined,
  227. -1,
  228. -1,
  229. NULL, //allocatedResources,
  230. NULL, //ioResourceReq,
  231. FALSE,
  232. &pdo
  233. );
  234. if (!NT_SUCCESS(status)) {
  235. DBGPRINT( DBG_ALL, DBG_ERROR,
  236. ("RamdiskDriverEntry: IoReportDetectedDevice failed: %x\n", status) );
  237. return status;
  238. }
  239. //
  240. // Attach a device object to the pdo
  241. //
  242. status = RamdiskAddDevice(DriverObject, pdo);
  243. if ( !NT_SUCCESS(status) ) {
  244. DBGPRINT( DBG_ALL, DBG_ERROR,
  245. ("RamdiskDriverEntry: RamdiskAddDevice failed: %x\n", status) );
  246. return status;
  247. }
  248. //
  249. // Indicate that the device is done initializing.
  250. //
  251. pdo->Flags &= ~DO_DEVICE_INITIALIZING;
  252. }
  253. //
  254. // Indicate that the driver has loaded successfully.
  255. //
  256. DBGPRINT( DBG_INIT, DBG_VERBOSE, ("%s", "DriverEntry: succeeded\n") );
  257. return STATUS_SUCCESS;
  258. } // DriverEntry
  259. NTSTATUS
  260. RamdiskCreateClose (
  261. IN PDEVICE_OBJECT DeviceObject,
  262. IN PIRP Irp
  263. )
  264. /*++
  265. Routine Description:
  266. This routine is called by the I/O system when a device owned by the driver
  267. is opened or closed.
  268. No action is performed other than completing the request successfully.
  269. Arguments:
  270. DeviceObject - a pointer to the object that represents the device on which
  271. I/O is to be performed
  272. Irp - a pointer to the I/O Request Packet for this request
  273. Return Value:
  274. NTSTATUS - STATUS_SUCCESS
  275. --*/
  276. {
  277. PAGED_CODE();
  278. COMPLETE_REQUEST( STATUS_SUCCESS, FILE_OPENED, Irp );
  279. return STATUS_SUCCESS;
  280. } // RamdiskCreateClose
  281. NTSTATUS
  282. RamdiskFlushBuffers (
  283. IN PDEVICE_OBJECT DeviceObject,
  284. IN PIRP Irp
  285. )
  286. /*++
  287. Routine Description:
  288. This routine is called by the I/O system when a FLUSH_BUFFERS IRP is
  289. issued.
  290. Arguments:
  291. DeviceObject - a pointer to the object that represents the device on which
  292. I/O is to be performed
  293. Irp - a pointer to the I/O Request Packet for this request
  294. Return Value:
  295. NTSTATUS - the status of the operation
  296. --*/
  297. {
  298. NTSTATUS status;
  299. PDISK_EXTENSION diskExtension = DeviceObject->DeviceExtension;
  300. PAGED_CODE();
  301. //
  302. // If the target RAM disk is not file-backed, there's nothing to do. If it
  303. // is file-backed, we need to do the work in a thread.
  304. //
  305. if ( (diskExtension->DeviceType != RamdiskDeviceTypeDiskPdo) ||
  306. !RAMDISK_IS_FILE_BACKED(diskExtension->DiskType) ) {
  307. COMPLETE_REQUEST( STATUS_SUCCESS, 0, Irp );
  308. return STATUS_SUCCESS;
  309. }
  310. status = SendIrpToThread( DeviceObject, Irp );
  311. if ( status != STATUS_PENDING ) {
  312. COMPLETE_REQUEST( status, 0, Irp );
  313. }
  314. return status;
  315. } // RamdiskFlushBuffers
  316. NTSTATUS
  317. RamdiskFlushBuffersReal (
  318. IN PDISK_EXTENSION DiskExtension
  319. )
  320. /*++
  321. Routine Description:
  322. This routine is called in a thread in the system process to handle a
  323. FLUSH_BUFFERS IRP.
  324. Arguments:
  325. DiskExtension - a pointer to the device object extension for the target
  326. device
  327. Return Value:
  328. NTSTATUS - the status of the operation
  329. --*/
  330. {
  331. PAGED_CODE();
  332. //
  333. // Flush the virtual memory associated with the RAM disk.
  334. //
  335. return RamdiskFlushViews( DiskExtension );
  336. } // RamdiskFlushBuffersReal
  337. NTSTATUS
  338. RamdiskSystemControl (
  339. IN PDEVICE_OBJECT DeviceObject,
  340. IN PIRP Irp
  341. )
  342. /*++
  343. Routine Description:
  344. This routine is called by the I/O system when a SYSTEM_CONTROL IRP is
  345. issued.
  346. Arguments:
  347. DeviceObject - a pointer to the object that represents the device on which
  348. I/O is to be performed
  349. Irp - a pointer to the I/O Request Packet for this request
  350. Return Value:
  351. NTSTATUS - the status of the operation
  352. --*/
  353. {
  354. PCOMMON_EXTENSION commonExtension;
  355. NTSTATUS status;
  356. PAGED_CODE();
  357. //
  358. // If the target device is a bus FDO, pass the IRP down to the next
  359. // device in the stack. Otherwise, the target is a disk PDO, in which
  360. // case we just complete the IRP with the current status.
  361. //
  362. commonExtension = DeviceObject->DeviceExtension;
  363. if ( commonExtension->DeviceType == RamdiskDeviceTypeBusFdo ) {
  364. IoSkipCurrentIrpStackLocation( Irp );
  365. return IoCallDriver( commonExtension->LowerDeviceObject, Irp );
  366. }
  367. status = Irp->IoStatus.Status;
  368. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  369. return status;
  370. } // RamdiskSystemControl
  371. VOID
  372. RamdiskUnload (
  373. IN PDRIVER_OBJECT DriverObject
  374. )
  375. /*++
  376. Routine Description:
  377. This routine is called by the I/O system to unload the driver.
  378. Any resources previously allocated must be freed.
  379. Arguments:
  380. DriverObject - a pointer to the object that represents our driver
  381. Return Value:
  382. None.
  383. --*/
  384. {
  385. PAGED_CODE();
  386. if ( DriverRegistryPath.Buffer != NULL ) {
  387. FREE_POOL( DriverRegistryPath.Buffer, TRUE );
  388. }
  389. //
  390. // ISSUE: What other cleanup is needed here?
  391. //
  392. return;
  393. } // RamdiskUnload
  394. VOID
  395. RamdiskWorkerThread (
  396. IN PDEVICE_OBJECT DeviceObject,
  397. IN PVOID Context
  398. )
  399. /*++
  400. Routine Description:
  401. This routine executes thread-based operations for the RAM disk driver.
  402. It runs in the context of the system process.
  403. Arguments:
  404. DeviceObject - a pointer to the object that represents the device on which
  405. I/O is to be performed
  406. Context - a pointer to the IRP for the I/O operation
  407. Return Value:
  408. None.
  409. --*/
  410. {
  411. NTSTATUS status;
  412. PLIST_ENTRY listEntry;
  413. PIRP irp;
  414. PIO_STACK_LOCATION irpSp;
  415. PCOMMON_EXTENSION commonExtension;
  416. PBUS_EXTENSION busExtension;
  417. PDISK_EXTENSION diskExtension;
  418. PSCSI_REQUEST_BLOCK srb;
  419. ULONG controlCode;
  420. PUCHAR originalDataBuffer;
  421. PUCHAR mappedDataBuffer;
  422. PUCHAR inputDataBuffer;
  423. PUCHAR systemAddress;
  424. ULONG originalDataBufferOffset;
  425. PAGED_CODE();
  426. //
  427. // Get a pointer to the IRP.
  428. //
  429. irp = Context;
  430. irpSp = IoGetCurrentIrpStackLocation( irp );
  431. //
  432. // Free the work item.
  433. //
  434. IoFreeWorkItem( irp->Tail.Overlay.DriverContext[0] );
  435. //
  436. // Get pointers to the device extension.
  437. //
  438. commonExtension = DeviceObject->DeviceExtension;
  439. busExtension = DeviceObject->DeviceExtension;
  440. diskExtension = DeviceObject->DeviceExtension;
  441. //
  442. // Acquire the remove lock for the device. If this fails, bail out.
  443. //
  444. status = IoAcquireRemoveLock( &commonExtension->RemoveLock, irp );
  445. if ( !NT_SUCCESS(status) ) {
  446. COMPLETE_REQUEST( status, 0, irp );
  447. return;
  448. }
  449. //
  450. // Dispatch based on the IRP function.
  451. //
  452. switch ( irpSp->MajorFunction ) {
  453. case IRP_MJ_READ:
  454. case IRP_MJ_WRITE:
  455. status = RamdiskReadWriteReal( irp, diskExtension );
  456. break;
  457. case IRP_MJ_FLUSH_BUFFERS:
  458. status = RamdiskFlushBuffersReal( diskExtension );
  459. irp->IoStatus.Information = 0;
  460. break;
  461. case IRP_MJ_DEVICE_CONTROL:
  462. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  463. case IOCTL_DISK_GET_DRIVE_LAYOUT:
  464. status = RamdiskGetDriveLayout( irp, diskExtension );
  465. break;
  466. case IOCTL_DISK_GET_PARTITION_INFO:
  467. status = RamdiskGetPartitionInfo( irp, diskExtension );
  468. break;
  469. case IOCTL_DISK_SET_PARTITION_INFO:
  470. status = RamdiskSetPartitionInfo( irp, diskExtension );
  471. break;
  472. case FSCTL_CREATE_RAM_DISK:
  473. status = RamdiskCreateRamDisk( DeviceObject, irp, FALSE );
  474. break;
  475. default:
  476. DBGPRINT( DBG_IOCTL, DBG_ERROR,
  477. ("RamdiskThread: bogus IOCTL IRP with code %x received\n",
  478. irpSp->Parameters.DeviceIoControl.IoControlCode) );
  479. ASSERT( FALSE );
  480. status = STATUS_INVALID_DEVICE_REQUEST;
  481. break;
  482. }
  483. break;
  484. case IRP_MJ_SCSI:
  485. srb = irpSp->Parameters.Scsi.Srb;
  486. controlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;
  487. //
  488. // Remember the original data buffer pointer. We might have to
  489. // change the pointer.
  490. //
  491. originalDataBuffer = srb->DataBuffer;
  492. status = STATUS_SUCCESS;
  493. if ( irp->MdlAddress != NULL ) {
  494. //
  495. // There is an MDL in the IRP. Get a usable system address for
  496. // the data buffer based on the MDL.
  497. //
  498. systemAddress = MmGetSystemAddressForMdlSafe(
  499. irp->MdlAddress,
  500. NormalPagePriority
  501. );
  502. if ( systemAddress != NULL ) {
  503. //
  504. // The SRB data buffer might be at an offset from the
  505. // start of the MDL. Calculate that offset and add it
  506. // to the system address just obtained. This is the
  507. // data buffer address that we will use.
  508. //
  509. originalDataBufferOffset = (ULONG)(originalDataBuffer -
  510. (PCHAR)MmGetMdlVirtualAddress( irp->MdlAddress ));
  511. mappedDataBuffer = systemAddress + originalDataBufferOffset;
  512. srb->DataBuffer = mappedDataBuffer;
  513. } else {
  514. //
  515. // Couldn't get a system address. Abort.
  516. //
  517. srb->SrbStatus = SRB_STATUS_ABORTED;
  518. status = STATUS_INSUFFICIENT_RESOURCES;
  519. }
  520. }
  521. if ( NT_SUCCESS(status) ) {
  522. //
  523. // Remember the data buffer address that we're sending down.
  524. // If it doesn't change, we'll need to reset the address to
  525. // that which was passed in to us.
  526. //
  527. inputDataBuffer = srb->DataBuffer;
  528. //
  529. // Dispatch based on the I/O type in the SRB.
  530. //
  531. if ( controlCode == IOCTL_SCSI_EXECUTE_NONE ) {
  532. status = RamdiskScsiExecuteNone(
  533. diskExtension->Pdo,
  534. irp,
  535. srb,
  536. controlCode
  537. );
  538. } else {
  539. status = RamdiskScsiExecuteIo(
  540. diskExtension->Pdo,
  541. irp,
  542. srb,
  543. controlCode
  544. );
  545. }
  546. //
  547. // If the data buffer address didn't change, put the original
  548. // address back in the SRB.
  549. //
  550. if ( srb->DataBuffer == inputDataBuffer ) {
  551. srb->DataBuffer = originalDataBuffer;
  552. }
  553. }
  554. //
  555. // If the I/O worked, write the transfer length into the IRP.
  556. //
  557. if ( NT_SUCCESS(status) ) {
  558. irp->IoStatus.Information = srb->DataTransferLength;
  559. } else {
  560. irp->IoStatus.Information = 0;
  561. }
  562. break;
  563. default:
  564. DBGPRINT( DBG_IOCTL, DBG_ERROR,
  565. ("RamdiskThread: bogus IRP with major function %x received\n",
  566. irpSp->MajorFunction) );
  567. ASSERT( FALSE );
  568. status = STATUS_INVALID_DEVICE_REQUEST;
  569. }
  570. //
  571. // Release the remove lock and complete the request.
  572. //
  573. IoReleaseRemoveLock( &commonExtension->RemoveLock, irp );
  574. ASSERT( status != STATUS_PENDING );
  575. irp->IoStatus.Status = status;
  576. IoCompleteRequest( irp, IO_DISK_INCREMENT );
  577. return;
  578. } // RamdiskWorkerThread
  579. VOID
  580. QueryParameters (
  581. IN PUNICODE_STRING RegistryPath
  582. )
  583. /*++
  584. Routine Description:
  585. This routine is called from DriverEntry() to get driver parameters from
  586. the registry. If the registry query fails, then default values are used.
  587. Arguments:
  588. RegistryPath - a pointer to the service path for the registry parameters
  589. Return Value:
  590. None.
  591. --*/
  592. {
  593. NTSTATUS status;
  594. RTL_QUERY_REGISTRY_TABLE queryTable[12];
  595. PRTL_QUERY_REGISTRY_TABLE queryEntry;
  596. PAGED_CODE();
  597. DBGPRINT( DBG_INIT, DBG_VERBOSE, ("%s", "QueryParameters\n") );
  598. ASSERT( RegistryPath->Buffer != NULL );
  599. //
  600. // Set the default values.
  601. //
  602. ReportDetectedDevice = FALSE;
  603. MarkRamdisksAsRemovable = FALSE;
  604. MinimumViewCount = MINIMUM_MINIMUM_VIEW_COUNT;
  605. DefaultViewCount = DEFAULT_DEFAULT_VIEW_COUNT;
  606. MaximumViewCount = DEFAULT_MAXIMUM_VIEW_COUNT;
  607. MinimumViewLength = MINIMUM_MINIMUM_VIEW_LENGTH;
  608. DefaultViewLength = DEFAULT_DEFAULT_VIEW_LENGTH;
  609. MaximumViewLength = DEFAULT_MAXIMUM_VIEW_LENGTH;
  610. MaximumPerDiskViewLength = DEFAULT_MAXIMUM_PER_DISK_VIEW_LENGTH;
  611. #if SUPPORT_DISK_NUMBERS
  612. DiskNumbersBitmapSize = DEFAULT_DISK_NUMBERS_BITMAP_SIZE;
  613. #endif // SUPPORT_DISK_NUMBERS
  614. //
  615. // Set up the query table.
  616. //
  617. RtlZeroMemory( queryTable, sizeof(queryTable) );
  618. //
  619. // We're looking for subkey "Parameters" under the given registry key.
  620. //
  621. queryEntry = &queryTable[0];
  622. queryEntry->Flags = RTL_QUERY_REGISTRY_SUBKEY;
  623. queryEntry->Name = L"Parameters";
  624. queryEntry->EntryContext = NULL;
  625. queryEntry->DefaultType = REG_NONE;
  626. queryEntry->DefaultData = NULL;
  627. queryEntry->DefaultLength = 0;
  628. //
  629. // These are the values we want to read.
  630. //
  631. queryEntry++;
  632. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  633. queryEntry->Name = L"ReportDetectedDevice";
  634. queryEntry->EntryContext = &ReportDetectedDevice;
  635. queryEntry->DefaultType = REG_NONE;
  636. queryEntry->DefaultData = NULL;
  637. queryEntry->DefaultLength = 0;
  638. queryEntry++;
  639. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  640. queryEntry->Name = L"MarkRamdisksAsRemovable";
  641. queryEntry->EntryContext = &MarkRamdisksAsRemovable;
  642. queryEntry->DefaultType = REG_NONE;
  643. queryEntry->DefaultData = NULL;
  644. queryEntry->DefaultLength = 0;
  645. queryEntry++;
  646. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  647. queryEntry->Name = L"MinimumViewCount";
  648. queryEntry->EntryContext = &MinimumViewCount;
  649. queryEntry->DefaultType = REG_NONE;
  650. queryEntry->DefaultData = NULL;
  651. queryEntry->DefaultLength = 0;
  652. queryEntry++;
  653. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  654. queryEntry->Name = L"DefaultViewCount";
  655. queryEntry->EntryContext = &DefaultViewCount;
  656. queryEntry->DefaultType = REG_NONE;
  657. queryEntry->DefaultData = NULL;
  658. queryEntry->DefaultLength = 0;
  659. queryEntry++;
  660. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  661. queryEntry->Name = L"MaximumViewCount";
  662. queryEntry->EntryContext = &MaximumViewCount;
  663. queryEntry->DefaultType = REG_NONE;
  664. queryEntry->DefaultData = NULL;
  665. queryEntry->DefaultLength = 0;
  666. queryEntry++;
  667. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  668. queryEntry->Name = L"MinimumViewLength";
  669. queryEntry->EntryContext = &MinimumViewLength;
  670. queryEntry->DefaultType = REG_NONE;
  671. queryEntry->DefaultData = NULL;
  672. queryEntry->DefaultLength = 0;
  673. queryEntry++;
  674. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  675. queryEntry->Name = L"DefaultViewLength";
  676. queryEntry->EntryContext = &DefaultViewLength;
  677. queryEntry->DefaultType = REG_NONE;
  678. queryEntry->DefaultData = NULL;
  679. queryEntry->DefaultLength = 0;
  680. queryEntry++;
  681. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  682. queryEntry->Name = L"MaximumViewLength";
  683. queryEntry->EntryContext = &MaximumViewLength;
  684. queryEntry->DefaultType = REG_NONE;
  685. queryEntry->DefaultData = NULL;
  686. queryEntry->DefaultLength = 0;
  687. queryEntry++;
  688. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  689. queryEntry->Name = L"MaximumPerDiskViewLength";
  690. queryEntry->EntryContext = &MaximumPerDiskViewLength;
  691. queryEntry->DefaultType = REG_NONE;
  692. queryEntry->DefaultData = NULL;
  693. queryEntry->DefaultLength = 0;
  694. #if SUPPORT_DISK_NUMBERS
  695. queryEntry++;
  696. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  697. queryEntry->Name = L"DiskNumbersBitmapSize";
  698. queryEntry->EntryContext = &DiskNumbersBitmapSize;
  699. queryEntry->DefaultType = REG_NONE;
  700. queryEntry->DefaultData = NULL;
  701. queryEntry->DefaultLength = 0;
  702. #endif // SUPPORT_DISK_NUMBERS
  703. //
  704. // Do the query.
  705. //
  706. status = RtlQueryRegistryValues(
  707. RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  708. RegistryPath->Buffer,
  709. queryTable,
  710. NULL,
  711. NULL
  712. );
  713. //
  714. // Check the validity of the parameters.
  715. //
  716. if ( MinimumViewCount < MINIMUM_MINIMUM_VIEW_COUNT ) {
  717. MinimumViewCount = MINIMUM_MINIMUM_VIEW_COUNT;
  718. } else if ( MinimumViewCount > MAXIMUM_MINIMUM_VIEW_COUNT ) {
  719. MinimumViewCount = MAXIMUM_MINIMUM_VIEW_COUNT;
  720. }
  721. if ( DefaultViewCount < MinimumViewCount ) {
  722. DefaultViewCount = MinimumViewCount;
  723. } else if ( DefaultViewCount > MAXIMUM_DEFAULT_VIEW_COUNT ) {
  724. DefaultViewCount = MAXIMUM_DEFAULT_VIEW_COUNT;
  725. }
  726. if ( MaximumViewCount < DefaultViewCount ) {
  727. MaximumViewCount = DefaultViewCount;
  728. } else if ( MaximumViewCount > MAXIMUM_MAXIMUM_VIEW_COUNT ) {
  729. MaximumViewCount = MAXIMUM_MAXIMUM_VIEW_COUNT;
  730. }
  731. if ( MinimumViewLength < MINIMUM_MINIMUM_VIEW_LENGTH ) {
  732. MinimumViewLength = MINIMUM_MINIMUM_VIEW_LENGTH;
  733. } else if ( MinimumViewLength > MAXIMUM_MINIMUM_VIEW_LENGTH ) {
  734. MinimumViewLength = MAXIMUM_MINIMUM_VIEW_LENGTH;
  735. }
  736. if ( DefaultViewLength < MinimumViewLength ) {
  737. DefaultViewLength = MinimumViewLength;
  738. } else if ( DefaultViewLength > MAXIMUM_DEFAULT_VIEW_LENGTH ) {
  739. DefaultViewLength = MAXIMUM_DEFAULT_VIEW_LENGTH;
  740. }
  741. if ( MaximumViewLength < DefaultViewLength ) {
  742. MaximumViewLength = DefaultViewLength;
  743. } else if ( MaximumViewLength > MAXIMUM_MAXIMUM_VIEW_LENGTH ) {
  744. MaximumViewLength = MAXIMUM_MAXIMUM_VIEW_LENGTH;
  745. }
  746. if ( MaximumPerDiskViewLength < MINIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH ) {
  747. MaximumPerDiskViewLength = MINIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH;
  748. } else if ( MaximumViewLength > MAXIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH ) {
  749. MaximumPerDiskViewLength = MAXIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH;
  750. }
  751. #if SUPPORT_DISK_NUMBERS
  752. if ( DiskNumbersBitmapSize < MINIMUM_DISK_NUMBERS_BITMAP_SIZE ) {
  753. DiskNumbersBitmapSize = MINIMUM_DISK_NUMBERS_BITMAP_SIZE;
  754. } else if ( DiskNumbersBitmapSize > MAXIMUM_DISK_NUMBERS_BITMAP_SIZE ) {
  755. DiskNumbersBitmapSize = MAXIMUM_DISK_NUMBERS_BITMAP_SIZE;
  756. }
  757. #endif // SUPPORT_DISK_NUMBERS
  758. DBGPRINT( DBG_INIT, DBG_INFO, ("DefaultViewCount = 0x%x\n", DefaultViewCount) );
  759. DBGPRINT( DBG_INIT, DBG_INFO, ("MaximumViewCount = 0x%x\n", MaximumViewCount) );
  760. DBGPRINT( DBG_INIT, DBG_INFO, ("DefaultViewLength = 0x%x\n", DefaultViewLength) );
  761. DBGPRINT( DBG_INIT, DBG_INFO, ("MaximumViewLength = 0x%x\n", MaximumViewLength) );
  762. DBGPRINT( DBG_INIT, DBG_INFO, ("MaximumPerDiskViewLength = 0x%x\n", MaximumPerDiskViewLength) );
  763. #if SUPPORT_DISK_NUMBERS
  764. DBGPRINT( DBG_INIT, DBG_INFO, ("DiskNumbersBitmapSize = 0x%x\n", DiskNumbersBitmapSize) );
  765. #endif // SUPPORT_DISK_NUMBERS
  766. return;
  767. } // QueryParameters
  768. #if DBG
  769. NTSTATUS
  770. RamdiskInvalidDeviceRequest (
  771. IN PDEVICE_OBJECT DeviceObject,
  772. IN PIRP Irp
  773. )
  774. /*++
  775. Routine Description:
  776. This routine is called by the I/O system when an IRP that we don't
  777. process is issued.
  778. Arguments:
  779. DeviceObject - a pointer to the object that represents the device on which
  780. I/O is to be performed
  781. Irp - a pointer to the I/O Request Packet for this request
  782. Return Value:
  783. NTSTATUS - STATUS_INVALID_DEVICE_REQUEST
  784. --*/
  785. {
  786. //
  787. // We really do recognize CLEANUP and SHUTDOWN IRPs. For any other IRP,
  788. // print a message and break into the debugger.
  789. //
  790. switch ( IoGetCurrentIrpStackLocation(Irp)->MajorFunction ) {
  791. case IRP_MJ_CLEANUP:
  792. case IRP_MJ_SHUTDOWN:
  793. break;
  794. default:
  795. DBGPRINT( DBG_IOCTL, DBG_ERROR,
  796. ("Ramdisk: Unrecognized IRP: major/minor = %x/%x\n",
  797. IoGetCurrentIrpStackLocation(Irp)->MajorFunction,
  798. IoGetCurrentIrpStackLocation(Irp)->MinorFunction) );
  799. ASSERT( FALSE );
  800. }
  801. //
  802. // If this is a power IRP, we need to start the next one.
  803. //
  804. if ( IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_POWER ) {
  805. PoStartNextPowerIrp( Irp );
  806. }
  807. //
  808. // Tell the I/O system that we don't recognize this IRP.
  809. //
  810. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  811. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  812. return STATUS_INVALID_DEVICE_REQUEST;
  813. } // RamdiskInvalidDeviceRequest
  814. VOID
  815. QueryDebugParameters (
  816. IN PUNICODE_STRING RegistryPath
  817. )
  818. /*++
  819. Routine Description:
  820. This routine is called from DriverEntry() to get the debug parameters
  821. from the registry. If the registry query fails, then default values are
  822. used.
  823. Arguments:
  824. RegistryPath - a pointer to the service path for the registry parameters
  825. Return Value:
  826. None.
  827. --*/
  828. {
  829. NTSTATUS status;
  830. RTL_QUERY_REGISTRY_TABLE queryTable[5];
  831. PRTL_QUERY_REGISTRY_TABLE queryEntry;
  832. PAGED_CODE();
  833. DBGPRINT( DBG_INIT, DBG_VERBOSE, ("%s", "QueryDebugParameters\n") );
  834. ASSERT( RegistryPath->Buffer != NULL );
  835. //
  836. // Set the default values.
  837. //
  838. BreakOnEntry = DEFAULT_BREAK_ON_ENTRY;
  839. DebugComponents = DEFAULT_DEBUG_COMPONENTS;
  840. DebugLevel = DEFAULT_DEBUG_LEVEL;
  841. //
  842. // Set up the query table.
  843. //
  844. RtlZeroMemory( queryTable, sizeof(queryTable) );
  845. //
  846. // We're looking for subkey "Debug" under the given registry key.
  847. //
  848. queryEntry = &queryTable[0];
  849. queryEntry->Flags = RTL_QUERY_REGISTRY_SUBKEY;
  850. queryEntry->Name = L"Debug";
  851. queryEntry->EntryContext = NULL;
  852. queryEntry->DefaultType = REG_NONE;
  853. queryEntry->DefaultData = NULL;
  854. queryEntry->DefaultLength = 0;
  855. //
  856. // These are the values we want to read.
  857. //
  858. queryEntry++;
  859. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  860. queryEntry->Name = L"BreakOnEntry";
  861. queryEntry->EntryContext = &BreakOnEntry;
  862. queryEntry->DefaultType = REG_NONE;
  863. queryEntry->DefaultData = NULL;
  864. queryEntry->DefaultLength = 0;
  865. queryEntry++;
  866. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  867. queryEntry->Name = L"DebugComponents";
  868. queryEntry->EntryContext = &DebugComponents;
  869. queryEntry->DefaultType = REG_NONE;
  870. queryEntry->DefaultData = NULL;
  871. queryEntry->DefaultLength = 0;
  872. queryEntry++;
  873. queryEntry->Flags = RTL_QUERY_REGISTRY_DIRECT;
  874. queryEntry->Name = L"DebugLevel";
  875. queryEntry->EntryContext = &DebugLevel;
  876. queryEntry->DefaultType = REG_NONE;
  877. queryEntry->DefaultData = NULL;
  878. queryEntry->DefaultLength = 0;
  879. //
  880. // Do the query.
  881. //
  882. status = RtlQueryRegistryValues(
  883. RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  884. RegistryPath->Buffer,
  885. queryTable,
  886. NULL,
  887. NULL
  888. );
  889. DBGPRINT( DBG_INIT, DBG_INFO, ("BreakOnEntry = 0x%x\n", BreakOnEntry) );
  890. DBGPRINT( DBG_INIT, DBG_INFO, ("DebugComponents = 0x%x\n", DebugComponents) );
  891. DBGPRINT( DBG_INIT, DBG_INFO, ("DebugLevel = 0x%x\n", DebugLevel) );
  892. return;
  893. } // QueryDebugParameters
  894. #endif