de6d2d5ca1081ae668f1528cf5bfa9b272694e13
[reactos.git] / drivers / storage / class / ramdisk / ramdisk.c
1 /*
2 * PROJECT: Ramdisk Class Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/storage/class/ramdisk/ramdisk.c
5 * PURPOSE: Main Driver Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <initguid.h>
12 #include <ntddk.h>
13 #include <ntifs.h>
14 #include <ntdddisk.h>
15 #include <ntddcdrm.h>
16 #include <scsi.h>
17 #include <ntddscsi.h>
18 #include <ntddvol.h>
19 #include <mountdev.h>
20 #include <mountmgr.h>
21 #include <ketypes.h>
22 #include <iotypes.h>
23 #include <rtlfuncs.h>
24 #include <arc/arc.h>
25 #include <reactos/drivers/ntddrdsk.h>
26 #include "../../../filesystems/fs_rec/fs_rec.h"
27 #include <stdio.h>
28 #define NDEBUG
29 #include <debug.h>
30
31 #define DO_XIP 0x00020000
32
33 /* GLOBALS ********************************************************************/
34
35 #define RAMDISK_SESSION_SIZE \
36 FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
37
38 #define RAMDISK_TOC_SIZE \
39 FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
40
41 #define TOC_DATA_TRACK (0x04)
42
43 typedef enum _RAMDISK_DEVICE_TYPE
44 {
45 RamdiskBus,
46 RamdiskDrive
47 } RAMDISK_DEVICE_TYPE;
48
49 typedef enum _RAMDISK_DEVICE_STATE
50 {
51 RamdiskStateUninitialized,
52 RamdiskStateStarted,
53 RamdiskStatePaused,
54 RamdiskStateStopped,
55 RamdiskStateRemoved,
56 RamdiskStateBusRemoved,
57 RamdiskStateEnumerated,
58 } RAMDISK_DEVICE_STATE;
59
60 DEFINE_GUID(RamdiskBusInterface,
61 0x5DC52DF0,
62 0x2F8A,
63 0x410F,
64 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
65
66 DEFINE_GUID(RamdiskDiskInterface,
67 0x31D909F0,
68 0x2CDF,
69 0x4A20,
70 0x9E, 0xD4, 0x7D, 0x65, 0x47, 0x6C, 0xA7, 0x68);
71
72 typedef struct _RAMDISK_EXTENSION
73 {
74 RAMDISK_DEVICE_TYPE Type;
75 RAMDISK_DEVICE_STATE State;
76 PDEVICE_OBJECT DeviceObject;
77 PDEVICE_OBJECT PhysicalDeviceObject;
78 PDEVICE_OBJECT AttachedDevice;
79 IO_REMOVE_LOCK RemoveLock;
80 UNICODE_STRING DriveDeviceName;
81 UNICODE_STRING BusDeviceName;
82 FAST_MUTEX DiskListLock;
83 LIST_ENTRY DiskList;
84 } RAMDISK_EXTENSION, *PRAMDISK_EXTENSION;
85
86 typedef struct _RAMDISK_BUS_EXTENSION
87 {
88 RAMDISK_EXTENSION;
89 } RAMDISK_BUS_EXTENSION, *PRAMDISK_BUS_EXTENSION;
90
91 typedef struct _RAMDISK_DRIVE_EXTENSION
92 {
93 /* Inherited base class */
94 RAMDISK_EXTENSION;
95
96 /* Data we get from the creator */
97 GUID DiskGuid;
98 UNICODE_STRING GuidString;
99 UNICODE_STRING SymbolicLinkName;
100 ULONG DiskType;
101 RAMDISK_CREATE_OPTIONS DiskOptions;
102 LARGE_INTEGER DiskLength;
103 LONG DiskOffset;
104 WCHAR DriveLetter;
105 ULONG BasePage;
106
107 /* Data we get from the disk */
108 ULONG BytesPerSector;
109 ULONG SectorsPerTrack;
110 ULONG NumberOfHeads;
111 ULONG Cylinders;
112 ULONG HiddenSectors;
113 } RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
114
115 ULONG MaximumViewLength;
116 ULONG MaximumPerDiskViewLength;
117 ULONG ReportDetectedDevice;
118 ULONG MarkRamdisksAsRemovable;
119 ULONG MinimumViewCount;
120 ULONG DefaultViewCount;
121 ULONG MaximumViewCount;
122 ULONG MinimumViewLength;
123 ULONG DefaultViewLength;
124 UNICODE_STRING DriverRegistryPath;
125 BOOLEAN ExportBootDiskAsCd;
126 BOOLEAN IsWinPEBoot;
127 PDEVICE_OBJECT RamdiskBusFdo;
128
129 /* FUNCTIONS ******************************************************************/
130
131 VOID
132 NTAPI
133 QueryParameters(IN PUNICODE_STRING RegistryPath)
134 {
135 ULONG MinView, DefView, MinViewLength, DefViewLength, MaxViewLength;
136 RTL_QUERY_REGISTRY_TABLE QueryTable[10];
137
138 /* Set defaults */
139 MaximumViewLength = 0x10000000u;
140 MaximumPerDiskViewLength = 0x10000000u;
141 ReportDetectedDevice = 0;
142 MarkRamdisksAsRemovable = 0;
143 MinimumViewCount = 2;
144 DefaultViewCount = 16;
145 MaximumViewCount = 64;
146 MinimumViewLength = 0x10000u;
147 DefaultViewLength = 0x100000u;
148
149 /* Setup the query table and query the registry */
150 RtlZeroMemory(QueryTable, sizeof(QueryTable));
151 QueryTable[0].Flags = 1;
152 QueryTable[0].Name = L"Parameters";
153 QueryTable[1].Flags = 32;
154 QueryTable[1].Name = L"ReportDetectedDevice";
155 QueryTable[1].EntryContext = &ReportDetectedDevice;
156 QueryTable[2].Flags = 32;
157 QueryTable[2].Name = L"MarkRamdisksAsRemovable";
158 QueryTable[2].EntryContext = &MarkRamdisksAsRemovable;
159 QueryTable[3].Flags = 32;
160 QueryTable[3].Name = L"MinimumViewCount";
161 QueryTable[3].EntryContext = &MinimumViewCount;
162 QueryTable[4].Flags = 32;
163 QueryTable[4].Name = L"DefaultViewCount";
164 QueryTable[4].EntryContext = &DefaultViewCount;
165 QueryTable[5].Flags = 32;
166 QueryTable[5].Name = L"MaximumViewCount";
167 QueryTable[5].EntryContext = &MaximumViewCount;
168 QueryTable[6].Flags = 32;
169 QueryTable[6].Name = L"MinimumViewLength";
170 QueryTable[6].EntryContext = &MinimumViewLength;
171 QueryTable[7].Flags = 32;
172 QueryTable[7].Name = L"DefaultViewLength";
173 QueryTable[7].EntryContext = &DefaultViewLength;
174 QueryTable[8].Flags = 32;
175 QueryTable[8].Name = L"MaximumViewLength";
176 QueryTable[8].EntryContext = &MaximumViewLength;
177 QueryTable[9].Flags = 32;
178 QueryTable[9].Name = L"MaximumPerDiskViewLength";
179 QueryTable[9].EntryContext = &MaximumPerDiskViewLength;
180 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL,
181 RegistryPath->Buffer,
182 QueryTable,
183 NULL,
184 NULL);
185
186 /* Parse minimum view count, cannot be bigger than 256 or smaller than 2 */
187 MinView = MinimumViewCount;
188 if (MinimumViewCount >= 2)
189 {
190 if (MinimumViewCount > 256) MinView = 256;
191 }
192 else
193 {
194 MinView = 2;
195 }
196 MinimumViewCount = MinView;
197
198 /* Parse default view count, cannot be bigger than 256 or smaller than minimum */
199 DefView = DefaultViewCount;
200 if (DefaultViewCount >= MinView)
201 {
202 if (DefaultViewCount > 256) DefView = 256;
203 }
204 else
205 {
206 DefView = MinView;
207 }
208 DefaultViewCount = DefView;
209
210 /* Parse maximum view count, cannot be bigger than 256 or smaller than default */
211 if (MaximumViewCount >= DefView)
212 {
213 if (MaximumViewCount > 256) MaximumViewCount = 256;
214 }
215 else
216 {
217 MaximumViewCount = DefView;
218 }
219
220 /* Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB */
221 MinViewLength = MinimumViewLength;
222 if (MinimumViewLength >= 0x10000)
223 {
224 if (MinimumViewLength > 0x40000000) MinViewLength = 0x40000000u;
225 }
226 else
227 {
228 MinViewLength = 0x10000u;
229 }
230 MinimumViewLength = MinViewLength;
231
232 /* Parse default view length, cannot be bigger than 1GB or smaller than minimum */
233 DefViewLength = DefaultViewLength;
234 if (DefaultViewLength >= MinViewLength)
235 {
236 if (DefaultViewLength > 0x40000000) DefViewLength = 0x40000000u;
237 }
238 else
239 {
240 DefViewLength = MinViewLength;
241 }
242 DefaultViewLength = DefViewLength;
243
244 /* Parse maximum view length, cannot be bigger than 1GB or smaller than default */
245 MaxViewLength = MaximumViewLength;
246 if (MaximumViewLength >= DefViewLength)
247 {
248 if (MaximumViewLength > 0x40000000) MaxViewLength = 0x40000000u;
249 }
250 else
251 {
252 MaxViewLength = DefViewLength;
253 }
254 MaximumViewLength = MaxViewLength;
255
256 /* Parse maximum view length per disk, cannot be smaller than 16MB */
257 if (MaximumPerDiskViewLength >= 0x1000000)
258 {
259 if (MaxViewLength > 0xFFFFFFFF) MaximumPerDiskViewLength = -1;
260 }
261 else
262 {
263 MaximumPerDiskViewLength = 0x1000000u;
264 }
265 }
266
267 PVOID
268 NTAPI
269 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
270 IN LARGE_INTEGER Offset,
271 IN ULONG Length,
272 OUT PULONG OutputLength)
273 {
274 PHYSICAL_ADDRESS PhysicalAddress;
275 PVOID MappedBase;
276 ULONG PageOffset;
277 SIZE_T ActualLength;
278 LARGE_INTEGER ActualOffset;
279 LARGE_INTEGER ActualPages;
280
281 /* We only support boot disks for now */
282 ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
283
284 /* Calculate the actual offset in the drive */
285 ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
286
287 /* Convert to pages */
288 ActualPages.QuadPart = ActualOffset.QuadPart >> PAGE_SHIFT;
289
290 /* Now add the base page */
291 ActualPages.QuadPart = DeviceExtension->BasePage + ActualPages.QuadPart;
292
293 /* Calculate final amount of bytes */
294 PhysicalAddress.QuadPart = ActualPages.QuadPart << PAGE_SHIFT;
295
296 /* Calculate pages spanned for the mapping */
297 ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
298
299 /* And convert this back to bytes */
300 ActualLength <<= PAGE_SHIFT;
301
302 /* Get the offset within the page */
303 PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
304
305 /* Map the I/O Space from the loader */
306 MappedBase = MmMapIoSpace(PhysicalAddress, ActualLength, MmCached);
307
308 /* Return actual offset within the page as well as the length */
309 if (MappedBase) MappedBase = (PVOID)((ULONG_PTR)MappedBase + PageOffset);
310 *OutputLength = Length;
311 return MappedBase;
312 }
313
314 VOID
315 NTAPI
316 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
317 IN PVOID BaseAddress,
318 IN LARGE_INTEGER Offset,
319 IN ULONG Length)
320 {
321 LARGE_INTEGER ActualOffset;
322 SIZE_T ActualLength;
323 ULONG PageOffset;
324
325 /* We only support boot disks for now */
326 ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
327
328 /* Calculate the actual offset in the drive */
329 ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
330
331 /* Calculate pages spanned for the mapping */
332 ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
333
334 /* And convert this back to bytes */
335 ActualLength <<= PAGE_SHIFT;
336
337 /* Get the offset within the page */
338 PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
339
340 /* Calculate actual base address where we mapped this */
341 BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - PageOffset);
342
343 /* Unmap the I/O space we got from the loader */
344 MmUnmapIoSpace(BaseAddress, ActualLength);
345 }
346
347 NTSTATUS
348 NTAPI
349 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
350 IN PRAMDISK_CREATE_INPUT Input,
351 IN BOOLEAN ValidateOnly,
352 OUT PRAMDISK_DRIVE_EXTENSION *NewDriveExtension)
353 {
354 ULONG BasePage, DiskType, Length;
355 //ULONG ViewCount;
356 NTSTATUS Status;
357 PDEVICE_OBJECT DeviceObject;
358 PRAMDISK_DRIVE_EXTENSION DriveExtension;
359 PVOID Buffer;
360 WCHAR LocalBuffer[16];
361 UNICODE_STRING SymbolicLinkName, DriveString, GuidString, DeviceName;
362 PPACKED_BOOT_SECTOR BootSector;
363 BIOS_PARAMETER_BLOCK BiosBlock;
364 ULONG BytesPerSector, SectorsPerTrack, Heads, BytesRead;
365 PVOID BaseAddress;
366 LARGE_INTEGER CurrentOffset, CylinderSize, DiskLength;
367 ULONG CylinderCount, SizeByCylinders;
368
369 /* Check if we're a boot RAM disk */
370 DiskType = Input->DiskType;
371 if (DiskType >= RAMDISK_BOOT_DISK)
372 {
373 /* Check if we're an ISO */
374 if (DiskType == RAMDISK_BOOT_DISK)
375 {
376 /* NTLDR mounted us somewhere */
377 BasePage = Input->BasePage;
378 if (!BasePage) return STATUS_INVALID_PARAMETER;
379
380 /* Sanitize disk options */
381 Input->Options.Fixed = TRUE;
382 Input->Options.Readonly = Input->Options.ExportAsCd |
383 Input->Options.Readonly;
384 Input->Options.Hidden = FALSE;
385 Input->Options.NoDosDevice = FALSE;
386 Input->Options.NoDriveLetter = IsWinPEBoot ? TRUE : FALSE;
387 }
388 else
389 {
390 /* The only other possibility is a WIM disk */
391 if (DiskType != RAMDISK_WIM_DISK)
392 {
393 /* Fail */
394 return STATUS_INVALID_PARAMETER;
395 }
396
397 /* Read the view count instead */
398 // ViewCount = Input->ViewCount;
399
400 /* Sanitize disk options */
401 Input->Options.Hidden = FALSE;
402 Input->Options.NoDosDevice = FALSE;
403 Input->Options.Readonly = FALSE;
404 Input->Options.NoDriveLetter = TRUE;
405 Input->Options.Fixed = TRUE;
406 }
407
408 /* Are we just validating and returning to the user? */
409 if (ValidateOnly) return STATUS_SUCCESS;
410
411 /* Build the GUID string */
412 Status = RtlStringFromGUID(&Input->DiskGuid, &GuidString);
413 if (!(NT_SUCCESS(Status)) || !(GuidString.Buffer))
414 {
415 /* Fail */
416 Status = STATUS_INSUFFICIENT_RESOURCES;
417 goto FailCreate;
418 }
419
420 /* Allocate our device name */
421 Length = GuidString.Length + 32;
422 Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, 'dmaR');
423 if (!Buffer)
424 {
425 /* Fail */
426 Status = STATUS_INSUFFICIENT_RESOURCES;
427 goto FailCreate;
428 }
429
430 /* Build the device name string */
431 DeviceName.Buffer = Buffer;
432 DeviceName.Length = Length - 2;
433 DeviceName.MaximumLength = Length;
434 wcsncpy(Buffer, L"\\Device\\Ramdisk", Length / sizeof(WCHAR));
435 wcsncat(Buffer, GuidString.Buffer, Length / sizeof(WCHAR));
436
437 /* Create the drive device */
438 Status = IoCreateDevice(DeviceExtension->DeviceObject->DriverObject,
439 sizeof(RAMDISK_DRIVE_EXTENSION),
440 &DeviceName,
441 (Input->Options.ExportAsCd) ?
442 FILE_DEVICE_CD_ROM : FILE_DEVICE_DISK,
443 0,
444 0,
445 &DeviceObject);
446 if (!NT_SUCCESS(Status)) goto FailCreate;
447
448 /* Grab the drive extension */
449 DriveExtension = DeviceObject->DeviceExtension;
450
451 /* Check if we need a DOS device */
452 if (!Input->Options.NoDosDevice)
453 {
454 /* Build the symbolic link name */
455 SymbolicLinkName.MaximumLength = GuidString.Length + 36;
456 SymbolicLinkName.Length = GuidString.Length + 34;
457 Buffer = ExAllocatePoolWithTag(NonPagedPool,
458 SymbolicLinkName.MaximumLength,
459 'dmaR');
460 SymbolicLinkName.Buffer = Buffer;
461 if (Buffer)
462 {
463 /* Create it */
464 wcsncpy(Buffer,
465 L"\\GLOBAL??\\Ramdisk",
466 SymbolicLinkName.MaximumLength / sizeof(WCHAR));
467 wcsncat(Buffer,
468 GuidString.Buffer,
469 SymbolicLinkName.MaximumLength / sizeof(WCHAR));
470 Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
471 if (!NT_SUCCESS(Status))
472 {
473 /* Nevermind... */
474 Input->Options.NoDosDevice = TRUE;
475 ExFreePool(Buffer);
476 SymbolicLinkName.Buffer = NULL;
477 }
478 }
479 else
480 {
481 /* No DOS device */
482 Input->Options.NoDosDevice = TRUE;
483 }
484
485 /* Is this an ISO boot ramdisk? */
486 if (Input->DiskType == RAMDISK_BOOT_DISK)
487 {
488 /* Does it need a drive letter? */
489 if (!Input->Options.NoDriveLetter)
490 {
491 /* Build it and take over the existing symbolic link */
492 _snwprintf(LocalBuffer,
493 30,
494 L"\\DosDevices\\%wc:",
495 Input->DriveLetter);
496 RtlInitUnicodeString(&DriveString, LocalBuffer);
497 IoDeleteSymbolicLink(&DriveString);
498 IoCreateSymbolicLink(&DriveString, &DeviceName);
499
500 /* Save the drive letter */
501 DriveExtension->DriveLetter = Input->DriveLetter;
502 }
503 }
504
505 }
506
507 /* Setup the device object flags */
508 DeviceObject->Flags |= (DO_XIP | DO_POWER_PAGABLE | DO_DIRECT_IO);
509 DeviceObject->AlignmentRequirement = 1;
510
511 /* Build the drive FDO */
512 *NewDriveExtension = DriveExtension;
513 DriveExtension->Type = RamdiskDrive;
514 DiskLength = Input->DiskLength;
515 ExInitializeFastMutex(&DriveExtension->DiskListLock);
516 IoInitializeRemoveLock(&DriveExtension->RemoveLock, 'dmaR', 1, 0);
517 DriveExtension->DriveDeviceName = DeviceName;
518 DriveExtension->SymbolicLinkName = SymbolicLinkName;
519 DriveExtension->GuidString = GuidString;
520 DriveExtension->DiskGuid = Input->DiskGuid;
521 DriveExtension->PhysicalDeviceObject = DeviceObject;
522 DriveExtension->DeviceObject = RamdiskBusFdo;
523 DriveExtension->AttachedDevice = RamdiskBusFdo;
524 DriveExtension->DiskType = Input->DiskType;
525 DriveExtension->DiskOptions = Input->Options;
526 DriveExtension->DiskLength = DiskLength;
527 DriveExtension->DiskOffset = Input->DiskOffset;
528 DriveExtension->BasePage = Input->BasePage;
529 DriveExtension->BytesPerSector = 0;
530 DriveExtension->SectorsPerTrack = 0;
531 DriveExtension->NumberOfHeads = 0;
532
533 /* Make sure we don't free it later */
534 DeviceName.Buffer = NULL;
535 SymbolicLinkName.Buffer = NULL;
536 GuidString.Buffer = NULL;
537
538 /* Check if this is a boot disk, or a registry ram drive */
539 if (!(Input->Options.ExportAsCd) &&
540 (Input->DiskType == RAMDISK_BOOT_DISK))
541 {
542 /* Not an ISO boot, but it's a boot FS -- map it to figure out the
543 * drive settings */
544 CurrentOffset.QuadPart = 0;
545 BaseAddress = RamdiskMapPages(DriveExtension,
546 CurrentOffset,
547 PAGE_SIZE,
548 &BytesRead);
549 if (BaseAddress)
550 {
551 /* Get the data */
552 BootSector = (PPACKED_BOOT_SECTOR)BaseAddress;
553 FatUnpackBios(&BiosBlock, &BootSector->PackedBpb);
554 BytesPerSector = BiosBlock.BytesPerSector;
555 SectorsPerTrack = BiosBlock.SectorsPerTrack;
556 Heads = BiosBlock.Heads;
557
558 /* Save it */
559 DriveExtension->BytesPerSector = BytesPerSector;
560 DriveExtension->SectorsPerTrack = SectorsPerTrack;
561 DriveExtension->NumberOfHeads = Heads;
562
563 /* Unmap now */
564 CurrentOffset.QuadPart = 0;
565 RamdiskUnmapPages(DriveExtension,
566 BaseAddress,
567 CurrentOffset,
568 BytesRead);
569 }
570 else
571 {
572 /* Fail */
573 Status = STATUS_INSUFFICIENT_RESOURCES;
574 goto FailCreate;
575 }
576 }
577
578 /* Check if the drive settings haven't been set yet */
579 if ((DriveExtension->BytesPerSector == 0) ||
580 (DriveExtension->SectorsPerTrack == 0) ||
581 (DriveExtension->NumberOfHeads == 0))
582 {
583 /* Check if this is a CD */
584 if (Input->Options.ExportAsCd)
585 {
586 /* Setup partition parameters default for ISO 9660 */
587 DriveExtension->BytesPerSector = 2048;
588 DriveExtension->SectorsPerTrack = 32;
589 DriveExtension->NumberOfHeads = 64;
590 }
591 else
592 {
593 /* Setup partition parameters default for FAT */
594 DriveExtension->BytesPerSector = 512;
595 DriveExtension->SectorsPerTrack = 128;
596 DriveExtension->NumberOfHeads = 16;
597 }
598 }
599
600 /* Calculate the cylinder size */
601 CylinderSize.QuadPart = DriveExtension->BytesPerSector *
602 DriveExtension->SectorsPerTrack *
603 DriveExtension->NumberOfHeads;
604 CylinderCount = DiskLength.QuadPart / CylinderSize.QuadPart;
605 SizeByCylinders = CylinderSize.QuadPart * CylinderCount;
606 DriveExtension->Cylinders = CylinderCount;
607 if ((DiskLength.HighPart > 0) || (SizeByCylinders < DiskLength.LowPart))
608 {
609 /* Align cylinder size up */
610 DriveExtension->Cylinders++;
611 }
612
613 /* Acquire the disk lock */
614 KeEnterCriticalRegion();
615 ExAcquireFastMutex(&DeviceExtension->DiskListLock);
616
617 /* Insert us */
618 InsertTailList(&DeviceExtension->DiskList, &DriveExtension->DiskList);
619
620 /* Release the lock */
621 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
622 KeLeaveCriticalRegion();
623
624 /* Clear init flag */
625 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
626 return STATUS_SUCCESS;
627 }
628
629 FailCreate:
630 UNIMPLEMENTED_DBGBREAK();
631 return STATUS_SUCCESS;
632 }
633
634 NTSTATUS
635 NTAPI
636 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
637 IN PIRP Irp,
638 IN BOOLEAN ValidateOnly)
639 {
640 PRAMDISK_CREATE_INPUT Input;
641 ULONG Length;
642 PRAMDISK_BUS_EXTENSION DeviceExtension;
643 PRAMDISK_DRIVE_EXTENSION DriveExtension;
644 ULONG DiskType;
645 PWCHAR FileNameStart, FileNameEnd;
646 NTSTATUS Status;
647 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
648
649 /* Get the device extension and our input data */
650 DeviceExtension = DeviceObject->DeviceExtension;
651 Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
652 Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer;
653
654 /* Validate input parameters */
655 if ((Length < sizeof(RAMDISK_CREATE_INPUT)) ||
656 (Input->Version != sizeof(RAMDISK_CREATE_INPUT)))
657 {
658 return STATUS_INVALID_PARAMETER;
659 }
660
661 /* Validate the disk type */
662 DiskType = Input->DiskType;
663 if (DiskType == RAMDISK_WIM_DISK) return STATUS_INVALID_PARAMETER;
664
665 /* Look at the disk type */
666 if (DiskType == RAMDISK_BOOT_DISK)
667 {
668 /* We only allow this as an early-init boot */
669 if (!KeLoaderBlock) return STATUS_INVALID_PARAMETER;
670
671 /* Save command-line flags */
672 if (ExportBootDiskAsCd) Input->Options.ExportAsCd = TRUE;
673 if (IsWinPEBoot) Input->Options.NoDriveLetter = TRUE;
674 }
675
676 /* Validate the disk type */
677 if ((Input->Options.ExportAsCd) && (DiskType != RAMDISK_BOOT_DISK))
678 {
679 /* If the type isn't CDFS, it has to at least be raw CD */
680 if (DiskType != RAMDISK_MEMORY_MAPPED_DISK) return STATUS_INVALID_PARAMETER;
681 }
682
683 /* Check if this is an actual file */
684 if (DiskType <= RAMDISK_MEMORY_MAPPED_DISK)
685 {
686 /* Validate the file name */
687 FileNameStart = (PWCHAR)((ULONG_PTR)Input + Length);
688 FileNameEnd = Input->FileName + 1;
689 while ((FileNameEnd < FileNameStart) && *(FileNameEnd)) FileNameEnd++;
690 if (FileNameEnd == FileNameStart) return STATUS_INVALID_PARAMETER;
691 }
692
693 /* Create the actual device */
694 Status = RamdiskCreateDiskDevice(DeviceExtension,
695 Input,
696 ValidateOnly,
697 &DriveExtension);
698 if (NT_SUCCESS(Status))
699 {
700 /* Invalidate and set success */
701 IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, 0);
702 Irp->IoStatus.Information = STATUS_SUCCESS;
703 }
704
705 /* We are done */
706 return Status;
707 }
708
709 NTSTATUS
710 NTAPI
711 RamdiskGetPartitionInfo(IN PIRP Irp,
712 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
713 {
714 NTSTATUS Status;
715 PPARTITION_INFORMATION PartitionInfo;
716 PVOID BaseAddress;
717 LARGE_INTEGER Zero = {{0, 0}};
718 ULONG Length;
719 PIO_STACK_LOCATION IoStackLocation;
720
721 /* Validate the length */
722 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
723 if (IoStackLocation->Parameters.DeviceIoControl.
724 OutputBufferLength < sizeof(PARTITION_INFORMATION))
725 {
726 /* Invalid length */
727 Status = STATUS_BUFFER_TOO_SMALL;
728 Irp->IoStatus.Status = Status;
729 Irp->IoStatus.Information = 0;
730 return Status;
731 }
732
733 /* Map the partition table */
734 BaseAddress = RamdiskMapPages(DeviceExtension, Zero, PAGE_SIZE, &Length);
735 if (!BaseAddress)
736 {
737 /* No memory */
738 Status = STATUS_INSUFFICIENT_RESOURCES;
739 Irp->IoStatus.Status = Status;
740 Irp->IoStatus.Information = 0;
741 return Status;
742 }
743
744 /* Fill out the information */
745 PartitionInfo = Irp->AssociatedIrp.SystemBuffer;
746 PartitionInfo->StartingOffset.QuadPart = DeviceExtension->BytesPerSector;
747 PartitionInfo->PartitionLength.QuadPart = DeviceExtension->BytesPerSector *
748 DeviceExtension->SectorsPerTrack *
749 DeviceExtension->NumberOfHeads *
750 DeviceExtension->Cylinders;
751 PartitionInfo->HiddenSectors = DeviceExtension->HiddenSectors;
752 PartitionInfo->PartitionNumber = 0;
753 PartitionInfo->PartitionType = *((PCHAR)BaseAddress + 450);
754 PartitionInfo->BootIndicator = (DeviceExtension->DiskType ==
755 RAMDISK_BOOT_DISK) ? TRUE: FALSE;
756 PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartitionInfo->
757 PartitionType);
758 PartitionInfo->RewritePartition = FALSE;
759
760 /* Unmap the partition table */
761 RamdiskUnmapPages(DeviceExtension, BaseAddress, Zero, Length);
762
763 /* Done */
764 Irp->IoStatus.Status = STATUS_SUCCESS;
765 Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
766 return STATUS_SUCCESS;
767 }
768
769 NTSTATUS
770 NTAPI
771 RamdiskSetPartitionInfo(IN PIRP Irp,
772 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
773 {
774 ULONG BytesRead;
775 NTSTATUS Status;
776 PVOID BaseAddress;
777 PIO_STACK_LOCATION Stack;
778 LARGE_INTEGER Zero = {{0, 0}};
779 PPARTITION_INFORMATION PartitionInfo;
780
781 /* First validate input */
782 Stack = IoGetCurrentIrpStackLocation(Irp);
783 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARTITION_INFORMATION))
784 {
785 Status = STATUS_INVALID_PARAMETER;
786 goto SetAndQuit;
787 }
788
789 /* Map to get MBR */
790 BaseAddress = RamdiskMapPages(DeviceExtension, Zero, PAGE_SIZE, &BytesRead);
791 if (BaseAddress == NULL)
792 {
793 Status = STATUS_INSUFFICIENT_RESOURCES;
794 goto SetAndQuit;
795 }
796
797 /* Set the new partition type on partition 0, field system indicator */
798 PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
799 *((PCHAR)BaseAddress + 450) = PartitionInfo->PartitionType;
800
801 /* And unmap */
802 RamdiskUnmapPages(DeviceExtension, BaseAddress, Zero, BytesRead);
803 Status = STATUS_SUCCESS;
804
805 SetAndQuit:
806 Irp->IoStatus.Status = Status;
807 Irp->IoStatus.Information = 0;
808 return Status;
809 }
810
811 VOID
812 NTAPI
813 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
814 IN PVOID Context)
815 {
816 PRAMDISK_BUS_EXTENSION DeviceExtension;
817 NTSTATUS Status;
818 PIO_STACK_LOCATION IoStackLocation;
819 PIRP Irp = Context;
820
821 /* Get the stack location */
822 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
823
824 /* Free the work item */
825 IoFreeWorkItem(Irp->Tail.Overlay.DriverContext[0]);
826
827 /* Grab the device extension and lock it */
828 DeviceExtension = DeviceObject->DeviceExtension;
829 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
830 if (NT_SUCCESS(Status))
831 {
832 /* Discriminate by major code */
833 switch (IoStackLocation->MajorFunction)
834 {
835 /* Device control */
836 case IRP_MJ_DEVICE_CONTROL:
837 {
838 /* Let's take a look at the IOCTL */
839 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
840 {
841 /* Ramdisk create request */
842 case FSCTL_CREATE_RAM_DISK:
843 {
844 /* This time we'll do it for real */
845 Status = RamdiskCreateRamdisk(DeviceObject, Irp, FALSE);
846 break;
847 }
848
849 case IOCTL_DISK_SET_PARTITION_INFO:
850 {
851 Status = RamdiskSetPartitionInfo(Irp, (PRAMDISK_DRIVE_EXTENSION)DeviceExtension);
852 break;
853 }
854
855 case IOCTL_DISK_GET_DRIVE_LAYOUT:
856 UNIMPLEMENTED_DBGBREAK("Get drive layout request\n");
857 break;
858
859 case IOCTL_DISK_GET_PARTITION_INFO:
860 {
861 Status = RamdiskGetPartitionInfo(Irp, (PRAMDISK_DRIVE_EXTENSION)DeviceExtension);
862 break;
863 }
864
865 default:
866 UNIMPLEMENTED_DBGBREAK("Invalid request\n");
867 break;
868 }
869
870 /* We're here */
871 break;
872 }
873
874 /* Read or write request */
875 case IRP_MJ_READ:
876 case IRP_MJ_WRITE:
877 UNIMPLEMENTED_DBGBREAK("Read/Write request\n");
878 break;
879
880 /* Internal request (SCSI?) */
881 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
882 UNIMPLEMENTED_DBGBREAK("SCSI request\n");
883 break;
884
885 /* Flush request */
886 case IRP_MJ_FLUSH_BUFFERS:
887 UNIMPLEMENTED_DBGBREAK("Flush request\n");
888 break;
889
890 /* Anything else */
891 default:
892 UNIMPLEMENTED_DBGBREAK("Invalid request: %lx\n",
893 IoStackLocation->MajorFunction);
894 break;
895 }
896
897 /* Complete the I/O */
898 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
899 Irp->IoStatus.Status = Status;
900 Irp->IoStatus.Information = 0;
901 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
902 return;
903 }
904
905 /* Fail the I/O */
906 Irp->IoStatus.Status = Status;
907 Irp->IoStatus.Information = 0;
908 IoCompleteRequest(Irp, IO_NO_INCREMENT);
909 }
910
911 NTSTATUS
912 NTAPI
913 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject,
914 IN PIRP Irp)
915 {
916 PIO_WORKITEM WorkItem;
917
918 /* Mark the IRP pending */
919 IoMarkIrpPending(Irp);
920
921 /* Allocate a work item */
922 WorkItem = IoAllocateWorkItem(DeviceObject);
923 if (WorkItem)
924 {
925 /* Queue it up */
926 Irp->Tail.Overlay.DriverContext[0] = WorkItem;
927 IoQueueWorkItem(WorkItem, RamdiskWorkerThread, DelayedWorkQueue, Irp);
928 return STATUS_PENDING;
929 }
930 else
931 {
932 /* Fail */
933 return STATUS_INSUFFICIENT_RESOURCES;
934 }
935 }
936
937 NTSTATUS
938 NTAPI
939 RamdiskReadWriteReal(IN PIRP Irp,
940 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
941 {
942 PMDL Mdl;
943 PVOID CurrentBase, SystemVa, BaseAddress;
944 PIO_STACK_LOCATION IoStackLocation;
945 LARGE_INTEGER CurrentOffset;
946 ULONG BytesRead, BytesLeft, CopyLength;
947 PVOID Source, Destination;
948 NTSTATUS Status;
949
950 /* Get the MDL and check if it's mapped */
951 Mdl = Irp->MdlAddress;
952 if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
953 {
954 /* Use the mapped address */
955 SystemVa = Mdl->MappedSystemVa;
956 }
957 else
958 {
959 /* Map it ourselves */
960 SystemVa = MmMapLockedPagesSpecifyCache(Mdl,
961 0,
962 MmCached,
963 NULL,
964 0,
965 NormalPagePriority);
966 }
967
968 /* Make sure we were able to map it */
969 CurrentBase = SystemVa;
970 if (!SystemVa) return STATUS_INSUFFICIENT_RESOURCES;
971
972 /* Initialize default */
973 Irp->IoStatus.Information = 0;
974
975 /* Get the I/O Stack Location and capture the data */
976 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
977 CurrentOffset = IoStackLocation->Parameters.Read.ByteOffset;
978 BytesLeft = IoStackLocation->Parameters.Read.Length;
979 if (!BytesLeft) return STATUS_INVALID_PARAMETER;
980
981 /* Do the copy loop */
982 while (TRUE)
983 {
984 /* Map the pages */
985 BaseAddress = RamdiskMapPages(DeviceExtension,
986 CurrentOffset,
987 BytesLeft,
988 &BytesRead);
989 if (!BaseAddress) return STATUS_INSUFFICIENT_RESOURCES;
990
991 /* Update our lengths */
992 Irp->IoStatus.Information += BytesRead;
993 CopyLength = BytesRead;
994
995 /* Check if this was a read or write */
996 Status = STATUS_SUCCESS;
997 if (IoStackLocation->MajorFunction == IRP_MJ_READ)
998 {
999 /* Set our copy parameters */
1000 Destination = CurrentBase;
1001 Source = BaseAddress;
1002 goto DoCopy;
1003 }
1004 else if (IoStackLocation->MajorFunction == IRP_MJ_WRITE)
1005 {
1006 /* Set our copy parameters */
1007 Destination = BaseAddress;
1008 Source = CurrentBase;
1009 DoCopy:
1010 /* Copy the data */
1011 RtlCopyMemory(Destination, Source, CopyLength);
1012 }
1013 else
1014 {
1015 /* Prepare us for failure */
1016 BytesLeft = CopyLength;
1017 Status = STATUS_INVALID_PARAMETER;
1018 }
1019
1020 /* Unmap the pages */
1021 RamdiskUnmapPages(DeviceExtension, BaseAddress, CurrentOffset, BytesRead);
1022
1023 /* Update offset and bytes left */
1024 BytesLeft -= BytesRead;
1025 CurrentOffset.QuadPart += BytesRead;
1026 CurrentBase = (PVOID)((ULONG_PTR)CurrentBase + BytesRead);
1027
1028 /* Check if we are done */
1029 if (!BytesLeft) return Status;
1030 }
1031 }
1032
1033 NTSTATUS
1034 NTAPI
1035 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
1036 IN PIRP Irp)
1037 {
1038 /* Complete the IRP */
1039 Irp->IoStatus.Information = 1;
1040 Irp->IoStatus.Status = STATUS_SUCCESS;
1041 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1042 return STATUS_SUCCESS;
1043 }
1044
1045 NTSTATUS
1046 NTAPI
1047 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
1048 IN PIRP Irp)
1049 {
1050 PRAMDISK_DRIVE_EXTENSION DeviceExtension;
1051 // ULONG Length;
1052 // LARGE_INTEGER ByteOffset;
1053 PIO_STACK_LOCATION IoStackLocation;
1054 NTSTATUS Status, ReturnStatus;
1055
1056 /* Get the device extension and make sure this isn't a bus */
1057 DeviceExtension = DeviceObject->DeviceExtension;
1058 if (DeviceExtension->Type == RamdiskBus)
1059 {
1060 /* Fail */
1061 Status = STATUS_INVALID_DEVICE_REQUEST;
1062 goto Complete;
1063 }
1064
1065 /* Capture parameters */
1066 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1067 // Length = IoStackLocation->Parameters.Read.Length;
1068 // ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
1069
1070 /* FIXME: Validate offset */
1071
1072 /* FIXME: Validate sector */
1073
1074 /* Validate write */
1075 if ((IoStackLocation->MajorFunction == IRP_MJ_WRITE) &&
1076 (DeviceExtension->DiskOptions.Readonly))
1077 {
1078 /* Fail, this is read-only */
1079 Status = STATUS_MEDIA_WRITE_PROTECTED;
1080 goto Complete;
1081 }
1082
1083 /* See if we want to do this sync or async */
1084 if (DeviceExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
1085 {
1086 /* Do it sync */
1087 Status = RamdiskReadWriteReal(Irp, DeviceExtension);
1088 goto Complete;
1089 }
1090
1091 /* Queue it to the worker */
1092 Status = SendIrpToThread(DeviceObject, Irp);
1093 ReturnStatus = STATUS_PENDING;
1094
1095 /* Check if we're pending or not */
1096 if (Status != STATUS_PENDING)
1097 {
1098 Complete:
1099 /* Complete the IRP */
1100 Irp->IoStatus.Status = Status;
1101 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
1102 ReturnStatus = Status;
1103 }
1104
1105 /* Return to caller */
1106 return ReturnStatus;
1107 }
1108
1109 NTSTATUS
1110 NTAPI
1111 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1112 IN PIRP Irp)
1113 {
1114 NTSTATUS Status;
1115 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1116 PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
1117 PRAMDISK_DRIVE_EXTENSION DriveExtension = (PVOID)DeviceExtension;
1118 ULONG Information;
1119 PCDROM_TOC Toc;
1120 PDISK_GEOMETRY DiskGeometry;
1121
1122 /* Grab the remove lock */
1123 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
1124 if (!NT_SUCCESS(Status))
1125 {
1126 /* Fail the IRP */
1127 Irp->IoStatus.Information = 0;
1128 Irp->IoStatus.Status = Status;
1129 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1130 return Status;
1131 }
1132
1133 /* Setup some defaults */
1134 Status = STATUS_INVALID_DEVICE_REQUEST;
1135 Information = 0;
1136
1137 /* Check if this is an bus device or the drive */
1138 if (DeviceExtension->Type == RamdiskBus)
1139 {
1140 /* Check what the request is */
1141 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
1142 {
1143 /* Request to create a ramdisk */
1144 case FSCTL_CREATE_RAM_DISK:
1145 {
1146 /* Do it */
1147 Status = RamdiskCreateRamdisk(DeviceObject, Irp, TRUE);
1148 if (!NT_SUCCESS(Status)) goto CompleteRequest;
1149 break;
1150 }
1151
1152 default:
1153 {
1154 /* We don't handle anything else yet */
1155 UNIMPLEMENTED_DBGBREAK("FSCTL: 0x%lx is UNSUPPORTED!\n",
1156 IoStackLocation->Parameters.DeviceIoControl.IoControlCode);
1157 }
1158 }
1159 }
1160 else
1161 {
1162 /* Check what the request is */
1163 switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
1164 {
1165 case IOCTL_DISK_CHECK_VERIFY:
1166 case IOCTL_STORAGE_CHECK_VERIFY:
1167 case IOCTL_STORAGE_CHECK_VERIFY2:
1168 case IOCTL_CDROM_CHECK_VERIFY:
1169 {
1170 /* Just pretend it's OK, don't do more */
1171 Status = STATUS_SUCCESS;
1172 break;
1173 }
1174
1175 case IOCTL_STORAGE_GET_MEDIA_TYPES:
1176 case IOCTL_DISK_GET_MEDIA_TYPES:
1177 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
1178 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
1179 {
1180 /* Validate the length */
1181 if (IoStackLocation->Parameters.DeviceIoControl.
1182 OutputBufferLength < sizeof(DISK_GEOMETRY))
1183 {
1184 /* Invalid length */
1185 Status = STATUS_BUFFER_TOO_SMALL;
1186 break;
1187 }
1188
1189 /* Fill it out */
1190 DiskGeometry = Irp->AssociatedIrp.SystemBuffer;
1191 DiskGeometry->Cylinders.QuadPart = DriveExtension->Cylinders;
1192 DiskGeometry->BytesPerSector = DriveExtension->BytesPerSector;
1193 DiskGeometry->SectorsPerTrack = DriveExtension->SectorsPerTrack;
1194 DiskGeometry->TracksPerCylinder = DriveExtension->NumberOfHeads;
1195 DiskGeometry->MediaType = DriveExtension->DiskOptions.Fixed ?
1196 FixedMedia : RemovableMedia;
1197
1198 /* We are done */
1199 Status = STATUS_SUCCESS;
1200 Information = sizeof(DISK_GEOMETRY);
1201 break;
1202 }
1203
1204 case IOCTL_CDROM_READ_TOC:
1205 {
1206 /* Validate the length */
1207 if (IoStackLocation->Parameters.DeviceIoControl.
1208 OutputBufferLength < sizeof(CDROM_TOC))
1209 {
1210 /* Invalid length */
1211 Status = STATUS_BUFFER_TOO_SMALL;
1212 break;
1213 }
1214
1215 /* Clear the TOC */
1216 Toc = Irp->AssociatedIrp.SystemBuffer;
1217 RtlZeroMemory(Toc, sizeof(CDROM_TOC));
1218
1219 /* Fill it out */
1220 Toc->Length[0] = 0;
1221 Toc->Length[1] = RAMDISK_TOC_SIZE - sizeof(Toc->Length);
1222 Toc->FirstTrack = 1;
1223 Toc->LastTrack = 1;
1224 Toc->TrackData[0].Adr = 1;
1225 Toc->TrackData[0].Control = TOC_DATA_TRACK;
1226 Toc->TrackData[0].TrackNumber = 1;
1227
1228 /* We are done */
1229 Status = STATUS_SUCCESS;
1230 Information = RAMDISK_TOC_SIZE;
1231 break;
1232 }
1233
1234 case IOCTL_DISK_SET_PARTITION_INFO:
1235 {
1236 Status = RamdiskSetPartitionInfo(Irp, DriveExtension);
1237 break;
1238 }
1239
1240 case IOCTL_DISK_GET_PARTITION_INFO:
1241 {
1242 /* Validate the length */
1243 if (IoStackLocation->Parameters.DeviceIoControl.
1244 OutputBufferLength < sizeof(PARTITION_INFORMATION))
1245 {
1246 /* Invalid length */
1247 Status = STATUS_BUFFER_TOO_SMALL;
1248 break;
1249 }
1250
1251 /* Check if we need to do this sync or async */
1252 if (DriveExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
1253 {
1254 /* Call the helper function */
1255 Status = RamdiskGetPartitionInfo(Irp, DriveExtension);
1256 }
1257 else
1258 {
1259 /* Do it asynchronously later */
1260 goto CallWorker;
1261 }
1262
1263 /* We are done */
1264 Information = Irp->IoStatus.Information;
1265 break;
1266 }
1267
1268 case IOCTL_DISK_GET_LENGTH_INFO:
1269 {
1270 PGET_LENGTH_INFORMATION LengthInformation = Irp->AssociatedIrp.SystemBuffer;
1271
1272 /* Validate the length */
1273 if (IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GET_LENGTH_INFORMATION))
1274 {
1275 /* Invalid length */
1276 Status = STATUS_BUFFER_TOO_SMALL;
1277 break;
1278 }
1279
1280 /* Fill it out */
1281 LengthInformation->Length = DriveExtension->DiskLength;
1282
1283 /* We are done */
1284 Status = STATUS_SUCCESS;
1285 Information = sizeof(GET_LENGTH_INFORMATION);
1286 break;
1287 }
1288 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES:
1289 {
1290 PVOLUME_GET_GPT_ATTRIBUTES_INFORMATION GptInformation;
1291
1292 /* Validate the length */
1293 if (IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength < sizeof(VOLUME_GET_GPT_ATTRIBUTES_INFORMATION))
1294 {
1295 /* Invalid length */
1296 Status = STATUS_BUFFER_TOO_SMALL;
1297 break;
1298 }
1299
1300 /* Fill it out */
1301 GptInformation = Irp->AssociatedIrp.SystemBuffer;
1302 GptInformation->GptAttributes = 0;
1303
1304 /* Translate the Attributes */
1305 if (DriveExtension->DiskOptions.Readonly)
1306 GptInformation->GptAttributes |= GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY;
1307 if (DriveExtension->DiskOptions.Hidden)
1308 GptInformation->GptAttributes |= GPT_BASIC_DATA_ATTRIBUTE_HIDDEN;
1309 if (DriveExtension->DiskOptions.NoDriveLetter)
1310 GptInformation->GptAttributes |= GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER;
1311
1312 /* We are done */
1313 Status = STATUS_SUCCESS;
1314 Information = sizeof(VOLUME_GET_GPT_ATTRIBUTES_INFORMATION);
1315 break;
1316 }
1317
1318 case IOCTL_DISK_GET_DRIVE_LAYOUT:
1319 case IOCTL_DISK_IS_WRITABLE:
1320 case IOCTL_SCSI_MINIPORT:
1321 case IOCTL_STORAGE_QUERY_PROPERTY:
1322 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
1323 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
1324 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
1325 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES:
1326 case IOCTL_VOLUME_OFFLINE:
1327 {
1328 UNIMPLEMENTED_DBGBREAK("IOCTL: 0x%lx is UNIMPLEMENTED!\n",
1329 IoStackLocation->Parameters.DeviceIoControl.IoControlCode);
1330 break;
1331 }
1332
1333 default:
1334 {
1335 /* Drive code not emulated */
1336 DPRINT1("IOCTL: 0x%lx is UNSUPPORTED!\n",
1337 IoStackLocation->Parameters.DeviceIoControl.IoControlCode);
1338 break;
1339 }
1340 }
1341
1342 /* If requests drop down here, we just return them complete them */
1343 goto CompleteRequest;
1344 }
1345
1346 /* Queue the request to our worker thread */
1347 CallWorker:
1348 Status = SendIrpToThread(DeviceObject, Irp);
1349
1350 CompleteRequest:
1351 /* Release the lock */
1352 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
1353 if (Status != STATUS_PENDING)
1354 {
1355 /* Complete the request */
1356 Irp->IoStatus.Status = Status;
1357 Irp->IoStatus.Information = Information;
1358 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1359 }
1360
1361 /* Return status */
1362 return Status;
1363 }
1364
1365 NTSTATUS
1366 NTAPI
1367 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type,
1368 IN PDEVICE_OBJECT DeviceObject,
1369 IN PIRP Irp)
1370 {
1371 PRAMDISK_BUS_EXTENSION DeviceExtension;
1372 PRAMDISK_DRIVE_EXTENSION DriveExtension;
1373 PDEVICE_RELATIONS DeviceRelations, OurDeviceRelations;
1374 ULONG Count, DiskCount, FinalCount;
1375 PLIST_ENTRY ListHead, NextEntry;
1376 PDEVICE_OBJECT* DriveDeviceObject;
1377 RAMDISK_DEVICE_STATE State;
1378
1379 /* Get the device extension and check if this is a drive */
1380 DeviceExtension = DeviceObject->DeviceExtension;
1381 if (DeviceExtension->Type == RamdiskDrive)
1382 {
1383 NTSTATUS Status;
1384 PDEVICE_RELATIONS DeviceRelations;
1385
1386 /* We're a child device, only handle target device relations */
1387 if (Type != TargetDeviceRelation)
1388 {
1389 Status = Irp->IoStatus.Status;
1390 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1391 return Status;
1392 }
1393
1394 /* Allocate a buffer big enough to contain only one DO */
1395 DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1396 sizeof(*DeviceRelations),
1397 'dmaR');
1398 if (DeviceRelations != NULL)
1399 {
1400 /* Reference the DO and add it to the buffer */
1401 ObReferenceObject(DeviceObject);
1402 DeviceRelations->Objects[0] = DeviceObject;
1403 DeviceRelations->Count = 1;
1404 Status = STATUS_SUCCESS;
1405 }
1406 else
1407 {
1408 Status = STATUS_INSUFFICIENT_RESOURCES;
1409 }
1410
1411 /* Return our processing & complete */
1412 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1413 Irp->IoStatus.Status = Status;
1414 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1415 return Status;
1416 }
1417
1418 /* We don't handle anything but bus relations */
1419 if (Type != BusRelations) goto PassToNext;
1420
1421 /* Acquire the disk list lock */
1422 KeEnterCriticalRegion();
1423 ExAcquireFastMutex(&DeviceExtension->DiskListLock);
1424
1425 /* Did a device already fill relations? */
1426 DeviceRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
1427 if (DeviceRelations)
1428 {
1429 /* Use the data */
1430 Count = DeviceRelations->Count;
1431 }
1432 else
1433 {
1434 /* We're the first */
1435 Count = 0;
1436 }
1437
1438 /* Now loop our drives */
1439 DiskCount = 0;
1440 ListHead = &DeviceExtension->DiskList;
1441 NextEntry = ListHead->Flink;
1442 while (NextEntry != ListHead)
1443 {
1444 /* As long as it wasn't removed, count it in */
1445 DriveExtension = CONTAINING_RECORD(NextEntry,
1446 RAMDISK_DRIVE_EXTENSION,
1447 DiskList);
1448 if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
1449
1450 /* Move to the next one */
1451 NextEntry = NextEntry->Flink;
1452 }
1453
1454 /* Now we know our final count */
1455 FinalCount = Count + DiskCount;
1456
1457 /* Allocate the structure */
1458 OurDeviceRelations = ExAllocatePoolWithTag(PagedPool,
1459 FIELD_OFFSET(DEVICE_RELATIONS,
1460 Objects) +
1461 FinalCount *
1462 sizeof(PDEVICE_OBJECT),
1463 'dmaR');
1464 if (!OurDeviceRelations)
1465 {
1466 /* Fail */
1467 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
1468 KeLeaveCriticalRegion();
1469 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1470 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1471 return STATUS_INSUFFICIENT_RESOURCES;
1472 }
1473
1474 /* Check if we already had some relations */
1475 if (Count)
1476 {
1477 /* Copy them in */
1478 RtlCopyMemory(OurDeviceRelations->Objects,
1479 DeviceRelations->Objects,
1480 Count * sizeof(PDEVICE_OBJECT));
1481 }
1482
1483 /* Save the count */
1484 OurDeviceRelations->Count = FinalCount;
1485
1486 /* Now loop our drives again */
1487 ListHead = &DeviceExtension->DiskList;
1488 NextEntry = ListHead->Flink;
1489 while (NextEntry != ListHead)
1490 {
1491 /* Go to the end of the list */
1492 DriveDeviceObject = &OurDeviceRelations->Objects[Count];
1493
1494 /* Get the drive state */
1495 DriveExtension = CONTAINING_RECORD(NextEntry,
1496 RAMDISK_DRIVE_EXTENSION,
1497 DiskList);
1498 State = DriveExtension->State;
1499
1500 /* If it was removed or enumerated, we don't touch the device object */
1501 if (State >= RamdiskStateBusRemoved)
1502 {
1503 /* If it was removed, we still have to keep track of this though */
1504 if (State == RamdiskStateBusRemoved)
1505 {
1506 /* Mark it as enumerated now, but don't actually reference it */
1507 DriveExtension->State = RamdiskStateEnumerated;
1508 }
1509 }
1510 else
1511 {
1512 /* First time it's enumerated, reference the device object */
1513 ObReferenceObject(DriveExtension->DeviceObject);
1514
1515 /* Save the object pointer and move on */
1516 *DriveDeviceObject++ = DriveExtension->PhysicalDeviceObject;
1517 }
1518
1519 if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
1520
1521 /* Move to the next one */
1522 NextEntry = NextEntry->Flink;
1523 }
1524
1525 /* Release the lock */
1526 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
1527 KeLeaveCriticalRegion();
1528
1529 /* Cleanup old relations */
1530 if (DeviceRelations) ExFreePool(DeviceRelations);
1531
1532 /* Complete our IRP */
1533 Irp->IoStatus.Information = (ULONG_PTR)OurDeviceRelations;
1534 Irp->IoStatus.Status = STATUS_SUCCESS;
1535
1536 /* Pass to the next driver */
1537 PassToNext:
1538 IoCopyCurrentIrpStackLocationToNext(Irp);
1539 return IoCallDriver(DeviceExtension->AttachedDevice, Irp);
1540 }
1541
1542 NTSTATUS
1543 NTAPI
1544 RamdiskDeleteDiskDevice(IN PDEVICE_OBJECT DeviceObject,
1545 IN PIRP Irp)
1546 {
1547 UNIMPLEMENTED_DBGBREAK();
1548 return STATUS_SUCCESS;
1549 }
1550
1551 NTSTATUS
1552 NTAPI
1553 RamdiskRemoveBusDevice(IN PDEVICE_OBJECT DeviceObject,
1554 IN PIRP Irp)
1555 {
1556 NTSTATUS Status;
1557 PLIST_ENTRY ListHead, NextEntry;
1558 PRAMDISK_BUS_EXTENSION DeviceExtension;
1559 PRAMDISK_DRIVE_EXTENSION DriveExtension;
1560
1561 DeviceExtension = DeviceObject->DeviceExtension;
1562
1563 /* Acquire disks list lock */
1564 KeEnterCriticalRegion();
1565 ExAcquireFastMutex(&DeviceExtension->DiskListLock);
1566
1567 /* Loop over drives */
1568 ListHead = &DeviceExtension->DiskList;
1569 NextEntry = ListHead->Flink;
1570 while (NextEntry != ListHead)
1571 {
1572 DriveExtension = CONTAINING_RECORD(NextEntry,
1573 RAMDISK_DRIVE_EXTENSION,
1574 DiskList);
1575
1576 /* Delete the disk */
1577 IoAcquireRemoveLock(&DriveExtension->RemoveLock, NULL);
1578 RamdiskDeleteDiskDevice(DriveExtension->PhysicalDeviceObject, NULL);
1579
1580 /* RamdiskDeleteDiskDevice releases list lock, so reacquire it */
1581 KeEnterCriticalRegion();
1582 ExAcquireFastMutex(&DeviceExtension->DiskListLock);
1583 }
1584
1585 /* Release disks list lock */
1586 ExReleaseFastMutex(&DeviceExtension->DiskListLock);
1587 KeLeaveCriticalRegion();
1588
1589 /* Prepare to pass to the lower driver */
1590 IoSkipCurrentIrpStackLocation(Irp);
1591 /* Here everything went fine */
1592 Irp->IoStatus.Status = STATUS_SUCCESS;
1593
1594 /* Call lower driver */
1595 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
1596
1597 /* Update state */
1598 DeviceExtension->State = RamdiskStateBusRemoved;
1599
1600 /* Release the lock and ensure that everyone has finished its job before
1601 * we continue. The lock has been acquired by the dispatcher */
1602 IoReleaseRemoveLockAndWait(&DeviceExtension->RemoveLock, Irp);
1603
1604 /* If there's a drive name */
1605 if (DeviceExtension->DriveDeviceName.Buffer)
1606 {
1607 /* Inform it's going to be disabled and free the drive name */
1608 IoSetDeviceInterfaceState(&DeviceExtension->DriveDeviceName, FALSE);
1609 RtlFreeUnicodeString(&DeviceExtension->DriveDeviceName);
1610 }
1611
1612 /* Part from the stack, detach from lower device */
1613 IoDetachDevice(DeviceExtension->AttachedDevice);
1614
1615 /* Finally, delete device */
1616 RamdiskBusFdo = NULL;
1617 IoDeleteDevice(DeviceObject);
1618
1619 /* Return status from lower driver */
1620 return Status;
1621 }
1622
1623 NTSTATUS
1624 NTAPI
1625 RamdiskQueryId(IN PRAMDISK_DRIVE_EXTENSION DriveExtension,
1626 IN PIRP Irp)
1627 {
1628 NTSTATUS Status;
1629 PIO_STACK_LOCATION IoStackLocation;
1630 PWSTR OutputString = NULL;
1631 ULONG StringLength;
1632
1633 Status = STATUS_SUCCESS;
1634 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1635
1636 /* Get what is being queried */
1637 switch (IoStackLocation->Parameters.QueryId.IdType)
1638 {
1639 case BusQueryDeviceID:
1640 {
1641 /* Allocate a buffer long enough to receive Ramdisk\RamDisk in any case
1642 * In case we don't have RAMDISK_REGISTRY_DISK, we then need two more
1643 * chars to store Ramdisk\RamVolume instead */
1644 StringLength = 4 * (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK) + sizeof(L"Ramdisk\\RamDisk");
1645 OutputString = ExAllocatePoolWithTag(PagedPool, StringLength, 'dmaR');
1646 if (OutputString == NULL)
1647 {
1648 Status = STATUS_INSUFFICIENT_RESOURCES;
1649 break;
1650 }
1651
1652 wcsncpy(OutputString, L"Ramdisk\\", StringLength / sizeof(WCHAR));
1653 if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK)
1654 {
1655 wcsncat(OutputString, L"RamVolume", StringLength / sizeof(WCHAR));
1656 }
1657 else
1658 {
1659 wcsncat(OutputString, L"RamDisk", StringLength / sizeof(WCHAR));
1660 }
1661
1662 break;
1663 }
1664
1665 case BusQueryHardwareIDs:
1666 {
1667 /* Allocate a buffer long enough to receive Ramdisk\RamDisk in any case
1668 * In case we don't have RAMDISK_REGISTRY_DISK, we then need two more
1669 * chars to store Ramdisk\RamVolume instead
1670 * We also need an extra char, because it is required that the string
1671 * is null-terminated twice */
1672 StringLength = 4 * (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK) +
1673 sizeof(UNICODE_NULL) + sizeof(L"Ramdisk\\RamDisk");
1674 OutputString = ExAllocatePoolWithTag(PagedPool, StringLength, 'dmaR');
1675 if (OutputString == NULL)
1676 {
1677 Status = STATUS_INSUFFICIENT_RESOURCES;
1678 break;
1679 }
1680
1681 wcsncpy(OutputString, L"Ramdisk\\", StringLength / sizeof(WCHAR));
1682 if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK)
1683 {
1684 wcsncat(OutputString, L"RamVolume", StringLength / sizeof(WCHAR));
1685 }
1686 else
1687 {
1688 wcsncat(OutputString, L"RamDisk", StringLength / sizeof(WCHAR));
1689 }
1690 OutputString[(StringLength / sizeof(WCHAR)) - 1] = UNICODE_NULL;
1691
1692 break;
1693 }
1694
1695 case BusQueryCompatibleIDs:
1696 {
1697 if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK)
1698 {
1699 Status = STATUS_INVALID_DEVICE_REQUEST;
1700 break;
1701 }
1702
1703 StringLength = sizeof(L"GenDisk");
1704 OutputString = ExAllocatePoolWithTag(PagedPool, StringLength, 'dmaR');
1705 if (OutputString == NULL)
1706 {
1707 Status = STATUS_INSUFFICIENT_RESOURCES;
1708 break;
1709 }
1710
1711 wcsncpy(OutputString, L"GenDisk", StringLength / sizeof(WCHAR));
1712 OutputString[(StringLength / sizeof(WCHAR)) - 1] = UNICODE_NULL;
1713
1714 break;
1715 }
1716
1717 case BusQueryInstanceID:
1718 {
1719 OutputString = ExAllocatePoolWithTag(PagedPool,
1720 DriveExtension->GuidString.MaximumLength,
1721 'dmaR');
1722 if (OutputString == NULL)
1723 {
1724 Status = STATUS_INSUFFICIENT_RESOURCES;
1725 break;
1726 }
1727
1728 wcsncpy(OutputString,
1729 DriveExtension->GuidString.Buffer,
1730 DriveExtension->GuidString.MaximumLength / sizeof(WCHAR));
1731
1732 break;
1733 }
1734
1735 case BusQueryDeviceSerialNumber:
1736 {
1737 /* Nothing to do */
1738 break;
1739 }
1740 }
1741
1742 Irp->IoStatus.Status = Status;
1743 Irp->IoStatus.Information = (ULONG_PTR)OutputString;
1744 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1745 return Status;
1746 }
1747
1748 NTSTATUS
1749 NTAPI
1750 RamdiskQueryCapabilities(IN PDEVICE_OBJECT DeviceObject,
1751 IN PIRP Irp)
1752 {
1753 NTSTATUS Status;
1754 PIO_STACK_LOCATION IoStackLocation;
1755 PDEVICE_CAPABILITIES DeviceCapabilities;
1756 PRAMDISK_DRIVE_EXTENSION DriveExtension;
1757
1758 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1759 DeviceCapabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities;
1760 DriveExtension = DeviceObject->DeviceExtension;
1761
1762 /* Validate our input buffer */
1763 if (DeviceCapabilities->Version != 1 ||
1764 DeviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
1765 {
1766 Status = STATUS_UNSUCCESSFUL;
1767 }
1768 else
1769 {
1770 /* And set everything we know about our capabilities */
1771 DeviceCapabilities->Removable = MarkRamdisksAsRemovable;
1772 DeviceCapabilities->UniqueID = TRUE;
1773 DeviceCapabilities->SilentInstall = TRUE;
1774 DeviceCapabilities->RawDeviceOK = TRUE;
1775 DeviceCapabilities->SurpriseRemovalOK = (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK);
1776 DeviceCapabilities->NoDisplayInUI = TRUE;
1777 Status = STATUS_SUCCESS;
1778 }
1779
1780 Irp->IoStatus.Status = Status;
1781 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1782 return Status;
1783 }
1784
1785 NTSTATUS
1786 NTAPI
1787 RamdiskQueryDeviceText(IN PRAMDISK_DRIVE_EXTENSION DriveExtension,
1788 IN PIRP Irp)
1789 {
1790 NTSTATUS Status;
1791 PIO_STACK_LOCATION IoStackLocation;
1792 DEVICE_TEXT_TYPE DeviceTextType;
1793 PWSTR OutputString = NULL;
1794
1795 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1796 DeviceTextType = IoStackLocation->Parameters.QueryDeviceText.DeviceTextType;
1797 Status = STATUS_SUCCESS;
1798
1799 /* Just copy our constants, according to the input */
1800 switch (DeviceTextType)
1801 {
1802 case DeviceTextDescription:
1803 {
1804 OutputString = ExAllocatePoolWithTag(PagedPool, sizeof(L"RamDisk"), 'dmaR');
1805 if (OutputString == NULL)
1806 {
1807 Status = STATUS_INSUFFICIENT_RESOURCES;
1808 break;
1809 }
1810
1811 wcsncpy(OutputString, L"RamDisk", sizeof(L"RamDisk") / sizeof(WCHAR));
1812
1813 break;
1814 }
1815
1816 case DeviceTextLocationInformation:
1817 {
1818 OutputString = ExAllocatePoolWithTag(PagedPool, sizeof(L"RamDisk\\0"), 'dmaR');
1819 if (OutputString == NULL)
1820 {
1821 Status = STATUS_INSUFFICIENT_RESOURCES;
1822 break;
1823 }
1824
1825 wcsncpy(OutputString, L"RamDisk\\0", sizeof(L"RamDisk\\0") / sizeof(WCHAR));
1826
1827 break;
1828 }
1829 }
1830
1831 Irp->IoStatus.Status = Status;
1832 Irp->IoStatus.Information = (ULONG_PTR)OutputString;
1833 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1834 return Status;
1835 }
1836
1837 NTSTATUS
1838 NTAPI
1839 RamdiskQueryBusInformation(IN PDEVICE_OBJECT DeviceObject,
1840 IN PIRP Irp)
1841 {
1842 PPNP_BUS_INFORMATION PnpBusInfo;
1843 NTSTATUS Status = STATUS_SUCCESS;
1844
1845 /* Allocate output memory */
1846 PnpBusInfo = ExAllocatePoolWithTag(PagedPool, sizeof(*PnpBusInfo), 'dmaR');
1847 if (PnpBusInfo == NULL)
1848 {
1849 Status = STATUS_INSUFFICIENT_RESOURCES;
1850 }
1851 else
1852 {
1853 /* Copy our bus GUID and set our legacy type */
1854 RtlCopyMemory(&PnpBusInfo->BusTypeGuid, &GUID_BUS_TYPE_RAMDISK, sizeof(GUID));
1855 PnpBusInfo->LegacyBusType = PNPBus;
1856 PnpBusInfo->BusNumber = 0;
1857 }
1858
1859 Irp->IoStatus.Status = Status;
1860 Irp->IoStatus.Information = (ULONG_PTR)PnpBusInfo;
1861 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1862 return Status;
1863 }
1864
1865 NTSTATUS
1866 NTAPI
1867 RamdiskIoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
1868 IN PIRP Irp,
1869 IN PVOID Context)
1870
1871 {
1872 /* Just set the event to unlock caller */
1873 KeSetEvent((PKEVENT)Context, 0, FALSE);
1874
1875 return STATUS_MORE_PROCESSING_REQUIRED;
1876 }
1877
1878 NTSTATUS
1879 NTAPI
1880 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
1881 IN PIRP Irp)
1882 {
1883 PIO_STACK_LOCATION IoStackLocation;
1884 PRAMDISK_BUS_EXTENSION DeviceExtension;
1885 NTSTATUS Status;
1886 UCHAR Minor;
1887 KEVENT Event;
1888
1889 /* Get the device extension and stack location */
1890 DeviceExtension = DeviceObject->DeviceExtension;
1891 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
1892 Minor = IoStackLocation->MinorFunction;
1893
1894 /* Check if the bus is removed */
1895 if (DeviceExtension->State == RamdiskStateBusRemoved)
1896 {
1897 /* Only remove-device and query-id are allowed */
1898 if ((Minor != IRP_MN_REMOVE_DEVICE) && (Minor != IRP_MN_QUERY_ID))
1899 {
1900 /* Fail anything else */
1901 Status = STATUS_NO_SUCH_DEVICE;
1902 Irp->IoStatus.Status = Status;
1903 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1904 return Status;
1905 }
1906 }
1907
1908 /* Acquire the remove lock */
1909 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
1910 if (!NT_SUCCESS(Status))
1911 {
1912 /* Fail the IRP */
1913 Irp->IoStatus.Information = 0;
1914 Irp->IoStatus.Status = Status;
1915 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1916 return Status;
1917 }
1918
1919 /* Query the IRP type */
1920 switch (Minor)
1921 {
1922 case IRP_MN_START_DEVICE:
1923 {
1924 if (DeviceExtension->Type == RamdiskDrive)
1925 {
1926 ULONG ResultLength;
1927 DEVICE_INSTALL_STATE InstallState;
1928 PRAMDISK_DRIVE_EXTENSION DriveExtension = (PRAMDISK_DRIVE_EXTENSION)DeviceExtension;
1929
1930 /* If we already have a drive name, free it */
1931 if (DriveExtension->DriveDeviceName.Buffer)
1932 {
1933 ExFreePool(DriveExtension->DriveDeviceName.Buffer);
1934 }
1935
1936 /* Register our device interface */
1937 if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK)
1938 {
1939 Status = IoRegisterDeviceInterface(DeviceObject,
1940 &GUID_DEVINTERFACE_VOLUME,
1941 NULL,
1942 &DriveExtension->DriveDeviceName);
1943 }
1944 else
1945 {
1946 Status = IoRegisterDeviceInterface(DeviceObject,
1947 &RamdiskDiskInterface,
1948 NULL,
1949 &DriveExtension->DriveDeviceName);
1950 }
1951
1952 /* If we were asked not to assign a drive letter or if getting
1953 * a name failed, just return saying we're now started */
1954 if (DriveExtension->DiskOptions.NoDriveLetter ||
1955 DriveExtension->DriveDeviceName.Buffer == NULL)
1956 {
1957 DriveExtension->State = RamdiskStateStarted;
1958 Irp->IoStatus.Status = Status;
1959 break;
1960 }
1961
1962 /* Now get our installation state */
1963 Status = IoGetDeviceProperty(DeviceObject,
1964 DevicePropertyInstallState,
1965 sizeof(InstallState),
1966 &InstallState,
1967 &ResultLength);
1968 /* If querying the information failed, assume success */
1969 if (!NT_SUCCESS(Status))
1970 {
1971 InstallState = InstallStateInstalled;
1972 }
1973
1974 /* If we were properly installed, then, enable the interface */
1975 if (InstallState == InstallStateInstalled)
1976 {
1977 Status = IoSetDeviceInterfaceState(&DriveExtension->DriveDeviceName, TRUE);
1978 }
1979
1980 /* We're fine & up */
1981 DriveExtension->State = RamdiskStateStarted;
1982 Irp->IoStatus.Status = Status;
1983 break;
1984 }
1985
1986 /* Prepare next stack to pass it down */
1987 IoCopyCurrentIrpStackLocationToNext(Irp);
1988
1989 /* Initialize our notification event & our completion routine */
1990 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1991 IoSetCompletionRoutine(Irp, RamdiskIoCompletionRoutine, &Event, TRUE, TRUE, TRUE);
1992
1993 /* Call lower driver */
1994 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
1995 if (Status == STATUS_PENDING)
1996 {
1997 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1998 Status = Irp->IoStatus.Status;
1999 }
2000
2001 /* If it succeed to start then enable ourselves and we're up! */
2002 if (NT_SUCCESS(Status))
2003 {
2004 Status = IoSetDeviceInterfaceState(&DeviceExtension->DriveDeviceName, TRUE);
2005 DeviceExtension->State = RamdiskStateStarted;
2006 }
2007
2008 Irp->IoStatus.Status = Status;
2009 break;
2010 }
2011
2012 case IRP_MN_QUERY_STOP_DEVICE:
2013 case IRP_MN_CANCEL_STOP_DEVICE:
2014 case IRP_MN_STOP_DEVICE:
2015 case IRP_MN_QUERY_REMOVE_DEVICE:
2016 case IRP_MN_CANCEL_REMOVE_DEVICE:
2017 {
2018 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor);
2019 break;
2020 }
2021
2022 case IRP_MN_REMOVE_DEVICE:
2023 {
2024 /* Remove the proper device */
2025 if (DeviceExtension->Type == RamdiskBus)
2026 {
2027 Status = RamdiskRemoveBusDevice(DeviceObject, Irp);
2028
2029 /* Return here, lower device has already been called
2030 * And remove lock released. This is needed by the function. */
2031 return Status;
2032 }
2033 else
2034 {
2035 Status = RamdiskDeleteDiskDevice(DeviceObject, Irp);
2036
2037 /* Complete the IRP here and return
2038 * Here again we don't have to release remove lock
2039 * This has already been done by the function. */
2040 Irp->IoStatus.Status = Status;
2041 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2042 return Status;
2043 }
2044 }
2045
2046 case IRP_MN_SURPRISE_REMOVAL:
2047 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor);
2048 break;
2049
2050 case IRP_MN_QUERY_ID:
2051 {
2052 /* Are we a drive? */
2053 if (DeviceExtension->Type == RamdiskDrive)
2054 {
2055 Status = RamdiskQueryId((PRAMDISK_DRIVE_EXTENSION)DeviceExtension, Irp);
2056 }
2057 break;
2058 }
2059
2060 case IRP_MN_QUERY_BUS_INFORMATION:
2061 {
2062 /* Are we a drive? */
2063 if (DeviceExtension->Type == RamdiskDrive)
2064 {
2065 Status = RamdiskQueryBusInformation(DeviceObject, Irp);
2066 }
2067 break;
2068 }
2069
2070 case IRP_MN_EJECT:
2071 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor);
2072 break;
2073
2074 case IRP_MN_QUERY_DEVICE_TEXT:
2075 {
2076 /* Are we a drive? */
2077 if (DeviceExtension->Type == RamdiskDrive)
2078 {
2079 Status = RamdiskQueryDeviceText((PRAMDISK_DRIVE_EXTENSION)DeviceExtension, Irp);
2080 }
2081 break;
2082 }
2083
2084 case IRP_MN_QUERY_DEVICE_RELATIONS:
2085 {
2086 /* Call our main routine */
2087 Status = RamdiskQueryDeviceRelations(IoStackLocation->
2088 Parameters.
2089 QueryDeviceRelations.Type,
2090 DeviceObject,
2091 Irp);
2092 goto ReleaseAndReturn;
2093 }
2094
2095 case IRP_MN_QUERY_CAPABILITIES:
2096 {
2097 /* Are we a drive? */
2098 if (DeviceExtension->Type == RamdiskDrive)
2099 {
2100 Status = RamdiskQueryCapabilities(DeviceObject, Irp);
2101 }
2102 break;
2103 }
2104
2105 case IRP_MN_QUERY_RESOURCES:
2106 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
2107 {
2108 /* Complete immediately without touching it */
2109 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2110 goto ReleaseAndReturn;
2111 }
2112
2113 default:
2114 DPRINT1("Illegal IRP: %lx\n", Minor);
2115 break;
2116 }
2117
2118 /* Are we the bus? */
2119 if (DeviceExtension->Type == RamdiskBus)
2120 {
2121 /* Do we have an attached device? */
2122 if (DeviceExtension->AttachedDevice)
2123 {
2124 /* Forward the IRP */
2125 IoSkipCurrentIrpStackLocation(Irp);
2126 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
2127 }
2128 }
2129
2130 /* Release the lock and return status */
2131 ReleaseAndReturn:
2132 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
2133 return Status;
2134 }
2135
2136 NTSTATUS
2137 NTAPI
2138 RamdiskPower(IN PDEVICE_OBJECT DeviceObject,
2139 IN PIRP Irp)
2140 {
2141 NTSTATUS Status;
2142 PIO_STACK_LOCATION IoStackLocation;
2143 PRAMDISK_BUS_EXTENSION DeviceExtension;
2144
2145 DeviceExtension = DeviceObject->DeviceExtension;
2146
2147 /* If we have a device extension, take extra caution with the lower driver */
2148 if (DeviceExtension != NULL)
2149 {
2150 PoStartNextPowerIrp(Irp);
2151
2152 /* Device has not been removed yet, so pass to the attached/lower driver */
2153 if (DeviceExtension->State < RamdiskStateBusRemoved)
2154 {
2155 IoSkipCurrentIrpStackLocation(Irp);
2156 return PoCallDriver(DeviceExtension->AttachedDevice, Irp);
2157 }
2158 /* Otherwise, simply complete the IRP notifying that deletion is pending */
2159 else
2160 {
2161 Irp->IoStatus.Status = STATUS_DELETE_PENDING;
2162 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2163 return STATUS_DELETE_PENDING;
2164 }
2165 }
2166
2167 /* Get stack and deal with minor functions */
2168 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
2169 switch (IoStackLocation->MinorFunction)
2170 {
2171 case IRP_MN_SET_POWER:
2172 {
2173 /* If setting device power state it's all fine and return success */
2174 if (DevicePowerState)
2175 {
2176 Irp->IoStatus.Status = STATUS_SUCCESS;
2177 }
2178
2179 /* Get appropriate status for return */
2180 Status = Irp->IoStatus.Status;
2181 PoStartNextPowerIrp(Irp);
2182 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2183 break;
2184 }
2185
2186 case IRP_MN_QUERY_POWER:
2187 {
2188 /* We can obviously accept all states so just return success */
2189 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
2190 PoStartNextPowerIrp(Irp);
2191 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2192 break;
2193 }
2194
2195 default:
2196 {
2197 /* Just complete and save status for return */
2198 Status = Irp->IoStatus.Status;
2199 PoStartNextPowerIrp(Irp);
2200 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2201 break;
2202 }
2203 }
2204
2205 return Status;
2206 }
2207
2208 NTSTATUS
2209 NTAPI
2210 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject,
2211 IN PIRP Irp)
2212 {
2213 NTSTATUS Status;
2214 PRAMDISK_BUS_EXTENSION DeviceExtension;
2215
2216 DeviceExtension = DeviceObject->DeviceExtension;
2217
2218 /* If we have a device extension, forward the IRP to the attached device */
2219 if (DeviceExtension != NULL)
2220 {
2221 IoSkipCurrentIrpStackLocation(Irp);
2222 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
2223 }
2224 /* Otherwise just complete the request
2225 * And return the status with which we complete it */
2226 else
2227 {
2228 Status = Irp->IoStatus.Status;
2229 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2230 }
2231
2232 return Status;
2233 }
2234
2235 NTSTATUS
2236 NTAPI
2237 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject,
2238 IN PIRP Irp)
2239 {
2240 NTSTATUS Status;
2241 PRAMDISK_BUS_EXTENSION DeviceExtension;
2242
2243 DeviceExtension = DeviceObject->DeviceExtension;
2244
2245 /* Having a proper device is mandatory */
2246 if (DeviceExtension->State > RamdiskStateStopped)
2247 {
2248 Status = STATUS_DEVICE_DOES_NOT_EXIST;
2249 goto CompleteIRP;
2250 }
2251
2252 /* Acquire the remove lock */
2253 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
2254 if (!NT_SUCCESS(Status))
2255 {
2256 goto CompleteIRP;
2257 }
2258
2259 /* Queue the IRP for worker */
2260 Status = SendIrpToThread(DeviceObject, Irp);
2261 if (Status != STATUS_PENDING)
2262 {
2263 goto CompleteIRP;
2264 }
2265
2266 /* Release the remove lock */
2267 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
2268 goto Quit;
2269
2270 CompleteIRP:
2271 Irp->IoStatus.Information = 0;
2272 Irp->IoStatus.Status = Status;
2273 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2274
2275 Quit:
2276 return Status;
2277 }
2278
2279 NTSTATUS
2280 NTAPI
2281 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
2282 IN PIRP Irp)
2283 {
2284 NTSTATUS Status;
2285 PRAMDISK_DRIVE_EXTENSION DeviceExtension;
2286
2287 DeviceExtension = DeviceObject->DeviceExtension;
2288
2289 /* Ensure we have drive extension
2290 * Only perform flush on disks that have been created
2291 * from registry entries */
2292 if (DeviceExtension->Type != RamdiskDrive ||
2293 DeviceExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
2294 {
2295 Irp->IoStatus.Information = 0;
2296 Irp->IoStatus.Status = STATUS_SUCCESS;
2297 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2298 return STATUS_SUCCESS;
2299 }
2300
2301 /* Queue the IRP for worker */
2302 Status = SendIrpToThread(DeviceObject, Irp);
2303 if (Status != STATUS_PENDING)
2304 {
2305 /* Queuing failed - complete the IRP and return failure */
2306 Irp->IoStatus.Information = 0;
2307 Irp->IoStatus.Status = Status;
2308 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2309 }
2310
2311 return Status;
2312 }
2313
2314 VOID
2315 NTAPI
2316 RamdiskUnload(IN PDRIVER_OBJECT DriverObject)
2317 {
2318 /* Just release registry path if previously allocated */
2319 if (DriverRegistryPath.Buffer)
2320 {
2321 ExFreePoolWithTag(DriverRegistryPath.Buffer, 'dmaR');
2322 }
2323 }
2324
2325 NTSTATUS
2326 NTAPI
2327 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
2328 IN PDEVICE_OBJECT PhysicalDeviceObject)
2329 {
2330 PRAMDISK_BUS_EXTENSION DeviceExtension;
2331 PDEVICE_OBJECT AttachedDevice;
2332 NTSTATUS Status;
2333 UNICODE_STRING DeviceName;
2334 PDEVICE_OBJECT DeviceObject;
2335
2336 /* Only create the bus FDO once */
2337 if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED;
2338
2339 /* Create the bus FDO */
2340 RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk");
2341 Status = IoCreateDevice(DriverObject,
2342 sizeof(RAMDISK_BUS_EXTENSION),
2343 &DeviceName,
2344 FILE_DEVICE_BUS_EXTENDER,
2345 FILE_DEVICE_SECURE_OPEN,
2346 0,
2347 &DeviceObject);
2348 if (NT_SUCCESS(Status))
2349 {
2350 /* Initialize the bus FDO extension */
2351 DeviceExtension = DeviceObject->DeviceExtension;
2352 RtlZeroMemory(DeviceExtension, sizeof(*DeviceExtension));
2353
2354 /* Set bus FDO flags */
2355 DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO;
2356
2357 /* Setup the bus FDO extension */
2358 DeviceExtension->Type = RamdiskBus;
2359 ExInitializeFastMutex(&DeviceExtension->DiskListLock);
2360 IoInitializeRemoveLock(&DeviceExtension->RemoveLock, 'dmaR', 1, 0);
2361 InitializeListHead(&DeviceExtension->DiskList);
2362 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
2363 DeviceExtension->DeviceObject = DeviceObject;
2364
2365 /* Register the RAM disk device interface */
2366 Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
2367 &RamdiskBusInterface,
2368 NULL,
2369 &DeviceExtension->BusDeviceName);
2370 if (!NT_SUCCESS(Status))
2371 {
2372 /* Fail */
2373 IoDeleteDevice(DeviceObject);
2374 return Status;
2375 }
2376
2377 /* Attach us to the device stack */
2378 AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
2379 PhysicalDeviceObject);
2380 DeviceExtension->AttachedDevice = AttachedDevice;
2381 if (!AttachedDevice)
2382 {
2383 /* Fail */
2384 IoSetDeviceInterfaceState(&DeviceExtension->BusDeviceName, 0);
2385 RtlFreeUnicodeString(&DeviceExtension->BusDeviceName);
2386 IoDeleteDevice(DeviceObject);
2387 return STATUS_NO_SUCH_DEVICE;
2388 }
2389
2390 /* Bus FDO is initialized */
2391 RamdiskBusFdo = DeviceObject;
2392
2393 /* Loop for loader block */
2394 if (KeLoaderBlock)
2395 {
2396 /* Are we being booted from setup? Not yet supported */
2397 if (KeLoaderBlock->SetupLdrBlock)
2398 DPRINT1("FIXME: RamdiskAddDevice is UNSUPPORTED when being started from SETUPLDR!\n");
2399 // ASSERT(!KeLoaderBlock->SetupLdrBlock);
2400 }
2401
2402 /* All done */
2403 DeviceObject->Flags &= DO_DEVICE_INITIALIZING;
2404 Status = STATUS_SUCCESS;
2405 }
2406
2407 /* Return status */
2408 return Status;
2409 }
2410
2411 NTSTATUS
2412 NTAPI
2413 DriverEntry(IN PDRIVER_OBJECT DriverObject,
2414 IN PUNICODE_STRING RegistryPath)
2415 {
2416 PCHAR BootDeviceName, CommandLine;
2417 PDEVICE_OBJECT PhysicalDeviceObject = NULL;
2418 NTSTATUS Status;
2419 DPRINT("RAM Disk Driver Initialized\n");
2420
2421 /* Query ramdisk parameters */
2422 QueryParameters(RegistryPath);
2423
2424 /* Save the registry path */
2425 DriverRegistryPath = *RegistryPath;
2426 DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
2427 RegistryPath->Length +
2428 sizeof(UNICODE_NULL),
2429 'dmaR');
2430 if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
2431 RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
2432
2433 /* Set device routines */
2434 DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose;
2435 DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose;
2436 DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
2437 DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
2438 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
2439 DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
2440 DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
2441 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
2442 DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
2443 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
2444 DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
2445 DriverObject->DriverUnload = RamdiskUnload;
2446
2447 /* Check for a loader block */
2448 if (KeLoaderBlock)
2449 {
2450 /* Get the boot device name */
2451 BootDeviceName = KeLoaderBlock->ArcBootDeviceName;
2452 if (BootDeviceName)
2453 {
2454 /* Check if we're booting from ramdisk */
2455 if ((strlen(BootDeviceName) >= 10) &&
2456 !(_strnicmp(BootDeviceName, "ramdisk(0)", 10)))
2457 {
2458 /* We'll have to tell the PnP Manager */
2459 ReportDetectedDevice = TRUE;
2460
2461 /* Check for a command line */
2462 CommandLine = KeLoaderBlock->LoadOptions;
2463 if (CommandLine)
2464 {
2465 /* Check if this is an ISO boot */
2466 if (strstr(CommandLine, "RDEXPORTASCD"))
2467 {
2468 /* Remember for later */
2469 ExportBootDiskAsCd = TRUE;
2470 }
2471
2472 /* Check if this is PE boot */
2473 if (strstr(CommandLine, "MININT"))
2474 {
2475 /* Remember for later */
2476 IsWinPEBoot = TRUE;
2477 }
2478 }
2479 }
2480
2481 }
2482 }
2483
2484 /* Installing from Ramdisk isn't supported yet */
2485 if (KeLoaderBlock->SetupLdrBlock)
2486 DPRINT1("FIXME: Installing from RamDisk is UNSUPPORTED!\n");
2487 // ASSERT(!KeLoaderBlock->SetupLdrBlock);
2488
2489 /* Are we reporting the device */
2490 if (ReportDetectedDevice)
2491 {
2492 /* Do it */
2493 Status = IoReportDetectedDevice(DriverObject,
2494 InterfaceTypeUndefined,
2495 0xFFFFFFFF,
2496 0xFFFFFFFF,
2497 NULL,
2498 NULL,
2499 0,
2500 &PhysicalDeviceObject);
2501 if (NT_SUCCESS(Status))
2502 {
2503 /* Create the device object */
2504 Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject);
2505 if (NT_SUCCESS(Status))
2506 {
2507 /* We are done */
2508 PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
2509 Status = STATUS_SUCCESS;
2510 }
2511 }
2512 }
2513 else
2514 {
2515 /* Done */
2516 Status = STATUS_SUCCESS;
2517 }
2518
2519 /* Done */
2520 return Status;
2521 }