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