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