xref: /reactos/modules/rosapps/drivers/vfd/vfdrdwr.c (revision 25c7e1a8)
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