1 /* 2 * PROJECT: VFAT Filesystem 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Temporary sector reading support 5 * COPYRIGHT: Copyright 1999-2001 David Welch <welch@cwcom.net> 6 */ 7 8 /* INCLUDES *****************************************************************/ 9 10 #include "vfat.h" 11 12 #define NDEBUG 13 #include <debug.h> 14 15 /* FUNCTIONS ***************************************************************/ 16 17 static IO_COMPLETION_ROUTINE VfatReadWritePartialCompletion; 18 19 static 20 NTSTATUS 21 NTAPI 22 VfatReadWritePartialCompletion( 23 IN PDEVICE_OBJECT DeviceObject, 24 IN PIRP Irp, 25 IN PVOID Context) 26 { 27 PVFAT_IRP_CONTEXT IrpContext; 28 PMDL Mdl; 29 30 UNREFERENCED_PARAMETER(DeviceObject); 31 32 DPRINT("VfatReadWritePartialCompletion() called\n"); 33 34 IrpContext = (PVFAT_IRP_CONTEXT)Context; 35 36 while ((Mdl = Irp->MdlAddress)) 37 { 38 Irp->MdlAddress = Mdl->Next; 39 IoFreeMdl(Mdl); 40 } 41 42 if (Irp->PendingReturned) 43 { 44 IrpContext->Flags |= IRPCONTEXT_PENDINGRETURNED; 45 } 46 else 47 { 48 IrpContext->Flags &= ~IRPCONTEXT_PENDINGRETURNED; 49 } 50 51 if (!NT_SUCCESS(Irp->IoStatus.Status)) 52 { 53 IrpContext->Irp->IoStatus.Status = Irp->IoStatus.Status; 54 } 55 56 if (0 == InterlockedDecrement((PLONG)&IrpContext->RefCount) && 57 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_PENDINGRETURNED)) 58 { 59 KeSetEvent(&IrpContext->Event, IO_NO_INCREMENT, FALSE); 60 } 61 62 IoFreeIrp(Irp); 63 64 DPRINT("VfatReadWritePartialCompletion() done\n"); 65 66 return STATUS_MORE_PROCESSING_REQUIRED; 67 } 68 69 NTSTATUS 70 VfatReadDisk( 71 IN PDEVICE_OBJECT pDeviceObject, 72 IN PLARGE_INTEGER ReadOffset, 73 IN ULONG ReadLength, 74 IN OUT PUCHAR Buffer, 75 IN BOOLEAN Override) 76 { 77 PIO_STACK_LOCATION Stack; 78 PIRP Irp; 79 IO_STATUS_BLOCK IoStatus; 80 KEVENT Event; 81 NTSTATUS Status; 82 83 again: 84 KeInitializeEvent(&Event, NotificationEvent, FALSE); 85 86 DPRINT("VfatReadDisk(pDeviceObject %p, Offset %I64x, Length %u, Buffer %p)\n", 87 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer); 88 89 DPRINT ("Building synchronous FSD Request...\n"); 90 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 91 pDeviceObject, 92 Buffer, 93 ReadLength, 94 ReadOffset, 95 &Event, 96 &IoStatus); 97 if (Irp == NULL) 98 { 99 DPRINT("IoBuildSynchronousFsdRequest failed\n"); 100 return STATUS_UNSUCCESSFUL; 101 } 102 103 if (Override) 104 { 105 Stack = IoGetNextIrpStackLocation(Irp); 106 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 107 } 108 109 DPRINT("Calling IO Driver... with irp %p\n", Irp); 110 Status = IoCallDriver (pDeviceObject, Irp); 111 112 DPRINT("Waiting for IO Operation for %p\n", Irp); 113 if (Status == STATUS_PENDING) 114 { 115 DPRINT("Operation pending\n"); 116 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 117 DPRINT("Getting IO Status... for %p\n", Irp); 118 Status = IoStatus.Status; 119 } 120 121 if (Status == STATUS_VERIFY_REQUIRED) 122 { 123 PDEVICE_OBJECT DeviceToVerify; 124 125 DPRINT1 ("Media change detected!\n"); 126 127 /* Find the device to verify and reset the thread field to empty value again. */ 128 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); 129 IoSetDeviceToVerify(PsGetCurrentThread(), NULL); 130 Status = IoVerifyVolume(DeviceToVerify, 131 FALSE); 132 if (NT_SUCCESS(Status)) 133 { 134 DPRINT1("Volume verification successful; Reissuing read request\n"); 135 goto again; 136 } 137 } 138 139 if (!NT_SUCCESS(Status)) 140 { 141 DPRINT("IO failed!!! VfatReadDisk : Error code: %x\n", Status); 142 DPRINT("(pDeviceObject %p, Offset %I64x, Size %u, Buffer %p\n", 143 pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer); 144 return Status; 145 } 146 DPRINT("Block request succeeded for %p\n", Irp); 147 return STATUS_SUCCESS; 148 } 149 150 NTSTATUS 151 VfatReadDiskPartial( 152 IN PVFAT_IRP_CONTEXT IrpContext, 153 IN PLARGE_INTEGER ReadOffset, 154 IN ULONG ReadLength, 155 ULONG BufferOffset, 156 IN BOOLEAN Wait) 157 { 158 PIRP Irp; 159 PIO_STACK_LOCATION StackPtr; 160 NTSTATUS Status; 161 PVOID Buffer; 162 163 DPRINT("VfatReadDiskPartial(IrpContext %p, ReadOffset %I64x, ReadLength %u, BufferOffset %u, Wait %u)\n", 164 IrpContext, ReadOffset->QuadPart, ReadLength, BufferOffset, Wait); 165 166 DPRINT("Building asynchronous FSD Request...\n"); 167 168 Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset; 169 170 again: 171 Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE); 172 if (Irp == NULL) 173 { 174 DPRINT("IoAllocateIrp failed\n"); 175 return STATUS_UNSUCCESSFUL; 176 } 177 178 Irp->UserIosb = NULL; 179 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 180 181 StackPtr = IoGetNextIrpStackLocation(Irp); 182 StackPtr->MajorFunction = IRP_MJ_READ; 183 StackPtr->MinorFunction = 0; 184 StackPtr->Flags = 0; 185 StackPtr->Control = 0; 186 StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice; 187 StackPtr->FileObject = NULL; 188 StackPtr->CompletionRoutine = NULL; 189 StackPtr->Parameters.Read.Length = ReadLength; 190 StackPtr->Parameters.Read.ByteOffset = *ReadOffset; 191 192 if (!IoAllocateMdl(Buffer, ReadLength, FALSE, FALSE, Irp)) 193 { 194 DPRINT("IoAllocateMdl failed\n"); 195 IoFreeIrp(Irp); 196 return STATUS_UNSUCCESSFUL; 197 } 198 199 IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, ReadLength); 200 201 IoSetCompletionRoutine(Irp, 202 VfatReadWritePartialCompletion, 203 IrpContext, 204 TRUE, 205 TRUE, 206 TRUE); 207 208 if (Wait) 209 { 210 KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE); 211 IrpContext->RefCount = 1; 212 } 213 else 214 { 215 InterlockedIncrement((PLONG)&IrpContext->RefCount); 216 } 217 218 DPRINT("Calling IO Driver... with irp %p\n", Irp); 219 Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp); 220 221 if (Wait && Status == STATUS_PENDING) 222 { 223 KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL); 224 Status = IrpContext->Irp->IoStatus.Status; 225 } 226 227 if (Status == STATUS_VERIFY_REQUIRED) 228 { 229 PDEVICE_OBJECT DeviceToVerify; 230 231 DPRINT1("Media change detected!\n"); 232 233 /* Find the device to verify and reset the thread field to empty value again. */ 234 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); 235 IoSetDeviceToVerify(PsGetCurrentThread(), NULL); 236 Status = IoVerifyVolume(DeviceToVerify, 237 FALSE); 238 if (NT_SUCCESS(Status)) 239 { 240 DPRINT1("Volume verification successful; Reissuing read request\n"); 241 goto again; 242 } 243 } 244 245 DPRINT("%x\n", Status); 246 return Status; 247 } 248 249 /* Used by dirty bit code, likely to be killed the day it's properly handle 250 * This is just a copy paste from VfatReadDisk() 251 */ 252 NTSTATUS 253 VfatWriteDisk( 254 IN PDEVICE_OBJECT pDeviceObject, 255 IN PLARGE_INTEGER WriteOffset, 256 IN ULONG WriteLength, 257 IN OUT PUCHAR Buffer, 258 IN BOOLEAN Override) 259 { 260 PIO_STACK_LOCATION Stack; 261 PIRP Irp; 262 IO_STATUS_BLOCK IoStatus; 263 KEVENT Event; 264 NTSTATUS Status; 265 266 again: 267 KeInitializeEvent(&Event, NotificationEvent, FALSE); 268 269 DPRINT("VfatWriteDisk(pDeviceObject %p, Offset %I64x, Length %u, Buffer %p)\n", 270 pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer); 271 272 DPRINT ("Building synchronous FSD Request...\n"); 273 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, 274 pDeviceObject, 275 Buffer, 276 WriteLength, 277 WriteOffset, 278 &Event, 279 &IoStatus); 280 if (Irp == NULL) 281 { 282 DPRINT("IoBuildSynchronousFsdRequest failed\n"); 283 return STATUS_UNSUCCESSFUL; 284 } 285 286 if (Override) 287 { 288 Stack = IoGetNextIrpStackLocation(Irp); 289 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 290 } 291 292 DPRINT("Calling IO Driver... with irp %p\n", Irp); 293 Status = IoCallDriver (pDeviceObject, Irp); 294 295 DPRINT("Waiting for IO Operation for %p\n", Irp); 296 if (Status == STATUS_PENDING) 297 { 298 DPRINT("Operation pending\n"); 299 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 300 DPRINT("Getting IO Status... for %p\n", Irp); 301 Status = IoStatus.Status; 302 } 303 304 if (Status == STATUS_VERIFY_REQUIRED) 305 { 306 PDEVICE_OBJECT DeviceToVerify; 307 308 DPRINT1 ("Media change detected!\n"); 309 310 /* Find the device to verify and reset the thread field to empty value again. */ 311 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); 312 IoSetDeviceToVerify(PsGetCurrentThread(), NULL); 313 Status = IoVerifyVolume(DeviceToVerify, 314 FALSE); 315 if (NT_SUCCESS(Status)) 316 { 317 DPRINT1("Volume verification successful; Reissuing write request\n"); 318 goto again; 319 } 320 } 321 322 if (!NT_SUCCESS(Status)) 323 { 324 DPRINT("IO failed!!! VfatWriteDisk : Error code: %x\n", Status); 325 DPRINT("(pDeviceObject %p, Offset %I64x, Size %u, Buffer %p\n", 326 pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer); 327 return Status; 328 } 329 DPRINT("Block request succeeded for %p\n", Irp); 330 return STATUS_SUCCESS; 331 } 332 333 NTSTATUS 334 VfatWriteDiskPartial( 335 IN PVFAT_IRP_CONTEXT IrpContext, 336 IN PLARGE_INTEGER WriteOffset, 337 IN ULONG WriteLength, 338 IN ULONG BufferOffset, 339 IN BOOLEAN Wait) 340 { 341 PIRP Irp; 342 PIO_STACK_LOCATION StackPtr; 343 NTSTATUS Status; 344 PVOID Buffer; 345 346 DPRINT("VfatWriteDiskPartial(IrpContext %p, WriteOffset %I64x, WriteLength %u, BufferOffset %x, Wait %u)\n", 347 IrpContext, WriteOffset->QuadPart, WriteLength, BufferOffset, Wait); 348 349 Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset; 350 351 again: 352 DPRINT("Building asynchronous FSD Request...\n"); 353 Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE); 354 if (Irp == NULL) 355 { 356 DPRINT("IoAllocateIrp failed\n"); 357 return STATUS_UNSUCCESSFUL; 358 } 359 360 Irp->UserIosb = NULL; 361 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 362 363 StackPtr = IoGetNextIrpStackLocation(Irp); 364 StackPtr->MajorFunction = IRP_MJ_WRITE; 365 StackPtr->MinorFunction = 0; 366 StackPtr->Flags = 0; 367 StackPtr->Control = 0; 368 StackPtr->DeviceObject = IrpContext->DeviceExt->StorageDevice; 369 StackPtr->FileObject = NULL; 370 StackPtr->CompletionRoutine = NULL; 371 StackPtr->Parameters.Read.Length = WriteLength; 372 StackPtr->Parameters.Read.ByteOffset = *WriteOffset; 373 374 if (!IoAllocateMdl(Buffer, WriteLength, FALSE, FALSE, Irp)) 375 { 376 DPRINT("IoAllocateMdl failed\n"); 377 IoFreeIrp(Irp); 378 return STATUS_UNSUCCESSFUL; 379 } 380 381 IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, WriteLength); 382 383 IoSetCompletionRoutine(Irp, 384 VfatReadWritePartialCompletion, 385 IrpContext, 386 TRUE, 387 TRUE, 388 TRUE); 389 390 if (Wait) 391 { 392 KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE); 393 IrpContext->RefCount = 1; 394 } 395 else 396 { 397 InterlockedIncrement((PLONG)&IrpContext->RefCount); 398 } 399 400 DPRINT("Calling IO Driver...\n"); 401 Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, Irp); 402 if (Wait && Status == STATUS_PENDING) 403 { 404 KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL); 405 Status = IrpContext->Irp->IoStatus.Status; 406 } 407 408 if (Status == STATUS_VERIFY_REQUIRED) 409 { 410 PDEVICE_OBJECT DeviceToVerify; 411 412 DPRINT1("Media change detected!\n"); 413 414 /* Find the device to verify and reset the thread field to empty value again. */ 415 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); 416 IoSetDeviceToVerify(PsGetCurrentThread(), NULL); 417 Status = IoVerifyVolume(DeviceToVerify, 418 FALSE); 419 if (NT_SUCCESS(Status)) 420 { 421 DPRINT1("Volume verification successful; Reissuing write request\n"); 422 goto again; 423 } 424 } 425 426 return Status; 427 } 428 429 NTSTATUS 430 VfatBlockDeviceIoControl( 431 IN PDEVICE_OBJECT DeviceObject, 432 IN ULONG CtlCode, 433 IN PVOID InputBuffer OPTIONAL, 434 IN ULONG InputBufferSize, 435 IN OUT PVOID OutputBuffer OPTIONAL, 436 IN OUT PULONG OutputBufferSize, 437 IN BOOLEAN Override) 438 { 439 PIO_STACK_LOCATION Stack; 440 KEVENT Event; 441 PIRP Irp; 442 IO_STATUS_BLOCK IoStatus; 443 NTSTATUS Status; 444 445 DPRINT("VfatBlockDeviceIoControl(DeviceObject %p, CtlCode %x, " 446 "InputBuffer %p, InputBufferSize %x, OutputBuffer %p, " 447 "OutputBufferSize %p (%x)\n", DeviceObject, CtlCode, 448 InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, 449 OutputBufferSize ? *OutputBufferSize : 0); 450 451 again: 452 KeInitializeEvent(&Event, NotificationEvent, FALSE); 453 454 DPRINT("Building device I/O control request ...\n"); 455 Irp = IoBuildDeviceIoControlRequest(CtlCode, 456 DeviceObject, 457 InputBuffer, 458 InputBufferSize, 459 OutputBuffer, 460 (OutputBufferSize) ? *OutputBufferSize : 0, 461 FALSE, 462 &Event, 463 &IoStatus); 464 if (Irp == NULL) 465 { 466 DPRINT("IoBuildDeviceIoControlRequest failed\n"); 467 return STATUS_INSUFFICIENT_RESOURCES; 468 } 469 470 if (Override) 471 { 472 Stack = IoGetNextIrpStackLocation(Irp); 473 Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 474 } 475 476 DPRINT("Calling IO Driver... with irp %p\n", Irp); 477 Status = IoCallDriver(DeviceObject, Irp); 478 479 DPRINT("Waiting for IO Operation for %p\n", Irp); 480 if (Status == STATUS_PENDING) 481 { 482 DPRINT("Operation pending\n"); 483 KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL); 484 DPRINT("Getting IO Status... for %p\n", Irp); 485 486 Status = IoStatus.Status; 487 } 488 489 if (Status == STATUS_VERIFY_REQUIRED) 490 { 491 PDEVICE_OBJECT DeviceToVerify; 492 493 DPRINT1("Media change detected!\n"); 494 495 /* Find the device to verify and reset the thread field to empty value again. */ 496 DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); 497 IoSetDeviceToVerify(PsGetCurrentThread(), NULL); 498 Status = IoVerifyVolume(DeviceToVerify, 499 FALSE); 500 501 if (NT_SUCCESS(Status)) 502 { 503 DPRINT1("Volume verification successful; Reissuing IOCTL request\n"); 504 goto again; 505 } 506 } 507 508 if (OutputBufferSize) 509 { 510 *OutputBufferSize = IoStatus.Information; 511 } 512 513 DPRINT("Returning Status %x\n", Status); 514 515 return Status; 516 } 517