4 Virtual Floppy Drive for Windows NT platform
5 Kernel mode driver: device create/delete functions
7 Copyright (C) 2003-2005 Ken Kato
15 #pragma alloc_text(PAGE, VfdCreateDevice)
16 #pragma alloc_text(PAGE, VfdDeleteDevice)
17 #endif // ALLOC_PRAGMA
20 // Create a VFD device object
24 IN PDRIVER_OBJECT DriverObject
,
30 UNICODE_STRING unicode_name
;
31 WCHAR name_buffer
[40];
33 PVFD_DRIVER_EXTENSION driver_extension
= NULL
;
34 PDEVICE_OBJECT device_object
= NULL
;
35 PDEVICE_EXTENSION device_extension
= NULL
;
36 HANDLE thread_handle
= NULL
;
38 VFDTRACE(VFDINFO
| VFDDEV
, ("[VFD] VfdCreateDevice - IN\n"));
42 // Get the driver device_extension for the driver object
43 driver_extension
= IoGetDriverObjectExtension(
44 DriverObject
, VFD_DRIVER_EXTENSION_ID
);
48 // The driver device_extension is passed as the Parameter
49 driver_extension
= (PVFD_DRIVER_EXTENSION
)Parameter
;
53 if (driver_extension
== NULL
) {
54 VFDTRACE(VFDERR
, ("[VFD] Failed to get the driver extension\n"));
55 return STATUS_DRIVER_INTERNAL_ERROR
;
59 // Create a device object
66 name_buffer
[sizeof(name_buffer
) - 1] = UNICODE_NULL
;
68 _snwprintf(name_buffer
, sizeof(name_buffer
) - 1,
69 L
"\\Device\\Floppy%lu", physical_num
);
71 name_buffer
[ARRAYSIZE(name_buffer
) - 1] = UNICODE_NULL
;
73 _snwprintf(name_buffer
, ARRAYSIZE(name_buffer
) - 1,
74 L
"\\Device\\Floppy%lu", physical_num
);
77 RtlInitUnicodeString(&unicode_name
, name_buffer
);
79 status
= IoCreateDevice(
81 sizeof(DEVICE_EXTENSION
),
84 FILE_REMOVABLE_MEDIA
| FILE_FLOPPY_DISKETTE
| FILE_DEVICE_SECURE_OPEN
,
88 if (status
!= STATUS_OBJECT_NAME_EXISTS
&&
89 status
!= STATUS_OBJECT_NAME_COLLISION
) {
93 while (++physical_num
< 100);
95 if (!NT_SUCCESS(status
)) {
97 ("[VFD] IoCreateDevice() %s\n",
98 GetStatusName(status
)));
102 IoGetConfigurationInformation()->FloppyCount
++;
104 VFDTRACE(VFDINFO
| VFDDEV
,
105 ("[VFD] Created a device object %ws\n", name_buffer
));
108 // Initialize the device object / device extension
111 device_object
->Flags
|= DO_DIRECT_IO
;
113 device_extension
= (PDEVICE_EXTENSION
)device_object
->DeviceExtension
;
115 RtlZeroMemory(device_extension
, sizeof(DEVICE_EXTENSION
));
117 // Store the back pointer to the device object
119 device_extension
->DeviceObject
= device_object
;
121 // Store the logical device number
123 device_extension
->DeviceNumber
= driver_extension
->NumberOfDevices
;
125 // Store the device name
127 if (!VfdCopyUnicode(&(device_extension
->DeviceName
), &unicode_name
)) {
129 ("[VFD] Failed to allocate device name buffer\n"));
130 status
= STATUS_INSUFFICIENT_RESOURCES
;
134 // set the default disk geometry (3.5" 1.44M)
136 device_extension
->Geometry
= &geom_tbl
[0];
138 // Create the interface link (\??\VirtualFD<n>)
141 name_buffer
[sizeof(name_buffer
) - 1] = UNICODE_NULL
;
143 _snwprintf(name_buffer
, sizeof(name_buffer
) - 1,
144 L
"\\??\\" VFD_DEVICE_BASENAME L
"%lu",
145 device_extension
->DeviceNumber
);
147 name_buffer
[ARRAYSIZE(name_buffer
) - 1] = UNICODE_NULL
;
149 _snwprintf(name_buffer
, ARRAYSIZE(name_buffer
) - 1,
150 L
"\\??\\" VFD_DEVICE_BASENAME L
"%lu",
151 device_extension
->DeviceNumber
);
154 RtlInitUnicodeString(&unicode_name
, name_buffer
);
156 status
= IoCreateSymbolicLink(
157 &unicode_name
, &device_extension
->DeviceName
);
159 if (!NT_SUCCESS(status
)) {
161 ("[VFD] IoCreateSymbolicLink(%ws) %s\n",
162 name_buffer
, GetStatusName(status
)));
166 VFDTRACE(VFDINFO
|VFDDEV
,
167 ("[VFD] Created a symbolic link %ws\n", name_buffer
));
169 // Prepare the IRP queue list for the device thread
171 InitializeListHead(&device_extension
->ListHead
);
173 KeInitializeSpinLock(&device_extension
->ListLock
);
176 &device_extension
->RequestEvent
,
177 SynchronizationEvent
,
180 // Create the device thread
182 device_extension
->TerminateThread
= FALSE
;
184 status
= PsCreateSystemThread(
193 if (!NT_SUCCESS(status
)) {
195 ("[VFD] PsCreateSystemThread() %s\n",
196 GetStatusName(status
)));
200 // get a reference pointer to the thread
202 status
= ObReferenceObjectByHandle(
207 &device_extension
->ThreadPointer
,
210 ZwClose(thread_handle
);
212 if (!NT_SUCCESS(status
)) {
214 ("[VFD] ObReferenceObjectByHandle() %s\n",
215 GetStatusName(status
)));
220 // Load the persistent drive letter from the registry
222 if (driver_extension
->RegistryPath
.Buffer
) {
223 VfdLoadLink(device_extension
,
224 driver_extension
->RegistryPath
.Buffer
);
225 // error is not fatal here
228 // increment the number of devices in the driver extension
230 driver_extension
->NumberOfDevices
++;
232 if (DriverObject
->DriverUnload
) {
233 // not called from the DriverEntry routine
234 device_object
->Flags
&= ~DO_DEVICE_INITIALIZING
;
239 // return the device object pointer
240 *(PDEVICE_OBJECT
*)Parameter
= device_object
;
243 device_extension
->DriverExtension
= driver_extension
;
246 VFDTRACE(VFDINFO
| VFDDEV
, ("[VFD] VfdCreateDevice - OK\n"));
248 return STATUS_SUCCESS
;
252 // Something went wrong at one point
253 // Delete all resources that might be created in this function
257 // terminate the device thread
258 device_extension
->TerminateThread
= TRUE
;
261 &device_extension
->RequestEvent
,
265 if (device_extension
->ThreadPointer
) {
266 ObDereferenceObject(device_extension
->ThreadPointer
);
270 VFDTRACE(VFDINFO
|VFDDEV
,
271 ("[VFD] Deleting symbolic link %ws\n", name_buffer
));
273 IoDeleteSymbolicLink(&unicode_name
);
275 if (device_extension
->DeviceName
.Buffer
) {
276 VFDTRACE(VFDINFO
|VFDDEV
, ("[VFD] Deleting device %ws\n",
277 device_extension
->DeviceName
.Buffer
));
279 ExFreePool(device_extension
->DeviceName
.Buffer
);
282 IoDeleteDevice(device_object
);
283 IoGetConfigurationInformation()->FloppyCount
--;
285 VFDTRACE(VFDINFO
|VFDDEV
,
286 ("[VFD] VfdCreateDevice - %s\n",
287 GetStatusName(status
)));
293 // delete a VFD device object
297 IN PDEVICE_OBJECT DeviceObject
)
299 PDEVICE_EXTENSION device_extension
;
300 PVFD_DRIVER_EXTENSION driver_extension
;
301 UNICODE_STRING unicode_name
;
302 WCHAR name_buffer
[40];
304 VFDTRACE(VFDINFO
|VFDDEV
, ("[VFD] VfdDeleteDevice - IN\n"));
306 device_extension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
309 // decrement the number of device in the driver extension
312 driver_extension
= IoGetDriverObjectExtension(
313 DeviceObject
->DriverObject
, VFD_DRIVER_EXTENSION_ID
);
315 driver_extension
= device_extension
->DriverExtension
;
318 if (driver_extension
) {
319 driver_extension
->NumberOfDevices
--;
323 // cleanup the device object
326 // Terminate the device thread
328 device_extension
->TerminateThread
= TRUE
;
331 &device_extension
->RequestEvent
,
335 KeWaitForSingleObject(
336 device_extension
->ThreadPointer
,
343 device_extension
->ThreadPointer
);
345 // Delete security context object
347 if (device_extension
->SecurityContext
) {
348 SeDeleteClientSecurity(device_extension
->SecurityContext
);
349 ExFreePool(device_extension
->SecurityContext
);
352 // Close the image file or free the image buffer
354 if (device_extension
->FileHandle
) {
355 ZwClose(device_extension
->FileHandle
);
358 if (device_extension
->FileBuffer
) {
359 ExFreePool(device_extension
->FileBuffer
);
362 // Release the image path buffer
364 if (device_extension
->FileName
.Buffer
) {
365 ExFreePool(device_extension
->FileName
.Buffer
);
368 // Remove the interface symbolic link
371 name_buffer
[sizeof(name_buffer
) - 1] = UNICODE_NULL
;
373 _snwprintf(name_buffer
, sizeof(name_buffer
) - 1,
374 L
"\\??\\" VFD_DEVICE_BASENAME L
"%lu",
375 device_extension
->DeviceNumber
);
377 name_buffer
[ARRAYSIZE(name_buffer
) - 1] = UNICODE_NULL
;
379 _snwprintf(name_buffer
, ARRAYSIZE(name_buffer
) - 1,
380 L
"\\??\\" VFD_DEVICE_BASENAME L
"%lu",
381 device_extension
->DeviceNumber
);
384 RtlInitUnicodeString(&unicode_name
, name_buffer
);
386 VFDTRACE(VFDINFO
|VFDDEV
,
387 ("[VFD] Deleting link %ws\n", name_buffer
));
389 IoDeleteSymbolicLink(&unicode_name
);
391 // Remove the persistent drive letter
393 if (device_extension
->DriveLetter
) {
394 #ifdef VFD_MOUNT_MANAGER
395 if (OsMajorVersion
>= 5) {
396 // Request the mount manager to remove the drive letter.
397 // This will cause the mount manager to update its database
398 // and it won't arbitrarily assign the drive letter the next
399 // time the driver starts.
400 VfdMountMgrMountPoint(device_extension
, 0);
403 #endif // VFD_MOUNT_MANAGER
405 // Windows NT style drive letter handling
406 // Simply remove the symbolic link
407 VfdSetLink(device_extension
, 0);
411 // Release the device name buffer
413 if (device_extension
->DeviceName
.Buffer
) {
414 VFDTRACE(VFDINFO
|VFDDEV
,
415 ("[VFD] Deleting device %ws\n",
416 device_extension
->DeviceName
.Buffer
));
418 ExFreePool(device_extension
->DeviceName
.Buffer
);
421 // Delete the device object
423 IoDeleteDevice(DeviceObject
);
424 IoGetConfigurationInformation()->FloppyCount
--;
426 VFDTRACE(VFDINFO
|VFDDEV
,
427 ("[VFD] VfdDeleteDevice - OUT\n"));