1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * COPYRIGHT:        See COPYING in the top level directory
3*c2c66affSColin Finck  * PROJECT:          ReactOS File System Recognizer
4*c2c66affSColin Finck  * FILE:             drivers/filesystems/fs_rec/blockdev.c
5*c2c66affSColin Finck  * PURPOSE:          Generic Helper Functions
6*c2c66affSColin Finck  * PROGRAMMER:       Alex Ionescu (alex.ionescu@reactos.org)
7*c2c66affSColin Finck  *                   Eric Kohl
8*c2c66affSColin Finck  */
9*c2c66affSColin Finck 
10*c2c66affSColin Finck /* INCLUDES *****************************************************************/
11*c2c66affSColin Finck 
12*c2c66affSColin Finck #include "fs_rec.h"
13*c2c66affSColin Finck 
14*c2c66affSColin Finck #include <ntdddisk.h>
15*c2c66affSColin Finck #include <ntddcdrm.h>
16*c2c66affSColin Finck 
17*c2c66affSColin Finck #define NDEBUG
18*c2c66affSColin Finck #include <debug.h>
19*c2c66affSColin Finck 
20*c2c66affSColin Finck /* FUNCTIONS ****************************************************************/
21*c2c66affSColin Finck 
22*c2c66affSColin Finck BOOLEAN
23*c2c66affSColin Finck NTAPI
FsRecGetDeviceSectors(IN PDEVICE_OBJECT DeviceObject,IN ULONG SectorSize,OUT PLARGE_INTEGER SectorCount)24*c2c66affSColin Finck FsRecGetDeviceSectors(IN PDEVICE_OBJECT DeviceObject,
25*c2c66affSColin Finck                       IN ULONG SectorSize,
26*c2c66affSColin Finck                       OUT PLARGE_INTEGER SectorCount)
27*c2c66affSColin Finck {
28*c2c66affSColin Finck     PARTITION_INFORMATION PartitionInfo;
29*c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
30*c2c66affSColin Finck     KEVENT Event;
31*c2c66affSColin Finck     PIRP Irp;
32*c2c66affSColin Finck     NTSTATUS Status;
33*c2c66affSColin Finck     ULONG Remainder;
34*c2c66affSColin Finck     PAGED_CODE();
35*c2c66affSColin Finck 
36*c2c66affSColin Finck     /* Only needed for disks */
37*c2c66affSColin Finck     if (DeviceObject->DeviceType != FILE_DEVICE_DISK) return FALSE;
38*c2c66affSColin Finck 
39*c2c66affSColin Finck     /* Build the information IRP */
40*c2c66affSColin Finck     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
41*c2c66affSColin Finck     Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO,
42*c2c66affSColin Finck                                         DeviceObject,
43*c2c66affSColin Finck                                         NULL,
44*c2c66affSColin Finck                                         0,
45*c2c66affSColin Finck                                         &PartitionInfo,
46*c2c66affSColin Finck                                         sizeof(PARTITION_INFORMATION),
47*c2c66affSColin Finck                                         FALSE,
48*c2c66affSColin Finck                                         &Event,
49*c2c66affSColin Finck                                         &IoStatusBlock);
50*c2c66affSColin Finck     if (!Irp) return FALSE;
51*c2c66affSColin Finck 
52*c2c66affSColin Finck     /* Override verification */
53*c2c66affSColin Finck     IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
54*c2c66affSColin Finck 
55*c2c66affSColin Finck     /* Do the request */
56*c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
57*c2c66affSColin Finck     if (Status == STATUS_PENDING)
58*c2c66affSColin Finck     {
59*c2c66affSColin Finck         /* Wait for completion */
60*c2c66affSColin Finck         KeWaitForSingleObject(&Event,
61*c2c66affSColin Finck                               Executive,
62*c2c66affSColin Finck                               KernelMode,
63*c2c66affSColin Finck                               FALSE,
64*c2c66affSColin Finck                               NULL);
65*c2c66affSColin Finck         Status = IoStatusBlock.Status;
66*c2c66affSColin Finck     }
67*c2c66affSColin Finck 
68*c2c66affSColin Finck     /* Fail if we couldn't get the data */
69*c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return FALSE;
70*c2c66affSColin Finck 
71*c2c66affSColin Finck     /* Otherwise, return the number of sectors */
72*c2c66affSColin Finck     *SectorCount = RtlExtendedLargeIntegerDivide(PartitionInfo.PartitionLength,
73*c2c66affSColin Finck                                                  SectorSize,
74*c2c66affSColin Finck                                                  &Remainder);
75*c2c66affSColin Finck     return TRUE;
76*c2c66affSColin Finck }
77*c2c66affSColin Finck 
78*c2c66affSColin Finck BOOLEAN
79*c2c66affSColin Finck NTAPI
FsRecGetDeviceSectorSize(IN PDEVICE_OBJECT DeviceObject,OUT PULONG SectorSize)80*c2c66affSColin Finck FsRecGetDeviceSectorSize(IN PDEVICE_OBJECT DeviceObject,
81*c2c66affSColin Finck                          OUT PULONG SectorSize)
82*c2c66affSColin Finck {
83*c2c66affSColin Finck     DISK_GEOMETRY DiskGeometry;
84*c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
85*c2c66affSColin Finck     KEVENT Event;
86*c2c66affSColin Finck     PIRP Irp;
87*c2c66affSColin Finck     NTSTATUS Status;
88*c2c66affSColin Finck     ULONG ControlCode;
89*c2c66affSColin Finck     PAGED_CODE();
90*c2c66affSColin Finck 
91*c2c66affSColin Finck     /* Check what device we have */
92*c2c66affSColin Finck     switch (DeviceObject->DeviceType)
93*c2c66affSColin Finck     {
94*c2c66affSColin Finck         case FILE_DEVICE_CD_ROM:
95*c2c66affSColin Finck 
96*c2c66affSColin Finck             /* Use the CD IOCTL */
97*c2c66affSColin Finck             ControlCode = IOCTL_CDROM_GET_DRIVE_GEOMETRY;
98*c2c66affSColin Finck             break;
99*c2c66affSColin Finck 
100*c2c66affSColin Finck         case FILE_DEVICE_DISK:
101*c2c66affSColin Finck 
102*c2c66affSColin Finck             /* Use the Disk IOCTL */
103*c2c66affSColin Finck             ControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY;
104*c2c66affSColin Finck             break;
105*c2c66affSColin Finck 
106*c2c66affSColin Finck         default:
107*c2c66affSColin Finck 
108*c2c66affSColin Finck             /* Invalid device type */
109*c2c66affSColin Finck             return FALSE;
110*c2c66affSColin Finck     }
111*c2c66affSColin Finck 
112*c2c66affSColin Finck     /* Build the information IRP */
113*c2c66affSColin Finck     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
114*c2c66affSColin Finck     Irp = IoBuildDeviceIoControlRequest(ControlCode,
115*c2c66affSColin Finck                                         DeviceObject,
116*c2c66affSColin Finck                                         NULL,
117*c2c66affSColin Finck                                         0,
118*c2c66affSColin Finck                                         &DiskGeometry,
119*c2c66affSColin Finck                                         sizeof(DISK_GEOMETRY),
120*c2c66affSColin Finck                                         FALSE,
121*c2c66affSColin Finck                                         &Event,
122*c2c66affSColin Finck                                         &IoStatusBlock);
123*c2c66affSColin Finck     if (!Irp) return FALSE;
124*c2c66affSColin Finck 
125*c2c66affSColin Finck     /* Override verification */
126*c2c66affSColin Finck     IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
127*c2c66affSColin Finck 
128*c2c66affSColin Finck     /* Do the request */
129*c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
130*c2c66affSColin Finck     if (Status == STATUS_PENDING)
131*c2c66affSColin Finck     {
132*c2c66affSColin Finck         /* Wait for completion */
133*c2c66affSColin Finck         KeWaitForSingleObject(&Event,
134*c2c66affSColin Finck                               Executive,
135*c2c66affSColin Finck                               KernelMode,
136*c2c66affSColin Finck                               FALSE,
137*c2c66affSColin Finck                               NULL);
138*c2c66affSColin Finck         Status = IoStatusBlock.Status;
139*c2c66affSColin Finck     }
140*c2c66affSColin Finck 
141*c2c66affSColin Finck     /* Fail if we couldn't get the data */
142*c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return FALSE;
143*c2c66affSColin Finck 
144*c2c66affSColin Finck     /* Return the sector size if it's valid */
145*c2c66affSColin Finck     if (!DiskGeometry.BytesPerSector) return FALSE;
146*c2c66affSColin Finck     *SectorSize = DiskGeometry.BytesPerSector;
147*c2c66affSColin Finck     return TRUE;
148*c2c66affSColin Finck }
149*c2c66affSColin Finck 
150*c2c66affSColin Finck BOOLEAN
151*c2c66affSColin Finck NTAPI
FsRecReadBlock(IN PDEVICE_OBJECT DeviceObject,IN PLARGE_INTEGER Offset,IN ULONG Length,IN ULONG SectorSize,IN OUT PVOID * Buffer,OUT PBOOLEAN DeviceError OPTIONAL)152*c2c66affSColin Finck FsRecReadBlock(IN PDEVICE_OBJECT DeviceObject,
153*c2c66affSColin Finck                IN PLARGE_INTEGER Offset,
154*c2c66affSColin Finck                IN ULONG Length,
155*c2c66affSColin Finck                IN ULONG SectorSize,
156*c2c66affSColin Finck                IN OUT PVOID *Buffer,
157*c2c66affSColin Finck                OUT PBOOLEAN DeviceError OPTIONAL)
158*c2c66affSColin Finck {
159*c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
160*c2c66affSColin Finck     KEVENT Event;
161*c2c66affSColin Finck     PIRP Irp;
162*c2c66affSColin Finck     NTSTATUS Status;
163*c2c66affSColin Finck     PAGED_CODE();
164*c2c66affSColin Finck 
165*c2c66affSColin Finck     /* Assume failure */
166*c2c66affSColin Finck     if (DeviceError) *DeviceError = FALSE;
167*c2c66affSColin Finck 
168*c2c66affSColin Finck     /* Check if the caller requested too little */
169*c2c66affSColin Finck     if (Length < SectorSize)
170*c2c66affSColin Finck     {
171*c2c66affSColin Finck         /* Read at least the sector size */
172*c2c66affSColin Finck         Length = SectorSize;
173*c2c66affSColin Finck     }
174*c2c66affSColin Finck     else
175*c2c66affSColin Finck     {
176*c2c66affSColin Finck         /* Otherwise, just round up the request to sector size */
177*c2c66affSColin Finck         Length = ROUND_UP(Length, SectorSize);
178*c2c66affSColin Finck     }
179*c2c66affSColin Finck 
180*c2c66affSColin Finck     /* Check if the caller gave us a buffer */
181*c2c66affSColin Finck     if (!*Buffer)
182*c2c66affSColin Finck     {
183*c2c66affSColin Finck         /* He didn't, allocate one */
184*c2c66affSColin Finck         *Buffer = ExAllocatePoolWithTag(NonPagedPool,
185*c2c66affSColin Finck                                         ROUND_TO_PAGES(Length),
186*c2c66affSColin Finck                                         FSREC_TAG);
187*c2c66affSColin Finck         if (!*Buffer) return FALSE;
188*c2c66affSColin Finck     }
189*c2c66affSColin Finck 
190*c2c66affSColin Finck     /* Build the IRP */
191*c2c66affSColin Finck     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
192*c2c66affSColin Finck     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
193*c2c66affSColin Finck                                        DeviceObject,
194*c2c66affSColin Finck                                        *Buffer,
195*c2c66affSColin Finck                                        Length,
196*c2c66affSColin Finck                                        Offset,
197*c2c66affSColin Finck                                        &Event,
198*c2c66affSColin Finck                                        &IoStatusBlock);
199*c2c66affSColin Finck     if (!Irp) return FALSE;
200*c2c66affSColin Finck 
201*c2c66affSColin Finck     /* Override verification */
202*c2c66affSColin Finck     IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
203*c2c66affSColin Finck 
204*c2c66affSColin Finck     /* Do the request */
205*c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
206*c2c66affSColin Finck     if (Status == STATUS_PENDING)
207*c2c66affSColin Finck     {
208*c2c66affSColin Finck         /* Wait for completion */
209*c2c66affSColin Finck         KeWaitForSingleObject(&Event,
210*c2c66affSColin Finck                               Executive,
211*c2c66affSColin Finck                               KernelMode,
212*c2c66affSColin Finck                               FALSE,
213*c2c66affSColin Finck                               NULL);
214*c2c66affSColin Finck         Status = IoStatusBlock.Status;
215*c2c66affSColin Finck     }
216*c2c66affSColin Finck 
217*c2c66affSColin Finck     /* Check if we couldn't get the data */
218*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
219*c2c66affSColin Finck     {
220*c2c66affSColin Finck         /* Check if caller wanted to know about the device and fail */
221*c2c66affSColin Finck         if (DeviceError) *DeviceError = TRUE;
222*c2c66affSColin Finck         return FALSE;
223*c2c66affSColin Finck     }
224*c2c66affSColin Finck 
225*c2c66affSColin Finck     /* All went well */
226*c2c66affSColin Finck     return TRUE;
227*c2c66affSColin Finck }
228