1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
10 Module: UDF File System Driver (Kernel mode execution only)
13 This file contains some miscellaneous support routines.
18 // define the file specific bug-check id
19 #define UDF_BUG_CHECK_ID UDF_FILE_MISC
23 //CCHAR DefLetter[] = {""};
27 Function: UDFInitializeZones()
30 Allocates some memory for global zones used to allocate FSD structures.
31 Either all memory will be allocated or we will back out gracefully.
33 Expected Interrupt Level (for execution) :
37 Return Value: STATUS_SUCCESS/Error
41 UDFInitializeZones(VOID
)
43 NTSTATUS RC
= STATUS_SUCCESS
;
44 uint32 SizeOfZone
= UDFGlobalData
.DefaultZoneSizeInNumStructs
;
45 uint32 SizeOfObjectNameZone
= 0;
46 uint32 SizeOfCCBZone
= 0;
47 // uint32 SizeOfFCBZone = 0;
48 uint32 SizeOfIrpContextZone
= 0;
49 // uint32 SizeOfFileInfoZone = 0;
53 // initialize the spinlock protecting the zones
54 KeInitializeSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
));
56 // determine memory requirements
57 switch (MmQuerySystemSize()) {
59 SizeOfObjectNameZone
= (4 * SizeOfZone
* UDFQuadAlign(sizeof(UDFObjectName
))) + sizeof(ZONE_SEGMENT_HEADER
);
60 SizeOfCCBZone
= (4 * SizeOfZone
* UDFQuadAlign(sizeof(UDFCCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
61 SizeOfIrpContextZone
= (4 * SizeOfZone
* UDFQuadAlign(sizeof(UDFIrpContext
))) + sizeof(ZONE_SEGMENT_HEADER
);
62 UDFGlobalData
.MaxDelayedCloseCount
= 24;
63 UDFGlobalData
.MinDelayedCloseCount
= 6;
64 UDFGlobalData
.MaxDirDelayedCloseCount
= 8;
65 UDFGlobalData
.MinDirDelayedCloseCount
= 2;
66 UDFGlobalData
.WCacheMaxFrames
= 8*4;
67 UDFGlobalData
.WCacheMaxBlocks
= 16*64;
68 UDFGlobalData
.WCacheBlocksPerFrameSh
= 8;
69 UDFGlobalData
.WCacheFramesToKeepFree
= 4;
72 SizeOfObjectNameZone
= (8 * SizeOfZone
* UDFQuadAlign(sizeof(UDFObjectName
))) + sizeof(ZONE_SEGMENT_HEADER
);
73 SizeOfCCBZone
= (8 * SizeOfZone
* UDFQuadAlign(sizeof(UDFCCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
74 SizeOfIrpContextZone
= (8 * SizeOfZone
* UDFQuadAlign(sizeof(UDFIrpContext
))) + sizeof(ZONE_SEGMENT_HEADER
);
75 UDFGlobalData
.MaxDelayedCloseCount
= 72;
76 UDFGlobalData
.MinDelayedCloseCount
= 18;
77 UDFGlobalData
.MaxDirDelayedCloseCount
= 24;
78 UDFGlobalData
.MinDirDelayedCloseCount
= 6;
79 UDFGlobalData
.WCacheMaxFrames
= 2*16*4;
80 UDFGlobalData
.WCacheMaxBlocks
= 2*16*64;
81 UDFGlobalData
.WCacheBlocksPerFrameSh
= 8;
82 UDFGlobalData
.WCacheFramesToKeepFree
= 8;
86 SizeOfObjectNameZone
= (2 * SizeOfZone
* UDFQuadAlign(sizeof(UDFObjectName
))) + sizeof(ZONE_SEGMENT_HEADER
);
87 SizeOfCCBZone
= (2 * SizeOfZone
* UDFQuadAlign(sizeof(UDFCCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
88 SizeOfIrpContextZone
= (2 * SizeOfZone
* UDFQuadAlign(sizeof(UDFIrpContext
))) + sizeof(ZONE_SEGMENT_HEADER
);
89 UDFGlobalData
.MaxDelayedCloseCount
= 8;
90 UDFGlobalData
.MinDelayedCloseCount
= 2;
91 UDFGlobalData
.MaxDirDelayedCloseCount
= 6;
92 UDFGlobalData
.MinDirDelayedCloseCount
= 1;
93 UDFGlobalData
.WCacheMaxFrames
= 8*4/2;
94 UDFGlobalData
.WCacheMaxBlocks
= 16*64/2;
95 UDFGlobalData
.WCacheBlocksPerFrameSh
= 8;
96 UDFGlobalData
.WCacheFramesToKeepFree
= 2;
99 // typical NT methodology (at least until *someone* exposed the "difference" between a server and workstation ;-)
100 if (MmIsThisAnNtAsSystem()) {
101 SizeOfObjectNameZone
*= UDF_NTAS_MULTIPLE
;
102 SizeOfCCBZone
*= UDF_NTAS_MULTIPLE
;
103 SizeOfIrpContextZone
*= UDF_NTAS_MULTIPLE
;
106 // allocate memory for each of the zones and initialize the zones ...
107 if (!(UDFGlobalData
.ObjectNameZone
= DbgAllocatePool(NonPagedPool
, SizeOfObjectNameZone
))) {
108 RC
= STATUS_INSUFFICIENT_RESOURCES
;
112 if (!(UDFGlobalData
.CCBZone
= DbgAllocatePool(NonPagedPool
, SizeOfCCBZone
))) {
113 RC
= STATUS_INSUFFICIENT_RESOURCES
;
117 if (!(UDFGlobalData
.IrpContextZone
= DbgAllocatePool(NonPagedPool
, SizeOfIrpContextZone
))) {
118 RC
= STATUS_INSUFFICIENT_RESOURCES
;
122 // initialize each of the zone headers ...
123 if (!NT_SUCCESS(RC
= ExInitializeZone(&(UDFGlobalData
.ObjectNameZoneHeader
),
124 UDFQuadAlign(sizeof(UDFObjectName
)),
125 UDFGlobalData
.ObjectNameZone
, SizeOfObjectNameZone
))) {
126 // failed the initialization, leave ...
130 if (!NT_SUCCESS(RC
= ExInitializeZone(&(UDFGlobalData
.CCBZoneHeader
),
131 UDFQuadAlign(sizeof(UDFCCB
)),
132 UDFGlobalData
.CCBZone
,
134 // failed the initialization, leave ...
138 if (!NT_SUCCESS(RC
= ExInitializeZone(&(UDFGlobalData
.IrpContextZoneHeader
),
139 UDFQuadAlign(sizeof(UDFIrpContext
)),
140 UDFGlobalData
.IrpContextZone
,
141 SizeOfIrpContextZone
))) {
142 // failed the initialization, leave ...
149 if (!NT_SUCCESS(RC
)) {
150 // invoke the destroy routine now ...
153 // mark the fact that we have allocated zones ...
154 UDFSetFlag(UDFGlobalData
.UDFFlags
, UDF_DATA_FLAGS_ZONES_INITIALIZED
);
162 /*************************************************************************
164 * Function: UDFDestroyZones()
167 * Free up the previously allocated memory. NEVER do this once the
168 * driver has been successfully loaded.
170 * Expected Interrupt Level (for execution) :
176 *************************************************************************/
177 VOID
UDFDestroyZones(VOID
)
182 // free up each of the pools
183 if(UDFGlobalData
.ObjectNameZone
) {
184 DbgFreePool(UDFGlobalData
.ObjectNameZone
);
185 UDFGlobalData
.ObjectNameZone
= NULL
;
187 if(UDFGlobalData
.CCBZone
) {
188 DbgFreePool(UDFGlobalData
.CCBZone
);
189 UDFGlobalData
.CCBZone
= NULL
;
191 if(UDFGlobalData
.IrpContextZone
) {
192 DbgFreePool(UDFGlobalData
.IrpContextZone
);
193 UDFGlobalData
.IrpContextZone
= NULL
;
199 UDFGlobalData
.UDFFlags
&= ~UDF_DATA_FLAGS_ZONES_INITIALIZED
;
206 /*************************************************************************
208 * Function: UDFIsIrpTopLevel()
211 * Helps the FSD determine who the "top level" caller is for this
212 * request. A request can originate directly from a user process
213 * (in which case, the "top level" will be NULL when this routine
214 * is invoked), OR the user may have originated either from the NT
215 * Cache Manager/VMM ("top level" may be set), or this could be a
216 * recursion into our code in which we would have set the "top level"
217 * field the last time around.
219 * Expected Interrupt Level (for execution) :
221 * whatever level a particular dispatch routine is invoked at.
223 * Return Value: TRUE/FALSE (TRUE if top level was NULL when routine invoked)
225 *************************************************************************/
229 PIRP Irp
) // the IRP sent to our dispatch routine
231 if(!IoGetTopLevelIrp()) {
232 // OK, so we can set ourselves to become the "top level" component
233 IoSetTopLevelIrp(Irp
);
240 /*************************************************************************
242 * Function: UDFExceptionFilter()
245 * This routines allows the driver to determine whether the exception
246 * is an "allowed" exception i.e. one we should not-so-quietly consume
247 * ourselves, or one which should be propagated onwards in which case
248 * we will most likely bring down the machine.
250 * This routine employs the services of FsRtlIsNtstatusExpected(). This
251 * routine returns a BOOLEAN result. A RC of FALSE will cause us to return
252 * EXCEPTION_CONTINUE_SEARCH which will probably cause a panic.
253 * The FsRtl.. routine returns FALSE iff exception values are (currently) :
254 * STATUS_DATATYPE_MISALIGNMENT || STATUS_ACCESS_VIOLATION ||
255 * STATUS_ILLEGAL_INSTRUCTION || STATUS_INSTRUCTION_MISALIGNMENT
257 * Expected Interrupt Level (for execution) :
261 * Return Value: EXCEPTION_EXECUTE_HANDLER/EXECEPTION_CONTINUE_SEARCH
263 *************************************************************************/
266 PtrUDFIrpContext PtrIrpContext
,
267 PEXCEPTION_POINTERS PtrExceptionPointers
270 long ReturnCode
= EXCEPTION_EXECUTE_HANDLER
;
271 NTSTATUS ExceptionCode
= STATUS_SUCCESS
;
272 #if defined UDF_DBG || defined PRINT_ALWAYS
275 UDFPrint(("UDFExceptionFilter\n"));
276 UDFPrint((" Ex. Code: %x\n",PtrExceptionPointers
->ExceptionRecord
->ExceptionCode
));
277 UDFPrint((" Ex. Addr: %x\n",PtrExceptionPointers
->ExceptionRecord
->ExceptionAddress
));
278 UDFPrint((" Ex. Flag: %x\n",PtrExceptionPointers
->ExceptionRecord
->ExceptionFlags
));
279 UDFPrint((" Ex. Pnum: %x\n",PtrExceptionPointers
->ExceptionRecord
->NumberParameters
));
280 for(i
=0;i
<PtrExceptionPointers
->ExceptionRecord
->NumberParameters
;i
++) {
281 UDFPrint((" %x\n",PtrExceptionPointers
->ExceptionRecord
->ExceptionInformation
[i
]));
284 UDFPrint(("Exception context:\n"));
285 if(PtrExceptionPointers
->ContextRecord
->ContextFlags
& CONTEXT_INTEGER
) {
286 UDFPrint(("EAX=%8.8x ",PtrExceptionPointers
->ContextRecord
->Eax
));
287 UDFPrint(("EBX=%8.8x ",PtrExceptionPointers
->ContextRecord
->Ebx
));
288 UDFPrint(("ECX=%8.8x ",PtrExceptionPointers
->ContextRecord
->Ecx
));
289 UDFPrint(("EDX=%8.8x\n",PtrExceptionPointers
->ContextRecord
->Edx
));
291 UDFPrint(("ESI=%8.8x ",PtrExceptionPointers
->ContextRecord
->Esi
));
292 UDFPrint(("EDI=%8.8x ",PtrExceptionPointers
->ContextRecord
->Edi
));
294 if(PtrExceptionPointers
->ContextRecord
->ContextFlags
& CONTEXT_CONTROL
) {
295 UDFPrint(("EBP=%8.8x ",PtrExceptionPointers
->ContextRecord
->Esp
));
296 UDFPrint(("ESP=%8.8x\n",PtrExceptionPointers
->ContextRecord
->Ebp
));
298 UDFPrint(("EIP=%8.8x\n",PtrExceptionPointers
->ContextRecord
->Eip
));
300 // UDFPrint(("Flags: %s %s ",PtrExceptionPointers->ContextRecord->Eip));
305 // figure out the exception code
306 ExceptionCode
= PtrExceptionPointers
->ExceptionRecord
->ExceptionCode
;
308 if ((ExceptionCode
== STATUS_IN_PAGE_ERROR
) && (PtrExceptionPointers
->ExceptionRecord
->NumberParameters
>= 3)) {
309 ExceptionCode
= PtrExceptionPointers
->ExceptionRecord
->ExceptionInformation
[2];
313 PtrIrpContext
->SavedExceptionCode
= ExceptionCode
;
314 UDFSetFlag(PtrIrpContext
->IrpContextFlags
, UDF_IRP_CONTEXT_EXCEPTION
);
317 // check if we should propagate this exception or not
318 if (!(FsRtlIsNtstatusExpected(ExceptionCode
))) {
320 // better free up the IrpContext now ...
322 UDFPrint((" UDF Driver internal error\n"));
325 // we are not ok, propagate this exception.
326 // NOTE: we will bring down the machine ...
327 ReturnCode
= EXCEPTION_CONTINUE_SEARCH
;
332 // return the appropriate code
334 } // end UDFExceptionFilter()
337 /*************************************************************************
339 * Function: UDFExceptionHandler()
342 * One of the routines in the FSD or in the modules we invoked encountered
343 * an exception. We have decided that we will "handle" the exception.
344 * Therefore we will prevent the machine from a panic ...
345 * You can do pretty much anything you choose to in your commercial
346 * driver at this point to ensure a graceful exit. In the UDF
347 * driver, We shall simply free up the IrpContext (if any), set the
348 * error code in the IRP and complete the IRP at this time ...
350 * Expected Interrupt Level (for execution) :
354 * Return Value: Error code
356 *************************************************************************/
359 PtrUDFIrpContext PtrIrpContext
,
364 NTSTATUS ExceptionCode
= STATUS_INSUFFICIENT_RESOURCES
;
365 PDEVICE_OBJECT Device
;
369 UDFPrint(("UDFExceptionHandler \n"));
374 UDFPrint((" !Irp, return\n"));
375 ASSERT(!PtrIrpContext
);
376 return ExceptionCode
;
378 // If it was a queued close (or something like this) then we need not
379 // completing it because of MUST_SUCCEED requirement.
382 ExceptionCode
= PtrIrpContext
->SavedExceptionCode
;
383 // Free irp context here
384 // UDFReleaseIrpContext(PtrIrpContext);
386 UDFPrint((" complete Irp and return\n"));
387 // must be insufficient resources ...?
388 ExceptionCode
= STATUS_INSUFFICIENT_RESOURCES
;
389 Irp
->IoStatus
.Status
= ExceptionCode
;
390 Irp
->IoStatus
.Information
= 0;
392 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
394 return ExceptionCode
;
397 // Check if we are posting this request. One of the following must be true
398 // if we are to post a request.
400 // - Status code is STATUS_CANT_WAIT and the request is asynchronous
401 // or we are forcing this to be posted.
403 // - Status code is STATUS_VERIFY_REQUIRED and we are at APC level
404 // or higher. Can't wait for IO in the verify path in this case.
406 // Set the MORE_PROCESSING flag in the IrpContext to keep if from being
407 // deleted if this is a retryable condition.
409 if (ExceptionCode
== STATUS_VERIFY_REQUIRED
) {
410 if (KeGetCurrentIrql() >= APC_LEVEL
) {
411 UDFPrint((" use UDFPostRequest()\n"));
412 ExceptionCode
= UDFPostRequest( PtrIrpContext
, Irp
);
416 // If we posted the request or our caller will retry then just return here.
417 if ((ExceptionCode
== STATUS_PENDING
) ||
418 (ExceptionCode
== STATUS_CANT_WAIT
)) {
420 UDFPrint((" STATUS_PENDING/STATUS_CANT_WAIT, return\n"));
421 return ExceptionCode
;
424 // Store this error into the Irp for posting back to the Io system.
425 Irp
->IoStatus
.Status
= ExceptionCode
;
426 if (IoIsErrorUserInduced( ExceptionCode
)) {
428 // Check for the various error conditions that can be caused by,
429 // and possibly resolved my the user.
430 if (ExceptionCode
== STATUS_VERIFY_REQUIRED
) {
432 // Now we are at the top level file system entry point.
434 // If we have already posted this request then the device to
435 // verify is in the original thread. Find this via the Irp.
436 Device
= IoGetDeviceToVerify( Irp
->Tail
.Overlay
.Thread
);
437 IoSetDeviceToVerify( Irp
->Tail
.Overlay
.Thread
, NULL
);
439 // If there is no device in that location then check in the
441 if (Device
== NULL
) {
443 Device
= IoGetDeviceToVerify( PsGetCurrentThread() );
444 IoSetDeviceToVerify( PsGetCurrentThread(), NULL
);
446 ASSERT( Device
!= NULL
);
448 // Let's not BugCheck just because the driver screwed up.
449 if (Device
== NULL
) {
451 UDFPrint((" Device == NULL, return\n"));
452 ExceptionCode
= STATUS_DRIVER_INTERNAL_ERROR
;
453 Irp
->IoStatus
.Status
= ExceptionCode
;
454 Irp
->IoStatus
.Information
= 0;
456 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
458 UDFReleaseIrpContext(PtrIrpContext
);
460 return ExceptionCode
;
464 UDFPrint((" use UDFPerformVerify()\n"));
465 // UDFPerformVerify() will do the right thing with the Irp.
466 // If we return STATUS_CANT_WAIT then the current thread
467 // can retry the request.
468 return UDFPerformVerify( PtrIrpContext
, Irp
, Device
);
472 // The other user induced conditions generate an error unless
473 // they have been disabled for this request.
476 if (FlagOn( PtrIrpContext
->IrpContextFlags
, UDF_IRP_CONTEXT_FLAG_DISABLE_POPUPS
)) {
478 UDFPrint((" DISABLE_POPUPS, complete Irp and return\n"));
479 Irp
->IoStatus
.Status
= ExceptionCode
;
480 Irp
->IoStatus
.Information
= 0;
482 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
484 UDFReleaseIrpContext(PtrIrpContext
);
485 return ExceptionCode
;
489 if (IoGetCurrentIrpStackLocation( Irp
)->FileObject
!= NULL
) {
491 Vpb
= IoGetCurrentIrpStackLocation( Irp
)->FileObject
->Vpb
;
496 // The device to verify is either in my thread local storage
497 // or that of the thread that owns the Irp.
498 Thread
= Irp
->Tail
.Overlay
.Thread
;
499 Device
= IoGetDeviceToVerify( Thread
);
501 if (Device
== NULL
) {
503 Thread
= PsGetCurrentThread();
504 Device
= IoGetDeviceToVerify( Thread
);
505 ASSERT( Device
!= NULL
);
507 // Let's not BugCheck just because the driver screwed up.
508 if (Device
== NULL
) {
509 UDFPrint((" Device == NULL, return(2)\n"));
510 Irp
->IoStatus
.Status
= ExceptionCode
;
511 Irp
->IoStatus
.Information
= 0;
513 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
515 UDFReleaseIrpContext(PtrIrpContext
);
517 return ExceptionCode
;
521 // This routine actually causes the pop-up. It usually
522 // does this by queuing an APC to the callers thread,
523 // but in some cases it will complete the request immediately,
524 // so it is very important to IoMarkIrpPending() first.
525 IoMarkIrpPending( Irp
);
526 IoRaiseHardError( Irp
, Vpb
, Device
);
528 // We will be handing control back to the caller here, so
529 // reset the saved device object.
531 UDFPrint((" use IoSetDeviceToVerify()\n"));
532 IoSetDeviceToVerify( Thread
, NULL
);
533 // The Irp will be completed by Io or resubmitted. In either
534 // case we must clean up the IrpContext here.
536 UDFReleaseIrpContext(PtrIrpContext
);
537 return STATUS_PENDING
;
541 // If it was a normal request from IOManager then complete it
543 UDFPrint((" complete Irp\n"));
544 // set the error code in the IRP
545 Irp
->IoStatus
.Status
= ExceptionCode
;
546 Irp
->IoStatus
.Information
= 0;
549 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
551 UDFReleaseIrpContext(PtrIrpContext
);
554 UDFPrint((" return from exception handler with code %x\n", ExceptionCode
));
555 return(ExceptionCode
);
556 } // end UDFExceptionHandler()
558 /*************************************************************************
560 * Function: UDFLogEvent()
563 * Log a message in the NT Event Log. This is a rather simplistic log
564 * methodology since we can potentially utilize the event log to
565 * provide a lot of information to the user (and you should too!)
567 * Expected Interrupt Level (for execution) :
573 *************************************************************************/
576 NTSTATUS UDFEventLogId
, // the UDF private message id
577 NTSTATUS RC
) // any NT error code we wish to log ...
581 // Implement a call to IoAllocateErrorLogEntry() followed by a call
582 // to IoWriteErrorLogEntry(). You should note that the call to IoWriteErrorLogEntry()
583 // will free memory for the entry once the write completes (which in actuality
584 // is an asynchronous operation).
586 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
587 // nothing really we can do here, just do not wish to crash ...
592 } // end UDFLogEvent()
595 /*************************************************************************
597 * Function: UDFAllocateObjectName()
600 * Allocate a new ObjectName structure to represent an open on-disk object.
601 * Also initialize the ObjectName structure to NULL.
603 * Expected Interrupt Level (for execution) :
607 * Return Value: A pointer to the ObjectName structure OR NULL.
609 *************************************************************************/
611 UDFAllocateObjectName(VOID
)
613 PtrUDFObjectName PtrObjectName
= NULL
;
614 BOOLEAN AllocatedFromZone
= TRUE
;
617 // first, __try to allocate out of the zone
618 KeAcquireSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
619 if (!ExIsFullZone(&(UDFGlobalData
.ObjectNameZoneHeader
))) {
620 // we have enough memory
621 PtrObjectName
= (PtrUDFObjectName
)ExAllocateFromZone(&(UDFGlobalData
.ObjectNameZoneHeader
));
623 // release the spinlock
624 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
626 // release the spinlock
627 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
629 // if we failed to obtain from the zone, get it directly from the VMM
630 PtrObjectName
= (PtrUDFObjectName
)MyAllocatePool__(NonPagedPool
, UDFQuadAlign(sizeof(UDFObjectName
)));
631 AllocatedFromZone
= FALSE
;
634 if (!PtrObjectName
) {
638 // zero out the allocated memory block
639 RtlZeroMemory(PtrObjectName
, UDFQuadAlign(sizeof(UDFObjectName
)));
641 // set up some fields ...
642 PtrObjectName
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_OBJECT_NAME
;
643 PtrObjectName
->NodeIdentifier
.NodeSize
= UDFQuadAlign(sizeof(UDFObjectName
));
646 if (!AllocatedFromZone
) {
647 UDFSetFlag(PtrObjectName
->ObjectNameFlags
, UDF_OBJ_NAME_NOT_FROM_ZONE
);
650 return(PtrObjectName
);
651 } // end UDFAllocateObjectName()
654 /*************************************************************************
656 * Function: UDFReleaseObjectName()
659 * Deallocate a previously allocated structure.
661 * Expected Interrupt Level (for execution) :
667 *************************************************************************/
670 UDFReleaseObjectName(
671 PtrUDFObjectName PtrObjectName
)
675 ASSERT(PtrObjectName
);
677 // give back memory either to the zone or to the VMM
678 if (!(PtrObjectName
->ObjectNameFlags
& UDF_OBJ_NAME_NOT_FROM_ZONE
)) {
680 KeAcquireSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
681 ExFreeToZone(&(UDFGlobalData
.ObjectNameZoneHeader
), PtrObjectName
);
682 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
684 MyFreePool__(PtrObjectName
);
688 } // end UDFReleaseObjectName()
691 /*************************************************************************
693 * Function: UDFAllocateCCB()
696 * Allocate a new CCB structure to represent an open on-disk object.
697 * Also initialize the CCB structure to NULL.
699 * Expected Interrupt Level (for execution) :
703 * Return Value: A pointer to the CCB structure OR NULL.
705 *************************************************************************/
709 PtrUDFCCB Ccb
= NULL
;
710 BOOLEAN AllocatedFromZone
= TRUE
;
713 // first, __try to allocate out of the zone
714 KeAcquireSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
715 if (!ExIsFullZone(&(UDFGlobalData
.CCBZoneHeader
))) {
716 // we have enough memory
717 Ccb
= (PtrUDFCCB
)ExAllocateFromZone(&(UDFGlobalData
.CCBZoneHeader
));
719 // release the spinlock
720 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
722 // release the spinlock
723 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
725 // if we failed to obtain from the zone, get it directly from the VMM
726 Ccb
= (PtrUDFCCB
)MyAllocatePool__(NonPagedPool
, UDFQuadAlign(sizeof(UDFCCB
)));
727 AllocatedFromZone
= FALSE
;
728 // UDFPrint((" CCB allocated @%x\n",Ccb));
735 // zero out the allocated memory block
736 RtlZeroMemory(Ccb
, UDFQuadAlign(sizeof(UDFCCB
)));
738 // set up some fields ...
739 Ccb
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_CCB
;
740 Ccb
->NodeIdentifier
.NodeSize
= UDFQuadAlign(sizeof(UDFCCB
));
743 if (!AllocatedFromZone
) {
744 UDFSetFlag(Ccb
->CCBFlags
, UDF_CCB_NOT_FROM_ZONE
);
747 UDFPrint(("UDFAllocateCCB: %x\n", Ccb
));
749 } // end UDFAllocateCCB()
752 /*************************************************************************
754 * Function: UDFReleaseCCB()
757 * Deallocate a previously allocated structure.
759 * Expected Interrupt Level (for execution) :
765 *************************************************************************/
776 UDFPrint(("UDFReleaseCCB: %x\n", Ccb
));
777 // give back memory either to the zone or to the VMM
778 if(!(Ccb
->CCBFlags
& UDF_CCB_NOT_FROM_ZONE
)) {
780 KeAcquireSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
781 ExFreeToZone(&(UDFGlobalData
.CCBZoneHeader
), Ccb
);
782 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
788 } // end UDFReleaseCCB()
791 Function: UDFCleanupCCB()
794 Cleanup and deallocate a previously allocated structure.
796 Expected Interrupt Level (for execution) :
809 if(!Ccb
) return; // probably, we havn't allocated it...
810 ASSERT(Ccb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_CCB
);
814 UDFTouch(&(Ccb
->Fcb
->CcbListResource
));
815 UDFAcquireResourceExclusive(&(Ccb
->Fcb
->CcbListResource
),TRUE
);
816 RemoveEntryList(&(Ccb
->NextCCB
));
817 UDFReleaseResource(&(Ccb
->Fcb
->CcbListResource
));
822 if (Ccb
->DirectorySearchPattern
) {
823 if (Ccb
->DirectorySearchPattern
->Buffer
) {
824 MyFreePool__(Ccb
->DirectorySearchPattern
->Buffer
);
825 Ccb
->DirectorySearchPattern
->Buffer
= NULL
;
828 MyFreePool__(Ccb
->DirectorySearchPattern
);
829 Ccb
->DirectorySearchPattern
= NULL
;
833 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
836 } // end UDFCleanUpCCB()
838 /*************************************************************************
840 * Function: UDFAllocateFCB()
843 * Allocate a new FCB structure to represent an open on-disk object.
844 * Also initialize the FCB structure to NULL.
846 * Expected Interrupt Level (for execution) :
850 * Return Value: A pointer to the FCB structure OR NULL.
852 *************************************************************************/
856 PtrUDFFCB Fcb
= NULL
;
858 Fcb
= (PtrUDFFCB
)MyAllocatePool__(UDF_FCB_MT
, UDFQuadAlign(sizeof(UDFFCB
)));
864 // zero out the allocated memory block
865 RtlZeroMemory(Fcb
, UDFQuadAlign(sizeof(UDFFCB
)));
867 // set up some fields ...
868 Fcb
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_FCB
;
869 Fcb
->NodeIdentifier
.NodeSize
= UDFQuadAlign(sizeof(UDFFCB
));
871 UDFPrint(("UDFAllocateFCB: %x\n", Fcb
));
873 } // end UDFAllocateFCB()
876 /*************************************************************************
878 * Function: UDFReleaseFCB()
881 * Deallocate a previously allocated structure.
883 * Expected Interrupt Level (for execution) :
889 *************************************************************************/
902 /*************************************************************************
905 *************************************************************************/
912 UDFPrint(("UDFCleanUpFCB: %x\n", Fcb
));
915 ASSERT(Fcb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_FCB
);
918 // Deinitialize FCBName field
920 if(Fcb
->FCBName
->ObjectName
.Buffer
) {
921 MyFreePool__(Fcb
->FCBName
->ObjectName
.Buffer
);
922 Fcb
->FCBName
->ObjectName
.Buffer
= NULL
;
924 Fcb
->FCBName
->ObjectName
.Length
=
925 Fcb
->FCBName
->ObjectName
.MaximumLength
= 0;
930 UDFPrint(("UDF: Fcb has invalid FCBName Buffer\n"));
934 UDFReleaseObjectName(Fcb
->FCBName
);
939 UDFPrint(("UDF: Fcb has invalid FCBName field\n"));
945 // begin transaction {
946 UDFTouch(&(Fcb
->Vcb
->FcbListResource
));
947 UDFAcquireResourceExclusive(&(Fcb
->Vcb
->FcbListResource
), TRUE
);
948 // Remove this FCB from list of all FCB in VCB
949 RemoveEntryList(&(Fcb
->NextFCB
));
950 UDFReleaseResource(&(Fcb
->Vcb
->FcbListResource
));
953 if(Fcb
->FCBFlags
& UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE
)
954 UDFDeleteResource(&(Fcb
->CcbListResource
));
958 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
961 } // end UDFCleanUpFCB()
964 ULONG IrpContextCounter
= 0;
967 /*************************************************************************
969 * Function: UDFAllocateIrpContext()
972 * The UDF FSD creates an IRP context for each request received. This
973 * routine simply allocates (and initializes to NULL) a UDFIrpContext
975 * Most of the fields in the context structure are then initialized here.
977 * Expected Interrupt Level (for execution) :
981 * Return Value: A pointer to the IrpContext structure OR NULL.
983 *************************************************************************/
985 UDFAllocateIrpContext(
987 PDEVICE_OBJECT PtrTargetDeviceObject
990 PtrUDFIrpContext PtrIrpContext
= NULL
;
991 BOOLEAN AllocatedFromZone
= TRUE
;
993 PIO_STACK_LOCATION IrpSp
= NULL
;
995 // first, __try to allocate out of the zone
996 KeAcquireSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
997 if (!ExIsFullZone(&(UDFGlobalData
.IrpContextZoneHeader
))) {
998 // we have enough memory
999 PtrIrpContext
= (PtrUDFIrpContext
)ExAllocateFromZone(&(UDFGlobalData
.IrpContextZoneHeader
));
1001 // release the spinlock
1002 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
1004 // release the spinlock
1005 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
1007 // if we failed to obtain from the zone, get it directly from the VMM
1008 PtrIrpContext
= (PtrUDFIrpContext
)MyAllocatePool__(NonPagedPool
, UDFQuadAlign(sizeof(UDFIrpContext
)));
1009 AllocatedFromZone
= FALSE
;
1012 // if we could not obtain the required memory, bug-check.
1013 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
1014 if (!PtrIrpContext
) {
1019 IrpContextCounter
++;
1022 // zero out the allocated memory block
1023 RtlZeroMemory(PtrIrpContext
, UDFQuadAlign(sizeof(UDFIrpContext
)));
1025 // set up some fields ...
1026 PtrIrpContext
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_IRP_CONTEXT
;
1027 PtrIrpContext
->NodeIdentifier
.NodeSize
= UDFQuadAlign(sizeof(UDFIrpContext
));
1030 PtrIrpContext
->Irp
= Irp
;
1031 PtrIrpContext
->TargetDeviceObject
= PtrTargetDeviceObject
;
1033 // copy over some fields from the IRP and set appropriate flag values
1035 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1038 PtrIrpContext
->MajorFunction
= IrpSp
->MajorFunction
;
1039 PtrIrpContext
->MinorFunction
= IrpSp
->MinorFunction
;
1041 // Often, a FSD cannot honor a request for asynchronous processing
1042 // of certain critical requests. For example, a "close" request on
1043 // a file object can typically never be deferred. Therefore, do not
1044 // be surprised if sometimes our FSD (just like all other FSD
1045 // implementations on the Windows NT system) has to override the flag
1047 if (IrpSp
->FileObject
== NULL
) {
1048 PtrIrpContext
->IrpContextFlags
|= UDF_IRP_CONTEXT_CAN_BLOCK
;
1050 if (IoIsOperationSynchronous(Irp
)) {
1051 PtrIrpContext
->IrpContextFlags
|= UDF_IRP_CONTEXT_CAN_BLOCK
;
1056 if (!AllocatedFromZone
) {
1057 UDFSetFlag(PtrIrpContext
->IrpContextFlags
, UDF_IRP_CONTEXT_NOT_FROM_ZONE
);
1060 // Are we top-level ? This information is used by the dispatching code
1061 // later (and also by the FSD dispatch routine)
1062 if (IoGetTopLevelIrp() != Irp
) {
1063 // We are not top-level. Note this fact in the context structure
1064 UDFSetFlag(PtrIrpContext
->IrpContextFlags
, UDF_IRP_CONTEXT_NOT_TOP_LEVEL
);
1067 return(PtrIrpContext
);
1068 } // end UDFAllocateIrpContext()
1071 /*************************************************************************
1073 * Function: UDFReleaseIrpContext()
1076 * Deallocate a previously allocated structure.
1078 * Expected Interrupt Level (for execution) :
1080 * IRQL_PASSIVE_LEVEL
1082 * Return Value: None
1084 *************************************************************************/
1086 UDFReleaseIrpContext(
1087 PtrUDFIrpContext PtrIrpContext
)
1089 if(!PtrIrpContext
) return;
1090 // ASSERT(PtrIrpContext);
1093 IrpContextCounter
--;
1096 // give back memory either to the zone or to the VMM
1097 if (!(PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_NOT_FROM_ZONE
)) {
1101 KeAcquireSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
1102 ExFreeToZone(&(UDFGlobalData
.IrpContextZoneHeader
), PtrIrpContext
);
1103 KeReleaseSpinLock(&(UDFGlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
1105 MyFreePool__(PtrIrpContext
);
1109 } // end UDFReleaseIrpContext()
1112 /*************************************************************************
1114 * Function: UDFPostRequest()
1117 * Queue up a request for deferred processing (in the context of a system
1118 * worker thread). The caller must have locked the user buffer (if required)
1120 * Expected Interrupt Level (for execution) :
1122 * IRQL_PASSIVE_LEVEL
1124 * Return Value: STATUS_PENDING
1126 *************************************************************************/
1129 IN PtrUDFIrpContext PtrIrpContext
,
1134 // PIO_STACK_LOCATION IrpSp;
1137 // IrpSp = IoGetCurrentIrpStackLocation(Irp);
1140 if(Vcb->StopOverflowQueue) {
1142 Irp->IoStatus.Status = STATUS_WRONG_VOLUME;
1143 Irp->IoStatus.Information = 0;
1144 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
1146 UDFReleaseIrpContext(PtrIrpContext);
1147 return STATUS_WRONG_VOLUME;
1150 // mark the IRP pending if this is not double post
1152 IoMarkIrpPending(Irp
);
1154 Vcb
= (PVCB
)(PtrIrpContext
->TargetDeviceObject
->DeviceExtension
);
1155 KeAcquireSpinLock(&(Vcb
->OverflowQueueSpinLock
), &SavedIrql
);
1157 if ( Vcb
->PostedRequestCount
> FSP_PER_DEVICE_THRESHOLD
) {
1159 // We cannot currently respond to this IRP so we'll just enqueue it
1160 // to the overflow queue on the volume.
1161 // Note: we just reuse LIST_ITEM field inside WorkQueueItem, this
1162 // doesn't matter to regular processing of WorkItems.
1163 InsertTailList( &(Vcb
->OverflowQueue
),
1164 &(PtrIrpContext
->WorkQueueItem
.List
) );
1165 Vcb
->OverflowQueueCount
++;
1166 KeReleaseSpinLock( &(Vcb
->OverflowQueueSpinLock
), SavedIrql
);
1170 // We are going to send this Irp to an ex worker thread so up
1172 Vcb
->PostedRequestCount
++;
1174 KeReleaseSpinLock( &(Vcb
->OverflowQueueSpinLock
), SavedIrql
);
1176 // queue up the request
1177 ExInitializeWorkItem(&(PtrIrpContext
->WorkQueueItem
), UDFCommonDispatch
, PtrIrpContext
);
1179 ExQueueWorkItem(&(PtrIrpContext
->WorkQueueItem
), CriticalWorkQueue
);
1180 // ExQueueWorkItem(&(PtrIrpContext->WorkQueueItem), DelayedWorkQueue);
1184 // return status pending
1185 return STATUS_PENDING
;
1186 } // end UDFPostRequest()
1189 /*************************************************************************
1191 * Function: UDFCommonDispatch()
1194 * The common dispatch routine invoked in the context of a system worker
1195 * thread. All we do here is pretty much case off the major function
1196 * code and invoke the appropriate FSD dispatch routine for further
1199 * Expected Interrupt Level (for execution) :
1201 * IRQL PASSIVE_LEVEL
1203 * Return Value: None
1205 *************************************************************************/
1209 IN PVOID Context
// actually is a pointer to IRPContext structure
1212 NTSTATUS RC
= STATUS_SUCCESS
;
1213 PtrUDFIrpContext PtrIrpContext
= NULL
;
1218 BOOLEAN SpinLock
= FALSE
;
1220 // The context must be a pointer to an IrpContext structure
1221 PtrIrpContext
= (PtrUDFIrpContext
)Context
;
1223 // Assert that the Context is legitimate
1224 if ( !PtrIrpContext
||
1225 (PtrIrpContext
->NodeIdentifier
.NodeType
!= UDF_NODE_TYPE_IRP_CONTEXT
) ||
1226 (PtrIrpContext
->NodeIdentifier
.NodeSize
!= UDFQuadAlign(sizeof(UDFIrpContext
))) /*||
1227 !(PtrIrpContext->Irp)*/) {
1228 UDFPrint((" Invalid Context\n"));
1233 Vcb
= (PVCB
)(PtrIrpContext
->TargetDeviceObject
->DeviceExtension
);
1236 UDFPrint((" *** Thr: %x ThCnt: %x QCnt: %x Started!\n", PsGetCurrentThread(), Vcb
->PostedRequestCount
, Vcb
->OverflowQueueCount
));
1240 UDFPrint((" Next IRP\n"));
1241 FsRtlEnterFileSystem();
1243 // Get a pointer to the IRP structure
1244 // in some cases we can get Zero pointer to Irp
1245 Irp
= PtrIrpContext
->Irp
;
1246 // Now, check if the FSD was top level when the IRP was originally invoked
1247 // and set the thread context (for the worker thread) appropriately
1248 if (PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_NOT_TOP_LEVEL
) {
1249 // The FSD is not top level for the original request
1250 // Set a constant value in TLS to reflect this fact
1251 IoSetTopLevelIrp((PIRP
)FSRTL_FSP_TOP_LEVEL_IRP
);
1253 IoSetTopLevelIrp(Irp
);
1256 // Since the FSD routine will now be invoked in the context of this worker
1257 // thread, we should inform the FSD that it is perfectly OK to block in
1258 // the context of this thread
1259 PtrIrpContext
->IrpContextFlags
|= UDF_IRP_CONTEXT_CAN_BLOCK
;
1263 // Pre-processing has been completed; check the Major Function code value
1264 // either in the IrpContext (copied from the IRP), or directly from the
1265 // IRP itself (we will need a pointer to the stack location to do that),
1266 // Then, switch based on the value on the Major Function code
1267 UDFPrint((" *** MJ: %x, Thr: %x\n", PtrIrpContext
->MajorFunction
, PsGetCurrentThread()));
1268 switch (PtrIrpContext
->MajorFunction
) {
1270 // Invoke the common create routine
1271 RC
= UDFCommonCreate(PtrIrpContext
, Irp
);
1274 // Invoke the common read routine
1275 RC
= UDFCommonRead(PtrIrpContext
, Irp
);
1277 #ifndef UDF_READ_ONLY_BUILD
1279 // Invoke the common write routine
1280 RC
= UDFCommonWrite(PtrIrpContext
, Irp
);
1282 #endif //UDF_READ_ONLY_BUILD
1283 case IRP_MJ_CLEANUP
:
1284 // Invoke the common cleanup routine
1285 RC
= UDFCommonCleanup(PtrIrpContext
, Irp
);
1288 // Invoke the common close routine
1289 RC
= UDFCommonClose(PtrIrpContext
, Irp
);
1291 case IRP_MJ_DIRECTORY_CONTROL
:
1292 // Invoke the common directory control routine
1293 RC
= UDFCommonDirControl(PtrIrpContext
, Irp
);
1295 case IRP_MJ_QUERY_INFORMATION
:
1296 #ifndef UDF_READ_ONLY_BUILD
1297 case IRP_MJ_SET_INFORMATION
:
1298 #endif //UDF_READ_ONLY_BUILD
1299 // Invoke the common query/set information routine
1300 RC
= UDFCommonFileInfo(PtrIrpContext
, Irp
);
1302 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
1303 // Invoke the common query volume routine
1304 RC
= UDFCommonQueryVolInfo(PtrIrpContext
, Irp
);
1306 #ifndef UDF_READ_ONLY_BUILD
1307 case IRP_MJ_SET_VOLUME_INFORMATION
:
1308 // Invoke the common query volume routine
1309 RC
= UDFCommonSetVolInfo(PtrIrpContext
, Irp
);
1311 #endif //UDF_READ_ONLY_BUILD
1312 #ifdef UDF_HANDLE_EAS
1313 /* case IRP_MJ_QUERY_EA:
1314 // Invoke the common query EAs routine
1315 RC = UDFCommonGetExtendedAttr(PtrIrpContext, Irp);
1318 // Invoke the common set EAs routine
1319 RC = UDFCommonSetExtendedAttr(PtrIrpContext, Irp);
1321 #endif // UDF_HANDLE_EAS
1322 #ifdef UDF_ENABLE_SECURITY
1323 case IRP_MJ_QUERY_SECURITY
:
1324 // Invoke the common query Security routine
1325 RC
= UDFCommonGetSecurity(PtrIrpContext
, Irp
);
1327 #ifndef UDF_READ_ONLY_BUILD
1328 case IRP_MJ_SET_SECURITY
:
1329 // Invoke the common set Security routine
1330 RC
= UDFCommonSetSecurity(PtrIrpContext
, Irp
);
1332 #endif //UDF_READ_ONLY_BUILD
1333 #endif // UDF_ENABLE_SECURITY
1334 // Continue with the remaining possible dispatch routines below ...
1336 UDFPrint((" unhandled *** MJ: %x, Thr: %x\n", PtrIrpContext
->MajorFunction
, PsGetCurrentThread()));
1337 // This is the case where we have an invalid major function
1338 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1339 Irp
->IoStatus
.Information
= 0;
1341 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1342 // Free up the Irp Context
1343 UDFReleaseIrpContext(PtrIrpContext
);
1347 // Note: PtrIrpContext is invalid here
1348 UDFPrint((" *** Thr: %x Done!\n", PsGetCurrentThread()));
1350 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
1352 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
1354 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
1357 // Enable preemption
1358 FsRtlExitFileSystem();
1360 // Ensure that the "top-level" field is cleared
1361 IoSetTopLevelIrp(NULL
);
1363 // If there are any entries on this volume's overflow queue, service
1370 KeAcquireSpinLock(&(Vcb
->OverflowQueueSpinLock
), &SavedIrql
);
1372 if(!Vcb
->OverflowQueueCount
)
1375 Vcb
->OverflowQueueCount
--;
1376 Entry
= RemoveHeadList(&Vcb
->OverflowQueue
);
1377 KeReleaseSpinLock(&(Vcb
->OverflowQueueSpinLock
), SavedIrql
);
1380 PtrIrpContext
= CONTAINING_RECORD( Entry
,
1382 WorkQueueItem
.List
);
1386 KeAcquireSpinLock(&(Vcb
->OverflowQueueSpinLock
), &SavedIrql
);
1387 Vcb
->PostedRequestCount
--;
1388 KeReleaseSpinLock(&(Vcb
->OverflowQueueSpinLock
), SavedIrql
);
1390 UDFPrint((" *** Thr: %x ThCnt: %x QCnt: %x Terminated!\n", PsGetCurrentThread(), Vcb
->PostedRequestCount
, Vcb
->OverflowQueueCount
));
1393 } // end UDFCommonDispatch()
1396 /*************************************************************************
1398 * Function: UDFInitializeVCB()
1401 * Perform the initialization for a VCB structure.
1403 * Expected Interrupt Level (for execution) :
1405 * IRQL PASSIVE_LEVEL
1407 * Return Value: status
1409 *************************************************************************/
1412 IN PDEVICE_OBJECT PtrVolumeDeviceObject
,
1413 IN PDEVICE_OBJECT PtrTargetDeviceObject
,
1417 NTSTATUS RC
= STATUS_SUCCESS
;
1421 BOOLEAN VCBResourceInit
= FALSE
;
1422 BOOLEAN BitMapResource1Init
= FALSE
;
1423 BOOLEAN FcbListResourceInit
= FALSE
;
1424 BOOLEAN FileIdResourceInit
= FALSE
;
1425 BOOLEAN DlocResourceInit
= FALSE
;
1426 BOOLEAN DlocResource2Init
= FALSE
;
1427 BOOLEAN FlushResourceInit
= FALSE
;
1428 BOOLEAN PreallocResourceInit
= FALSE
;
1429 BOOLEAN IoResourceInit
= FALSE
;
1431 Vcb
= (PVCB
)(PtrVolumeDeviceObject
->DeviceExtension
);
1434 // Zero it out (typically this has already been done by the I/O
1435 // Manager but it does not hurt to do it again)!
1436 RtlZeroMemory(Vcb
, sizeof(VCB
));
1438 // Initialize the signature fields
1439 Vcb
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_VCB
;
1440 Vcb
->NodeIdentifier
.NodeSize
= sizeof(VCB
);
1442 // Initialize the ERESOURCE object.
1443 RC
= UDFInitializeResourceLite(&(Vcb
->VCBResource
));
1446 VCBResourceInit
= TRUE
;
1448 RC
= UDFInitializeResourceLite(&(Vcb
->BitMapResource1
));
1451 BitMapResource1Init
= TRUE
;
1453 RC
= UDFInitializeResourceLite(&(Vcb
->FcbListResource
));
1456 FcbListResourceInit
= TRUE
;
1458 RC
= UDFInitializeResourceLite(&(Vcb
->FileIdResource
));
1461 FileIdResourceInit
= TRUE
;
1463 RC
= UDFInitializeResourceLite(&(Vcb
->DlocResource
));
1466 DlocResourceInit
= TRUE
;
1468 RC
= UDFInitializeResourceLite(&(Vcb
->DlocResource2
));
1471 DlocResource2Init
= TRUE
;
1473 RC
= UDFInitializeResourceLite(&(Vcb
->FlushResource
));
1476 FlushResourceInit
= TRUE
;
1478 RC
= UDFInitializeResourceLite(&(Vcb
->PreallocResource
));
1481 PreallocResourceInit
= TRUE
;
1483 RC
= UDFInitializeResourceLite(&(Vcb
->IoResource
));
1486 IoResourceInit
= TRUE
;
1488 // RC = UDFInitializeResourceLite(&(Vcb->DelayedCloseResource));
1489 // ASSERT(NT_SUCCESS(RC));
1491 // Allocate buffer for statistics
1492 Vcb
->Statistics
= (PFILE_SYSTEM_STATISTICS
)MyAllocatePool__(NonPagedPool
, sizeof(FILE_SYSTEM_STATISTICS
) * KeNumberProcessors
);
1493 if(!Vcb
->Statistics
)
1494 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
1495 RtlZeroMemory( Vcb
->Statistics
, sizeof(FILE_SYSTEM_STATISTICS
) * KeNumberProcessors
);
1496 for (i
=0; i
< (KeNumberProcessors
); i
++) {
1497 Vcb
->Statistics
[i
].Common
.FileSystemType
= FILESYSTEM_STATISTICS_TYPE_NTFS
;
1498 Vcb
->Statistics
[i
].Common
.Version
= 1;
1499 Vcb
->Statistics
[i
].Common
.SizeOfCompleteStructure
=
1500 sizeof(FILE_SYSTEM_STATISTICS
);
1503 // We know the target device object.
1504 // Note that this is not neccessarily a pointer to the actual
1505 // physical/virtual device on which the logical volume should
1506 // be mounted. This is actually a pointer to either the actual
1507 // (real) device or to any device object that may have been
1508 // attached to it. Any IRPs that we send down should be sent to this
1509 // device object. However, the "real" physical/virtual device object
1510 // on which we perform our mount operation can be determined from the
1511 // RealDevice field in the VPB sent to us.
1512 Vcb
->TargetDeviceObject
= PtrTargetDeviceObject
;
1514 // We also have a pointer to the newly created device object representing
1515 // this logical volume (remember that this VCB structure is simply an
1516 // extension of the created device object).
1517 Vcb
->VCBDeviceObject
= PtrVolumeDeviceObject
;
1519 // We also have the VPB pointer. This was obtained from the
1520 // Parameters.MountVolume.Vpb field in the current I/O stack location
1521 // for the mount IRP.
1523 // Target Vcb field in Vcb onto itself. This required for check in
1524 // open/lock/unlock volume dispatch poits
1527 // Set the removable media flag based on the real device's
1529 if (PtrVPB
->RealDevice
->Characteristics
& FILE_REMOVABLE_MEDIA
) {
1530 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_REMOVABLE_MEDIA
;
1533 // Initialize the list anchor (head) for some lists in this VCB.
1534 InitializeListHead(&(Vcb
->NextFCB
));
1535 InitializeListHead(&(Vcb
->NextNotifyIRP
));
1536 InitializeListHead(&(Vcb
->VolumeOpenListHead
));
1538 // Initialize the overflow queue for the volume
1539 Vcb
->OverflowQueueCount
= 0;
1540 InitializeListHead(&(Vcb
->OverflowQueue
));
1542 Vcb
->PostedRequestCount
= 0;
1543 KeInitializeSpinLock(&(Vcb
->OverflowQueueSpinLock
));
1545 // Initialize the notify IRP list mutex
1546 FsRtlNotifyInitializeSync(&(Vcb
->NotifyIRPMutex
));
1548 // Intilize NtRequiredFCB for this VCB
1549 Vcb
->NTRequiredFCB
= (PtrUDFNTRequiredFCB
)MyAllocatePool__(NonPagedPool
, UDFQuadAlign(sizeof(UDFNTRequiredFCB
)));
1550 if(!Vcb
->NTRequiredFCB
)
1551 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
1552 RtlZeroMemory(Vcb
->NTRequiredFCB
, UDFQuadAlign(sizeof(UDFNTRequiredFCB
)));
1554 // Set the initial file size values appropriately. Note that our FSD may
1555 // wish to guess at the initial amount of information we would like to
1556 // read from the disk until we have really determined that this a valid
1557 // logical volume (on disk) that we wish to mount.
1558 // Vcb->FileSize = Vcb->AllocationSize = ??
1560 // We do not want to bother with valid data length callbacks
1561 // from the Cache Manager for the file stream opened for volume metadata
1563 Vcb
->NTRequiredFCB
->CommonFCBHeader
.ValidDataLength
.QuadPart
= 0x7FFFFFFFFFFFFFFFULL
;
1565 Vcb
->VolumeLockPID
= -1;
1567 Vcb
->VCBOpenCount
= 1;
1569 Vcb
->WCacheMaxBlocks
= UDFGlobalData
.WCacheMaxBlocks
;
1570 Vcb
->WCacheMaxFrames
= UDFGlobalData
.WCacheMaxFrames
;
1571 Vcb
->WCacheBlocksPerFrameSh
= UDFGlobalData
.WCacheBlocksPerFrameSh
;
1572 Vcb
->WCacheFramesToKeepFree
= UDFGlobalData
.WCacheFramesToKeepFree
;
1574 // Create a stream file object for this volume.
1575 //Vcb->PtrStreamFileObject = IoCreateStreamFileObject(NULL,
1576 // Vcb->Vpb->RealDevice);
1577 //ASSERT(Vcb->PtrStreamFileObject);
1579 // Initialize some important fields in the newly created file object.
1580 //Vcb->PtrStreamFileObject->FsContext = (PVOID)Vcb;
1581 //Vcb->PtrStreamFileObject->FsContext2 = NULL;
1582 //Vcb->PtrStreamFileObject->SectionObjectPointer = &(Vcb->SectionObject);
1584 //Vcb->PtrStreamFileObject->Vpb = PtrVPB;
1586 // Link this chap onto the global linked list of all VCB structures.
1587 // We consider that GlobalDataResource was acquired in past
1588 UDFAcquireResourceExclusive(&(UDFGlobalData
.GlobalDataResource
), TRUE
);
1589 InsertTailList(&(UDFGlobalData
.VCBQueue
), &(Vcb
->NextVCB
));
1591 Vcb
->TargetDevName
.Buffer
= (PWCHAR
)MyAllocatePool__(NonPagedPool
, sizeof(MOUNTDEV_NAME
));
1592 if(!Vcb
->TargetDevName
.Buffer
)
1593 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
1595 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_DEVICE_NAME
/*IOCTL_MOUNTDEV_QUERY_DEVICE_NAME*/, Vcb
->TargetDeviceObject
,
1597 (PVOID
)(Vcb
->TargetDevName
.Buffer
),sizeof(MOUNTDEV_NAME
),
1599 if(!NT_SUCCESS(RC
)) {
1601 if(RC
== STATUS_BUFFER_OVERFLOW
) {
1602 if(!MyReallocPool__((PCHAR
)(Vcb
->TargetDevName
.Buffer
), sizeof(MOUNTDEV_NAME
),
1603 (PCHAR
*)&(Vcb
->TargetDevName
.Buffer
), Vcb
->TargetDevName
.Buffer
[0]+sizeof(MOUNTDEV_NAME
)) ) {
1604 goto Kill_DevName_buffer
;
1607 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_DEVICE_NAME
/*IOCTL_MOUNTDEV_QUERY_DEVICE_NAME*/, Vcb
->TargetDeviceObject
,
1609 (PVOID
)(Vcb
->TargetDevName
.Buffer
), Vcb
->TargetDevName
.Buffer
[0]+sizeof(MOUNTDEV_NAME
),
1612 goto Kill_DevName_buffer
;
1615 Kill_DevName_buffer
:
1616 if(!MyReallocPool__((PCHAR
)Vcb
->TargetDevName
.Buffer
, sizeof(MOUNTDEV_NAME
),
1617 (PCHAR
*)&(Vcb
->TargetDevName
.Buffer
), sizeof(REG_NAMELESS_DEV
)))
1618 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
1619 RtlCopyMemory(Vcb
->TargetDevName
.Buffer
, REG_NAMELESS_DEV
, sizeof(REG_NAMELESS_DEV
));
1620 Vcb
->TargetDevName
.Length
= sizeof(REG_NAMELESS_DEV
)-sizeof(WCHAR
);
1621 Vcb
->TargetDevName
.MaximumLength
= sizeof(REG_NAMELESS_DEV
);
1626 Vcb
->TargetDevName
.MaximumLength
=
1627 (Vcb
->TargetDevName
.Length
= Vcb
->TargetDevName
.Buffer
[0]) + sizeof(WCHAR
);
1628 RtlMoveMemory((PVOID
)(Vcb
->TargetDevName
.Buffer
), (PVOID
)(Vcb
->TargetDevName
.Buffer
+1), Vcb
->TargetDevName
.Buffer
[0]);
1629 Vcb
->TargetDevName
.Buffer
[i
= (SHORT
)(Vcb
->TargetDevName
.Length
/sizeof(WCHAR
))] = 0;
1632 if(Vcb
->TargetDevName
.Buffer
[i
] == L
'\\') {
1634 Vcb
->TargetDevName
.Length
-= i
*sizeof(WCHAR
);
1635 RtlMoveMemory((PVOID
)(Vcb
->TargetDevName
.Buffer
), (PVOID
)(Vcb
->TargetDevName
.Buffer
+i
), Vcb
->TargetDevName
.Length
);
1636 Vcb
->TargetDevName
.Buffer
[Vcb
->TargetDevName
.Length
/sizeof(WCHAR
)] = 0;
1641 UDFPrint((" TargetDevName: %S\n", Vcb
->TargetDevName
.Buffer
));
1643 // Initialize caching for the stream file object.
1644 //CcInitializeCacheMap(Vcb->PtrStreamFileObject, (PCC_FILE_SIZES)(&(Vcb->AllocationSize)),
1645 // TRUE, // We will use pinned access.
1646 // &(UDFGlobalData.CacheMgrCallBacks), Vcb);
1650 UDFReleaseResource(&(UDFGlobalData
.GlobalDataResource
));
1652 // Mark the fact that this VCB structure is initialized.
1653 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VCB_INITIALIZED
;
1655 RC
= STATUS_SUCCESS
;
1661 if(!NT_SUCCESS(RC
)) {
1662 if(Vcb
->TargetDevName
.Buffer
)
1663 MyFreePool__(Vcb
->TargetDevName
.Buffer
);
1664 if(Vcb
->NTRequiredFCB
)
1665 MyFreePool__(Vcb
->NTRequiredFCB
);
1667 MyFreePool__(Vcb
->Statistics
);
1670 UDFDeleteResource(&(Vcb
->VCBResource
));
1671 if(BitMapResource1Init
)
1672 UDFDeleteResource(&(Vcb
->BitMapResource1
));
1673 if(FcbListResourceInit
)
1674 UDFDeleteResource(&(Vcb
->FcbListResource
));
1675 if(FileIdResourceInit
)
1676 UDFDeleteResource(&(Vcb
->FileIdResource
));
1677 if(DlocResourceInit
)
1678 UDFDeleteResource(&(Vcb
->DlocResource
));
1679 if(DlocResource2Init
)
1680 UDFDeleteResource(&(Vcb
->DlocResource2
));
1681 if(FlushResourceInit
)
1682 UDFDeleteResource(&(Vcb
->FlushResource
));
1683 if(PreallocResourceInit
)
1684 UDFDeleteResource(&(Vcb
->PreallocResource
));
1686 UDFDeleteResource(&(Vcb
->IoResource
));
1691 } // end UDFInitializeVCB()
1698 switch(Vcb
->FsDeviceType
) {
1699 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
1700 if(Vcb
->VCBFlags
& (UDF_VCB_FLAGS_VOLUME_READ_ONLY
|
1701 UDF_VCB_FLAGS_MEDIA_READ_ONLY
))
1705 if((Vcb
->MediaType
>= MediaType_UnknownSize_CDR
) &&
1706 (Vcb
->MediaType
< MediaType_UnknownSize_CDRW
)) {
1709 if((Vcb
->MediaType
>= MediaType_UnknownSize_CDRW
) &&
1710 (Vcb
->MediaType
< MediaType_UnknownSize_Unknown
)) {
1713 if(Vcb
->MediaClassEx
== CdMediaClass_CDR
) {
1716 if(Vcb
->MediaClassEx
== CdMediaClass_DVDR
||
1717 Vcb
->MediaClassEx
== CdMediaClass_DVDpR
||
1718 Vcb
->MediaClassEx
== CdMediaClass_HD_DVDR
||
1719 Vcb
->MediaClassEx
== CdMediaClass_BDR
) {
1722 if(Vcb
->MediaClassEx
== CdMediaClass_CDRW
) {
1725 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
1726 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
1727 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
||
1728 Vcb
->MediaClassEx
== CdMediaClass_HD_DVDRW
||
1729 Vcb
->MediaClassEx
== CdMediaClass_HD_DVDRAM
||
1730 Vcb
->MediaClassEx
== CdMediaClass_BDRE
) {
1734 if(Vcb
->MediaClassEx
== CdMediaClass_CDROM
||
1735 Vcb
->MediaClassEx
== CdMediaClass_DVDROM
||
1736 Vcb
->MediaClassEx
== CdMediaClass_HD_DVDROM
||
1737 Vcb
->MediaClassEx
== CdMediaClass_BDROM
) {
1741 #ifdef UDF_HDD_SUPPORT
1742 case FILE_DEVICE_DISK_FILE_SYSTEM
:
1743 if(Vcb
->TargetDeviceObject
->Characteristics
& FILE_FLOPPY_DISKETTE
)
1745 if(Vcb
->TargetDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
1748 #endif //UDF_HDD_SUPPORT
1750 return MediaUnknown
;
1751 } // end UDFGetMediaClass()
1754 (*ptrUDFGetParameter
)(
1761 UDFUpdateCompatOption(
1770 ptrUDFGetParameter UDFGetParameter
= UseCfg
? UDFGetCfgParameter
: UDFGetRegParameter
;
1772 if(UDFGetParameter(Vcb
, Name
, Update
? ((Vcb
->CompatFlags
& Flag
) ? TRUE
: FALSE
) : Default
)) {
1773 Vcb
->CompatFlags
|= Flag
;
1775 Vcb
->CompatFlags
&= ~Flag
;
1777 } // end UDFUpdateCompatOption()
1787 ptrUDFGetParameter UDFGetParameter
= UseCfg
? UDFGetCfgParameter
: UDFGetRegParameter
;
1789 Vcb
->DefaultRegName
= UDFMediaClassName
[(ULONG
)UDFGetMediaClass(Vcb
)].ClassName
;
1791 // Should we use Extended FE by default ?
1792 Vcb
->UseExtendedFE
= (UCHAR
)UDFGetParameter(Vcb
, REG_USEEXTENDEDFE_NAME
,
1793 Update
? Vcb
->UseExtendedFE
: FALSE
);
1794 if(Vcb
->UseExtendedFE
!= TRUE
) Vcb
->UseExtendedFE
= FALSE
;
1795 // What type of AllocDescs should we use
1796 Vcb
->DefaultAllocMode
= (USHORT
)UDFGetParameter(Vcb
, REG_DEFALLOCMODE_NAME
,
1797 Update
? Vcb
->DefaultAllocMode
: ICB_FLAG_AD_SHORT
);
1798 if(Vcb
->DefaultAllocMode
> ICB_FLAG_AD_LONG
) Vcb
->DefaultAllocMode
= ICB_FLAG_AD_SHORT
;
1799 // Default UID & GID to be set on newly created files
1800 Vcb
->DefaultUID
= UDFGetParameter(Vcb
, UDF_DEFAULT_UID_NAME
, Update
? Vcb
->DefaultUID
: -1);
1801 Vcb
->DefaultGID
= UDFGetParameter(Vcb
, UDF_DEFAULT_GID_NAME
, Update
? Vcb
->DefaultGID
: -1);
1802 // FE allocation charge for plain Dirs
1803 Vcb
->FECharge
= UDFGetParameter(Vcb
, UDF_FE_CHARGE_NAME
, Update
? Vcb
->FECharge
: 0);
1805 Vcb
->FECharge
= UDF_DEFAULT_FE_CHARGE
;
1806 // FE allocation charge for Stream Dirs (SDir)
1807 Vcb
->FEChargeSDir
= UDFGetParameter(Vcb
, UDF_FE_CHARGE_SDIR_NAME
,
1808 Update
? Vcb
->FEChargeSDir
: 0);
1809 if(!Vcb
->FEChargeSDir
)
1810 Vcb
->FEChargeSDir
= UDF_DEFAULT_FE_CHARGE_SDIR
;
1811 // How many Deleted entries should contain Directory to make us
1812 // start packing it.
1813 Vcb
->PackDirThreshold
= UDFGetParameter(Vcb
, UDF_DIR_PACK_THRESHOLD_NAME
,
1814 Update
? Vcb
->PackDirThreshold
: 0);
1815 if(Vcb
->PackDirThreshold
== 0xffffffff)
1816 Vcb
->PackDirThreshold
= UDF_DEFAULT_DIR_PACK_THRESHOLD
;
1817 // The binary exponent for the number of Pages to be read-ahead'ed
1818 // This information would be sent to System Cache Manager
1820 Vcb
->SystemCacheGran
= (1 << UDFGetParameter(Vcb
, UDF_READAHEAD_GRAN_NAME
, 0)) * PAGE_SIZE
;
1821 if(!Vcb
->SystemCacheGran
)
1822 Vcb
->SystemCacheGran
= UDF_DEFAULT_READAHEAD_GRAN
;
1824 // Timeouts for FreeSpaceBitMap & TheWholeDirTree flushes
1825 Vcb
->BM_FlushPriod
= UDFGetParameter(Vcb
, UDF_BM_FLUSH_PERIOD_NAME
,
1826 Update
? Vcb
->BM_FlushPriod
: 0);
1827 if(!Vcb
->BM_FlushPriod
) {
1828 Vcb
->BM_FlushPriod
= UDF_DEFAULT_BM_FLUSH_TIMEOUT
;
1830 if(Vcb
->BM_FlushPriod
== (ULONG
)-1) {
1831 Vcb
->BM_FlushPriod
= 0;
1833 Vcb
->Tree_FlushPriod
= UDFGetParameter(Vcb
, UDF_TREE_FLUSH_PERIOD_NAME
,
1834 Update
? Vcb
->Tree_FlushPriod
: 0);
1835 if(!Vcb
->Tree_FlushPriod
) {
1836 Vcb
->Tree_FlushPriod
= UDF_DEFAULT_TREE_FLUSH_TIMEOUT
;
1838 if(Vcb
->Tree_FlushPriod
== (ULONG
)-1) {
1839 Vcb
->Tree_FlushPriod
= 0;
1841 Vcb
->SkipCountLimit
= UDFGetParameter(Vcb
, UDF_NO_UPDATE_PERIOD_NAME
,
1842 Update
? Vcb
->SkipCountLimit
: 0);
1843 if(!Vcb
->SkipCountLimit
)
1844 Vcb
->SkipCountLimit
= -1;
1846 Vcb
->SkipEjectCountLimit
= UDFGetParameter(Vcb
, UDF_NO_EJECT_PERIOD_NAME
,
1847 Update
? Vcb
->SkipEjectCountLimit
: 3);
1850 // How many threads are allowed to sodomize Disc simultaneously on each CPU
1851 Vcb
->ThreadsPerCpu
= UDFGetParameter(Vcb
, UDF_FSP_THREAD_PER_CPU_NAME
,
1852 Update
? Vcb
->ThreadsPerCpu
: 2);
1853 if(Vcb
->ThreadsPerCpu
< 2)
1854 Vcb
->ThreadsPerCpu
= UDF_DEFAULT_FSP_THREAD_PER_CPU
;
1856 // The mimimum FileSize increment when we'll decide not to allocate
1858 Vcb
->SparseThreshold
= UDFGetParameter(Vcb
, UDF_SPARSE_THRESHOLD_NAME
,
1859 Update
? Vcb
->SparseThreshold
: 0);
1860 if(!Vcb
->SparseThreshold
)
1861 Vcb
->SparseThreshold
= UDF_DEFAULT_SPARSE_THRESHOLD
;
1862 // This option is used to VERIFY all the data written. It decreases performance
1863 Vcb
->VerifyOnWrite
= UDFGetParameter(Vcb
, UDF_VERIFY_ON_WRITE_NAME
,
1864 Update
? Vcb
->VerifyOnWrite
: FALSE
) ? TRUE
: FALSE
;
1866 #ifndef UDF_READ_ONLY_BUILD
1867 // Should we update AttrFileTime on Attr changes
1868 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_UPDATE_TIMES_ATTR
, UDF_VCB_IC_UPDATE_ATTR_TIME
, FALSE
);
1869 // Should we update ModifyFileTime on Writes changes
1870 // It also affects ARCHIVE bit setting on write operations
1871 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_UPDATE_TIMES_MOD
, UDF_VCB_IC_UPDATE_MODIFY_TIME
, FALSE
);
1872 // Should we update AccessFileTime on Exec & so on.
1873 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_UPDATE_TIMES_ACCS
, UDF_VCB_IC_UPDATE_ACCESS_TIME
, FALSE
);
1874 // Should we update Archive bit
1875 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_UPDATE_ATTR_ARCH
, UDF_VCB_IC_UPDATE_ARCH_BIT
, FALSE
);
1876 // Should we update Dir's Times & Attrs on Modify
1877 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_UPDATE_DIR_TIMES_ATTR_W
, UDF_VCB_IC_UPDATE_DIR_WRITE
, FALSE
);
1878 // Should we update Dir's Times & Attrs on Access
1879 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_UPDATE_DIR_TIMES_ATTR_R
, UDF_VCB_IC_UPDATE_DIR_READ
, FALSE
);
1880 // Should we allow user to write into Read-Only Directory
1881 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_ALLOW_WRITE_IN_RO_DIR
, UDF_VCB_IC_WRITE_IN_RO_DIR
, TRUE
);
1882 // Should we allow user to change Access Time for unchanged Directory
1883 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_ALLOW_UPDATE_TIMES_ACCS_UCHG_DIR
, UDF_VCB_IC_UPDATE_UCHG_DIR_ACCESS_TIME
, FALSE
);
1884 #endif //UDF_READ_ONLY_BUILD
1885 // Should we record Allocation Descriptors in W2k-compatible form
1886 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_W2K_COMPAT_ALLOC_DESCS
, UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS
, TRUE
);
1887 // Should we read LONG_ADs with invalid PartitionReferenceNumber (generated by Nero Instant Burner)
1888 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_INSTANT_COMPAT_ALLOC_DESCS
, UDF_VCB_IC_INSTANT_COMPAT_ALLOC_DESCS
, TRUE
);
1889 // Should we make a copy of VolumeLabel in LVD
1890 // usually only PVD is updated
1891 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_W2K_COMPAT_VLABEL
, UDF_VCB_IC_W2K_COMPAT_VLABEL
, TRUE
);
1892 // Should we handle or ignore HW_RO flag
1893 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_HANDLE_HW_RO
, UDF_VCB_IC_HW_RO
, FALSE
);
1894 // Should we handle or ignore SOFT_RO flag
1895 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_HANDLE_SOFT_RO
, UDF_VCB_IC_SOFT_RO
, TRUE
);
1897 // Check if we should generate UDF-style or OS-style DOS-names
1898 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_OS_NATIVE_DOS_NAME
, UDF_VCB_IC_OS_NATIVE_DOS_NAME
, FALSE
);
1899 #ifndef UDF_READ_ONLY_BUILD
1900 // should we force FO_WRITE_THROUGH on removable media
1901 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_FORCE_WRITE_THROUGH_NAME
, UDF_VCB_IC_FORCE_WRITE_THROUGH
,
1902 (Vcb
->TargetDeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) ? TRUE
: FALSE
1904 #endif //UDF_READ_ONLY_BUILD
1905 // Should we ignore FO_SEQUENTIAL_ONLY
1906 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_IGNORE_SEQUENTIAL_IO
, UDF_VCB_IC_IGNORE_SEQUENTIAL_IO
, FALSE
);
1907 // Force Read-only mounts
1908 #ifndef UDF_READ_ONLY_BUILD
1909 UDFUpdateCompatOption(Vcb
, Update
, UseCfg
, UDF_FORCE_HW_RO
, UDF_VCB_IC_FORCE_HW_RO
, FALSE
);
1910 #else //UDF_READ_ONLY_BUILD
1911 Vcb
->CompatFlags
|= UDF_VCB_IC_FORCE_HW_RO
;
1912 #endif //UDF_READ_ONLY_BUILD
1913 // Check if we should send FLUSH request for File/Dir down to
1914 // underlaying driver
1915 if(UDFGetParameter(Vcb
, UDF_FLUSH_MEDIA
,Update
? Vcb
->FlushMedia
: FALSE
)) {
1916 Vcb
->FlushMedia
= TRUE
;
1918 Vcb
->FlushMedia
= FALSE
;
1920 // compare data from packet with data to be writen there
1921 // before physical writing
1922 if(!UDFGetParameter(Vcb
, UDF_COMPARE_BEFORE_WRITE
, Update
? Vcb
->DoNotCompareBeforeWrite
: FALSE
)) {
1923 Vcb
->DoNotCompareBeforeWrite
= TRUE
;
1925 Vcb
->DoNotCompareBeforeWrite
= FALSE
;
1928 if(UDFGetParameter(Vcb
, UDF_CHAINED_IO
, TRUE
)) {
1929 Vcb
->CacheChainedIo
= TRUE
;
1932 if(UDFGetParameter(Vcb
, UDF_FORCE_MOUNT_ALL
, FALSE
)) {
1933 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
1935 // Should we show Blank.Cd file on damaged/unformatted,
1936 // but UDF-compatible disks
1937 Vcb
->ShowBlankCd
= (UCHAR
)UDFGetParameter(Vcb
, UDF_SHOW_BLANK_CD
, FALSE
);
1938 if(Vcb
->ShowBlankCd
) {
1939 Vcb
->CompatFlags
|= UDF_VCB_IC_SHOW_BLANK_CD
;
1940 if(Vcb
->ShowBlankCd
> 2) {
1941 Vcb
->ShowBlankCd
= 2;
1944 // Should we wait util CD device return from
1945 // Becoming Ready state
1946 if(UDFGetParameter(Vcb
, UDF_WAIT_CD_SPINUP
, TRUE
)) {
1947 Vcb
->CompatFlags
|= UDF_VCB_IC_WAIT_CD_SPINUP
;
1949 // Should we remenber bad VDS locations during mount
1950 // Caching will improve mount performance on bad disks, but
1951 // will degrade mauntability of unreliable discs
1952 if(UDFGetParameter(Vcb
, UDF_CACHE_BAD_VDS
, TRUE
)) {
1953 Vcb
->CompatFlags
|= UDF_VCB_IC_CACHE_BAD_VDS
;
1956 // Set partitially damaged volume mount mode
1957 Vcb
->PartitialDamagedVolumeAction
= (UCHAR
)UDFGetParameter(Vcb
, UDF_PART_DAMAGED_BEHAVIOR
, UDF_PART_DAMAGED_RW
);
1958 if(Vcb
->PartitialDamagedVolumeAction
> 2) {
1959 Vcb
->PartitialDamagedVolumeAction
= UDF_PART_DAMAGED_RW
;
1962 // Set partitially damaged volume mount mode
1963 Vcb
->NoFreeRelocationSpaceVolumeAction
= (UCHAR
)UDFGetParameter(Vcb
, UDF_NO_SPARE_BEHAVIOR
, UDF_PART_DAMAGED_RW
);
1964 if(Vcb
->NoFreeRelocationSpaceVolumeAction
> 1) {
1965 Vcb
->NoFreeRelocationSpaceVolumeAction
= UDF_PART_DAMAGED_RW
;
1968 // Set dirty volume mount mode
1969 if(UDFGetParameter(Vcb
, UDF_DIRTY_VOLUME_BEHAVIOR
, UDF_PART_DAMAGED_RO
)) {
1970 Vcb
->CompatFlags
|= UDF_VCB_IC_DIRTY_RO
;
1973 mult
= UDFGetParameter(Vcb
, UDF_CACHE_SIZE_MULTIPLIER
, 1);
1975 Vcb
->WCacheMaxBlocks
*= mult
;
1976 Vcb
->WCacheMaxFrames
*= mult
;
1978 if(UDFGetParameter(Vcb
, UDF_USE_EJECT_BUTTON
, TRUE
)) {
1979 Vcb
->UseEvent
= TRUE
;
1983 } // end UDFReadRegKeys()
1992 return UDFRegCheckParameterValue(&(UDFGlobalData
.SavedRegPath
),
1994 Vcb
? &(Vcb
->TargetDevName
) : NULL
,
1995 Vcb
? Vcb
->DefaultRegName
: NULL
,
1997 } // end UDFGetRegParameter()
2010 BOOLEAN wait_name
=TRUE
;
2011 BOOLEAN wait_val
=FALSE
;
2012 BOOLEAN wait_nl
=FALSE
;
2016 PUCHAR Cfg
= Vcb
->Cfg
;
2017 ULONG Length
= Vcb
->CfgLength
;
2023 if(len
>= sizeof(NameA
))
2025 sprintf(NameA
, "%S", Name
);
2027 for(i
=0; i
<Length
; i
++) {
2038 case '[': // ignore sections for now, treat as comment
2055 if(i
+len
+2 > Length
)
2057 if(RtlCompareMemory(Cfg
+i
, NameA
, len
) == len
) {
2088 if(a
=='0' && Cfg
[i
+1]=='x') {
2110 if(a
>= '0' && a
<= '9') {
2115 if(a
>= 'a' && a
<= 'f') {
2118 if(a
>= 'A' && a
<= 'F') {
2125 ret_val
= ret_val
*radix
+ a
;
2134 } // end UDFGetCfgParameter()
2141 LARGE_INTEGER delay
;
2142 UDFPrint(("UDFReleaseVCB\n"));
2144 delay
.QuadPart
= -500000; // 0.05 sec
2145 while(Vcb
->PostedRequestCount
) {
2146 UDFPrint(("UDFReleaseVCB: PostedRequestCount = %d\n", Vcb
->PostedRequestCount
));
2147 // spin until all queues IRPs are processed
2148 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
2149 delay
.QuadPart
-= 500000; // grow delay 0.05 sec
2153 UDFPrint(("UDF: Flushing buffers\n"));
2155 WCacheFlushAll__(&(Vcb
->FastCache
),Vcb
);
2156 WCacheRelease__(&(Vcb
->FastCache
));
2158 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
2164 if (!ExIsResourceAcquiredShared(&UDFGlobalData
.GlobalDataResource
)) {
2165 UDFPrint(("UDF: attempt to access to not protected data\n"));
2166 UDFPrint(("UDF: UDFGlobalData\n"));
2169 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
2175 RemoveEntryList(&(Vcb
->NextVCB
));
2176 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
2181 if(Vcb->VCBFlags & UDF_VCB_FLAGS_STOP_WAITER_EVENT)
2182 KeWaitForSingleObject(&(Vcb->WaiterStopped), Executive, KernelMode, FALSE, NULL);
2183 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_STOP_WAITER_EVENT;
2184 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
2189 UDFPrint(("UDF: Delete resources\n"));
2190 UDFDeleteResource(&(Vcb
->VCBResource
));
2191 UDFDeleteResource(&(Vcb
->BitMapResource1
));
2192 UDFDeleteResource(&(Vcb
->FcbListResource
));
2193 UDFDeleteResource(&(Vcb
->FileIdResource
));
2194 UDFDeleteResource(&(Vcb
->DlocResource
));
2195 UDFDeleteResource(&(Vcb
->DlocResource2
));
2196 UDFDeleteResource(&(Vcb
->FlushResource
));
2197 UDFDeleteResource(&(Vcb
->PreallocResource
));
2198 UDFDeleteResource(&(Vcb
->IoResource
));
2199 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
2204 UDFPrint(("UDF: Cleanup VCB\n"));
2205 ASSERT(IsListEmpty(&(Vcb
->NextNotifyIRP
)));
2206 FsRtlNotifyUninitializeSync(&(Vcb
->NotifyIRPMutex
));
2208 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
2213 UDFPrint(("UDF: Delete DO\n"));
2214 IoDeleteDevice(Vcb
->VCBDeviceObject
);
2215 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
2219 } // end UDFReleaseVCB()
2222 Read DWORD from Registry
2225 UDFRegCheckParameterValue(
2226 IN PUNICODE_STRING RegistryPath
,
2228 IN PUNICODE_STRING PtrVolumePath
,
2229 IN PCWSTR DefaultPath
,
2235 ULONG val
= DefValue
;
2237 UNICODE_STRING paramStr
;
2238 UNICODE_STRING defaultParamStr
;
2239 UNICODE_STRING paramPathUnknownStr
;
2241 UNICODE_STRING paramSuffix
;
2242 UNICODE_STRING paramPath
;
2243 UNICODE_STRING paramPathUnknown
;
2244 UNICODE_STRING paramDevPath
;
2245 UNICODE_STRING defaultParamPath
;
2249 paramPath
.Buffer
= NULL
;
2250 paramDevPath
.Buffer
= NULL
;
2251 paramPathUnknown
.Buffer
= NULL
;
2252 defaultParamPath
.Buffer
= NULL
;
2254 // First append \Parameters to the passed in registry path
2255 // Note, RtlInitUnicodeString doesn't allocate memory
2256 RtlInitUnicodeString(¶mStr
, L
"\\Parameters");
2257 RtlInitUnicodeString(¶mPath
, NULL
);
2259 RtlInitUnicodeString(¶mPathUnknownStr
, REG_DEFAULT_UNKNOWN
);
2260 RtlInitUnicodeString(¶mPathUnknown
, NULL
);
2262 paramPathUnknown
.MaximumLength
= RegistryPath
->Length
+ paramPathUnknownStr
.Length
+ paramStr
.Length
+ sizeof(WCHAR
);
2263 paramPath
.MaximumLength
= RegistryPath
->Length
+ paramStr
.Length
+ sizeof(WCHAR
);
2265 paramPath
.Buffer
= (PWCH
)MyAllocatePool__(PagedPool
, paramPath
.MaximumLength
);
2266 if(!paramPath
.Buffer
) {
2267 UDFPrint(("UDFCheckRegValue: couldn't allocate paramPath\n"));
2268 try_return(val
= DefValue
);
2270 paramPathUnknown
.Buffer
= (PWCH
)MyAllocatePool__(PagedPool
, paramPathUnknown
.MaximumLength
);
2271 if(!paramPathUnknown
.Buffer
) {
2272 UDFPrint(("UDFCheckRegValue: couldn't allocate paramPathUnknown\n"));
2273 try_return(val
= DefValue
);
2276 RtlZeroMemory(paramPath
.Buffer
, paramPath
.MaximumLength
);
2277 status
= RtlAppendUnicodeToString(¶mPath
, RegistryPath
->Buffer
);
2278 if(!NT_SUCCESS(status
)) {
2279 try_return(val
= DefValue
);
2281 status
= RtlAppendUnicodeToString(¶mPath
, paramStr
.Buffer
);
2282 if(!NT_SUCCESS(status
)) {
2283 try_return(val
= DefValue
);
2285 UDFPrint(("UDFCheckRegValue: (1) |%S|\n", paramPath
.Buffer
));
2287 RtlZeroMemory(paramPathUnknown
.Buffer
, paramPathUnknown
.MaximumLength
);
2288 status
= RtlAppendUnicodeToString(¶mPathUnknown
, RegistryPath
->Buffer
);
2289 if(!NT_SUCCESS(status
)) {
2290 try_return(val
= DefValue
);
2292 status
= RtlAppendUnicodeToString(¶mPathUnknown
, paramStr
.Buffer
);
2293 if(!NT_SUCCESS(status
)) {
2294 try_return(val
= DefValue
);
2296 status
= RtlAppendUnicodeToString(¶mPathUnknown
, paramPathUnknownStr
.Buffer
);
2297 if(!NT_SUCCESS(status
)) {
2298 try_return(val
= DefValue
);
2300 UDFPrint(("UDFCheckRegValue: (2) |%S|\n", paramPathUnknown
.Buffer
));
2302 // First append \Parameters\Default_XXX to the passed in registry path
2304 RtlInitUnicodeString(&defaultParamStr
, DefaultPath
);
2305 RtlInitUnicodeString(&defaultParamPath
, NULL
);
2306 defaultParamPath
.MaximumLength
= paramPath
.Length
+ defaultParamStr
.Length
+ sizeof(WCHAR
);
2307 defaultParamPath
.Buffer
= (PWCH
)MyAllocatePool__(PagedPool
, defaultParamPath
.MaximumLength
);
2308 if(!defaultParamPath
.Buffer
) {
2309 UDFPrint(("UDFCheckRegValue: couldn't allocate defaultParamPath\n"));
2310 try_return(val
= DefValue
);
2313 RtlZeroMemory(defaultParamPath
.Buffer
, defaultParamPath
.MaximumLength
);
2314 status
= RtlAppendUnicodeToString(&defaultParamPath
, paramPath
.Buffer
);
2315 if(!NT_SUCCESS(status
)) {
2316 try_return(val
= DefValue
);
2318 status
= RtlAppendUnicodeToString(&defaultParamPath
, defaultParamStr
.Buffer
);
2319 if(!NT_SUCCESS(status
)) {
2320 try_return(val
= DefValue
);
2322 UDFPrint(("UDFCheckRegValue: (3) |%S|\n", defaultParamPath
.Buffer
));
2326 paramSuffix
= *PtrVolumePath
;
2328 RtlInitUnicodeString(¶mSuffix
, NULL
);
2331 RtlInitUnicodeString(¶mDevPath
, NULL
);
2332 // now build the device specific path
2333 paramDevPath
.MaximumLength
= paramPath
.Length
+ paramSuffix
.Length
+ sizeof(WCHAR
);
2334 paramDevPath
.Buffer
= (PWCH
)MyAllocatePool__(PagedPool
, paramDevPath
.MaximumLength
);
2335 if(!paramDevPath
.Buffer
) {
2336 try_return(val
= DefValue
);
2339 RtlZeroMemory(paramDevPath
.Buffer
, paramDevPath
.MaximumLength
);
2340 status
= RtlAppendUnicodeToString(¶mDevPath
, paramPath
.Buffer
);
2341 if(!NT_SUCCESS(status
)) {
2342 try_return(val
= DefValue
);
2344 if(paramSuffix
.Buffer
) {
2345 status
= RtlAppendUnicodeToString(¶mDevPath
, paramSuffix
.Buffer
);
2346 if(!NT_SUCCESS(status
)) {
2347 try_return(val
= DefValue
);
2351 UDFPrint(( " Parameter = %ws\n", Name
));
2355 status
= RegTGetKeyHandle(NULL
, RegistryPath
->Buffer
, &hk
);
2356 if(NT_SUCCESS(status
)) {
2357 RegTCloseKeyHandle(hk
);
2362 // *** Read GLOBAL_DEFAULTS from
2363 // "\DwUdf\Parameters_Unknown\"
2365 status
= RegTGetDwordValue(NULL
, paramPath
.Buffer
, Name
, &val
);
2367 // *** Read DEV_CLASS_SPEC_DEFAULTS (if any) from
2368 // "\DwUdf\Parameters_%DevClass%\"
2371 status
= RegTGetDwordValue(NULL
, defaultParamPath
.Buffer
, Name
, &val
);
2374 // *** Read DEV_SPEC_PARAMS from (if device supports GetDevName)
2375 // "\DwUdf\Parameters\%DevName%\"
2377 status
= RegTGetDwordValue(NULL
, paramDevPath
.Buffer
, Name
, &val
);
2383 if(DefaultPath
&& defaultParamPath
.Buffer
) {
2384 MyFreePool__(defaultParamPath
.Buffer
);
2386 if(paramPath
.Buffer
) {
2387 MyFreePool__(paramPath
.Buffer
);
2389 if(paramDevPath
.Buffer
) {
2390 MyFreePool__(paramDevPath
.Buffer
);
2392 if(paramPathUnknown
.Buffer
) {
2393 MyFreePool__(paramPathUnknown
.Buffer
);
2397 UDFPrint(( "UDFCheckRegValue: %ws for drive %s is %x\n\n", Name
, PtrVolumePath
, val
));
2399 } // end UDFRegCheckParameterValue()
2402 Routine Description:
2403 This routine is called to initialize an IrpContext for the current
2404 UDFFS request. The IrpContext is on the stack and we need to initialize
2405 it for the current request. The request is a close operation.
2409 IrpContext - IrpContext to initialize.
2411 IrpContextLite - source for initialization
2419 UDFInitializeIrpContextFromLite(
2420 OUT PtrUDFIrpContext
*IrpContext
,
2421 IN PtrUDFIrpContextLite IrpContextLite
2424 (*IrpContext
) = UDFAllocateIrpContext(NULL
, IrpContextLite
->RealDevice
);
2425 // Zero and then initialize the structure.
2427 // Major/Minor Function codes
2428 (*IrpContext
)->MajorFunction
= IRP_MJ_CLOSE
;
2429 (*IrpContext
)->Fcb
= IrpContextLite
->Fcb
;
2430 (*IrpContext
)->TreeLength
= IrpContextLite
->TreeLength
;
2431 (*IrpContext
)->IrpContextFlags
|= (IrpContextLite
->IrpContextFlags
& ~UDF_IRP_CONTEXT_NOT_FROM_ZONE
);
2433 // Set the wait parameter
2434 UDFSetFlag( (*IrpContext
)->IrpContextFlags
, UDF_IRP_CONTEXT_CAN_BLOCK
);
2437 } // end UDFInitializeIrpContextFromLite()
2440 Routine Description:
2441 This routine is called to initialize an IrpContext for the current
2442 UDFFS request. The IrpContext is on the stack and we need to initialize
2443 it for the current request. The request is a close operation.
2447 IrpContext - IrpContext to initialize.
2449 IrpContextLite - source for initialization
2457 UDFInitializeIrpContextLite(
2458 OUT PtrUDFIrpContextLite
*IrpContextLite
,
2459 IN PtrUDFIrpContext IrpContext
,
2463 PtrUDFIrpContextLite LocalIrpContextLite
= (PtrUDFIrpContextLite
)MyAllocatePool__(NonPagedPool
,sizeof(UDFIrpContextLite
));
2464 if(!LocalIrpContextLite
)
2465 return STATUS_INSUFFICIENT_RESOURCES
;
2466 // Zero and then initialize the structure.
2467 RtlZeroMemory( LocalIrpContextLite
, sizeof( UDFIrpContextLite
));
2469 LocalIrpContextLite
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_IRP_CONTEXT_LITE
;
2470 LocalIrpContextLite
->NodeIdentifier
.NodeSize
= sizeof(UDFIrpContextLite
);
2472 LocalIrpContextLite
->Fcb
= Fcb
;
2473 LocalIrpContextLite
->TreeLength
= IrpContext
->TreeLength
;
2474 // Copy RealDevice for workque algorithms.
2475 LocalIrpContextLite
->RealDevice
= IrpContext
->TargetDeviceObject
;
2476 LocalIrpContextLite
->IrpContextFlags
= IrpContext
->IrpContextFlags
;
2477 *IrpContextLite
= LocalIrpContextLite
;
2479 return STATUS_SUCCESS
;
2480 } // end UDFInitializeIrpContextLite()
2485 PDEVICE_OBJECT DeviceObject
, // the logical volume device object
2486 PIRP Irp
// I/O Request Packet
2489 NTSTATUS RC
= STATUS_SUCCESS
;
2490 // PtrUDFIrpContext PtrIrpContext = NULL;
2491 BOOLEAN AreWeTopLevel
= FALSE
;
2493 UDFPrint(("UDFQuerySetEA: \n"));
2495 FsRtlEnterFileSystem();
2496 ASSERT(DeviceObject
);
2499 // set the top level context
2500 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
2502 RC
= STATUS_EAS_NOT_SUPPORTED
;
2503 Irp
->IoStatus
.Status
= RC
;
2504 Irp
->IoStatus
.Information
= 0;
2506 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
2509 IoSetTopLevelIrp(NULL
);
2512 FsRtlExitFileSystem();
2515 } // end UDFQuerySetEA()
2518 UDFIsResourceAcquired(
2519 IN PERESOURCE Resource
2523 ExIsResourceAcquiredExclusiveLite(Resource
) ? 1 :
2524 (ExIsResourceAcquiredSharedLite(Resource
) ? 2 : 0);
2526 } // end UDFIsResourceAcquired()
2529 UDFAcquireResourceExclusiveWithCheck(
2530 IN PERESOURCE Resource
2534 ExIsResourceAcquiredExclusiveLite(Resource
) ? 1 :
2535 (ExIsResourceAcquiredSharedLite(Resource
) ? 2 : 0);
2537 UDFPrint(("UDFAcquireResourceExclusiveWithCheck: ReAcqRes, %x\n", ReAcqRes
));
2546 UDFPrint(("UDFAcquireResourceExclusiveWithCheck: !!! Shared !!!\n"));
2549 UDFAcquireResourceExclusive(Resource
, TRUE
);
2553 } // end UDFAcquireResourceExclusiveWithCheck()
2556 UDFAcquireResourceSharedWithCheck(
2557 IN PERESOURCE Resource
2561 ExIsResourceAcquiredExclusiveLite(Resource
) ? 1 :
2562 (ExIsResourceAcquiredSharedLite(Resource
) ? 2 : 0);
2564 UDFPrint(("UDFAcquireResourceSharedWithCheck: ReAcqRes, %x\n", ReAcqRes
));
2573 UDFPrint(("UDFAcquireResourceSharedWithCheck: Exclusive\n"));
2576 UDFAcquireResourceShared(Resource
, TRUE
);
2580 } // end UDFAcquireResourceSharedWithCheck()
2583 UDFWCacheErrorHandler(
2585 IN PWCACHE_ERROR_CONTEXT ErrorInfo
2588 InterlockedIncrement((PLONG
)&(((PVCB
)Context
)->IoErrorCounter
));
2589 return ErrorInfo
->Status
;
2592 #include "Include/misc_common.cpp"
2593 #include "Include/regtools.cpp"