1 /* 2 vfddev.c 3 4 Virtual Floppy Drive for Windows NT platform 5 Kernel mode driver: device create/delete functions 6 7 Copyright (C) 2003-2005 Ken Kato 8 */ 9 10 #include "imports.h" 11 #include "vfddrv.h" 12 #include "vfddbg.h" 13 14 #ifdef ALLOC_PRAGMA 15 #pragma alloc_text(PAGE, VfdCreateDevice) 16 #pragma alloc_text(PAGE, VfdDeleteDevice) 17 #endif // ALLOC_PRAGMA 18 19 // 20 // Create a VFD device object 21 // 22 NTSTATUS 23 VfdCreateDevice( 24 IN PDRIVER_OBJECT DriverObject, 25 OUT PVOID Parameter) 26 { 27 NTSTATUS status; 28 ULONG physical_num; 29 30 UNICODE_STRING unicode_name; 31 WCHAR name_buffer[40]; 32 33 PVFD_DRIVER_EXTENSION driver_extension = NULL; 34 PDEVICE_OBJECT device_object = NULL; 35 PDEVICE_EXTENSION device_extension = NULL; 36 HANDLE thread_handle = NULL; 37 38 VFDTRACE(VFDINFO | VFDDEV, ("[VFD] VfdCreateDevice - IN\n")); 39 40 #ifdef VFD_PNP 41 42 // Get the driver device_extension for the driver object 43 driver_extension = IoGetDriverObjectExtension( 44 DriverObject, VFD_DRIVER_EXTENSION_ID); 45 46 #else // VFD_PNP 47 48 // The driver device_extension is passed as the Parameter 49 driver_extension = (PVFD_DRIVER_EXTENSION)Parameter; 50 51 #endif // VFD_PNP 52 53 if (driver_extension == NULL) { 54 VFDTRACE(VFDERR, ("[VFD] Failed to get the driver extension\n")); 55 return STATUS_DRIVER_INTERNAL_ERROR; 56 } 57 58 // 59 // Create a device object 60 // \Device\Floppy<n> 61 // 62 physical_num = 0; 63 64 do { 65 #ifndef __REACTOS__ 66 name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL; 67 68 _snwprintf(name_buffer, sizeof(name_buffer) - 1, 69 L"\\Device\\Floppy%lu", physical_num); 70 #else 71 name_buffer[ARRAYSIZE(name_buffer) - 1] = UNICODE_NULL; 72 73 _snwprintf(name_buffer, ARRAYSIZE(name_buffer) - 1, 74 L"\\Device\\Floppy%lu", physical_num); 75 #endif 76 77 RtlInitUnicodeString(&unicode_name, name_buffer); 78 79 status = IoCreateDevice( 80 DriverObject, 81 sizeof(DEVICE_EXTENSION), 82 &unicode_name, 83 FILE_DEVICE_DISK, 84 FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE | FILE_DEVICE_SECURE_OPEN, 85 FALSE, 86 &device_object); 87 88 if (status != STATUS_OBJECT_NAME_EXISTS && 89 status != STATUS_OBJECT_NAME_COLLISION) { 90 break; 91 } 92 } 93 while (++physical_num < 100); 94 95 if (!NT_SUCCESS(status)) { 96 VFDTRACE(VFDERR, 97 ("[VFD] IoCreateDevice() %s\n", 98 GetStatusName(status))); 99 return status; 100 } 101 102 IoGetConfigurationInformation()->FloppyCount++; 103 104 VFDTRACE(VFDINFO | VFDDEV, 105 ("[VFD] Created a device object %ws\n", name_buffer)); 106 107 // 108 // Initialize the device object / device extension 109 // 110 111 device_object->Flags |= DO_DIRECT_IO; 112 113 device_extension = (PDEVICE_EXTENSION)device_object->DeviceExtension; 114 115 RtlZeroMemory(device_extension, sizeof(DEVICE_EXTENSION)); 116 117 // Store the back pointer to the device object 118 119 device_extension->DeviceObject = device_object; 120 121 // Store the logical device number 122 123 device_extension->DeviceNumber = driver_extension->NumberOfDevices; 124 125 // Store the device name 126 127 if (!VfdCopyUnicode(&(device_extension->DeviceName), &unicode_name)) { 128 VFDTRACE(VFDERR, 129 ("[VFD] Failed to allocate device name buffer\n")); 130 status = STATUS_INSUFFICIENT_RESOURCES; 131 goto cleanup; 132 } 133 134 // set the default disk geometry (3.5" 1.44M) 135 136 device_extension->Geometry = &geom_tbl[0]; 137 138 // Create the interface link (\??\VirtualFD<n>) 139 140 #ifndef __REACTOS__ 141 name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL; 142 143 _snwprintf(name_buffer, sizeof(name_buffer) - 1, 144 L"\\??\\" VFD_DEVICE_BASENAME L"%lu", 145 device_extension->DeviceNumber); 146 #else 147 name_buffer[ARRAYSIZE(name_buffer) - 1] = UNICODE_NULL; 148 149 _snwprintf(name_buffer, ARRAYSIZE(name_buffer) - 1, 150 L"\\??\\" VFD_DEVICE_BASENAME L"%lu", 151 device_extension->DeviceNumber); 152 #endif 153 154 RtlInitUnicodeString(&unicode_name, name_buffer); 155 156 status = IoCreateSymbolicLink( 157 &unicode_name, &device_extension->DeviceName); 158 159 if (!NT_SUCCESS(status)) { 160 VFDTRACE(VFDERR, 161 ("[VFD] IoCreateSymbolicLink(%ws) %s\n", 162 name_buffer, GetStatusName(status))); 163 goto cleanup; 164 } 165 166 VFDTRACE(VFDINFO|VFDDEV, 167 ("[VFD] Created a symbolic link %ws\n", name_buffer)); 168 169 // Prepare the IRP queue list for the device thread 170 171 InitializeListHead(&device_extension->ListHead); 172 173 KeInitializeSpinLock(&device_extension->ListLock); 174 175 KeInitializeEvent( 176 &device_extension->RequestEvent, 177 SynchronizationEvent, 178 FALSE); 179 180 // Create the device thread 181 182 device_extension->TerminateThread = FALSE; 183 184 status = PsCreateSystemThread( 185 &thread_handle, 186 (ACCESS_MASK) 0L, 187 NULL, 188 NULL, 189 NULL, 190 VfdDeviceThread, 191 device_object); 192 193 if (!NT_SUCCESS(status)) { 194 VFDTRACE(VFDERR, 195 ("[VFD] PsCreateSystemThread() %s\n", 196 GetStatusName(status))); 197 goto cleanup; 198 } 199 200 // get a reference pointer to the thread 201 202 status = ObReferenceObjectByHandle( 203 thread_handle, 204 THREAD_ALL_ACCESS, 205 NULL, 206 KernelMode, 207 &device_extension->ThreadPointer, 208 NULL); 209 210 ZwClose(thread_handle); 211 212 if (!NT_SUCCESS(status)) { 213 VFDTRACE(VFDERR, 214 ("[VFD] ObReferenceObjectByHandle() %s\n", 215 GetStatusName(status))); 216 goto cleanup; 217 } 218 219 // 220 // Load the persistent drive letter from the registry 221 // 222 if (driver_extension->RegistryPath.Buffer) { 223 VfdLoadLink(device_extension, 224 driver_extension->RegistryPath.Buffer); 225 // error is not fatal here 226 } 227 228 // increment the number of devices in the driver extension 229 230 driver_extension->NumberOfDevices++; 231 232 if (DriverObject->DriverUnload) { 233 // not called from the DriverEntry routine 234 device_object->Flags &= ~DO_DEVICE_INITIALIZING; 235 } 236 237 #ifdef VFD_PNP 238 if (Parameter) { 239 // return the device object pointer 240 *(PDEVICE_OBJECT *)Parameter = device_object; 241 } 242 #else // VFD_PNP 243 device_extension->DriverExtension = driver_extension; 244 #endif // VFD_PNP 245 246 VFDTRACE(VFDINFO | VFDDEV, ("[VFD] VfdCreateDevice - OK\n")); 247 248 return STATUS_SUCCESS; 249 250 cleanup: 251 // 252 // Something went wrong at one point 253 // Delete all resources that might be created in this function 254 // 255 if (thread_handle) { 256 257 // terminate the device thread 258 device_extension->TerminateThread = TRUE; 259 260 KeSetEvent( 261 &device_extension->RequestEvent, 262 (KPRIORITY) 0, 263 FALSE); 264 265 if (device_extension->ThreadPointer) { 266 ObDereferenceObject(device_extension->ThreadPointer); 267 } 268 } 269 270 VFDTRACE(VFDINFO|VFDDEV, 271 ("[VFD] Deleting symbolic link %ws\n", name_buffer)); 272 273 IoDeleteSymbolicLink(&unicode_name); 274 275 if (device_extension->DeviceName.Buffer) { 276 VFDTRACE(VFDINFO|VFDDEV, ("[VFD] Deleting device %ws\n", 277 device_extension->DeviceName.Buffer)); 278 279 ExFreePool(device_extension->DeviceName.Buffer); 280 } 281 282 IoDeleteDevice(device_object); 283 IoGetConfigurationInformation()->FloppyCount--; 284 285 VFDTRACE(VFDINFO|VFDDEV, 286 ("[VFD] VfdCreateDevice - %s\n", 287 GetStatusName(status))); 288 289 return status; 290 } 291 292 // 293 // delete a VFD device object 294 // 295 VOID 296 VfdDeleteDevice( 297 IN PDEVICE_OBJECT DeviceObject) 298 { 299 PDEVICE_EXTENSION device_extension; 300 PVFD_DRIVER_EXTENSION driver_extension; 301 UNICODE_STRING unicode_name; 302 WCHAR name_buffer[40]; 303 304 VFDTRACE(VFDINFO|VFDDEV, ("[VFD] VfdDeleteDevice - IN\n")); 305 306 device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 307 308 // 309 // decrement the number of device in the driver extension 310 // 311 #ifdef VFD_PNP 312 driver_extension = IoGetDriverObjectExtension( 313 DeviceObject->DriverObject, VFD_DRIVER_EXTENSION_ID); 314 #else // VFD_PNP 315 driver_extension = device_extension->DriverExtension; 316 #endif // VFD_PNP 317 318 if (driver_extension) { 319 driver_extension->NumberOfDevices--; 320 } 321 322 // 323 // cleanup the device object 324 // 325 326 // Terminate the device thread 327 328 device_extension->TerminateThread = TRUE; 329 330 KeSetEvent( 331 &device_extension->RequestEvent, 332 (KPRIORITY) 0, 333 FALSE); 334 335 KeWaitForSingleObject( 336 device_extension->ThreadPointer, 337 Executive, 338 KernelMode, 339 FALSE, 340 NULL); 341 342 ObDereferenceObject( 343 device_extension->ThreadPointer); 344 345 // Delete security context object 346 347 if (device_extension->SecurityContext) { 348 SeDeleteClientSecurity(device_extension->SecurityContext); 349 ExFreePool(device_extension->SecurityContext); 350 } 351 352 // Close the image file or free the image buffer 353 354 if (device_extension->FileHandle) { 355 ZwClose(device_extension->FileHandle); 356 } 357 358 if (device_extension->FileBuffer) { 359 ExFreePool(device_extension->FileBuffer); 360 } 361 362 // Release the image path buffer 363 364 if (device_extension->FileName.Buffer) { 365 ExFreePool(device_extension->FileName.Buffer); 366 } 367 368 // Remove the interface symbolic link 369 370 #ifndef __REACTOS__ 371 name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL; 372 373 _snwprintf(name_buffer, sizeof(name_buffer) - 1, 374 L"\\??\\" VFD_DEVICE_BASENAME L"%lu", 375 device_extension->DeviceNumber); 376 #else 377 name_buffer[ARRAYSIZE(name_buffer) - 1] = UNICODE_NULL; 378 379 _snwprintf(name_buffer, ARRAYSIZE(name_buffer) - 1, 380 L"\\??\\" VFD_DEVICE_BASENAME L"%lu", 381 device_extension->DeviceNumber); 382 #endif 383 384 RtlInitUnicodeString(&unicode_name, name_buffer); 385 386 VFDTRACE(VFDINFO|VFDDEV, 387 ("[VFD] Deleting link %ws\n", name_buffer)); 388 389 IoDeleteSymbolicLink(&unicode_name); 390 391 // Remove the persistent drive letter 392 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); 401 } 402 else 403 #endif // VFD_MOUNT_MANAGER 404 { 405 // Windows NT style drive letter handling 406 // Simply remove the symbolic link 407 VfdSetLink(device_extension, 0); 408 } 409 } 410 411 // Release the device name buffer 412 413 if (device_extension->DeviceName.Buffer) { 414 VFDTRACE(VFDINFO|VFDDEV, 415 ("[VFD] Deleting device %ws\n", 416 device_extension->DeviceName.Buffer)); 417 418 ExFreePool(device_extension->DeviceName.Buffer); 419 } 420 421 // Delete the device object 422 423 IoDeleteDevice(DeviceObject); 424 IoGetConfigurationInformation()->FloppyCount--; 425 426 VFDTRACE(VFDINFO|VFDDEV, 427 ("[VFD] VfdDeleteDevice - OUT\n")); 428 429 return; 430 } 431