xref: /reactos/modules/rosapps/drivers/vfd/vfddrv.c (revision 25c7e1a8)
1*25c7e1a8SPierre Schweitzer /*
2*25c7e1a8SPierre Schweitzer 	vfddrv.c
3*25c7e1a8SPierre Schweitzer 
4*25c7e1a8SPierre Schweitzer 	Virtual Floppy Drive for Windows NT platform
5*25c7e1a8SPierre Schweitzer 	Kernel mode driver: miscellaneous driver 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 //	driver reinitialize routine
16*25c7e1a8SPierre Schweitzer //	-- create a drive letter for each device
17*25c7e1a8SPierre Schweitzer //
18*25c7e1a8SPierre Schweitzer #ifdef __cplusplus
19*25c7e1a8SPierre Schweitzer extern "C"
20*25c7e1a8SPierre Schweitzer #endif	// __cplusplus
21*25c7e1a8SPierre Schweitzer static VOID
22*25c7e1a8SPierre Schweitzer NTAPI
23*25c7e1a8SPierre Schweitzer VfdReinitialize(
24*25c7e1a8SPierre Schweitzer 	IN PDRIVER_OBJECT			DriverObject,
25*25c7e1a8SPierre Schweitzer 	IN PVOID					Context,
26*25c7e1a8SPierre Schweitzer 	IN ULONG					Count);
27*25c7e1a8SPierre Schweitzer 
28*25c7e1a8SPierre Schweitzer //
29*25c7e1a8SPierre Schweitzer //	specify code segment
30*25c7e1a8SPierre Schweitzer //
31*25c7e1a8SPierre Schweitzer #ifdef ALLOC_PRAGMA
32*25c7e1a8SPierre Schweitzer #pragma alloc_text(INIT, DriverEntry)
33*25c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdReinitialize)
34*25c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdUnloadDriver)
35*25c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdCreateClose)
36*25c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdCopyUnicode)
37*25c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdFreeUnicode)
38*25c7e1a8SPierre Schweitzer #endif	// ALLOC_PRAGMA
39*25c7e1a8SPierre Schweitzer 
40*25c7e1a8SPierre Schweitzer //
41*25c7e1a8SPierre Schweitzer //	operating system version
42*25c7e1a8SPierre Schweitzer //
43*25c7e1a8SPierre Schweitzer #ifndef __REACTOS__
44*25c7e1a8SPierre Schweitzer extern ULONG OsMajorVersion = 0;
45*25c7e1a8SPierre Schweitzer extern ULONG OsMinorVersion = 0;
46*25c7e1a8SPierre Schweitzer extern ULONG OsBuildNumber	= 0;
47*25c7e1a8SPierre Schweitzer #else
48*25c7e1a8SPierre Schweitzer ULONG OsMajorVersion = 0;
49*25c7e1a8SPierre Schweitzer ULONG OsMinorVersion = 0;
50*25c7e1a8SPierre Schweitzer ULONG OsBuildNumber	= 0;
51*25c7e1a8SPierre Schweitzer #endif
52*25c7e1a8SPierre Schweitzer 
53*25c7e1a8SPierre Schweitzer //
54*25c7e1a8SPierre Schweitzer //	Trace level flag
55*25c7e1a8SPierre Schweitzer //
56*25c7e1a8SPierre Schweitzer #if DBG
57*25c7e1a8SPierre Schweitzer #ifndef __REACTOS__
58*25c7e1a8SPierre Schweitzer extern ULONG TraceFlags	= (ULONG)-1;
59*25c7e1a8SPierre Schweitzer #else
60*25c7e1a8SPierre Schweitzer ULONG TraceFlags	= (ULONG)-1;
61*25c7e1a8SPierre Schweitzer #endif
62*25c7e1a8SPierre Schweitzer #endif	// DBG
63*25c7e1a8SPierre Schweitzer 
64*25c7e1a8SPierre Schweitzer //
65*25c7e1a8SPierre Schweitzer //	Driver Entry routine
66*25c7e1a8SPierre Schweitzer //
67*25c7e1a8SPierre Schweitzer NTSTATUS
68*25c7e1a8SPierre Schweitzer NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)69*25c7e1a8SPierre Schweitzer DriverEntry (
70*25c7e1a8SPierre Schweitzer 	IN PDRIVER_OBJECT			DriverObject,
71*25c7e1a8SPierre Schweitzer 	IN PUNICODE_STRING			RegistryPath)
72*25c7e1a8SPierre Schweitzer {
73*25c7e1a8SPierre Schweitzer 	NTSTATUS					status;
74*25c7e1a8SPierre Schweitzer 	PVFD_DRIVER_EXTENSION		driver_extension;
75*25c7e1a8SPierre Schweitzer 	ULONG						number_of_devices = VFD_DEFAULT_DEVICES;
76*25c7e1a8SPierre Schweitzer 
77*25c7e1a8SPierre Schweitzer 	ASSERT(DriverObject);
78*25c7e1a8SPierre Schweitzer 
79*25c7e1a8SPierre Schweitzer 	//	Get operating system version
80*25c7e1a8SPierre Schweitzer 
81*25c7e1a8SPierre Schweitzer 	PsGetVersion(&OsMajorVersion, &OsMinorVersion, &OsBuildNumber, NULL);
82*25c7e1a8SPierre Schweitzer 
83*25c7e1a8SPierre Schweitzer #ifdef VFD_PNP
84*25c7e1a8SPierre Schweitzer #define VFD_PNP_TAG	"(Plug & Play version)"
85*25c7e1a8SPierre Schweitzer #else
86*25c7e1a8SPierre Schweitzer #define VFD_PNP_TAG
87*25c7e1a8SPierre Schweitzer #endif
88*25c7e1a8SPierre Schweitzer 
89*25c7e1a8SPierre Schweitzer 	VFDTRACE(0, ("[VFD] %s %s" VFD_PNP_TAG "\n",
90*25c7e1a8SPierre Schweitzer 		VFD_PRODUCT_NAME, VFD_DRIVER_VERSION_STR));
91*25c7e1a8SPierre Schweitzer 
92*25c7e1a8SPierre Schweitzer 	VFDTRACE(0,
93*25c7e1a8SPierre Schweitzer 		("[VFD] Running on Windows NT %lu.%lu build %lu\n",
94*25c7e1a8SPierre Schweitzer 		OsMajorVersion, OsMinorVersion, OsBuildNumber));
95*25c7e1a8SPierre Schweitzer 
96*25c7e1a8SPierre Schweitzer 	VFDTRACE(0,
97*25c7e1a8SPierre Schweitzer 		("[VFD] Build Target Environment: %d\n", VER_PRODUCTBUILD));
98*25c7e1a8SPierre Schweitzer 
99*25c7e1a8SPierre Schweitzer #ifdef VFD_PNP
100*25c7e1a8SPierre Schweitzer 
101*25c7e1a8SPierre Schweitzer 	// Create device_extension for the driver object to store driver specific
102*25c7e1a8SPierre Schweitzer 	// information. Device specific information are stored in device extension
103*25c7e1a8SPierre Schweitzer 	// for each device object.
104*25c7e1a8SPierre Schweitzer 
105*25c7e1a8SPierre Schweitzer 	status = IoAllocateDriverObjectExtension(
106*25c7e1a8SPierre Schweitzer 		DriverObject,
107*25c7e1a8SPierre Schweitzer 		VFD_DRIVER_EXTENSION_ID,
108*25c7e1a8SPierre Schweitzer 		sizeof(VFD_DRIVER_EXTENSION),
109*25c7e1a8SPierre Schweitzer 		&driver_extension);
110*25c7e1a8SPierre Schweitzer 
111*25c7e1a8SPierre Schweitzer 	if(!NT_SUCCESS(status)) {
112*25c7e1a8SPierre Schweitzer 		VFDTRACE(0, ("[VFD] IoAllocateDriverObjectExtension - %s\n",
113*25c7e1a8SPierre Schweitzer 			GetStatusName(status)));
114*25c7e1a8SPierre Schweitzer 		return status;
115*25c7e1a8SPierre Schweitzer 	}
116*25c7e1a8SPierre Schweitzer 
117*25c7e1a8SPierre Schweitzer #else	// VFD_PNP
118*25c7e1a8SPierre Schweitzer 
119*25c7e1a8SPierre Schweitzer 	//	Windows NT doesn't have the IoAllocateDriverObjectExtension
120*25c7e1a8SPierre Schweitzer 	//	function and I think there's little point in making a non-PnP
121*25c7e1a8SPierre Schweitzer 	//	driver incompatible with Windows NT.
122*25c7e1a8SPierre Schweitzer 
123*25c7e1a8SPierre Schweitzer 	driver_extension = (PVFD_DRIVER_EXTENSION)ExAllocatePoolWithTag(
124*25c7e1a8SPierre Schweitzer 		PagedPool, sizeof(VFD_DRIVER_EXTENSION), VFD_POOL_TAG);
125*25c7e1a8SPierre Schweitzer 
126*25c7e1a8SPierre Schweitzer 	if (!driver_extension) {
127*25c7e1a8SPierre Schweitzer 		VFDTRACE(0, ("[VFD] failed to allocate the driver extension.\n"));
128*25c7e1a8SPierre Schweitzer 		return STATUS_INSUFFICIENT_RESOURCES;
129*25c7e1a8SPierre Schweitzer 	}
130*25c7e1a8SPierre Schweitzer 
131*25c7e1a8SPierre Schweitzer #endif	// VFD_PNP
132*25c7e1a8SPierre Schweitzer 
133*25c7e1a8SPierre Schweitzer 	RtlZeroMemory(driver_extension, sizeof(VFD_DRIVER_EXTENSION));
134*25c7e1a8SPierre Schweitzer 
135*25c7e1a8SPierre Schweitzer 	//
136*25c7e1a8SPierre Schweitzer 	// Copy the registry path into the driver extension so we can use it later
137*25c7e1a8SPierre Schweitzer 	//
138*25c7e1a8SPierre Schweitzer 	if (VfdCopyUnicode(&(driver_extension->RegistryPath), RegistryPath)) {
139*25c7e1a8SPierre Schweitzer 
140*25c7e1a8SPierre Schweitzer 		//
141*25c7e1a8SPierre Schweitzer 		//	Read config values from the registry
142*25c7e1a8SPierre Schweitzer 		//
143*25c7e1a8SPierre Schweitzer 		RTL_QUERY_REGISTRY_TABLE params[3];
144*25c7e1a8SPierre Schweitzer 		ULONG default_devs	= VFD_DEFAULT_DEVICES;
145*25c7e1a8SPierre Schweitzer #if DBG
146*25c7e1a8SPierre Schweitzer 		ULONG default_trace = (ULONG)-1;
147*25c7e1a8SPierre Schweitzer #endif
148*25c7e1a8SPierre Schweitzer 
149*25c7e1a8SPierre Schweitzer 		RtlZeroMemory(params, sizeof(params));
150*25c7e1a8SPierre Schweitzer 
151*25c7e1a8SPierre Schweitzer 		VFDTRACE(0, ("[VFD] Registry Path: %ws\n",
152*25c7e1a8SPierre Schweitzer 			driver_extension->RegistryPath.Buffer));
153*25c7e1a8SPierre Schweitzer 
154*25c7e1a8SPierre Schweitzer 		params[0].Flags			= RTL_QUERY_REGISTRY_DIRECT;
155*25c7e1a8SPierre Schweitzer 		params[0].Name			= VFD_REG_DEVICE_NUMBER;
156*25c7e1a8SPierre Schweitzer 		params[0].EntryContext	= &number_of_devices;
157*25c7e1a8SPierre Schweitzer 		params[0].DefaultType	= REG_DWORD;
158*25c7e1a8SPierre Schweitzer 		params[0].DefaultData	= &default_devs;
159*25c7e1a8SPierre Schweitzer 		params[0].DefaultLength	= sizeof(ULONG);
160*25c7e1a8SPierre Schweitzer 
161*25c7e1a8SPierre Schweitzer #if DBG
162*25c7e1a8SPierre Schweitzer 		params[1].Flags			= RTL_QUERY_REGISTRY_DIRECT;
163*25c7e1a8SPierre Schweitzer 		params[1].Name			= VFD_REG_TRACE_FLAGS;
164*25c7e1a8SPierre Schweitzer 		params[1].EntryContext	= &TraceFlags;
165*25c7e1a8SPierre Schweitzer 		params[1].DefaultType	= REG_DWORD;
166*25c7e1a8SPierre Schweitzer 		params[1].DefaultData	= &default_trace;
167*25c7e1a8SPierre Schweitzer 		params[1].DefaultLength	= sizeof(ULONG);
168*25c7e1a8SPierre Schweitzer #endif	// DBG
169*25c7e1a8SPierre Schweitzer 
170*25c7e1a8SPierre Schweitzer 		status = RtlQueryRegistryValues(
171*25c7e1a8SPierre Schweitzer 			RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
172*25c7e1a8SPierre Schweitzer 			driver_extension->RegistryPath.Buffer,
173*25c7e1a8SPierre Schweitzer 			params, NULL, NULL);
174*25c7e1a8SPierre Schweitzer 
175*25c7e1a8SPierre Schweitzer 		if (!NT_SUCCESS(status) ||
176*25c7e1a8SPierre Schweitzer 			number_of_devices == 0 ||
177*25c7e1a8SPierre Schweitzer 			number_of_devices > VFD_MAXIMUM_DEVICES) {
178*25c7e1a8SPierre Schweitzer 			number_of_devices = VFD_DEFAULT_DEVICES;
179*25c7e1a8SPierre Schweitzer 		}
180*25c7e1a8SPierre Schweitzer 
181*25c7e1a8SPierre Schweitzer 		VFDTRACE(0,("[VFD] NumberOfDevices = %lu\n", number_of_devices));
182*25c7e1a8SPierre Schweitzer 		VFDTRACE(0,("[VFD] TraceFlags = 0x%08x\n", TraceFlags));
183*25c7e1a8SPierre Schweitzer 	}
184*25c7e1a8SPierre Schweitzer 	else {
185*25c7e1a8SPierre Schweitzer 		VFDTRACE(0, ("[VFD] failed to allocate the registry path buffer.\n"));
186*25c7e1a8SPierre Schweitzer 		// this error is not fatal
187*25c7e1a8SPierre Schweitzer 	}
188*25c7e1a8SPierre Schweitzer 
189*25c7e1a8SPierre Schweitzer 	//
190*25c7e1a8SPierre Schweitzer 	//	Create VFD device objects
191*25c7e1a8SPierre Schweitzer 	//
192*25c7e1a8SPierre Schweitzer 	do {
193*25c7e1a8SPierre Schweitzer #ifdef VFD_PNP
194*25c7e1a8SPierre Schweitzer 		status = VfdCreateDevice(DriverObject, NULL);
195*25c7e1a8SPierre Schweitzer #else	// VFD_PNP
196*25c7e1a8SPierre Schweitzer 		status = VfdCreateDevice(DriverObject, driver_extension);
197*25c7e1a8SPierre Schweitzer #endif	// VFD_PNP
198*25c7e1a8SPierre Schweitzer 
199*25c7e1a8SPierre Schweitzer 		if (!NT_SUCCESS(status)) {
200*25c7e1a8SPierre Schweitzer 			break;
201*25c7e1a8SPierre Schweitzer 		}
202*25c7e1a8SPierre Schweitzer 	}
203*25c7e1a8SPierre Schweitzer 	while (driver_extension->NumberOfDevices < number_of_devices);
204*25c7e1a8SPierre Schweitzer 
205*25c7e1a8SPierre Schweitzer 	if (!driver_extension->NumberOfDevices) {
206*25c7e1a8SPierre Schweitzer 
207*25c7e1a8SPierre Schweitzer 		//	Failed to create even one device
208*25c7e1a8SPierre Schweitzer 
209*25c7e1a8SPierre Schweitzer 		VfdFreeUnicode(&(driver_extension->RegistryPath));
210*25c7e1a8SPierre Schweitzer 
211*25c7e1a8SPierre Schweitzer 		return status;
212*25c7e1a8SPierre Schweitzer 	}
213*25c7e1a8SPierre Schweitzer 
214*25c7e1a8SPierre Schweitzer 	//	Setup dispatch table
215*25c7e1a8SPierre Schweitzer 
216*25c7e1a8SPierre Schweitzer 	DriverObject->MajorFunction[IRP_MJ_CREATE]			= VfdCreateClose;
217*25c7e1a8SPierre Schweitzer 	DriverObject->MajorFunction[IRP_MJ_CLOSE]			= VfdCreateClose;
218*25c7e1a8SPierre Schweitzer 	DriverObject->MajorFunction[IRP_MJ_READ]			= VfdReadWrite;
219*25c7e1a8SPierre Schweitzer 	DriverObject->MajorFunction[IRP_MJ_WRITE]			= VfdReadWrite;
220*25c7e1a8SPierre Schweitzer 	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]	= VfdDeviceControl;
221*25c7e1a8SPierre Schweitzer 
222*25c7e1a8SPierre Schweitzer #ifdef VFD_PNP
223*25c7e1a8SPierre Schweitzer 	DriverObject->MajorFunction[IRP_MJ_PNP]				= VfdPlugAndPlay;
224*25c7e1a8SPierre Schweitzer 	DriverObject->MajorFunction[IRP_MJ_POWER]			= VfdPowerControl;
225*25c7e1a8SPierre Schweitzer 	DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL]	= VfdSystemControl;
226*25c7e1a8SPierre Schweitzer 	DriverObject->DriverExtension->AddDevice			= VfdAddDevice;
227*25c7e1a8SPierre Schweitzer #endif	// VFDPNP
228*25c7e1a8SPierre Schweitzer 
229*25c7e1a8SPierre Schweitzer 	DriverObject->DriverUnload = VfdUnloadDriver;
230*25c7e1a8SPierre Schweitzer 
231*25c7e1a8SPierre Schweitzer 	//	Register the driver reinitialize routine to be called
232*25c7e1a8SPierre Schweitzer 	//	*after* the DriverEntry routine returns
233*25c7e1a8SPierre Schweitzer 
234*25c7e1a8SPierre Schweitzer 	IoRegisterDriverReinitialization(
235*25c7e1a8SPierre Schweitzer 		DriverObject, VfdReinitialize, NULL);
236*25c7e1a8SPierre Schweitzer 
237*25c7e1a8SPierre Schweitzer 	VFDTRACE(VFDINFO,
238*25c7e1a8SPierre Schweitzer 		("[VFD] driver initialized with %lu devices.\n",
239*25c7e1a8SPierre Schweitzer 		driver_extension->NumberOfDevices));
240*25c7e1a8SPierre Schweitzer 
241*25c7e1a8SPierre Schweitzer 	return STATUS_SUCCESS;
242*25c7e1a8SPierre Schweitzer }
243*25c7e1a8SPierre Schweitzer 
244*25c7e1a8SPierre Schweitzer //
245*25c7e1a8SPierre Schweitzer //	Driver unload routine
246*25c7e1a8SPierre Schweitzer //	Cleans up the device objects and other resources
247*25c7e1a8SPierre Schweitzer //
248*25c7e1a8SPierre Schweitzer VOID
249*25c7e1a8SPierre Schweitzer NTAPI
VfdUnloadDriver(IN PDRIVER_OBJECT DriverObject)250*25c7e1a8SPierre Schweitzer VfdUnloadDriver (
251*25c7e1a8SPierre Schweitzer 	IN PDRIVER_OBJECT			DriverObject)
252*25c7e1a8SPierre Schweitzer {
253*25c7e1a8SPierre Schweitzer 	PDEVICE_OBJECT				device_object;
254*25c7e1a8SPierre Schweitzer 	PVFD_DRIVER_EXTENSION		driver_extension;
255*25c7e1a8SPierre Schweitzer 
256*25c7e1a8SPierre Schweitzer 	VFDTRACE(VFDINFO, ("[VFD] VfdUnloadDriver - IN\n"));
257*25c7e1a8SPierre Schweitzer 
258*25c7e1a8SPierre Schweitzer 	device_object = DriverObject->DeviceObject;
259*25c7e1a8SPierre Schweitzer 
260*25c7e1a8SPierre Schweitzer #ifdef VFD_PNP
261*25c7e1a8SPierre Schweitzer 	driver_extension = IoGetDriverObjectExtension(
262*25c7e1a8SPierre Schweitzer 		DriverObject, VFD_DRIVER_EXTENSION_ID);
263*25c7e1a8SPierre Schweitzer #else
264*25c7e1a8SPierre Schweitzer 	if (device_object && device_object->DeviceExtension) {
265*25c7e1a8SPierre Schweitzer 		driver_extension =
266*25c7e1a8SPierre Schweitzer 			((PDEVICE_EXTENSION)(device_object->DeviceExtension))->DriverExtension;
267*25c7e1a8SPierre Schweitzer 	}
268*25c7e1a8SPierre Schweitzer 	else {
269*25c7e1a8SPierre Schweitzer 		driver_extension = NULL;
270*25c7e1a8SPierre Schweitzer 	}
271*25c7e1a8SPierre Schweitzer #endif	// VFD_PNP
272*25c7e1a8SPierre Schweitzer 
273*25c7e1a8SPierre Schweitzer 	//
274*25c7e1a8SPierre Schweitzer 	//	Delete all remaining device objects
275*25c7e1a8SPierre Schweitzer 	//
276*25c7e1a8SPierre Schweitzer 	while (device_object) {
277*25c7e1a8SPierre Schweitzer 
278*25c7e1a8SPierre Schweitzer 		PDEVICE_OBJECT next_device = device_object->NextDevice;
279*25c7e1a8SPierre Schweitzer 
280*25c7e1a8SPierre Schweitzer 		VfdDeleteDevice(device_object);
281*25c7e1a8SPierre Schweitzer 
282*25c7e1a8SPierre Schweitzer 		device_object = next_device;
283*25c7e1a8SPierre Schweitzer 	}
284*25c7e1a8SPierre Schweitzer 
285*25c7e1a8SPierre Schweitzer 	//
286*25c7e1a8SPierre Schweitzer 	//	Release the driver extension and the registry path buffer
287*25c7e1a8SPierre Schweitzer 	//
288*25c7e1a8SPierre Schweitzer 	if (driver_extension) {
289*25c7e1a8SPierre Schweitzer 
290*25c7e1a8SPierre Schweitzer 		if (driver_extension->RegistryPath.Buffer) {
291*25c7e1a8SPierre Schweitzer 			VFDTRACE(0, ("[VFD] Releasing the registry path buffer\n"));
292*25c7e1a8SPierre Schweitzer 			ExFreePool(driver_extension->RegistryPath.Buffer);
293*25c7e1a8SPierre Schweitzer 		}
294*25c7e1a8SPierre Schweitzer 
295*25c7e1a8SPierre Schweitzer #ifndef VFD_PNP
296*25c7e1a8SPierre Schweitzer 		//	The system takes care of freeing the driver extension
297*25c7e1a8SPierre Schweitzer 		//	allocated with IoAllocateDriverObjectExtension in a PnP driver.
298*25c7e1a8SPierre Schweitzer 		VFDTRACE(0, ("[VFD] Releasing the driver extension\n"));
299*25c7e1a8SPierre Schweitzer 		ExFreePool(driver_extension);
300*25c7e1a8SPierre Schweitzer #endif	// VFD_PNP
301*25c7e1a8SPierre Schweitzer 	}
302*25c7e1a8SPierre Schweitzer 
303*25c7e1a8SPierre Schweitzer 	VFDTRACE(VFDINFO, ("[VFD] VfdUnloadDriver - OUT\n"));
304*25c7e1a8SPierre Schweitzer }
305*25c7e1a8SPierre Schweitzer 
306*25c7e1a8SPierre Schweitzer //
307*25c7e1a8SPierre Schweitzer //	IRP_MJ_CREATE and IRP_MJ_CLOSE handler
308*25c7e1a8SPierre Schweitzer //	Really nothing to do here...
309*25c7e1a8SPierre Schweitzer //
310*25c7e1a8SPierre Schweitzer NTSTATUS
311*25c7e1a8SPierre Schweitzer NTAPI
VfdCreateClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)312*25c7e1a8SPierre Schweitzer VfdCreateClose (
313*25c7e1a8SPierre Schweitzer 	IN PDEVICE_OBJECT			DeviceObject,
314*25c7e1a8SPierre Schweitzer 	IN PIRP						Irp)
315*25c7e1a8SPierre Schweitzer {
316*25c7e1a8SPierre Schweitzer #if DBG
317*25c7e1a8SPierre Schweitzer 	if (DeviceObject && DeviceObject->DeviceExtension &&
318*25c7e1a8SPierre Schweitzer 		((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer) {
319*25c7e1a8SPierre Schweitzer 
320*25c7e1a8SPierre Schweitzer 		VFDTRACE(VFDINFO, ("[VFD] %-40s %ws\n",
321*25c7e1a8SPierre Schweitzer 			GetMajorFuncName(IoGetCurrentIrpStackLocation(Irp)->MajorFunction),
322*25c7e1a8SPierre Schweitzer 			((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer));
323*25c7e1a8SPierre Schweitzer 	}
324*25c7e1a8SPierre Schweitzer 	else {
325*25c7e1a8SPierre Schweitzer 		VFDTRACE(VFDINFO, ("[VFD] %-40s %p\n",
326*25c7e1a8SPierre Schweitzer 			GetMajorFuncName(IoGetCurrentIrpStackLocation(Irp)->MajorFunction),
327*25c7e1a8SPierre Schweitzer 			DeviceObject));
328*25c7e1a8SPierre Schweitzer 	}
329*25c7e1a8SPierre Schweitzer #endif	// DBG
330*25c7e1a8SPierre Schweitzer 
331*25c7e1a8SPierre Schweitzer 	Irp->IoStatus.Status = STATUS_SUCCESS;
332*25c7e1a8SPierre Schweitzer 	Irp->IoStatus.Information = FILE_OPENED;
333*25c7e1a8SPierre Schweitzer 
334*25c7e1a8SPierre Schweitzer 	IoCompleteRequest(Irp, IO_NO_INCREMENT);
335*25c7e1a8SPierre Schweitzer 
336*25c7e1a8SPierre Schweitzer 	return STATUS_SUCCESS;
337*25c7e1a8SPierre Schweitzer }
338*25c7e1a8SPierre Schweitzer 
339*25c7e1a8SPierre Schweitzer //
340*25c7e1a8SPierre Schweitzer //	Called after the DriverEntry routine has returned
341*25c7e1a8SPierre Schweitzer //	(Re)Create a persistent drive letter for each device
342*25c7e1a8SPierre Schweitzer //
343*25c7e1a8SPierre Schweitzer VOID
344*25c7e1a8SPierre Schweitzer NTAPI
VfdReinitialize(IN PDRIVER_OBJECT DriverObject,IN PVOID Context,IN ULONG Count)345*25c7e1a8SPierre Schweitzer VfdReinitialize(
346*25c7e1a8SPierre Schweitzer 	IN PDRIVER_OBJECT			DriverObject,
347*25c7e1a8SPierre Schweitzer 	IN PVOID					Context,
348*25c7e1a8SPierre Schweitzer 	IN ULONG					Count)
349*25c7e1a8SPierre Schweitzer {
350*25c7e1a8SPierre Schweitzer 	PDEVICE_OBJECT				device_object;
351*25c7e1a8SPierre Schweitzer 	PDEVICE_EXTENSION			device_extension;
352*25c7e1a8SPierre Schweitzer 
353*25c7e1a8SPierre Schweitzer 	UNREFERENCED_PARAMETER(Context);
354*25c7e1a8SPierre Schweitzer 	UNREFERENCED_PARAMETER(Count);
355*25c7e1a8SPierre Schweitzer 
356*25c7e1a8SPierre Schweitzer 	VFDTRACE(VFDINFO, ("[VFD] VfdReinitialize - IN\n"));
357*25c7e1a8SPierre Schweitzer 
358*25c7e1a8SPierre Schweitzer 	device_object = DriverObject->DeviceObject;
359*25c7e1a8SPierre Schweitzer 
360*25c7e1a8SPierre Schweitzer 	while (device_object) {
361*25c7e1a8SPierre Schweitzer 		device_extension = (PDEVICE_EXTENSION)device_object->DeviceExtension;
362*25c7e1a8SPierre Schweitzer 
363*25c7e1a8SPierre Schweitzer #ifdef VFD_MOUNT_MANAGER
364*25c7e1a8SPierre Schweitzer 		if (OsMajorVersion >= 5) {
365*25c7e1a8SPierre Schweitzer 			//	Windows 2000 / XP
366*25c7e1a8SPierre Schweitzer 			//	Notify the mount manager of a VFD volume arrival
367*25c7e1a8SPierre Schweitzer 			VfdMountMgrNotifyVolume(device_extension);
368*25c7e1a8SPierre Schweitzer 
369*25c7e1a8SPierre Schweitzer 			if (device_extension->DriveLetter) {
370*25c7e1a8SPierre Schweitzer 				//	Create a drive letter via the mount manager.
371*25c7e1a8SPierre Schweitzer 				//	The mount manager may have created a drive letter
372*25c7e1a8SPierre Schweitzer 				//	in response to the volume arrival notification above.
373*25c7e1a8SPierre Schweitzer 				//	In that case, the following call just fails.
374*25c7e1a8SPierre Schweitzer 				VfdMountMgrMountPoint(
375*25c7e1a8SPierre Schweitzer 					device_extension, device_extension->DriveLetter);
376*25c7e1a8SPierre Schweitzer 				//	ignoring the error for it is not fatal here
377*25c7e1a8SPierre Schweitzer 			}
378*25c7e1a8SPierre Schweitzer 		}
379*25c7e1a8SPierre Schweitzer 		else
380*25c7e1a8SPierre Schweitzer #endif	// VFD_MOUNT_MANAGER
381*25c7e1a8SPierre Schweitzer 		{
382*25c7e1a8SPierre Schweitzer 			//	Windows NT style drive letter assignment
383*25c7e1a8SPierre Schweitzer 			//	Simply create a symbolic link here
384*25c7e1a8SPierre Schweitzer 			if (device_extension->DriveLetter) {
385*25c7e1a8SPierre Schweitzer 				VfdSetLink(
386*25c7e1a8SPierre Schweitzer 					device_extension, device_extension->DriveLetter);
387*25c7e1a8SPierre Schweitzer 				//	ignoring the error for it is not fatal here
388*25c7e1a8SPierre Schweitzer 			}
389*25c7e1a8SPierre Schweitzer 		}
390*25c7e1a8SPierre Schweitzer 
391*25c7e1a8SPierre Schweitzer 		device_object = device_object->NextDevice;
392*25c7e1a8SPierre Schweitzer 	}
393*25c7e1a8SPierre Schweitzer 
394*25c7e1a8SPierre Schweitzer 	VFDTRACE(VFDINFO, ("[VFD] VfdReinitialize - OUT\n"));
395*25c7e1a8SPierre Schweitzer }
396*25c7e1a8SPierre Schweitzer 
397*25c7e1a8SPierre Schweitzer //
398*25c7e1a8SPierre Schweitzer //	Device dedicated thread routine
399*25c7e1a8SPierre Schweitzer //	Dispatch read, write and device I/O request
400*25c7e1a8SPierre Schweitzer //	redirected from the driver dispatch routines
401*25c7e1a8SPierre Schweitzer //
402*25c7e1a8SPierre Schweitzer VOID
403*25c7e1a8SPierre Schweitzer NTAPI
VfdDeviceThread(IN PVOID ThreadContext)404*25c7e1a8SPierre Schweitzer VfdDeviceThread (
405*25c7e1a8SPierre Schweitzer 	IN PVOID					ThreadContext)
406*25c7e1a8SPierre Schweitzer {
407*25c7e1a8SPierre Schweitzer 	PDEVICE_OBJECT				device_object;
408*25c7e1a8SPierre Schweitzer 	PDEVICE_EXTENSION			device_extension;
409*25c7e1a8SPierre Schweitzer 	PLIST_ENTRY					request;
410*25c7e1a8SPierre Schweitzer 	PIRP						irp;
411*25c7e1a8SPierre Schweitzer 	PIO_STACK_LOCATION			io_stack;
412*25c7e1a8SPierre Schweitzer 
413*25c7e1a8SPierre Schweitzer 	ASSERT(ThreadContext != NULL);
414*25c7e1a8SPierre Schweitzer 
415*25c7e1a8SPierre Schweitzer 	device_object = (PDEVICE_OBJECT)ThreadContext;
416*25c7e1a8SPierre Schweitzer 
417*25c7e1a8SPierre Schweitzer 	device_extension = (PDEVICE_EXTENSION)device_object->DeviceExtension;
418*25c7e1a8SPierre Schweitzer 
419*25c7e1a8SPierre Schweitzer 	KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
420*25c7e1a8SPierre Schweitzer 
421*25c7e1a8SPierre Schweitzer 	for (;;) {
422*25c7e1a8SPierre Schweitzer 		//	wait for the request event to be signalled
423*25c7e1a8SPierre Schweitzer 		KeWaitForSingleObject(
424*25c7e1a8SPierre Schweitzer 			&device_extension->RequestEvent,
425*25c7e1a8SPierre Schweitzer 			Executive,
426*25c7e1a8SPierre Schweitzer 			KernelMode,
427*25c7e1a8SPierre Schweitzer 			FALSE,
428*25c7e1a8SPierre Schweitzer 			NULL);
429*25c7e1a8SPierre Schweitzer 
430*25c7e1a8SPierre Schweitzer 		//	terminate request ?
431*25c7e1a8SPierre Schweitzer 		if (device_extension->TerminateThread) {
432*25c7e1a8SPierre Schweitzer 			VFDTRACE(0, ("[VFD] Exitting the I/O thread\n"));
433*25c7e1a8SPierre Schweitzer 			PsTerminateSystemThread(STATUS_SUCCESS);
434*25c7e1a8SPierre Schweitzer 		}
435*25c7e1a8SPierre Schweitzer 
436*25c7e1a8SPierre Schweitzer 		//	perform requested tasks
437*25c7e1a8SPierre Schweitzer 
438*25c7e1a8SPierre Schweitzer 		while ((request = ExInterlockedRemoveHeadList(
439*25c7e1a8SPierre Schweitzer 			&device_extension->ListHead,
440*25c7e1a8SPierre Schweitzer 			&device_extension->ListLock)) != NULL)
441*25c7e1a8SPierre Schweitzer 		{
442*25c7e1a8SPierre Schweitzer 			irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry);
443*25c7e1a8SPierre Schweitzer 
444*25c7e1a8SPierre Schweitzer 			io_stack = IoGetCurrentIrpStackLocation(irp);
445*25c7e1a8SPierre Schweitzer 
446*25c7e1a8SPierre Schweitzer 			irp->IoStatus.Information = 0;
447*25c7e1a8SPierre Schweitzer 
448*25c7e1a8SPierre Schweitzer 			switch (io_stack->MajorFunction) {
449*25c7e1a8SPierre Schweitzer 			case IRP_MJ_READ:
450*25c7e1a8SPierre Schweitzer 				VfdReadData(device_extension, irp,
451*25c7e1a8SPierre Schweitzer 					io_stack->Parameters.Read.Length,
452*25c7e1a8SPierre Schweitzer 					&io_stack->Parameters.Read.ByteOffset);
453*25c7e1a8SPierre Schweitzer 				break;
454*25c7e1a8SPierre Schweitzer 
455*25c7e1a8SPierre Schweitzer 			case IRP_MJ_WRITE:
456*25c7e1a8SPierre Schweitzer 				VfdWriteData(device_extension, irp,
457*25c7e1a8SPierre Schweitzer 					io_stack->Parameters.Write.Length,
458*25c7e1a8SPierre Schweitzer 					&io_stack->Parameters.Write.ByteOffset);
459*25c7e1a8SPierre Schweitzer 				break;
460*25c7e1a8SPierre Schweitzer 
461*25c7e1a8SPierre Schweitzer 			case IRP_MJ_DEVICE_CONTROL:
462*25c7e1a8SPierre Schweitzer 				VfdIoCtlThread(device_extension, irp,
463*25c7e1a8SPierre Schweitzer 					io_stack->Parameters.DeviceIoControl.IoControlCode);
464*25c7e1a8SPierre Schweitzer 				break;
465*25c7e1a8SPierre Schweitzer 
466*25c7e1a8SPierre Schweitzer 			default:
467*25c7e1a8SPierre Schweitzer 				//	This shouldn't happen...
468*25c7e1a8SPierre Schweitzer 				VFDTRACE(0,
469*25c7e1a8SPierre Schweitzer 					("[VFD] %s passed to the I/O thread\n",
470*25c7e1a8SPierre Schweitzer 					GetMajorFuncName(io_stack->MajorFunction)));
471*25c7e1a8SPierre Schweitzer 
472*25c7e1a8SPierre Schweitzer 				irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
473*25c7e1a8SPierre Schweitzer 			}
474*25c7e1a8SPierre Schweitzer 
475*25c7e1a8SPierre Schweitzer 			IoCompleteRequest(irp,
476*25c7e1a8SPierre Schweitzer 				(CCHAR)(NT_SUCCESS(irp->IoStatus.Status) ?
477*25c7e1a8SPierre Schweitzer 					IO_DISK_INCREMENT : IO_NO_INCREMENT));
478*25c7e1a8SPierre Schweitzer 
479*25c7e1a8SPierre Schweitzer #ifdef VFD_PNP
480*25c7e1a8SPierre Schweitzer 			IoReleaseRemoveLock(&device_extension->RemoveLock, irp);
481*25c7e1a8SPierre Schweitzer #endif	// VFD_PNP
482*25c7e1a8SPierre Schweitzer 		} // while
483*25c7e1a8SPierre Schweitzer 	} // for (;;)
484*25c7e1a8SPierre Schweitzer }
485*25c7e1a8SPierre Schweitzer 
486*25c7e1a8SPierre Schweitzer //
487*25c7e1a8SPierre Schweitzer //	Copy a UNICODE_STRING adding a trailing NULL characer
488*25c7e1a8SPierre Schweitzer //
VfdCopyUnicode(PUNICODE_STRING dst,PUNICODE_STRING src)489*25c7e1a8SPierre Schweitzer PWSTR VfdCopyUnicode(
490*25c7e1a8SPierre Schweitzer 	PUNICODE_STRING				dst,
491*25c7e1a8SPierre Schweitzer 	PUNICODE_STRING				src)
492*25c7e1a8SPierre Schweitzer {
493*25c7e1a8SPierre Schweitzer 	RtlZeroMemory(dst, sizeof(UNICODE_STRING));
494*25c7e1a8SPierre Schweitzer 
495*25c7e1a8SPierre Schweitzer 	dst->MaximumLength =
496*25c7e1a8SPierre Schweitzer 		(USHORT)(src->MaximumLength + sizeof(UNICODE_NULL));
497*25c7e1a8SPierre Schweitzer 
498*25c7e1a8SPierre Schweitzer 	dst->Buffer = (PWSTR)ExAllocatePoolWithTag(
499*25c7e1a8SPierre Schweitzer 		PagedPool, dst->MaximumLength, VFD_POOL_TAG);
500*25c7e1a8SPierre Schweitzer 
501*25c7e1a8SPierre Schweitzer 	if(dst->Buffer) {
502*25c7e1a8SPierre Schweitzer 		dst->Length = src->Length;
503*25c7e1a8SPierre Schweitzer 		RtlZeroMemory(dst->Buffer, dst->MaximumLength);
504*25c7e1a8SPierre Schweitzer 
505*25c7e1a8SPierre Schweitzer 		if (src->Length) {
506*25c7e1a8SPierre Schweitzer 			RtlCopyMemory(dst->Buffer, src->Buffer, src->Length);
507*25c7e1a8SPierre Schweitzer 		}
508*25c7e1a8SPierre Schweitzer 	}
509*25c7e1a8SPierre Schweitzer 
510*25c7e1a8SPierre Schweitzer 	return dst->Buffer;
511*25c7e1a8SPierre Schweitzer }
512*25c7e1a8SPierre Schweitzer 
513*25c7e1a8SPierre Schweitzer //
514*25c7e1a8SPierre Schweitzer //	Free a UNICODE_STRING buffer
515*25c7e1a8SPierre Schweitzer //
VfdFreeUnicode(PUNICODE_STRING str)516*25c7e1a8SPierre Schweitzer VOID VfdFreeUnicode(
517*25c7e1a8SPierre Schweitzer 	PUNICODE_STRING				str)
518*25c7e1a8SPierre Schweitzer {
519*25c7e1a8SPierre Schweitzer 	if (str->Buffer) {
520*25c7e1a8SPierre Schweitzer 		ExFreePool(str->Buffer);
521*25c7e1a8SPierre Schweitzer 	}
522*25c7e1a8SPierre Schweitzer 	RtlZeroMemory(str, sizeof(UNICODE_STRING));
523*25c7e1a8SPierre Schweitzer }
524