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