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