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