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
65 name_buffer
[sizeof(name_buffer
) - 1] = UNICODE_NULL
;
67 _snwprintf(name_buffer
, sizeof(name_buffer
) - 1,
68 L
"\\Device\\Floppy%lu", physical_num
);
70 RtlInitUnicodeString(&unicode_name
, name_buffer
);
72 status
= IoCreateDevice(
74 sizeof(DEVICE_EXTENSION
),
77 FILE_REMOVABLE_MEDIA
| FILE_FLOPPY_DISKETTE
| FILE_DEVICE_SECURE_OPEN
,
81 if (status
!= STATUS_OBJECT_NAME_EXISTS
&&
82 status
!= STATUS_OBJECT_NAME_COLLISION
) {
86 while (++physical_num
< 100);
88 if (!NT_SUCCESS(status
)) {
90 ("[VFD] IoCreateDevice() %s\n",
91 GetStatusName(status
)));
95 IoGetConfigurationInformation()->FloppyCount
++;
97 VFDTRACE(VFDINFO
| VFDDEV
,
98 ("[VFD] Created a device object %ws\n", name_buffer
));
101 // Initialize the device object / device extension
104 device_object
->Flags
|= DO_DIRECT_IO
;
106 device_extension
= (PDEVICE_EXTENSION
)device_object
->DeviceExtension
;
108 RtlZeroMemory(device_extension
, sizeof(DEVICE_EXTENSION
));
110 // Store the back pointer to the device object
112 device_extension
->DeviceObject
= device_object
;
114 // Store the logical device number
116 device_extension
->DeviceNumber
= driver_extension
->NumberOfDevices
;
118 // Store the device name
120 if (!VfdCopyUnicode(&(device_extension
->DeviceName
), &unicode_name
)) {
122 ("[VFD] Failed to allocate device name buffer\n"));
123 status
= STATUS_INSUFFICIENT_RESOURCES
;
127 // set the default disk geometry (3.5" 1.44M)
129 device_extension
->Geometry
= &geom_tbl
[0];
131 // Create the interface link (\??\VirtualFD<n>)
133 name_buffer
[sizeof(name_buffer
) - 1] = UNICODE_NULL
;
135 _snwprintf(name_buffer
, sizeof(name_buffer
) - 1,
136 L
"\\??\\" VFD_DEVICE_BASENAME L
"%lu",
137 device_extension
->DeviceNumber
);
139 RtlInitUnicodeString(&unicode_name
, name_buffer
);
141 status
= IoCreateSymbolicLink(
142 &unicode_name
, &device_extension
->DeviceName
);
144 if (!NT_SUCCESS(status
)) {
146 ("[VFD] IoCreateSymbolicLink(%ws) %s\n",
147 name_buffer
, GetStatusName(status
)));
151 VFDTRACE(VFDINFO
|VFDDEV
,
152 ("[VFD] Created a symbolic link %ws\n", name_buffer
));
154 // Prepare the IRP queue list for the device thread
156 InitializeListHead(&device_extension
->ListHead
);
158 KeInitializeSpinLock(&device_extension
->ListLock
);
161 &device_extension
->RequestEvent
,
162 SynchronizationEvent
,
165 // Create the device thread
167 device_extension
->TerminateThread
= FALSE
;
169 status
= PsCreateSystemThread(
178 if (!NT_SUCCESS(status
)) {
180 ("[VFD] PsCreateSystemThread() %s\n",
181 GetStatusName(status
)));
185 // get a reference pointer to the thread
187 status
= ObReferenceObjectByHandle(
192 &device_extension
->ThreadPointer
,
195 ZwClose(thread_handle
);
197 if (!NT_SUCCESS(status
)) {
199 ("[VFD] ObReferenceObjectByHandle() %s\n",
200 GetStatusName(status
)));
205 // Load the persistent drive letter from the registry
207 if (driver_extension
->RegistryPath
.Buffer
) {
208 VfdLoadLink(device_extension
,
209 driver_extension
->RegistryPath
.Buffer
);
210 // error is not fatal here
213 // increment the number of devices in the driver extension
215 driver_extension
->NumberOfDevices
++;
217 if (DriverObject
->DriverUnload
) {
218 // not called from the DriverEntry routine
219 device_object
->Flags
&= ~DO_DEVICE_INITIALIZING
;
224 // return the device object pointer
225 *(PDEVICE_OBJECT
*)Parameter
= device_object
;
228 device_extension
->DriverExtension
= driver_extension
;
231 VFDTRACE(VFDINFO
| VFDDEV
, ("[VFD] VfdCreateDevice - OK\n"));
233 return STATUS_SUCCESS
;
237 // Something went wrong at one point
238 // Delete all resources that might be created in this function
242 // terminate the device thread
243 device_extension
->TerminateThread
= TRUE
;
246 &device_extension
->RequestEvent
,
250 if (device_extension
->ThreadPointer
) {
251 ObDereferenceObject(device_extension
->ThreadPointer
);
255 VFDTRACE(VFDINFO
|VFDDEV
,
256 ("[VFD] Deleting symbolic link %ws\n", name_buffer
));
258 IoDeleteSymbolicLink(&unicode_name
);
260 if (device_extension
->DeviceName
.Buffer
) {
261 VFDTRACE(VFDINFO
|VFDDEV
, ("[VFD] Deleting device %ws\n",
262 device_extension
->DeviceName
.Buffer
));
264 ExFreePool(device_extension
->DeviceName
.Buffer
);
267 IoDeleteDevice(device_object
);
268 IoGetConfigurationInformation()->FloppyCount
--;
270 VFDTRACE(VFDINFO
|VFDDEV
,
271 ("[VFD] VfdCreateDevice - %s\n",
272 GetStatusName(status
)));
278 // delete a VFD device object
282 IN PDEVICE_OBJECT DeviceObject
)
284 PDEVICE_EXTENSION device_extension
;
285 PVFD_DRIVER_EXTENSION driver_extension
;
286 UNICODE_STRING unicode_name
;
287 WCHAR name_buffer
[40];
289 VFDTRACE(VFDINFO
|VFDDEV
, ("[VFD] VfdDeleteDevice - IN\n"));
291 device_extension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
294 // decrement the number of device in the driver extension
297 driver_extension
= IoGetDriverObjectExtension(
298 DeviceObject
->DriverObject
, VFD_DRIVER_EXTENSION_ID
);
300 driver_extension
= device_extension
->DriverExtension
;
303 if (driver_extension
) {
304 driver_extension
->NumberOfDevices
--;
308 // cleanup the device object
311 // Terminate the device thread
313 device_extension
->TerminateThread
= TRUE
;
316 &device_extension
->RequestEvent
,
320 KeWaitForSingleObject(
321 device_extension
->ThreadPointer
,
328 device_extension
->ThreadPointer
);
330 // Delete security context object
332 if (device_extension
->SecurityContext
) {
333 SeDeleteClientSecurity(device_extension
->SecurityContext
);
334 ExFreePool(device_extension
->SecurityContext
);
337 // Close the image file or free the image buffer
339 if (device_extension
->FileHandle
) {
340 ZwClose(device_extension
->FileHandle
);
343 if (device_extension
->FileBuffer
) {
344 ExFreePool(device_extension
->FileBuffer
);
347 // Release the image path buffer
349 if (device_extension
->FileName
.Buffer
) {
350 ExFreePool(device_extension
->FileName
.Buffer
);
353 // Remove the interface symbolic link
355 name_buffer
[sizeof(name_buffer
) - 1] = UNICODE_NULL
;
357 _snwprintf(name_buffer
, sizeof(name_buffer
) - 1,
358 L
"\\??\\" VFD_DEVICE_BASENAME L
"%lu",
359 device_extension
->DeviceNumber
);
361 RtlInitUnicodeString(&unicode_name
, name_buffer
);
363 VFDTRACE(VFDINFO
|VFDDEV
,
364 ("[VFD] Deleting link %ws\n", name_buffer
));
366 IoDeleteSymbolicLink(&unicode_name
);
368 // Remove the persistent drive letter
370 if (device_extension
->DriveLetter
) {
371 #ifdef VFD_MOUNT_MANAGER
372 if (OsMajorVersion
>= 5) {
373 // Request the mount manager to remove the drive letter.
374 // This will cause the mount manager to update its database
375 // and it won't arbitrarily assign the drive letter the next
376 // time the driver starts.
377 VfdMountMgrMountPoint(device_extension
, 0);
380 #endif // VFD_MOUNT_MANAGER
382 // Windows NT style drive letter handling
383 // Simply remove the symbolic link
384 VfdSetLink(device_extension
, 0);
388 // Release the device name buffer
390 if (device_extension
->DeviceName
.Buffer
) {
391 VFDTRACE(VFDINFO
|VFDDEV
,
392 ("[VFD] Deleting device %ws\n",
393 device_extension
->DeviceName
.Buffer
));
395 ExFreePool(device_extension
->DeviceName
.Buffer
);
398 // Delete the device object
400 IoDeleteDevice(DeviceObject
);
401 IoGetConfigurationInformation()->FloppyCount
--;
403 VFDTRACE(VFDINFO
|VFDDEV
,
404 ("[VFD] VfdDeleteDevice - OUT\n"));