1 //////////////////////////////////////////////////////////////////// 2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3 // All rights reserved 4 // This file was released under the GPLv2 on June 2015. 5 //////////////////////////////////////////////////////////////////// 6 /************************************************************************* 7 * 8 * File: Env_Spec.cpp 9 * 10 * Module: UDF File System Driver (Kernel mode execution only) 11 * 12 * Description: 13 * Contains environment-secific code to handle physical 14 * operations: read, write and device IOCTLS 15 * 16 *************************************************************************/ 17 18 #include "udffs.h" 19 // define the file specific bug-check id 20 #define UDF_BUG_CHECK_ID UDF_FILE_ENV_SPEC 21 22 #define MEASURE_IO_PERFORMANCE 23 24 #ifdef MEASURE_IO_PERFORMANCE 25 LONGLONG IoReadTime=0; 26 LONGLONG IoWriteTime=0; 27 LONGLONG WrittenData=0; 28 LONGLONG IoRelWriteTime=0; 29 #endif //MEASURE_IO_PERFORMANCE 30 31 #ifdef DBG 32 ULONG UDF_SIMULATE_WRITES=0; 33 #endif //DBG 34 35 /* 36 37 */ 38 NTSTATUS 39 NTAPI 40 UDFAsyncCompletionRoutine( 41 IN PDEVICE_OBJECT DeviceObject, 42 IN PIRP Irp, 43 IN PVOID Contxt 44 ) 45 { 46 UDFPrint(("UDFAsyncCompletionRoutine ctx=%x\n", Contxt)); 47 PUDF_PH_CALL_CONTEXT Context = (PUDF_PH_CALL_CONTEXT)Contxt; 48 PMDL Mdl, NextMdl; 49 50 Context->IosbToUse = Irp->IoStatus; 51 #if 1 52 // Unlock pages that are described by MDL (if any)... 53 Mdl = Irp->MdlAddress; 54 while(Mdl) { 55 MmPrint((" Unlock MDL=%x\n", Mdl)); 56 MmUnlockPages(Mdl); 57 Mdl = Mdl->Next; 58 } 59 // ... and free MDL 60 Mdl = Irp->MdlAddress; 61 while(Mdl) { 62 MmPrint((" Free MDL=%x\n", Mdl)); 63 NextMdl = Mdl->Next; 64 IoFreeMdl(Mdl); 65 Mdl = NextMdl; 66 } 67 Irp->MdlAddress = NULL; 68 IoFreeIrp(Irp); 69 70 KeSetEvent( &(Context->event), 0, FALSE ); 71 72 return STATUS_MORE_PROCESSING_REQUIRED; 73 #else 74 KeSetEvent( &(Context->event), 0, FALSE ); 75 76 return STATUS_SUCCESS; 77 #endif 78 } // end UDFAsyncCompletionRoutine() 79 80 NTSTATUS 81 NTAPI 82 UDFSyncCompletionRoutine( 83 IN PDEVICE_OBJECT DeviceObject, 84 IN PIRP Irp, 85 IN PVOID Contxt 86 ) 87 { 88 UDFPrint(("UDFSyncCompletionRoutine ctx=%x\n", Contxt)); 89 PUDF_PH_CALL_CONTEXT Context = (PUDF_PH_CALL_CONTEXT)Contxt; 90 91 Context->IosbToUse = Irp->IoStatus; 92 //KeSetEvent( &(Context->event), 0, FALSE ); 93 94 return STATUS_SUCCESS; 95 } // end UDFSyncCompletionRoutine() 96 97 /* 98 NTSTATUS 99 UDFSyncCompletionRoutine2( 100 IN PDEVICE_OBJECT DeviceObject, 101 IN PIRP Irp, 102 IN PVOID Contxt 103 ) 104 { 105 UDFPrint(("UDFSyncCompletionRoutine2\n")); 106 PKEVENT SyncEvent = (PKEVENT)Contxt; 107 108 KeSetEvent( SyncEvent, 0, FALSE ); 109 110 return STATUS_SUCCESS; 111 } // end UDFSyncCompletionRoutine2() 112 */ 113 114 /* 115 116 Function: UDFPhReadSynchronous() 117 118 Description: 119 UDFFSD will invoke this rotine to read physical device synchronously/asynchronously 120 121 Expected Interrupt Level (for execution) : 122 123 <= IRQL_DISPATCH_LEVEL 124 125 Return Value: STATUS_SUCCESS/Error 126 127 */ 128 NTSTATUS 129 NTAPI 130 UDFPhReadSynchronous( 131 PDEVICE_OBJECT DeviceObject, // the physical device object 132 PVOID Buffer, 133 ULONG Length, 134 LONGLONG Offset, 135 PULONG ReadBytes, 136 ULONG Flags 137 ) 138 { 139 NTSTATUS RC = STATUS_SUCCESS; 140 LARGE_INTEGER ROffset; 141 PUDF_PH_CALL_CONTEXT Context; 142 PIRP irp; 143 KIRQL CurIrql = KeGetCurrentIrql(); 144 PVOID IoBuf = NULL; 145 // ULONG i; 146 #ifdef MEASURE_IO_PERFORMANCE 147 LONGLONG IoEnterTime; 148 LONGLONG IoExitTime; 149 ULONG dt; 150 ULONG dtm; 151 #endif //MEASURE_IO_PERFORMANCE 152 #ifdef _BROWSE_UDF_ 153 PVCB Vcb = NULL; 154 if(Flags & PH_VCB_IN_RETLEN) { 155 Vcb = (PVCB)(*ReadBytes); 156 } 157 #endif //_BROWSE_UDF_ 158 159 #ifdef MEASURE_IO_PERFORMANCE 160 KeQuerySystemTime((PLARGE_INTEGER)&IoEnterTime); 161 #endif //MEASURE_IO_PERFORMANCE 162 163 UDFPrint(("UDFPhRead: Length: %x Lba: %lx\n",Length>>0xb,Offset>>0xb)); 164 // UDFPrint(("UDFPhRead: Length: %x Lba: %lx\n",Length>>0x9,Offset>>0x9)); 165 166 ROffset.QuadPart = Offset; 167 (*ReadBytes) = 0; 168 /* 169 // DEBUG !!! 170 Flags |= PH_TMP_BUFFER; 171 */ 172 if(Flags & PH_TMP_BUFFER) { 173 IoBuf = Buffer; 174 } else { 175 IoBuf = DbgAllocatePoolWithTag(NonPagedPool, Length, 'bNWD'); 176 } 177 if (!IoBuf) { 178 UDFPrint((" !IoBuf\n")); 179 return STATUS_INSUFFICIENT_RESOURCES; 180 } 181 Context = (PUDF_PH_CALL_CONTEXT)MyAllocatePool__( NonPagedPool, sizeof(UDF_PH_CALL_CONTEXT) ); 182 if (!Context) { 183 UDFPrint((" !Context\n")); 184 try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 185 } 186 // Create notification event object to be used to signal the request completion. 187 KeInitializeEvent(&(Context->event), NotificationEvent, FALSE); 188 189 if (CurIrql > PASSIVE_LEVEL) { 190 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ, DeviceObject, IoBuf, 191 Length, &ROffset, &(Context->IosbToUse) ); 192 if (!irp) { 193 UDFPrint((" !irp Async\n")); 194 try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 195 } 196 MmPrint((" Alloc async Irp MDL=%x, ctx=%x\n", irp->MdlAddress, Context)); 197 IoSetCompletionRoutine( irp, &UDFAsyncCompletionRoutine, 198 Context, TRUE, TRUE, TRUE ); 199 } else { 200 irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, IoBuf, 201 Length, &ROffset, &(Context->event), &(Context->IosbToUse) ); 202 if (!irp) { 203 UDFPrint((" !irp Sync\n")); 204 try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 205 } 206 MmPrint((" Alloc Irp MDL=%x, ctx=%x\n", irp->MdlAddress, Context)); 207 } 208 209 (IoGetNextIrpStackLocation(irp))->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 210 RC = IoCallDriver(DeviceObject, irp); 211 212 if (RC == STATUS_PENDING) { 213 DbgWaitForSingleObject(&(Context->event), NULL); 214 if ((RC = Context->IosbToUse.Status) == STATUS_DATA_OVERRUN) { 215 RC = STATUS_SUCCESS; 216 } 217 // *ReadBytes = Context->IosbToUse.Information; 218 } else { 219 // *ReadBytes = irp->IoStatus.Information; 220 } 221 if(NT_SUCCESS(RC)) { 222 (*ReadBytes) = Context->IosbToUse.Information; 223 } 224 if(!(Flags & PH_TMP_BUFFER)) { 225 RtlCopyMemory(Buffer, IoBuf, *ReadBytes); 226 } 227 228 if(NT_SUCCESS(RC)) { 229 /* 230 for(i=0; i<(*ReadBytes); i+=2048) { 231 UDFPrint(("IOCRC %8.8x R %x\n", crc32((PUCHAR)Buffer+i, 2048), (ULONG)((Offset+i)/2048) )); 232 } 233 */ 234 #ifdef _BROWSE_UDF_ 235 if(Vcb) { 236 RC = UDFVRead(Vcb, IoBuf, Length >> Vcb->BlockSizeBits, (ULONG)(Offset >> Vcb->BlockSizeBits), Flags); 237 } 238 #endif //_BROWSE_UDF_ 239 } 240 241 try_exit: NOTHING; 242 243 if(Context) MyFreePool__(Context); 244 if(IoBuf && !(Flags & PH_TMP_BUFFER)) DbgFreePool(IoBuf); 245 246 #ifdef MEASURE_IO_PERFORMANCE 247 KeQuerySystemTime((PLARGE_INTEGER)&IoExitTime); 248 IoReadTime += (IoExitTime-IoEnterTime); 249 dt = (ULONG)((IoExitTime-IoEnterTime)/10/1000); 250 dtm = (ULONG)(((IoExitTime-IoEnterTime)/10)%1000); 251 PerfPrint(("\nUDFPhReadSynchronous() exit: %08X, after %d.%4.4d msec.\n", RC, dt, dtm)); 252 #else 253 UDFPrint(("UDFPhReadSynchronous() exit: %08X\n", RC)); 254 #endif //MEASURE_IO_PERFORMANCE 255 256 return(RC); 257 } // end UDFPhReadSynchronous() 258 259 260 /* 261 262 Function: UDFPhWriteSynchronous() 263 264 Description: 265 UDFFSD will invoke this rotine to write physical device synchronously 266 267 Expected Interrupt Level (for execution) : 268 269 <= IRQL_DISPATCH_LEVEL 270 271 Return Value: STATUS_SUCCESS/Error 272 273 */ 274 NTSTATUS 275 NTAPI 276 UDFPhWriteSynchronous( 277 PDEVICE_OBJECT DeviceObject, // the physical device object 278 PVOID Buffer, 279 ULONG Length, 280 LONGLONG Offset, 281 PULONG WrittenBytes, 282 ULONG Flags 283 ) 284 { 285 NTSTATUS RC = STATUS_SUCCESS; 286 LARGE_INTEGER ROffset; 287 PUDF_PH_CALL_CONTEXT Context; 288 PIRP irp; 289 // LARGE_INTEGER timeout; 290 KIRQL CurIrql = KeGetCurrentIrql(); 291 PVOID IoBuf = NULL; 292 // ULONG i; 293 #ifdef MEASURE_IO_PERFORMANCE 294 LONGLONG IoEnterTime; 295 LONGLONG IoExitTime; 296 ULONG dt; 297 ULONG dtm; 298 #endif //MEASURE_IO_PERFORMANCE 299 #ifdef _BROWSE_UDF_ 300 PVCB Vcb = NULL; 301 if(Flags & PH_VCB_IN_RETLEN) { 302 Vcb = (PVCB)(*WrittenBytes); 303 } 304 #endif //_BROWSE_UDF_ 305 306 #ifdef MEASURE_IO_PERFORMANCE 307 KeQuerySystemTime((PLARGE_INTEGER)&IoEnterTime); 308 #endif //MEASURE_IO_PERFORMANCE 309 310 #if defined UDF_DBG || defined USE_PERF_PRINT 311 ULONG Lba = (ULONG)(Offset>>0xb); 312 // ASSERT(!(Lba & (32-1))); 313 PerfPrint(("UDFPhWrite: Length: %x Lba: %lx\n",Length>>0xb,Lba)); 314 // UDFPrint(("UDFPhWrite: Length: %x Lba: %lx\n",Length>>0x9,Offset>>0x9)); 315 #endif //DBG 316 317 #ifdef DBG 318 if(UDF_SIMULATE_WRITES) { 319 /* FIXME ReactOS 320 If this function is to force a read from the bufffer to simulate any segfaults, then it makes sense. 321 Else, this forloop is useless. 322 UCHAR a; 323 for(ULONG i=0; i<Length; i++) { 324 a = ((PUCHAR)Buffer)[i]; 325 } 326 */ 327 *WrittenBytes = Length; 328 return STATUS_SUCCESS; 329 } 330 #endif //DBG 331 332 ROffset.QuadPart = Offset; 333 (*WrittenBytes) = 0; 334 335 /* IoBuf = ExAllocatePool(NonPagedPool, Length); 336 if (!IoBuf) return STATUS_INSUFFICIENT_RESOURCES; 337 RtlCopyMemory(IoBuf, Buffer, Length);*/ 338 IoBuf = Buffer; 339 340 /* if(Flags & PH_TMP_BUFFER) { 341 IoBuf = Buffer; 342 } else { 343 IoBuf = DbgAllocatePool(NonPagedPool, Length); 344 RtlCopyMemory(IoBuf, Buffer, Length); 345 }*/ 346 347 Context = (PUDF_PH_CALL_CONTEXT)MyAllocatePool__( NonPagedPool, sizeof(UDF_PH_CALL_CONTEXT) ); 348 if (!Context) try_return (RC = STATUS_INSUFFICIENT_RESOURCES); 349 // Create notification event object to be used to signal the request completion. 350 KeInitializeEvent(&(Context->event), NotificationEvent, FALSE); 351 352 if (CurIrql > PASSIVE_LEVEL) { 353 irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, IoBuf, 354 Length, &ROffset, &(Context->IosbToUse) ); 355 if (!irp) try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 356 MmPrint((" Alloc async Irp MDL=%x, ctx=%x\n", irp->MdlAddress, Context)); 357 IoSetCompletionRoutine( irp, &UDFAsyncCompletionRoutine, 358 Context, TRUE, TRUE, TRUE ); 359 } else { 360 irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, IoBuf, 361 Length, &ROffset, &(Context->event), &(Context->IosbToUse) ); 362 if (!irp) try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 363 MmPrint((" Alloc Irp MDL=%x\n, ctx=%x", irp->MdlAddress, Context)); 364 } 365 366 (IoGetNextIrpStackLocation(irp))->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 367 RC = IoCallDriver(DeviceObject, irp); 368 /* 369 for(i=0; i<Length; i+=2048) { 370 UDFPrint(("IOCRC %8.8x W %x\n", crc32((PUCHAR)Buffer+i, 2048), (ULONG)((Offset+i)/2048) )); 371 } 372 */ 373 #ifdef _BROWSE_UDF_ 374 if(Vcb) { 375 UDFVWrite(Vcb, IoBuf, Length >> Vcb->BlockSizeBits, (ULONG)(Offset >> Vcb->BlockSizeBits), Flags); 376 } 377 #endif //_BROWSE_UDF_ 378 379 if (RC == STATUS_PENDING) { 380 DbgWaitForSingleObject(&(Context->event), NULL); 381 if ((RC = Context->IosbToUse.Status) == STATUS_DATA_OVERRUN) { 382 RC = STATUS_SUCCESS; 383 } 384 // *WrittenBytes = Context->IosbToUse.Information; 385 } else { 386 // *WrittenBytes = irp->IoStatus.Information; 387 } 388 if(NT_SUCCESS(RC)) { 389 (*WrittenBytes) = Context->IosbToUse.Information; 390 } 391 392 try_exit: NOTHING; 393 394 if(Context) MyFreePool__(Context); 395 // if(IoBuf) ExFreePool(IoBuf); 396 // if(IoBuf && !(Flags & PH_TMP_BUFFER)) DbgFreePool(IoBuf); 397 if(!NT_SUCCESS(RC)) { 398 UDFPrint(("WriteError\n")); 399 } 400 401 #ifdef MEASURE_IO_PERFORMANCE 402 KeQuerySystemTime((PLARGE_INTEGER)&IoExitTime); 403 IoWriteTime += (IoExitTime-IoEnterTime); 404 if (WrittenData > 1024*1024*8) { 405 PerfPrint(("\nUDFPhWriteSynchronous() Relative size=%I64d, time=%I64d.\n", WrittenData, IoRelWriteTime)); 406 WrittenData = IoRelWriteTime = 0; 407 } 408 WrittenData += Length; 409 IoRelWriteTime += (IoExitTime-IoEnterTime); 410 dt = (ULONG)((IoExitTime-IoEnterTime)/10/1000); 411 dtm = (ULONG)(((IoExitTime-IoEnterTime)/10)%1000); 412 PerfPrint(("\nUDFPhWriteSynchronous() exit: %08X, after %d.%4.4d msec.\n", RC, dt, dtm)); 413 #else 414 UDFPrint(("nUDFPhWriteSynchronous() exit: %08X\n", RC)); 415 #endif //MEASURE_IO_PERFORMANCE 416 417 return(RC); 418 } // end UDFPhWriteSynchronous() 419 420 #if 0 421 NTSTATUS 422 UDFPhWriteVerifySynchronous( 423 PDEVICE_OBJECT DeviceObject, // the physical device object 424 PVOID Buffer, 425 ULONG Length, 426 LONGLONG Offset, 427 PULONG WrittenBytes, 428 ULONG Flags 429 ) 430 { 431 NTSTATUS RC; 432 //PUCHAR v_buff = NULL; 433 //ULONG ReadBytes; 434 435 RC = UDFPhWriteSynchronous(DeviceObject, Buffer, Length, Offset, WrittenBytes, Flags); 436 /* 437 if(!Verify) 438 return RC; 439 v_buff = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Length, 'bNWD'); 440 if(!v_buff) 441 return RC; 442 RC = UDFPhReadSynchronous(DeviceObject, v_buff, Length, Offset, &ReadBytes, Flags); 443 if(!NT_SUCCESS(RC)) { 444 BrutePoint(); 445 DbgFreePool(v_buff); 446 return RC; 447 } 448 if(RtlCompareMemory(v_buff, Buffer, ReadBytes) == Length) { 449 DbgFreePool(v_buff); 450 return RC; 451 } 452 BrutePoint(); 453 DbgFreePool(v_buff); 454 return STATUS_LOST_WRITEBEHIND_DATA; 455 */ 456 return RC; 457 } // end UDFPhWriteVerifySynchronous() 458 #endif //0 459 460 NTSTATUS 461 NTAPI 462 UDFTSendIOCTL( 463 IN ULONG IoControlCode, 464 IN PVCB Vcb, 465 IN PVOID InputBuffer , 466 IN ULONG InputBufferLength, 467 OUT PVOID OutputBuffer , 468 IN ULONG OutputBufferLength, 469 IN BOOLEAN OverrideVerify, 470 OUT PIO_STATUS_BLOCK Iosb OPTIONAL 471 ) 472 { 473 NTSTATUS RC = STATUS_SUCCESS; 474 BOOLEAN Acquired; 475 476 Acquired = UDFAcquireResourceExclusiveWithCheck(&(Vcb->IoResource)); 477 478 _SEH2_TRY { 479 480 RC = UDFPhSendIOCTL(IoControlCode, 481 Vcb->TargetDeviceObject, 482 InputBuffer , 483 InputBufferLength, 484 OutputBuffer , 485 OutputBufferLength, 486 OverrideVerify, 487 Iosb 488 ); 489 490 } _SEH2_FINALLY { 491 if(Acquired) 492 UDFReleaseResource(&(Vcb->IoResource)); 493 } _SEH2_END; 494 495 return RC; 496 } // end UDFTSendIOCTL() 497 498 /* 499 500 Function: UDFPhSendIOCTL() 501 502 Description: 503 UDF FSD will invoke this rotine to send IOCTL's to physical 504 device 505 506 Return Value: STATUS_SUCCESS/Error 507 508 */ 509 NTSTATUS 510 NTAPI 511 UDFPhSendIOCTL( 512 IN ULONG IoControlCode, 513 IN PDEVICE_OBJECT DeviceObject, 514 IN PVOID InputBuffer , 515 IN ULONG InputBufferLength, 516 OUT PVOID OutputBuffer , 517 IN ULONG OutputBufferLength, 518 IN BOOLEAN OverrideVerify, 519 OUT PIO_STATUS_BLOCK Iosb OPTIONAL 520 ) 521 { 522 NTSTATUS RC = STATUS_SUCCESS; 523 PIRP irp; 524 PUDF_PH_CALL_CONTEXT Context; 525 LARGE_INTEGER timeout; 526 527 UDFPrint(("UDFPhDevIOCTL: Code %8x \n",IoControlCode)); 528 529 Context = (PUDF_PH_CALL_CONTEXT)MyAllocatePool__( NonPagedPool, sizeof(UDF_PH_CALL_CONTEXT) ); 530 if (!Context) return STATUS_INSUFFICIENT_RESOURCES; 531 // Check if the user gave us an Iosb. 532 533 // Create notification event object to be used to signal the request completion. 534 KeInitializeEvent(&(Context->event), NotificationEvent, FALSE); 535 536 irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceObject, InputBuffer , 537 InputBufferLength, OutputBuffer, OutputBufferLength,FALSE,&(Context->event),&(Context->IosbToUse)); 538 539 if (!irp) try_return (RC = STATUS_INSUFFICIENT_RESOURCES); 540 MmPrint((" Alloc Irp MDL=%x, ctx=%x\n", irp->MdlAddress, Context)); 541 /* 542 if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 543 UDFPrint(("Setting completion routine\n")); 544 IoSetCompletionRoutine( irp, &UDFSyncCompletionRoutine, 545 Context, TRUE, TRUE, TRUE ); 546 } 547 */ 548 if(OverrideVerify) { 549 (IoGetNextIrpStackLocation(irp))->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 550 } 551 552 RC = IoCallDriver(DeviceObject, irp); 553 554 if (RC == STATUS_PENDING) { 555 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 556 UDFPrint(("Enter wait state on evt %x\n", Context)); 557 558 if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 559 timeout.QuadPart = -1000; 560 UDFPrint(("waiting, TO=%I64d\n", timeout.QuadPart)); 561 RC = DbgWaitForSingleObject(&(Context->event), &timeout); 562 while(RC == STATUS_TIMEOUT) { 563 timeout.QuadPart *= 2; 564 UDFPrint(("waiting, TO=%I64d\n", timeout.QuadPart)); 565 RC = DbgWaitForSingleObject(&(Context->event), &timeout); 566 } 567 568 } else { 569 DbgWaitForSingleObject(&(Context->event), NULL); 570 } 571 if ((RC = Context->IosbToUse.Status) == STATUS_DATA_OVERRUN) { 572 RC = STATUS_SUCCESS; 573 } 574 UDFPrint(("Exit wait state on evt %x, status %8.8x\n", Context, RC)); 575 /* if(Iosb) { 576 (*Iosb) = Context->IosbToUse; 577 }*/ 578 } else { 579 UDFPrint(("No wait completion on evt %x\n", Context)); 580 /* if(Iosb) { 581 (*Iosb) = irp->IoStatus; 582 }*/ 583 } 584 585 if(Iosb) { 586 (*Iosb) = Context->IosbToUse; 587 } 588 589 try_exit: NOTHING; 590 591 if(Context) MyFreePool__(Context); 592 return(RC); 593 } // end UDFPhSendIOCTL() 594 595 596 #ifdef UDF_DBG 597 VOID 598 UDFNotifyFullReportChange( 599 PVCB V, 600 PUDF_FILE_INFO FI, 601 ULONG E, 602 ULONG A 603 ) 604 { 605 if((FI)->ParentFile) { 606 FsRtlNotifyFullReportChange( (V)->NotifyIRPMutex, &((V)->NextNotifyIRP), 607 (PSTRING)&((FI)->Fcb->FCBName->ObjectName), 608 ((FI)->ParentFile->Fcb->FCBName->ObjectName.Length + sizeof(WCHAR)), 609 NULL,NULL, 610 E, A, 611 NULL); 612 } else { 613 FsRtlNotifyFullReportChange( (V)->NotifyIRPMutex, &((V)->NextNotifyIRP), 614 (PSTRING)&((FI)->Fcb->FCBName->ObjectName), 615 0, 616 NULL,NULL, 617 E, A, 618 NULL); 619 } 620 } // end UDFNotifyFullReportChange() 621 622 VOID 623 UDFNotifyVolumeEvent( 624 IN PFILE_OBJECT FileObject, 625 IN ULONG EventCode 626 ) 627 { 628 /* ReactOS FIXME This is always true, and we return anyway. */ 629 // if(!FsRtlNotifyVolumeEvent) 630 return; 631 //FsRtlNotifyVolumeEvent(FileObject, EventCode); 632 } // end UDFNotifyVolumeEvent() 633 #endif // UDF_DBG 634 635