[CMAKE]
[reactos.git] / drivers / filesystems / fastfat / blockdev.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/vfat/blockdev.c
5 * PURPOSE: Temporary sector reading support
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #define NDEBUG
13 #include "vfat.h"
14
15 /* FUNCTIONS ***************************************************************/
16
17 static IO_COMPLETION_ROUTINE VfatReadWritePartialCompletion;
18 static NTSTATUS NTAPI
19 VfatReadWritePartialCompletion (IN PDEVICE_OBJECT DeviceObject,
20 IN PIRP Irp,
21 IN PVOID Context)
22 {
23 PVFAT_IRP_CONTEXT IrpContext;
24 PMDL Mdl;
25
26 UNREFERENCED_PARAMETER(DeviceObject);
27
28 DPRINT("VfatReadWritePartialCompletion() called\n");
29
30 IrpContext = (PVFAT_IRP_CONTEXT)Context;
31
32 while ((Mdl = Irp->MdlAddress))
33 {
34 Irp->MdlAddress = Mdl->Next;
35 IoFreeMdl(Mdl);
36 }
37 if (Irp->PendingReturned)
38 {
39 IrpContext->Flags |= IRPCONTEXT_PENDINGRETURNED;
40 }
41 if (!NT_SUCCESS(Irp->IoStatus.Status))
42 {
43 IrpContext->Irp->IoStatus.Status = Irp->IoStatus.Status;
44 }
45 if (0 == InterlockedDecrement((PLONG)&IrpContext->RefCount) &&
46 IrpContext->Flags & IRPCONTEXT_PENDINGRETURNED)
47 {
48 KeSetEvent(&IrpContext->Event, IO_NO_INCREMENT, FALSE);
49 }
50 IoFreeIrp(Irp);
51
52 DPRINT("VfatReadWritePartialCompletion() done\n");
53
54 return STATUS_MORE_PROCESSING_REQUIRED;
55 }
56
57 NTSTATUS
58 VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject,
59 IN PLARGE_INTEGER ReadOffset,
60 IN ULONG ReadLength,
61 IN OUT PUCHAR Buffer,
62 IN BOOLEAN Override)
63 {
64 PIO_STACK_LOCATION Stack;
65 PIRP Irp;
66 IO_STATUS_BLOCK IoStatus;
67 KEVENT event;
68 NTSTATUS Status;
69
70 KeInitializeEvent (&event, NotificationEvent, FALSE);
71
72 DPRINT ("VfatReadDisk(pDeviceObject %p, Offset %I64x, Length %d, Buffer %p)\n",
73 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
74
75 DPRINT ("Building synchronous FSD Request...\n");
76 Irp = IoBuildSynchronousFsdRequest (IRP_MJ_READ,
77 pDeviceObject,
78 Buffer,
79 ReadLength,
80 ReadOffset,
81 &event,
82 &IoStatus);
83 if (Irp == NULL)
84 {
85 DPRINT("IoBuildSynchronousFsdRequest failed\n");
86 return(STATUS_UNSUCCESSFUL);
87 }
88
89 if (Override)
90 {
91 Stack = IoGetNextIrpStackLocation(Irp);
92 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
93 }
94
95 DPRINT ("Calling IO Driver... with irp %p\n", Irp);
96 Status = IoCallDriver (pDeviceObject, Irp);
97
98 DPRINT ("Waiting for IO Operation for %p\n", Irp);
99 if (Status == STATUS_PENDING)
100 {
101 DPRINT ("Operation pending\n");
102 KeWaitForSingleObject (&event, Suspended, KernelMode, FALSE, NULL);
103 DPRINT ("Getting IO Status... for %p\n", Irp);
104 Status = IoStatus.Status;
105 }
106
107 if (!NT_SUCCESS (Status))
108 {
109 DPRINT ("IO failed!!! VfatReadDisk : Error code: %x\n", Status);
110 DPRINT ("(pDeviceObject %p, Offset %I64x, Size %d, Buffer %p\n",
111 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
112 return (Status);
113 }
114 DPRINT ("Block request succeeded for %p\n", Irp);
115 return (STATUS_SUCCESS);
116 }
117
118 NTSTATUS
119 VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
120 IN PLARGE_INTEGER ReadOffset,
121 IN ULONG ReadLength,
122 ULONG BufferOffset,
123 IN BOOLEAN Wait)
124 {
125 PIRP Irp;
126 PIO_STACK_LOCATION StackPtr;
127 NTSTATUS Status;
128 PVOID Buffer;
129
130 DPRINT ("VfatReadDiskPartial(IrpContext %p, ReadOffset %I64x, ReadLength %d, BufferOffset %x, Wait %d)\n",
131 IrpContext, ReadOffset->QuadPart, ReadLength, BufferOffset, Wait);
132
133 DPRINT ("Building asynchronous FSD Request...\n");
134
135 Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
136
137 Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);
138 if (Irp == NULL)
139 {
140 DPRINT("IoAllocateIrp failed\n");
141 return(STATUS_UNSUCCESSFUL);
142 }
143
144 Irp->UserIosb = NULL;
145 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
146
147 StackPtr = IoGetNextIrpStackLocation(Irp);
148 StackPtr->MajorFunction = IRP_MJ_READ;
149 StackPtr->MinorFunction = 0;
150 StackPtr->Flags = 0;
151 StackPtr->Control = 0;
152 StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice;
153 StackPtr->FileObject = NULL;
154 StackPtr->CompletionRoutine = NULL;
155 StackPtr->Parameters.Read.Length = ReadLength;
156 StackPtr->Parameters.Read.ByteOffset = *ReadOffset;
157
158 if (!IoAllocateMdl(Buffer, ReadLength, FALSE, FALSE, Irp))
159 {
160 DPRINT("IoAllocateMdl failed\n");
161 IoFreeIrp(Irp);
162 return STATUS_UNSUCCESSFUL;
163 }
164
165 IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, ReadLength);
166
167 IoSetCompletionRoutine(Irp,
168 VfatReadWritePartialCompletion,
169 IrpContext,
170 TRUE,
171 TRUE,
172 TRUE);
173
174 if (Wait)
175 {
176 KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
177 IrpContext->RefCount = 1;
178 }
179 else
180 {
181 InterlockedIncrement((PLONG)&IrpContext->RefCount);
182 }
183
184 DPRINT ("Calling IO Driver... with irp %p\n", Irp);
185 Status = IoCallDriver (IrpContext->DeviceExt->StorageDevice, Irp);
186
187 if (Wait && Status == STATUS_PENDING)
188 {
189 KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
190 Status = IrpContext->Irp->IoStatus.Status;
191 }
192
193 DPRINT("%x\n", Status);
194 return Status;
195 }
196
197
198 NTSTATUS
199 VfatWriteDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
200 IN PLARGE_INTEGER WriteOffset,
201 IN ULONG WriteLength,
202 IN ULONG BufferOffset,
203 IN BOOLEAN Wait)
204 {
205 PIRP Irp;
206 PIO_STACK_LOCATION StackPtr;
207 NTSTATUS Status;
208 PVOID Buffer;
209
210 DPRINT ("VfatWriteDiskPartial(IrpContext %p, WriteOffset %I64x, WriteLength %d, BufferOffset %x, Wait %d)\n",
211 IrpContext, WriteOffset->QuadPart, WriteLength, BufferOffset, Wait);
212
213 Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
214
215 DPRINT ("Building asynchronous FSD Request...\n");
216 Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE);
217 if (Irp == NULL)
218 {
219 DPRINT("IoAllocateIrp failed\n");
220 return(STATUS_UNSUCCESSFUL);
221 }
222
223 Irp->UserIosb = NULL;
224 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
225
226 StackPtr = IoGetNextIrpStackLocation(Irp);
227 StackPtr->MajorFunction = IRP_MJ_WRITE;
228 StackPtr->MinorFunction = 0;
229 StackPtr->Flags = 0;
230 StackPtr->Control = 0;
231 StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice;
232 StackPtr->FileObject = NULL;
233 StackPtr->CompletionRoutine = NULL;
234 StackPtr->Parameters.Read.Length = WriteLength;
235 StackPtr->Parameters.Read.ByteOffset = *WriteOffset;
236
237 if (!IoAllocateMdl(Buffer, WriteLength, FALSE, FALSE, Irp))
238 {
239 DPRINT("IoAllocateMdl failed\n");
240 IoFreeIrp(Irp);
241 return STATUS_UNSUCCESSFUL;
242 }
243 IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, WriteLength);
244
245 IoSetCompletionRoutine(Irp,
246 VfatReadWritePartialCompletion,
247 IrpContext,
248 TRUE,
249 TRUE,
250 TRUE);
251
252 if (Wait)
253 {
254 KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
255 IrpContext->RefCount = 1;
256 }
257 else
258 {
259 InterlockedIncrement((PLONG)&IrpContext->RefCount);
260 }
261
262
263 DPRINT ("Calling IO Driver...\n");
264 Status = IoCallDriver (IrpContext->DeviceExt->StorageDevice, Irp);
265 if (Wait && Status == STATUS_PENDING)
266 {
267 KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
268 Status = IrpContext->Irp->IoStatus.Status;
269 }
270
271 return Status;
272 }
273
274 NTSTATUS
275 VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
276 IN ULONG CtlCode,
277 IN PVOID InputBuffer OPTIONAL,
278 IN ULONG InputBufferSize,
279 IN OUT PVOID OutputBuffer OPTIONAL,
280 IN OUT PULONG OutputBufferSize,
281 IN BOOLEAN Override)
282 {
283 PIO_STACK_LOCATION Stack;
284 KEVENT Event;
285 PIRP Irp;
286 IO_STATUS_BLOCK IoStatus;
287 NTSTATUS Status;
288
289 DPRINT("VfatBlockDeviceIoControl(DeviceObject %p, CtlCode %x, "
290 "InputBuffer %p, InputBufferSize %x, OutputBuffer %p, "
291 "OutputBufferSize %p (%x)\n", DeviceObject, CtlCode,
292 InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize,
293 OutputBufferSize ? *OutputBufferSize : 0);
294
295 KeInitializeEvent (&Event, NotificationEvent, FALSE);
296
297 DPRINT("Building device I/O control request ...\n");
298 Irp = IoBuildDeviceIoControlRequest(CtlCode,
299 DeviceObject,
300 InputBuffer,
301 InputBufferSize,
302 OutputBuffer,
303 (OutputBufferSize) ? *OutputBufferSize : 0,
304 FALSE,
305 &Event,
306 &IoStatus);
307 if (Irp == NULL)
308 {
309 DPRINT("IoBuildDeviceIoControlRequest failed\n");
310 return STATUS_INSUFFICIENT_RESOURCES;
311 }
312
313 if (Override)
314 {
315 Stack = IoGetNextIrpStackLocation(Irp);
316 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
317 }
318
319 DPRINT ("Calling IO Driver... with irp %p\n", Irp);
320 Status = IoCallDriver(DeviceObject, Irp);
321
322 DPRINT ("Waiting for IO Operation for %p\n", Irp);
323 if (Status == STATUS_PENDING)
324 {
325 DPRINT ("Operation pending\n");
326 KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
327 DPRINT ("Getting IO Status... for %p\n", Irp);
328
329 Status = IoStatus.Status;
330 }
331
332 if (OutputBufferSize)
333 {
334 *OutputBufferSize = IoStatus.Information;
335 }
336
337 DPRINT("Returning Status %x\n", Status);
338
339 return Status;
340 }