[TASKMGR] Process page: Allow using "Open File Location" functionality without runnin...
[reactos.git] / modules / rosapps / drivers / vfd / vfdrdwr.c
1 /*
2 vfdrdwr.c
3
4 Virtual Floppy Drive for Windows NT platform
5 Kernel mode driver: Read and Write functions
6
7 Copyright (C) 2003-2005 Ken Kato
8 */
9
10 #include "imports.h"
11 #include "vfddrv.h"
12 #include "vfddbg.h"
13
14 //
15 // IRP_MJ_READ and IRP_MJ_WRITE dispatcher
16 // Insert the IRP into the IRP queue list.
17 // Actual operation is performed by the device thread
18 //
19 #define IO_READ_OFF(p) (p)->Parameters.Read.ByteOffset.QuadPart
20 #define IO_READ_LEN(p) (p)->Parameters.Read.Length
21
22 NTSTATUS
23 NTAPI
24 VfdReadWrite (
25 IN PDEVICE_OBJECT DeviceObject,
26 IN PIRP Irp)
27 {
28 PDEVICE_EXTENSION device_extension;
29 PIO_STACK_LOCATION io_stack;
30 NTSTATUS status;
31
32 device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
33
34 io_stack = IoGetCurrentIrpStackLocation(Irp);
35
36 #if DBG
37 if (DeviceObject && DeviceObject->DeviceExtension &&
38 ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer) {
39
40 VFDTRACE(VFDINFO, ("[VFD] %-40s %ws\n",
41 GetMajorFuncName(io_stack->MajorFunction),
42 ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer));
43 }
44 else {
45 VFDTRACE(VFDINFO, ("[VFD] %-40s %p\n",
46 GetMajorFuncName(io_stack->MajorFunction),
47 DeviceObject));
48 }
49 #endif // DBG
50
51 #ifdef VFD_PNP
52
53 if (device_extension->DeviceState != VFD_WORKING) {
54
55 // Device is not yet started or being removed, reject any IO request
56 // TODO: Queue the IRPs
57
58 VFDTRACE(VFDWARN, ("[VFD] Device not ready\n"));
59
60 status = STATUS_INVALID_DEVICE_STATE;
61 goto complete_request;
62 }
63 else {
64 status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
65
66 if (!NT_SUCCESS(status)) {
67 VFDTRACE(0, ("[VFD] Acquire RemoveLock failed: %s\n", GetStatusName(status)));
68
69 goto complete_request;
70 }
71 }
72 #endif // VFD_PNP
73
74 /*
75 // Check if volume verification is required
76
77 if ((DeviceObject->Flags & DO_VERIFY_VOLUME) &&
78 !(io_stack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) {
79
80 status = STATUS_VERIFY_REQUIRED;
81 goto complete_request;
82 }
83 */
84
85 // Check if an image is opened
86
87 if (!device_extension->FileHandle &&
88 !device_extension->FileBuffer) {
89
90 status = STATUS_NO_MEDIA_IN_DEVICE;
91 goto complete_request;
92 }
93
94
95 // Check if write operation is allowed
96
97 if (io_stack->MajorFunction == IRP_MJ_WRITE &&
98 (device_extension->MediaFlags & VFD_FLAG_WRITE_PROTECTED)) {
99
100 status = STATUS_MEDIA_WRITE_PROTECTED;
101 goto complete_request;
102 }
103
104
105 // Check for invalid parameters. It is an error for the starting offset
106 // + length to go past the end of the partition, or for the length or
107 // offset to not be a proper multiple of the sector size.
108 //
109 // Others are possible, but we don't check them since we trust the
110 // file system and they aren't deadly.
111
112 if ((IO_READ_OFF(io_stack) + IO_READ_LEN(io_stack)) >
113 VFD_SECTOR_TO_BYTE(device_extension->Sectors)) {
114
115 VFDTRACE(VFDWARN,
116 ("[VFD] Offset:%I64u + Length:%u goes past the media size %lu\n",
117 IO_READ_OFF(io_stack), IO_READ_LEN(io_stack),
118 VFD_SECTOR_TO_BYTE(device_extension->Sectors)));
119
120 status = STATUS_INVALID_PARAMETER;
121 goto complete_request;
122 }
123
124 if (!VFD_SECTOR_ALIGNED((IO_READ_LEN(io_stack))) ||
125 !VFD_SECTOR_ALIGNED((IO_READ_OFF(io_stack)))) {
126
127 VFDTRACE(VFDWARN,
128 ("[VFD] Invalid Alignment Offset:%I64u Length:%u\n",
129 IO_READ_OFF(io_stack), IO_READ_LEN(io_stack)));
130
131 status = STATUS_INVALID_PARAMETER;
132 goto complete_request;
133 }
134
135 // If read/write data length is 0, we are done
136
137 if (IO_READ_LEN(io_stack) == 0) {
138 status = STATUS_SUCCESS;
139 goto complete_request;
140 }
141
142 // It seems that actual read/write operation is going to take place
143 // so mark the IRP as pending, insert the IRP into queue list
144 // then signal the device thread to perform the operation
145
146 IoMarkIrpPending(Irp);
147
148 ExInterlockedInsertTailList(
149 &device_extension->ListHead,
150 &Irp->Tail.Overlay.ListEntry,
151 &device_extension->ListLock);
152
153 KeSetEvent(
154 &device_extension->RequestEvent,
155 (KPRIORITY) 0,
156 FALSE);
157
158 VFDTRACE(VFDINFO,("[VFD] %-40s - STATUS_PENDING\n",
159 GetMajorFuncName(io_stack->MajorFunction)));
160
161 return STATUS_PENDING;
162
163 complete_request:
164
165 // complete the request immediately
166
167 Irp->IoStatus.Status = status;
168 Irp->IoStatus.Information = 0;
169 IoCompleteRequest(Irp, IO_NO_INCREMENT);
170
171 VFDTRACE(VFDWARN,("[VFD] %-40s - %s\n",
172 GetMajorFuncName(io_stack->MajorFunction),
173 GetStatusName(status)));
174
175 return status;
176 }
177
178 //
179 // Substitute for MmGetSystemAddressForMdlSafe
180 // for NT 4.0 DDK does not provide its equivqlent
181 // originally written by Bruce Engle for filedisk
182 //
183 static PVOID
184 MmGetSystemAddressForMdlPrettySafe(
185 IN PMDL Mdl,
186 IN MM_PAGE_PRIORITY Priority)
187 {
188 #if (VER_PRODUCTBUILD >= 2195)
189 if (OsMajorVersion >= 5) {
190 return MmGetSystemAddressForMdlSafe(Mdl, Priority);
191 }
192 else {
193 #endif // (VER_PRODUCTBUILD >= 2195)
194 CSHORT MdlMappingCanFail;
195 PVOID MappedSystemVa;
196
197 MdlMappingCanFail = (CSHORT)(Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL);
198
199 Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
200
201 MappedSystemVa = MmGetSystemAddressForMdl(Mdl);
202
203 if (!MdlMappingCanFail) {
204 Mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
205 }
206
207 return MappedSystemVa;
208 #if (VER_PRODUCTBUILD >= 2195)
209 }
210 #endif // (VER_PRODUCTBUILD >= 2195)
211 }
212
213 //
214 // Read sectors from image file or RAM disk buffer into read buffer
215 //
216 VOID
217 VfdReadData(
218 IN PDEVICE_EXTENSION DeviceExtension,
219 IN OUT PIRP Irp,
220 IN ULONG Length,
221 IN PLARGE_INTEGER Offset)
222 {
223 PVOID buf;
224
225 VFDTRACE(VFDINFO,("[VFD] VfdReadData - IN\n"));
226
227 buf = MmGetSystemAddressForMdlPrettySafe(
228 Irp->MdlAddress, NormalPagePriority);
229
230 if (!buf) {
231 VFDTRACE(0,
232 ("[VFD] MmGetSystemAddressForMdlPrettySafe\n"));
233
234 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
235 return;
236 }
237
238 if (DeviceExtension->FileHandle) {
239
240 // Read from image file
241 Irp->IoStatus.Status = ZwReadFile(
242 DeviceExtension->FileHandle,
243 NULL,
244 NULL,
245 NULL,
246 &Irp->IoStatus,
247 buf,
248 Length,
249 Offset,
250 NULL);
251
252 if (NT_SUCCESS(Irp->IoStatus.Status)) {
253 Irp->IoStatus.Information = Length;
254 }
255 else {
256 VFDTRACE(0,
257 ("[VFD] ZwReadFile - %s\n",
258 GetStatusName(Irp->IoStatus.Status)));
259 }
260 }
261 else if (DeviceExtension->FileBuffer) {
262
263 // Copy from RAM disk buffer
264 RtlMoveMemory(
265 buf,
266 DeviceExtension->FileBuffer + Offset->QuadPart,
267 Length);
268
269 Irp->IoStatus.Status = STATUS_SUCCESS;
270 Irp->IoStatus.Information = Length;
271 }
272 else {
273 // no image opened
274 Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
275 }
276
277 VFDTRACE(VFDINFO,("[VFD] VfdReadData - %s\n",
278 GetStatusName(Irp->IoStatus.Status)));
279
280 return;
281 }
282
283 //
284 // Write sectors from write buffer into image file or RAM image buffer
285 //
286 VOID
287 VfdWriteData(
288 IN PDEVICE_EXTENSION DeviceExtension,
289 IN OUT PIRP Irp,
290 IN ULONG Length,
291 IN PLARGE_INTEGER Offset)
292 {
293 PVOID buf;
294
295 VFDTRACE(VFDINFO,("[VFD] VfdWriteData - IN\n"));
296
297 buf = MmGetSystemAddressForMdlPrettySafe(
298 Irp->MdlAddress, NormalPagePriority);
299
300 if (!buf) {
301 VFDTRACE(0,
302 ("[VFD] MmGetSystemAddressForMdlPrettySafe\n"));
303
304 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
305 return;
306 }
307
308 if (DeviceExtension->FileHandle) {
309
310 // Write into image file
311 Irp->IoStatus.Status = ZwWriteFile(
312 DeviceExtension->FileHandle,
313 NULL,
314 NULL,
315 NULL,
316 &Irp->IoStatus,
317 buf,
318 Length,
319 Offset,
320 NULL);
321
322 if (NT_SUCCESS(Irp->IoStatus.Status)) {
323 Irp->IoStatus.Information = Length;
324 }
325 else {
326 VFDTRACE(0,
327 ("[VFD] ZwWriteFile - %s\n",
328 GetStatusName(Irp->IoStatus.Status)));
329 }
330 }
331 else if (DeviceExtension->FileBuffer) {
332
333 // Deal with the modify flag
334 if (RtlCompareMemory(
335 DeviceExtension->FileBuffer + Offset->QuadPart,
336 buf, Length) != Length) {
337 DeviceExtension->MediaFlags |= VFD_FLAG_DATA_MODIFIED;
338 }
339
340 // Copy into RAM image buffer
341 RtlMoveMemory(
342 DeviceExtension->FileBuffer + Offset->QuadPart,
343 buf, Length);
344
345 Irp->IoStatus.Status = STATUS_SUCCESS;
346 Irp->IoStatus.Information = Length;
347 }
348 else {
349 // no image opened
350 Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
351 }
352
353 VFDTRACE(VFDINFO,("[VFD] VfdWriteData - %s\n",
354 GetStatusName(Irp->IoStatus.Status)));
355
356 return;
357 }