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