[FASTFAT] Implement delayed close
[reactos.git] / drivers / filesystems / udfs / env_spec.cpp
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