1 /* 2 vfdpnp.c 3 4 Virtual Floppy Drive for Windows NT platform 5 Kernel mode driver: Plug & Play functions 6 7 Copyright (C) 2003-2005 Ken Kato 8 */ 9 10 #ifndef VFD_PNP 11 /* 12 Not in working order for the time being 13 so DO NOT define VFD_PNP macro 14 unless you know exactly what you are doing... 15 */ 16 // suppress empty compile unit warning 17 #ifdef _MSC_VER 18 #pragma warning (disable: 4206) 19 #pragma message ("Plug and play support feature is disabled.") 20 #endif 21 22 #else // VFD_PNP 23 24 #include "imports.h" 25 #include "vfddrv.h" 26 #include "vfddbg.h" 27 28 static NTSTATUS 29 VfdReportDevice( 30 PDEVICE_EXTENSION device_extension); 31 32 #ifdef ALLOC_PRAGMA 33 #pragma alloc_text(PAGE, VfdPlugAndPlay) 34 #pragma alloc_text(PAGE, VfdPowerControl) 35 #pragma alloc_text(PAGE, VfdSystemControl) 36 #pragma alloc_text(PAGE, VfdAddDevice) 37 #pragma alloc_text(PAGE, VfdReportDevice) 38 #endif // ALLOC_PRAGMA 39 40 #define REMLOCK_TAG 'LdfV' // "VfdL" 41 #define REMLOCK_MAXIMUM 1 // Max minutes system allows lock to be held 42 #define REMLOCK_HIGHWATER 10 // Max number of irps holding lock at one time 43 44 #if DBG 45 static PCSTR StateTable[] ={ 46 { "STOPPED" }, 47 { "WORKING" }, 48 { "PENDINGSTOP" }, 49 { "PENDINGREMOVE" }, 50 { "SURPRISEREMOVED" }, 51 { "REMOVED" }, 52 { "UNKNOWN" } 53 }; 54 #endif // DBG 55 56 // 57 // PnP I/O request dispatch 58 // 59 NTSTATUS 60 VfdPlugAndPlay( 61 IN PDEVICE_OBJECT DeviceObject, 62 IN PIRP Irp) 63 { 64 PIO_STACK_LOCATION io_stack; 65 PDEVICE_EXTENSION device_extension; 66 NTSTATUS status = STATUS_SUCCESS; 67 BOOLEAN lockHeld = TRUE; 68 69 // 70 // setup necessary pointers 71 // 72 io_stack = IoGetCurrentIrpStackLocation( Irp ); 73 device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 74 75 ASSERT(device_extension->DeviceState < VFD_MAX_STATE); 76 77 VFDTRACE(VFDINFO, ("[VFD] VfdPlugAndPlay - IN. %ws %s Device State=%s\n", 78 device_extension->device_name.Buffer, 79 GetPnpIrpName(io_stack->MinorFunction), 80 StateTable[device_extension->DeviceState])); 81 82 // 83 // Acquire remove lock 84 // 85 status = IoAcquireRemoveLock(&device_extension->RemoveLock, Irp); 86 87 if (!NT_SUCCESS(status)) { 88 VFDTRACE(0, ("Acquire RemoveLock failed - %s\n", NtStatusToStr(status))); 89 90 Irp->IoStatus.Status = status; 91 Irp->IoStatus.Information = 0; 92 IoCompleteRequest(Irp, IO_NO_INCREMENT); 93 return status; 94 } 95 96 // 97 // Process the PnP I/O request 98 // 99 switch (io_stack->MinorFunction) { 100 case IRP_MN_START_DEVICE: // 0x00 101 // 102 // Start the device 103 // 104 device_extension->DeviceState = VFD_WORKING; 105 status = STATUS_SUCCESS; 106 107 Irp->IoStatus.Status = status; 108 Irp->IoStatus.Information = 0; 109 IoCompleteRequest(Irp, IO_NO_INCREMENT); 110 break; 111 112 case IRP_MN_QUERY_REMOVE_DEVICE: // 0x01 113 // 114 // Prepare device removal 115 // 116 device_extension->DeviceState = VFD_PENDINGREMOVE; 117 status = STATUS_SUCCESS; 118 119 Irp->IoStatus.Status = status; 120 Irp->IoStatus.Information = 0; 121 IoCompleteRequest(Irp, IO_NO_INCREMENT); 122 break; 123 124 case IRP_MN_REMOVE_DEVICE: // 0x02 125 // 126 // Remove the device 127 // 128 status = STATUS_SUCCESS; 129 130 // complete the current request 131 Irp->IoStatus.Status = status; 132 Irp->IoStatus.Information = 0; 133 IoCompleteRequest(Irp, IO_NO_INCREMENT); 134 135 // 136 // Set the device status to REMOVED and wait for other drivers 137 // to release the lock, then delete the device object 138 // 139 device_extension->DeviceState = VFD_REMOVED; 140 IoReleaseRemoveLockAndWait(&device_extension->RemoveLock, Irp); 141 lockHeld = FALSE; 142 143 VfdRemoveDevice(DeviceObject); 144 break; 145 146 case IRP_MN_CANCEL_REMOVE_DEVICE: // 0x03 147 // 148 // Before sending the IRP down make sure we have received 149 // a IRP_MN_QUERY_REMOVE_DEVICE. We may get Cancel Remove 150 // without receiving a Query Remove earlier, if the 151 // driver on top fails a Query Remove and passes down the 152 // Cancel Remove. 153 // 154 155 if (device_extension->DeviceState == VFD_PENDINGREMOVE) { 156 device_extension->DeviceState = VFD_WORKING; 157 } 158 159 status = STATUS_SUCCESS; 160 Irp->IoStatus.Status = status; 161 Irp->IoStatus.Information = 0; 162 IoCompleteRequest(Irp, IO_NO_INCREMENT); 163 164 break; 165 166 case IRP_MN_STOP_DEVICE: // 0x04 167 device_extension->DeviceState = VFD_STOPPED; 168 169 status = STATUS_SUCCESS; 170 Irp->IoStatus.Status = status; 171 Irp->IoStatus.Information = 0; 172 IoCompleteRequest(Irp, IO_NO_INCREMENT); 173 break; 174 175 case IRP_MN_QUERY_STOP_DEVICE: // 0x05 176 device_extension->DeviceState = VFD_PENDINGSTOP; 177 178 status = STATUS_SUCCESS; 179 Irp->IoStatus.Status = status; 180 Irp->IoStatus.Information = 0; 181 IoCompleteRequest(Irp, IO_NO_INCREMENT); 182 break; 183 184 case IRP_MN_CANCEL_STOP_DEVICE: // 0x06 185 // 186 // Before sending the IRP down make sure we have received 187 // a IRP_MN_QUERY_STOP_DEVICE. We may get Cancel Stop 188 // without receiving a Query Stop earlier, if the 189 // driver on top fails a Query Stop and passes down the 190 // Cancel Stop. 191 // 192 193 if (device_extension->DeviceState == VFD_PENDINGSTOP ) { 194 device_extension->DeviceState = VFD_WORKING; 195 } 196 197 status = STATUS_SUCCESS; 198 Irp->IoStatus.Status = status; 199 Irp->IoStatus.Information = 0; 200 IoCompleteRequest(Irp, IO_NO_INCREMENT); 201 break; 202 203 case IRP_MN_QUERY_DEVICE_RELATIONS: // 0x07 204 status = STATUS_SUCCESS; 205 Irp->IoStatus.Information = 0; 206 207 switch (io_stack->Parameters.QueryDeviceRelations.Type) { 208 case BusRelations: 209 VFDTRACE(VFDINFO, ("------- BusRelations Query\n")); 210 break; 211 212 case EjectionRelations: 213 VFDTRACE(VFDINFO, ("------- EjectionRelations Query\n")); 214 break; 215 216 case PowerRelations: 217 VFDTRACE(VFDINFO, ("------- PowerRelations Query\n")); 218 break; 219 220 case RemovalRelations: 221 VFDTRACE(VFDINFO, ("------- RemovalRelations Query\n")); 222 break; 223 224 case TargetDeviceRelation: 225 VFDTRACE(VFDINFO, ("------- TargetDeviceRelation Query\n")); 226 227 Irp->IoStatus.Information = (LONG)ExAllocatePoolWithTag( 228 PagedPool, sizeof(DEVICE_RELATIONS), VFD_POOL_TAG); 229 230 if (Irp->IoStatus.Information) { 231 PDEVICE_RELATIONS rel = (PDEVICE_RELATIONS)Irp->IoStatus.Information; 232 233 rel->Count = 1; 234 rel->Objects[0] = device_extension->device_object; 235 236 status = STATUS_SUCCESS; 237 } 238 else { 239 status = STATUS_INSUFFICIENT_RESOURCES; 240 } 241 break; 242 243 default: 244 VFDTRACE(VFDINFO, ("------- Unknown Query\n")); 245 break; 246 } 247 Irp->IoStatus.Status = status; 248 IoCompleteRequest(Irp, IO_NO_INCREMENT); 249 250 break; 251 252 // case IRP_MN_QUERY_INTERFACE: // 0x08 253 // case IRP_MN_QUERY_CAPABILITIES: // 0x09 254 // case IRP_MN_QUERY_RESOURCES: // 0x0A 255 // case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: // 0x0B 256 // case IRP_MN_QUERY_DEVICE_TEXT: // 0x0C 257 // case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: // 0x0D 258 // case IRP_MN_READ_CONFIG: // 0x0F 259 // case IRP_MN_WRITE_CONFIG: // 0x10 260 // case IRP_MN_EJECT: // 0x11 261 // case IRP_MN_SET_LOCK: // 0x12 262 // case IRP_MN_QUERY_ID: // 0x13 263 // case IRP_MN_QUERY_PNP_DEVICE_STATE: // 0x14 264 // case IRP_MN_QUERY_BUS_INFORMATION: // 0x15 265 // case IRP_MN_DEVICE_USAGE_NOTIFICATION: // 0x16 266 267 case IRP_MN_SURPRISE_REMOVAL: // 0x17 268 device_extension->DeviceState = VFD_SURPRISEREMOVED; 269 270 status = STATUS_SUCCESS; 271 Irp->IoStatus.Status = status; 272 Irp->IoStatus.Information = 0; 273 IoCompleteRequest(Irp, IO_NO_INCREMENT); 274 break; 275 276 // case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: // 0x18 277 278 default: 279 // 280 // unknown request -- simply pass it to the lower device 281 // 282 status = STATUS_INVALID_DEVICE_REQUEST; 283 Irp->IoStatus.Status = status; 284 Irp->IoStatus.Information = 0; 285 IoCompleteRequest(Irp, IO_NO_INCREMENT); 286 break; 287 } 288 289 // 290 // Device Extenion is gone if the current IRP is IRP_MN_REMOVE_DEVICE 291 // 292 if (lockHeld == TRUE) { 293 IoReleaseRemoveLock(&device_extension->RemoveLock, Irp); 294 } 295 296 VFDTRACE(VFDINFO, ("[VFD] VfdPlugAndPlay - %s\n", NtStatusToStr(status))); 297 298 return status; 299 } 300 301 // 302 // Power management I/O request dispatch 303 // 304 NTSTATUS 305 VfdPowerControl( 306 IN PDEVICE_OBJECT DeviceObject, 307 IN PIRP Irp) 308 { 309 PIO_STACK_LOCATION io_stack; 310 PDEVICE_EXTENSION device_extension; 311 NTSTATUS status; 312 313 io_stack = IoGetCurrentIrpStackLocation( Irp ); 314 device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 315 316 VFDTRACE(VFDINFO, ("[VFD] VfdPowerControl - IN. %ws %s Device State=%s\n", 317 device_extension->device_name.Buffer, 318 GetPnpIrpName(io_stack->MinorFunction), 319 StateTable[device_extension->DeviceState])); 320 321 PoStartNextPowerIrp(Irp); 322 323 // 324 // If the device has been removed, the driver should not pass 325 // the IRP down to the next lower driver. 326 // 327 328 if (device_extension->DeviceState == VFD_REMOVED) { 329 status = STATUS_DELETE_PENDING; 330 } 331 else { 332 status = STATUS_SUCCESS; 333 } 334 335 Irp->IoStatus.Status = status; 336 Irp->IoStatus.Information = 0; 337 IoCompleteRequest(Irp, IO_NO_INCREMENT); 338 339 VFDTRACE(VFDINFO, ("[VFD] VfdPowerControl - %s\n", NtStatusToStr(status))); 340 341 return status; 342 } 343 344 // 345 // WMI I/O request dispatch 346 // 347 NTSTATUS 348 VfdSystemControl( 349 IN PDEVICE_OBJECT DeviceObject, 350 IN PIRP Irp) 351 { 352 PIO_STACK_LOCATION io_stack; 353 PDEVICE_EXTENSION device_extension; 354 NTSTATUS status; 355 356 io_stack = IoGetCurrentIrpStackLocation(Irp); 357 device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 358 359 VFDTRACE(VFDINFO, ("[VFD] VfdSystemControl - IN. %ws %s Device State=%s\n", 360 device_extension->device_name.Buffer, 361 GetPnpIrpName(io_stack->MinorFunction), 362 StateTable[device_extension->DeviceState])); 363 364 status = STATUS_SUCCESS; 365 Irp->IoStatus.Status = status; 366 Irp->IoStatus.Information = 0; 367 IoCompleteRequest(Irp, IO_NO_INCREMENT); 368 369 VFDTRACE(VFDINFO, ("[VFD] VfdSystemControl - %s\n", NtStatusToStr(status))); 370 371 return status; 372 } 373 374 // 375 // PnP AddDevice function 376 // 377 NTSTATUS 378 VfdAddDevice( 379 IN PDRIVER_OBJECT DriverObject, 380 IN OUT PDEVICE_OBJECT PhysicalDevice) 381 { 382 PDEVICE_OBJECT device_object; 383 PDEVICE_EXTENSION device_extension; 384 NTSTATUS status; 385 386 VFDTRACE(VFDINFO, ("[VFD] VfdAddDevice - IN\n")); 387 388 status = VfdCreateDevice(DriverObject, &device_object); 389 390 if (NT_SUCCESS(status)) { 391 392 device_object->Flags |= DO_POWER_PAGABLE; 393 394 device_extension = 395 (PDEVICE_EXTENSION)device_object->DeviceExtension; 396 397 // Device starts in Stopped state 398 device_extension->DeviceState = VFD_STOPPED; 399 400 VFDTRACE(VFDINFO, ("[VFD] Initializing the remove lock\n")); 401 402 IoInitializeRemoveLock( 403 &device_extension->RemoveLock, 404 REMLOCK_TAG, 405 REMLOCK_MAXIMUM, 406 REMLOCK_HIGHWATER); 407 408 if (PhysicalDevice) { 409 device_extension->PhysicalDevice = PhysicalDevice; 410 } 411 else { 412 VfdReportDevice(device_extension); 413 } 414 VfdRegisterInterface(device_extension); 415 VfdMountMgrNotifyVolume(device_extension); 416 } 417 418 return status; 419 } 420 421 // 422 // Report a VFD device to the PnP manager 423 // 424 NTSTATUS 425 VfdReportDevice( 426 PDEVICE_EXTENSION device_extension) 427 { 428 NTSTATUS status = STATUS_SUCCESS; 429 CM_RESOURCE_LIST list = {0}; 430 PCM_FULL_RESOURCE_DESCRIPTOR full = &(list.List[0]); 431 PCM_PARTIAL_RESOURCE_LIST part = &(full->PartialResourceList); 432 PCM_PARTIAL_RESOURCE_DESCRIPTOR desc = &(part->PartialDescriptors[0]);; 433 434 list.Count = 1; 435 436 full->InterfaceType = Internal; 437 full->BusNumber = device_extension->device_number; 438 439 part->Version = 1; 440 part->Revision = 1; 441 part->Count = 1; 442 443 desc->Type = CmResourceTypeDeviceSpecific; 444 desc->ShareDisposition = CmResourceShareShared; 445 desc->Flags = 0; 446 447 VFDTRACE(VFDINFO,("[VFD] Reporting device %lu to the PnP manager\n", 448 device_extension->device_number)); 449 450 status = IoReportDetectedDevice( 451 device_extension->device_object->DriverObject, // IN PDRIVER_OBJECT DriverObject, 452 Internal, // IN INTERFACE_TYPE LegacyBusType, 453 (ULONG)-1, // IN ULONG BusNumber, 454 (ULONG)-1, // IN ULONG SlotNumber, 455 &list, // IN PCM_RESOURCE_LIST ResourceList, 456 NULL, // IN PIO_RESOURCE_REQUIREMENTS_LIST OPTIONAL, 457 TRUE, // IN BOOLEAN ResourceAssigned, 458 &(device_extension->PhysicalDevice) // IN OUT PDEVICE_OBJECT *DeviceObject 459 ); 460 461 if (!NT_SUCCESS(status)) { 462 VFDTRACE(0, 463 ("[VFD] IoReportDetectedDevice - %s\n", 464 NtStatusToStr(status))); 465 } 466 467 device_extension->TargetDevice = IoAttachDeviceToDeviceStack( 468 device_extension->device_object, 469 device_extension->PhysicalDevice); 470 471 return status; 472 } 473 474 #endif // VFD_PNP 475