ReactOS  0.4.14-dev-49-gfb4591c
vfdrdwr.c
Go to the documentation of this file.
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 
23 NTAPI
26  IN PIRP Irp)
27 {
29  PIO_STACK_LOCATION io_stack;
31 
33 
35 
36 #if DBG
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 
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 
91  goto complete_request;
92  }
93 
94 
95  // Check if write operation is allowed
96 
97  if (io_stack->MajorFunction == IRP_MJ_WRITE &&
99 
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)) >
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),
119 
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 
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) {
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 
147 
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;
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
185  IN PMDL Mdl,
187 {
188 #if (VER_PRODUCTBUILD >= 2195)
189  if (OsMajorVersion >= 5) {
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
218  IN PDEVICE_EXTENSION DeviceExtension,
219  IN OUT PIRP Irp,
220  IN ULONG Length,
222 {
223  PVOID buf;
224 
225  VFDTRACE(VFDINFO,("[VFD] VfdReadData - IN\n"));
226 
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
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
288  IN PDEVICE_EXTENSION DeviceExtension,
289  IN OUT PIRP Irp,
290  IN ULONG Length,
292 {
293  PVOID buf;
294 
295  VFDTRACE(VFDINFO,("[VFD] VfdWriteData - IN\n"));
296 
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
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 }
ULONG OsMajorVersion
#define IN
Definition: typedefs.h:38
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
struct _device_extension device_extension
enum _MM_PAGE_PRIORITY MM_PAGE_PRIORITY
PLIST_ENTRY NTAPI ExInterlockedInsertTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:140
LONG NTSTATUS
Definition: precomp.h:26
#define VFD_SECTOR_TO_BYTE(s)
Definition: vfdio.h:45
_In_ KPRIORITY Priority
Definition: kefuncs.h:516
VOID VfdReadData(IN PDEVICE_EXTENSION DeviceExtension, IN OUT PIRP Irp, IN ULONG Length, IN PLARGE_INTEGER Offset)
Definition: vfdrdwr.c:217
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
LONG KPRIORITY
Definition: compat.h:454
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define VFD_FLAG_DATA_MODIFIED
Definition: vfdtypes.h:69
#define MDL_MAPPING_CAN_FAIL
Definition: mmtypes.h:31
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define VFD_FLAG_WRITE_PROTECTED
Definition: vfdtypes.h:68
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define VFDTRACE(LEVEL, STRING)
Definition: vfddbg.h:72
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static PVOID MmGetSystemAddressForMdlPrettySafe(IN PMDL Mdl, IN MM_PAGE_PRIORITY Priority)
Definition: vfdrdwr.c:184
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define VFD_SECTOR_ALIGNED(b)
Definition: vfdio.h:46
#define IO_READ_OFF(p)
Definition: vfdrdwr.c:19
#define IO_READ_LEN(p)
Definition: vfdrdwr.c:20
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
#define MmGetSystemAddressForMdl(Mdl)
NTSTATUS NTAPI VfdReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: vfdrdwr.c:24
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
VOID VfdWriteData(IN PDEVICE_EXTENSION DeviceExtension, IN OUT PIRP Irp, IN ULONG Length, IN PLARGE_INTEGER Offset)
Definition: vfdrdwr.c:287
return STATUS_SUCCESS
Definition: btrfs.c:2966
IoMarkIrpPending(Irp)
short CSHORT
Definition: umtypes.h:127
static SERVICE_STATUS status
Definition: service.c:31
struct _BEEP_DEVICE_EXTENSION * PDEVICE_EXTENSION
#define IoAcquireRemoveLock(RemoveLock, Tag)
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
Definition: ps.c:97