1 /*************************************************************************
5 * Module: Ext2 File System Driver (Kernel mode execution only)
8 * This file contains some miscellaneous support routines.
10 * Author: Manoj Paul Joseph
13 *************************************************************************/
17 // define the file specific bug-check id
18 #define EXT2_BUG_CHECK_ID EXT2_FILE_MISC
20 #define DEBUG_LEVEL ( DEBUG_TRACE_MISC )
22 /*************************************************************************
24 * Function: Ext2InitializeZones()
27 * Allocates some memory for global zones used to allocate FSD structures.
28 * Either all memory will be allocated or we will back out gracefully.
30 * Expected Interrupt Level (for execution) :
34 * Return Value: STATUS_SUCCESS/Error
36 *************************************************************************/
37 NTSTATUS NTAPI
Ext2InitializeZones(
40 NTSTATUS RC
= STATUS_SUCCESS
;
41 uint32 SizeOfZone
= Ext2GlobalData
.DefaultZoneSizeInNumStructs
;
42 uint32 SizeOfObjectNameZone
= 0;
43 uint32 SizeOfCCBZone
= 0;
44 uint32 SizeOfFCBZone
= 0;
45 uint32 SizeOfByteLockZone
= 0;
46 uint32 SizeOfIrpContextZone
= 0;
50 // initialize the spinlock protecting the zones
51 KeInitializeSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
));
53 // determine memory requirements
54 switch (MmQuerySystemSize()) {
56 // this is just for illustration purposes. I will multiply
57 // number of structures with some arbitrary amount depending
58 // upon available memory in the system ... You should choose a
59 // more intelligent method suitable to your memory consumption
60 // and the amount of memory available.
61 SizeOfObjectNameZone
= (2 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2ObjectName
))) + sizeof(ZONE_SEGMENT_HEADER
);
62 SizeOfCCBZone
= (2 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2CCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
63 SizeOfFCBZone
= (2 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2FCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
64 SizeOfByteLockZone
= (2 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2FileLockInfo
))) + sizeof(ZONE_SEGMENT_HEADER
);
65 SizeOfIrpContextZone
= (2 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2IrpContext
))) + sizeof(ZONE_SEGMENT_HEADER
);
68 SizeOfObjectNameZone
= (4 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2ObjectName
))) + sizeof(ZONE_SEGMENT_HEADER
);
69 SizeOfCCBZone
= (4 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2CCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
70 SizeOfFCBZone
= (4 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2FCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
71 SizeOfByteLockZone
= (4 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2FileLockInfo
))) + sizeof(ZONE_SEGMENT_HEADER
);
72 SizeOfIrpContextZone
= (4 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2IrpContext
))) + sizeof(ZONE_SEGMENT_HEADER
);
75 SizeOfObjectNameZone
= (8 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2ObjectName
))) + sizeof(ZONE_SEGMENT_HEADER
);
76 SizeOfCCBZone
= (8 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2CCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
77 SizeOfFCBZone
= (8 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2FCB
))) + sizeof(ZONE_SEGMENT_HEADER
);
78 SizeOfByteLockZone
= (8 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2FileLockInfo
))) + sizeof(ZONE_SEGMENT_HEADER
);
79 SizeOfIrpContextZone
= (8 * SizeOfZone
* Ext2QuadAlign(sizeof(Ext2IrpContext
))) + sizeof(ZONE_SEGMENT_HEADER
);
83 // typical NT methodology (at least until *someone* exposed the "difference" between a server and workstation ;-)
84 if (MmIsThisAnNtAsSystem()) {
85 SizeOfObjectNameZone
*= EXT2_NTAS_MULTIPLE
;
86 SizeOfCCBZone
*= EXT2_NTAS_MULTIPLE
;
87 SizeOfFCBZone
*= EXT2_NTAS_MULTIPLE
;
88 SizeOfByteLockZone
*= EXT2_NTAS_MULTIPLE
;
89 SizeOfIrpContextZone
*= EXT2_NTAS_MULTIPLE
;
92 // allocate memory for each of the zones and initialize the zones ...
93 if (!(Ext2GlobalData
.ObjectNameZone
= Ext2AllocatePool(NonPagedPool
, SizeOfObjectNameZone
))) {
94 RC
= STATUS_INSUFFICIENT_RESOURCES
;
98 if (!(Ext2GlobalData
.CCBZone
= Ext2AllocatePool(NonPagedPool
, SizeOfCCBZone
))) {
99 RC
= STATUS_INSUFFICIENT_RESOURCES
;
103 if (!(Ext2GlobalData
.FCBZone
= Ext2AllocatePool(NonPagedPool
, SizeOfFCBZone
))) {
104 RC
= STATUS_INSUFFICIENT_RESOURCES
;
108 if (!(Ext2GlobalData
.ByteLockZone
= Ext2AllocatePool(NonPagedPool
, SizeOfByteLockZone
))) {
109 RC
= STATUS_INSUFFICIENT_RESOURCES
;
113 if (!(Ext2GlobalData
.IrpContextZone
= Ext2AllocatePool(NonPagedPool
, SizeOfIrpContextZone
))) {
114 RC
= STATUS_INSUFFICIENT_RESOURCES
;
118 // initialize each of the zone headers ...
119 if (!NT_SUCCESS(RC
= ExInitializeZone(&(Ext2GlobalData
.ObjectNameZoneHeader
),
120 Ext2QuadAlign(sizeof(Ext2ObjectName
)),
121 Ext2GlobalData
.ObjectNameZone
, SizeOfObjectNameZone
))) {
122 // failed the initialization, leave ...
126 if (!NT_SUCCESS(RC
= ExInitializeZone(&(Ext2GlobalData
.CCBZoneHeader
),
127 Ext2QuadAlign(sizeof(Ext2CCB
)),
128 Ext2GlobalData
.CCBZone
,
130 // failed the initialization, leave ...
134 if (!NT_SUCCESS(RC
= ExInitializeZone(&(Ext2GlobalData
.FCBZoneHeader
),
135 Ext2QuadAlign(sizeof(Ext2FCB
)),
136 Ext2GlobalData
.FCBZone
,
138 // failed the initialization, leave ...
142 if (!NT_SUCCESS(RC
= ExInitializeZone(&(Ext2GlobalData
.ByteLockZoneHeader
),
143 Ext2QuadAlign(sizeof(Ext2FileLockInfo
)),
144 Ext2GlobalData
.ByteLockZone
,
145 SizeOfByteLockZone
))) {
146 // failed the initialization, leave ...
150 if (!NT_SUCCESS(RC
= ExInitializeZone(&(Ext2GlobalData
.IrpContextZoneHeader
),
151 Ext2QuadAlign(sizeof(Ext2IrpContext
)),
152 Ext2GlobalData
.IrpContextZone
,
153 SizeOfIrpContextZone
))) {
154 // failed the initialization, leave ...
161 if (!NT_SUCCESS(RC
)) {
162 // invoke the destroy routine now ...
165 // mark the fact that we have allocated zones ...
166 Ext2SetFlag(Ext2GlobalData
.Ext2Flags
, EXT2_DATA_FLAGS_ZONES_INITIALIZED
);
174 /*************************************************************************
176 * Function: Ext2DestroyZones()
179 * Free up the previously allocated memory. NEVER do this once the
180 * driver has been successfully loaded.
182 * Expected Interrupt Level (for execution) :
188 *************************************************************************/
189 void NTAPI
Ext2DestroyZones(
193 // free up each of the pools
194 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", Ext2GlobalData
.ObjectNameZone
);
195 ExFreePool(Ext2GlobalData
.ObjectNameZone
);
197 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", Ext2GlobalData
.CCBZone
);
198 ExFreePool(Ext2GlobalData
.CCBZone
);
200 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", Ext2GlobalData
.FCBZone
);
201 ExFreePool(Ext2GlobalData
.FCBZone
);
203 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", Ext2GlobalData
.ByteLockZone
);
204 ExFreePool(Ext2GlobalData
.ByteLockZone
);
206 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", Ext2GlobalData
.IrpContextZone
);
207 ExFreePool(Ext2GlobalData
.IrpContextZone
);
211 Ext2ClearFlag(Ext2GlobalData
.Ext2Flags
, EXT2_DATA_FLAGS_ZONES_INITIALIZED
);
218 /*************************************************************************
220 * Function: Ext2IsIrpTopLevel()
223 * Helps the FSD determine who the "top level" caller is for this
224 * request. A request can originate directly from a user process
225 * (in which case, the "top level" will be NULL when this routine
226 * is invoked), OR the user may have originated either from the NT
227 * Cache Manager/VMM ("top level" may be set), or this could be a
228 * recursion into our code in which we would have set the "top level"
229 * field the last time around.
231 * Expected Interrupt Level (for execution) :
233 * whatever level a particular dispatch routine is invoked at.
235 * Return Value: TRUE/FALSE (TRUE if top level was NULL when routine invoked)
237 *************************************************************************/
238 BOOLEAN NTAPI
Ext2IsIrpTopLevel(
239 PIRP Irp
) // the IRP sent to our dispatch routine
241 BOOLEAN ReturnCode
= FALSE
;
243 if (IoGetTopLevelIrp() == NULL
)
245 // OK, so we can set ourselves to become the "top level" component
246 IoSetTopLevelIrp( Irp
);
254 /*************************************************************************
256 * Function: Ext2ExceptionFilter()
259 * This routines allows the driver to determine whether the exception
260 * is an "allowed" exception i.e. one we should not-so-quietly consume
261 * ourselves, or one which should be propagated onwards in which case
262 * we will most likely bring down the machine.
264 * This routine employs the services of FsRtlIsNtstatusExpected(). This
265 * routine returns a BOOLEAN result. A RC of FALSE will cause us to return
266 * EXCEPTION_CONTINUE_SEARCH which will probably cause a panic.
267 * The FsRtl.. routine returns FALSE iff exception values are (currently) :
268 * STATUS_DATATYPE_MISALIGNMENT || STATUS_ACCESS_VIOLATION ||
269 * STATUS_ILLEGAL_INSTRUCTION || STATUS_INSTRUCTION_MISALIGNMENT
271 * Expected Interrupt Level (for execution) :
275 * Return Value: EXCEPTION_EXECUTE_HANDLER/EXECEPTION_CONTINUE_SEARCH
277 *************************************************************************/
278 long NTAPI
Ext2ExceptionFilter(
279 PtrExt2IrpContext PtrIrpContext
,
280 PEXCEPTION_POINTERS PtrExceptionPointers
)
282 long ReturnCode
= EXCEPTION_EXECUTE_HANDLER
;
283 NTSTATUS ExceptionCode
= STATUS_SUCCESS
;
285 // figure out the exception code
286 ExceptionCode
= PtrExceptionPointers
->ExceptionRecord
->ExceptionCode
;
288 if ((ExceptionCode
== STATUS_IN_PAGE_ERROR
) && (PtrExceptionPointers
->ExceptionRecord
->NumberParameters
>= 3))
290 ExceptionCode
= PtrExceptionPointers
->ExceptionRecord
->ExceptionInformation
[2];
295 PtrIrpContext
->SavedExceptionCode
= ExceptionCode
;
296 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_EXCEPTION
);
299 // check if we should propagate this exception or not
300 if (!(FsRtlIsNtstatusExpected(ExceptionCode
)))
302 // we are not ok, propagate this exception.
303 // NOTE: we will bring down the machine ...
304 ReturnCode
= EXCEPTION_CONTINUE_SEARCH
;
306 // better free up the IrpContext now ...
309 Ext2ReleaseIrpContext(PtrIrpContext
);
313 // if you wish to perform some special processing when
314 // not propagating the exception, set up the state for
315 // special processing now ...
317 // return the appropriate code
321 /*************************************************************************
323 * Function: Ext2ExceptionHandler()
326 * One of the routines in the FSD or in the modules we invoked encountered
327 * an exception. We have decided that we will "handle" the exception.
328 * Therefore we will prevent the machine from a panic ...
329 * You can do pretty much anything you choose to in your commercial
330 * driver at this point to ensure a graceful exit. In the sample
331 * driver, I will simply free up the IrpContext (if any), set the
332 * error code in the IRP and complete the IRP at this time ...
334 * Expected Interrupt Level (for execution) :
338 * Return Value: Error code
340 *************************************************************************/
341 NTSTATUS NTAPI
Ext2ExceptionHandler(
342 PtrExt2IrpContext PtrIrpContext
,
351 RC
= PtrIrpContext
->SavedExceptionCode
;
352 // Free irp context here
353 Ext2ReleaseIrpContext(PtrIrpContext
);
357 // must be insufficient resources ...?
358 RC
= STATUS_INSUFFICIENT_RESOURCES
;
361 // set the error code in the IRP
362 Irp
->IoStatus
.Status
= RC
;
363 Irp
->IoStatus
.Information
= 0;
366 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
371 /*************************************************************************
373 * Function: Ext2LogEvent()
376 * Log a message in the NT Event Log. This is a rather simplistic log
377 * methodology since you can potentially utilize the event log to
378 * provide a lot of information to the user (and you should too!)
380 * Expected Interrupt Level (for execution) :
386 *************************************************************************/
387 void NTAPI
Ext2LogEvent(
388 NTSTATUS Ext2EventLogId
, // the Ext2 private message id
389 NTSTATUS RC
) // any NT error code we wish to log ...
394 // Implement a call to IoAllocateErrorLogEntry() followed by a call
395 // to IoWriteErrorLogEntry(). You should note that the call to IoWriteErrorLogEntry()
396 // will free memory for the entry once the write completes (which in actuality
397 // is an asynchronous operation).
400 except (EXCEPTION_EXECUTE_HANDLER
)
402 // nothing really we can do here, just do not wish to crash ...
409 /*************************************************************************
411 * Function: Ext2AllocateObjectName()
414 * Allocate a new ObjectName structure to represent an open on-disk object.
415 * Also initialize the ObjectName structure to NULL.
417 * Expected Interrupt Level (for execution) :
421 * Return Value: A pointer to the ObjectName structure OR NULL.
423 *************************************************************************/
424 PtrExt2ObjectName NTAPI
Ext2AllocateObjectName(
427 PtrExt2ObjectName PtrObjectName
= NULL
;
428 BOOLEAN AllocatedFromZone
= TRUE
;
431 // first, try to allocate out of the zone
432 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
433 if (!ExIsFullZone(&(Ext2GlobalData.ObjectNameZoneHeader))) {
434 // we have enough memory
435 PtrObjectName = (PtrExt2ObjectName)ExAllocateFromZone(&(Ext2GlobalData.ObjectNameZoneHeader));
437 // release the spinlock
438 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
440 // release the spinlock
441 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
443 // if we failed to obtain from the zone, get it directly from the VMM
445 PtrObjectName
= (PtrExt2ObjectName
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2ObjectName
)) );
446 AllocatedFromZone
= FALSE
;
450 // if we could not obtain the required memory, bug-check.
451 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
454 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2ObjectName
)), 0);
457 // zero out the allocated memory block
458 RtlZeroMemory( PtrObjectName
, Ext2QuadAlign(sizeof(Ext2ObjectName
)) );
460 // set up some fields ...
461 PtrObjectName
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_OBJECT_NAME
;
462 PtrObjectName
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2ObjectName
));
465 if (!AllocatedFromZone
)
467 Ext2SetFlag(PtrObjectName
->ObjectNameFlags
, EXT2_OB_NAME_NOT_FROM_ZONE
);
470 return(PtrObjectName
);
474 /*************************************************************************
476 * Function: Ext2ReleaseObjectName()
479 * Deallocate a previously allocated structure.
481 * Expected Interrupt Level (for execution) :
487 *************************************************************************/
488 void NTAPI
Ext2ReleaseObjectName(
489 PtrExt2ObjectName PtrObjectName
)
495 ASSERT(PtrObjectName
);
496 PtrObjectName
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FREED
;
499 // give back memory either to the zone or to the VMM
500 if (!(PtrObjectName
->ObjectNameFlags
& EXT2_OB_NAME_NOT_FROM_ZONE
))
503 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
504 ExFreeToZone(&(Ext2GlobalData
.ObjectNameZoneHeader
), PtrObjectName
);
505 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
511 Ext2DeallocateUnicodeString( & PtrObjectName
->ObjectName
);
513 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrObjectName
);
514 ExFreePool(PtrObjectName
);
522 /*************************************************************************
524 * Function: Ext2AllocateCCB()
527 * Allocate a new CCB structure to represent an open on-disk object.
528 * Also initialize the CCB structure to NULL.
530 * Expected Interrupt Level (for execution) :
534 * Return Value: A pointer to the CCB structure OR NULL.
536 *************************************************************************/
537 PtrExt2CCB NTAPI
Ext2AllocateCCB(
540 PtrExt2CCB PtrCCB
= NULL
;
541 BOOLEAN AllocatedFromZone
= TRUE
;
548 // first, try to allocate out of the zone
549 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
550 if (!ExIsFullZone(&(Ext2GlobalData
.CCBZoneHeader
)))
552 // we have enough memory
553 PtrCCB
= (PtrExt2CCB
)ExAllocateFromZone(&(Ext2GlobalData
.CCBZoneHeader
));
555 // release the spinlock
556 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
560 // release the spinlock
561 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
562 // if we failed to obtain from the zone, get it directly from the VMM
565 PtrCCB
= (PtrExt2CCB
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2CCB
)) );
566 AllocatedFromZone
= FALSE
;
572 // if we could not obtain the required memory, bug-check.
573 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
576 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2CCB
)), 0);
579 // zero out the allocated memory block
580 RtlZeroMemory(PtrCCB
, Ext2QuadAlign(sizeof(Ext2CCB
)));
582 // set up some fields ...
583 PtrCCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_CCB
;
584 PtrCCB
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2CCB
));
587 if (!AllocatedFromZone
)
589 Ext2SetFlag(PtrCCB
->CCBFlags
, EXT2_CCB_NOT_FROM_ZONE
);
595 /*************************************************************************
597 * Function: Ext2ReleaseCCB()
600 * Deallocate a previously allocated structure.
602 * Expected Interrupt Level (for execution) :
608 *************************************************************************/
609 void NTAPI
Ext2ReleaseCCB(
617 if(PtrCCB
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_CCB
)
619 Ext2Panic( PtrCCB
, PtrCCB
->NodeIdentifier
.NodeType
, EXT2_NODE_TYPE_CCB
) ;
622 Ext2DeallocateUnicodeString( &PtrCCB
->DirectorySearchPattern
);
623 Ext2DeallocateUnicodeString( &PtrCCB
->AbsolutePathName
);
624 Ext2DeallocateUnicodeString( &PtrCCB
->RenameLinkTargetFileName
);
629 // give back memory either to the zone or to the VMM
630 if (!(PtrCCB
->CCBFlags
& EXT2_CCB_NOT_FROM_ZONE
))
633 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
634 ExFreeToZone(&(Ext2GlobalData
.CCBZoneHeader
), PtrCCB
);
635 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
640 PtrCCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FREED
;
641 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrCCB
);
651 /*************************************************************************
653 * Function: Ext2AllocateFCB()
656 * Allocate a new FCB structure to represent an open on-disk object.
657 * Also initialize the FCB structure to NULL.
659 * Expected Interrupt Level (for execution) :
663 * Return Value: A pointer to the FCB structure OR NULL.
665 *************************************************************************/
666 PtrExt2FCB NTAPI
Ext2AllocateFCB(
669 PtrExt2FCB PtrFCB
= NULL
;
670 BOOLEAN AllocatedFromZone
= TRUE
;
675 // first, try to allocate out of the zone
678 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
679 if (!ExIsFullZone(&(Ext2GlobalData
.FCBZoneHeader
))) {
680 // we have enough memory
681 PtrFCB
= (PtrExt2FCB
)ExAllocateFromZone(&(Ext2GlobalData
.FCBZoneHeader
));
683 // release the spinlock
684 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
686 // release the spinlock
687 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
689 // if we failed to obtain from the zone, get it directly from the VMM
690 PtrFCB
= (PtrExt2FCB
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2FCB
)) );
691 AllocatedFromZone
= FALSE
;
697 // if we could not obtain the required memory, bug-check.
698 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
701 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2FCB
)), 0);
704 // zero out the allocated memory block
705 RtlZeroMemory(PtrFCB
, Ext2QuadAlign(sizeof(Ext2FCB
)));
707 // set up some fields ...
708 PtrFCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FCB
;
709 PtrFCB
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2FCB
));
712 if (!AllocatedFromZone
)
714 Ext2SetFlag(PtrFCB
->FCBFlags
, EXT2_FCB_NOT_FROM_ZONE
);
721 /*************************************************************************
723 * Function: Ext2CreateNewFCB()
726 * We want to create a new FCB. We will also create a new CCB (presumably)
727 * later. Simply allocate a new FCB structure and initialize fields
729 * This function also takes the file size values that the caller must
730 * have obtained and will set the file size fields appropriately in the
732 * Finally, this routine will initialize the FileObject structure passed
733 * in to this function. If you decide to fail the call later, remember
734 * to uninitialize the fields.
736 * Expected Interrupt Level (for execution) :
740 * Return Value: A pointer to the FCB structure OR NULL.
742 *************************************************************************/
743 NTSTATUS NTAPI
Ext2CreateNewFCB(
744 PtrExt2FCB
*ReturnedFCB
,
745 LARGE_INTEGER AllocationSize
,
746 LARGE_INTEGER EndOfFile
,
747 PFILE_OBJECT PtrFileObject
,
749 PtrExt2ObjectName PtrObjectName
)
751 NTSTATUS RC
= STATUS_SUCCESS
;
753 PtrExt2FCB PtrFCB
= NULL
;
754 PtrExt2NTRequiredFCB PtrReqdFCB
= NULL
;
755 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader
= NULL
;
763 PtrFCB
= Ext2GetUsedFCB( PtrVCB
);
768 // Obtain a new FCB structure.
769 // The function Ext2AllocateFCB() will obtain a new structure either
770 // from a zone or from memory requested directly from the VMM.
771 PtrFCB
= Ext2AllocateFCB();
775 // Assume lack of memory.
776 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
779 // Initialize fields required to interface with the NT Cache Manager.
780 // Note that the returned structure has already been zeroed. This means
781 // that the SectionObject structure has been zeroed which is a
782 // requirement for newly created FCB structures.
783 PtrReqdFCB
= &(PtrFCB
->NTRequiredFCB
);
785 // Initialize the MainResource and PagingIoResource structures now.
786 ExInitializeResourceLite(&(PtrReqdFCB
->MainResource
));
787 Ext2SetFlag(PtrFCB
->FCBFlags
, EXT2_INITIALIZED_MAIN_RESOURCE
);
789 ExInitializeResourceLite(&(PtrReqdFCB
->PagingIoResource
));
790 Ext2SetFlag(PtrFCB
->FCBFlags
, EXT2_INITIALIZED_PAGING_IO_RESOURCE
);
792 // Start initializing the fields contained in the CommonFCBHeader.
793 PtrCommonFCBHeader
= &(PtrReqdFCB
->CommonFCBHeader
);
795 // Disallow fast-IO for now.
796 PtrCommonFCBHeader
->IsFastIoPossible
= FastIoIsNotPossible
;
798 // Initialize the MainResource and PagingIoResource pointers in
799 // the CommonFCBHeader structure to point to the ERESOURCE structures we
800 // have allocated and already initialized above.
801 PtrCommonFCBHeader
->Resource
= &(PtrReqdFCB
->MainResource
);
802 PtrCommonFCBHeader
->PagingIoResource
= &(PtrReqdFCB
->PagingIoResource
);
804 // Ignore the Flags field in the CommonFCBHeader for now. Part 3
805 // of the book describes it in greater detail.
807 // Initialize the file size values here.
808 PtrCommonFCBHeader
->AllocationSize
= AllocationSize
;
809 PtrCommonFCBHeader
->FileSize
= EndOfFile
;
811 // The following will disable ValidDataLength support. However, your
812 // FSD may choose to support this concept.
813 PtrCommonFCBHeader
->ValidDataLength
.LowPart
= 0xFFFFFFFF;
814 PtrCommonFCBHeader
->ValidDataLength
.HighPart
= 0x7FFFFFFF;
816 // Initialize other fields for the FCB here ...
817 PtrFCB
->PtrVCB
= PtrVCB
;
819 // caller MUST ensure that VCB has been acquired exclusively
820 InsertTailList(&(PtrVCB
->FCBListHead
), &(PtrFCB
->NextFCB
));
823 InitializeListHead(&(PtrFCB
->CCBListHead
));
825 // Initialize fields contained in the file object now.
828 PtrFileObject
->PrivateCacheMap
= NULL
;
829 // Note that we could have just as well taken the value of PtrReqdFCB
830 // directly below. The bottom line however is that the FsContext
831 // field must point to a FSRTL_COMMON_FCB_HEADER structure.
832 PtrFileObject
->FsContext
= (void *)(PtrCommonFCBHeader
);
833 PtrFileObject
->SectionObjectPointer
= &(PtrFCB
->NTRequiredFCB
.SectionObject
) ;
836 // Initialising the object name...
837 PtrFCB
->FCBName
= PtrObjectName
;
839 // Returning the FCB...
840 *ReturnedFCB
= PtrFCB
;
853 /*************************************************************************
855 * Function: Ext2ReleaseFCB()
858 * Deallocate a previously allocated structure.
860 * Expected Interrupt Level (for execution) :
866 *************************************************************************/
867 void NTAPI
Ext2ReleaseFCB(
874 if( PtrFCB
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_FCB
)
876 Ext2Panic( PtrFCB
, PtrFCB
->NodeIdentifier
.NodeType
, EXT2_NODE_TYPE_FCB
) ;
880 PtrFCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FREED
;
883 // give back memory either to the zone or to the VMM
884 if (!(PtrFCB->FCBFlags & EXT2_FCB_NOT_FROM_ZONE))
887 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
888 ExFreeToZone(&(Ext2GlobalData.FCBZoneHeader), PtrFCB);
889 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
895 ExDeleteResourceLite( &PtrFCB
->NTRequiredFCB
.MainResource
);
896 ExDeleteResourceLite( &PtrFCB
->NTRequiredFCB
.PagingIoResource
);
898 RemoveEntryList(&(PtrFCB
->NextFCB
));
900 if( PtrFCB
->FCBName
)
902 Ext2ReleaseObjectName( PtrFCB
->FCBName
);
905 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrFCB
);
915 /*************************************************************************
917 * Function: Ext2AllocateByteLocks()
920 * Allocate a new byte range lock structure and initialize it to NULL.
922 * Expected Interrupt Level (for execution) :
926 * Return Value: A pointer to the Ext2ByteLocks structure OR NULL.
928 *************************************************************************/
929 PtrExt2FileLockInfo NTAPI
Ext2AllocateByteLocks(
932 PtrExt2FileLockInfo PtrByteLocks
= NULL
;
933 BOOLEAN AllocatedFromZone
= TRUE
;
936 // first, try to allocate out of the zone
937 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
938 if (!ExIsFullZone(&(Ext2GlobalData
.ByteLockZoneHeader
)))
940 // we have enough memory
941 PtrByteLocks
= (PtrExt2FileLockInfo
)ExAllocateFromZone(&(Ext2GlobalData
.ByteLockZoneHeader
));
943 // release the spinlock
944 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
948 // release the spinlock
949 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
951 // if we failed to obtain from the zone, get it directly from the VMM
952 PtrByteLocks
= (PtrExt2FileLockInfo
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2FileLockInfo
)) );
953 AllocatedFromZone
= FALSE
;
956 // if we could not obtain the required memory, bug-check.
957 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
960 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2FileLockInfo
)), 0);
963 // zero out the allocated memory block
964 RtlZeroMemory(PtrByteLocks
, Ext2QuadAlign(sizeof(PtrExt2FileLockInfo
)));
966 if (!AllocatedFromZone
)
968 Ext2SetFlag(PtrByteLocks
->FileLockFlags
, EXT2_BYTE_LOCK_NOT_FROM_ZONE
);
971 return(PtrByteLocks
);
974 /*************************************************************************
976 * Function: Ext2ReleaseByteLocks()
979 * Deallocate a previously allocated structure.
981 * Expected Interrupt Level (for execution) :
987 *************************************************************************/
988 void NTAPI
Ext2ReleaseByteLocks(
989 PtrExt2FileLockInfo PtrByteLocks
)
993 ASSERT(PtrByteLocks
);
995 // give back memory either to the zone or to the VMM
996 if (!(PtrByteLocks
->FileLockFlags
& EXT2_BYTE_LOCK_NOT_FROM_ZONE
)) {
998 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
999 ExFreeToZone(&(Ext2GlobalData
.ByteLockZoneHeader
), PtrByteLocks
);
1000 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
1004 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrByteLocks
);
1005 ExFreePool(PtrByteLocks
);
1012 /*************************************************************************
1014 * Function: Ext2AllocateIrpContext()
1017 * The sample FSD creates an IRP context for each request received. This
1018 * routine simply allocates (and initializes to NULL) a Ext2IrpContext
1020 * Most of the fields in the context structure are then initialized here.
1022 * Expected Interrupt Level (for execution) :
1024 * IRQL_PASSIVE_LEVEL
1026 * Return Value: A pointer to the IrpContext structure OR NULL.
1028 *************************************************************************/
1029 PtrExt2IrpContext NTAPI
Ext2AllocateIrpContext(
1031 PDEVICE_OBJECT PtrTargetDeviceObject
)
1033 PtrExt2IrpContext PtrIrpContext
= NULL
;
1034 BOOLEAN AllocatedFromZone
= TRUE
;
1035 //KIRQL CurrentIrql;
1036 PIO_STACK_LOCATION PtrIoStackLocation
= NULL
;
1039 // Allocation from zone not done at present...
1041 // first, try to allocate out of the zone
1042 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
1043 if (!ExIsFullZone(&(Ext2GlobalData.IrpContextZoneHeader))) {
1044 // we have enough memory
1045 PtrIrpContext = (PtrExt2IrpContext)ExAllocateFromZone(&(Ext2GlobalData.IrpContextZoneHeader));
1047 // release the spinlock
1048 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
1050 // release the spinlock
1051 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
1056 // if we failed to obtain from the zone, get it directly from the VMM
1057 PtrIrpContext = (PtrExt2IrpContext)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2IrpContext)) );
1058 AllocatedFromZone = FALSE;
1061 //No Zone handling for now
1064 PtrIrpContext
= (PtrExt2IrpContext
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2IrpContext
)) );
1065 AllocatedFromZone
= FALSE
;
1067 // if we could not obtain the required memory, bug-check.
1068 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
1071 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2IrpContext
)), 0);
1074 // zero out the allocated memory block
1075 RtlZeroMemory(PtrIrpContext
, Ext2QuadAlign(sizeof(Ext2IrpContext
)));
1077 // set up some fields ...
1078 PtrIrpContext
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_IRP_CONTEXT
;
1079 PtrIrpContext
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2IrpContext
));
1082 PtrIrpContext
->Irp
= Irp
;
1083 PtrIrpContext
->TargetDeviceObject
= PtrTargetDeviceObject
;
1085 // copy over some fields from the IRP and set appropriate flag values
1088 PtrIoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1089 ASSERT(PtrIoStackLocation
);
1091 PtrIrpContext
->MajorFunction
= PtrIoStackLocation
->MajorFunction
;
1092 PtrIrpContext
->MinorFunction
= PtrIoStackLocation
->MinorFunction
;
1094 // Often, a FSD cannot honor a request for asynchronous processing
1095 // of certain critical requests. For example, a "close" request on
1096 // a file object can typically never be deferred. Therefore, do not
1097 // be surprised if sometimes your FSD (just like all other FSD
1098 // implementations on the Windows NT system) has to override the flag
1100 if( PtrIoStackLocation
->FileObject
)
1102 if (IoIsOperationSynchronous(Irp
) )
1104 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_CAN_BLOCK
);
1109 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_CAN_BLOCK
);
1113 if (!AllocatedFromZone
)
1115 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_NOT_FROM_ZONE
);
1118 // Are we top-level ? This information is used by the dispatching code
1119 // later (and also by the FSD dispatch routine)
1120 if (IoGetTopLevelIrp() != Irp
)
1122 // We are not top-level. Note this fact in the context structure
1123 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_NOT_TOP_LEVEL
);
1126 InitializeListHead( &PtrIrpContext
->SavedBCBsListHead
);
1128 return(PtrIrpContext
);
1132 /*************************************************************************
1134 * Function: Ext2ReleaseIrpContext()
1137 * Deallocate a previously allocated structure.
1139 * Expected Interrupt Level (for execution) :
1141 * IRQL_PASSIVE_LEVEL
1143 * Return Value: None
1145 *************************************************************************/
1146 void NTAPI
Ext2ReleaseIrpContext(
1147 PtrExt2IrpContext PtrIrpContext
)
1151 ASSERT(PtrIrpContext
);
1153 // Flush the saved BCBs...
1154 Ext2FlushSavedBCBs( PtrIrpContext
);
1156 // give back memory either to the zone or to the VMM
1157 if (!(PtrIrpContext
->IrpContextFlags
& EXT2_IRP_CONTEXT_NOT_FROM_ZONE
))
1160 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
1161 ExFreeToZone(&(Ext2GlobalData
.IrpContextZoneHeader
), PtrIrpContext
);
1162 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
1166 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrIrpContext
);
1167 ExFreePool(PtrIrpContext
);
1173 /*************************************************************************
1175 * Function: Ext2PostRequest()
1178 * Queue up a request for deferred processing (in the context of a system
1179 * worker thread). The caller must have locked the user buffer (if required)
1181 * Expected Interrupt Level (for execution) :
1183 * IRQL_PASSIVE_LEVEL
1185 * Return Value: STATUS_PENDING
1187 *************************************************************************/
1188 NTSTATUS NTAPI
Ext2PostRequest(
1189 PtrExt2IrpContext PtrIrpContext
,
1192 NTSTATUS RC
= STATUS_PENDING
;
1194 DebugTrace(DEBUG_TRACE_ASYNC
, " === Asynchronous request. Deferring processing", 0);
1196 // mark the IRP pending
1197 IoMarkIrpPending(PtrIrp
);
1199 // queue up the request
1200 ExInterlockedInsertTailList(
1201 &Ext2GlobalData
.ThreadQueue
.ThreadQueueListHead
,
1202 &PtrIrpContext
->ThreadQueueListEntry
,
1203 &Ext2GlobalData
.ThreadQueue
.SpinLock
);
1205 KeSetEvent( &Ext2GlobalData
.ThreadQueue
.QueueEvent
, 0, FALSE
);
1208 /***************** not using system worker threads *****************
1209 ExInitializeWorkItem(&(PtrIrpContext->WorkQueueItem), Ext2CommonDispatch, PtrIrpContext);
1210 ExQueueWorkItem( &( PtrIrpContext->WorkQueueItem ), DelayedWorkQueue );
1211 // CriticalWorkQueue
1212 *****************************************************************************/
1214 // return status pending
1219 /*************************************************************************
1221 * Function: Ext2CommonDispatch()
1224 * The common dispatch routine invoked in the context of a system worker
1225 * thread. All we do here is pretty much case off the major function
1226 * code and invoke the appropriate FSD dispatch routine for further
1229 * Expected Interrupt Level (for execution) :
1231 * IRQL PASSIVE_LEVEL
1233 * Return Value: None
1235 *************************************************************************/
1236 void NTAPI
Ext2CommonDispatch(
1237 void *Context
) // actually an IRPContext structure
1239 NTSTATUS RC
= STATUS_SUCCESS
;
1240 PtrExt2IrpContext PtrIrpContext
= NULL
;
1243 // The context must be a pointer to an IrpContext structure
1244 PtrIrpContext
= (PtrExt2IrpContext
)Context
;
1245 ASSERT(PtrIrpContext
);
1247 // Assert that the Context is legitimate
1248 if ((PtrIrpContext
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_IRP_CONTEXT
) || (PtrIrpContext
->NodeIdentifier
.NodeSize
!= Ext2QuadAlign(sizeof(Ext2IrpContext
))))
1250 // This does not look good
1251 Ext2Panic(EXT2_ERROR_INTERNAL_ERROR
, PtrIrpContext
->NodeIdentifier
.NodeType
, PtrIrpContext
->NodeIdentifier
.NodeSize
);
1254 // Get a pointer to the IRP structure
1255 PtrIrp
= PtrIrpContext
->Irp
;
1258 // Now, check if the FSD was top level when the IRP was originally invoked
1259 // and set the thread context (for the worker thread) appropriately
1260 if (PtrIrpContext
->IrpContextFlags
& EXT2_IRP_CONTEXT_NOT_TOP_LEVEL
)
1262 // The FSD is not top level for the original request
1263 // Set a constant value in TLS to reflect this fact
1264 IoSetTopLevelIrp((PIRP
)FSRTL_FSP_TOP_LEVEL_IRP
);
1267 // Since the FSD routine will now be invoked in the context of this worker
1268 // thread, we should inform the FSD that it is perfectly OK to block in
1269 // the context of this thread
1270 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_CAN_BLOCK
);
1272 FsRtlEnterFileSystem();
1277 // Pre-processing has been completed; check the Major Function code value
1278 // either in the IrpContext (copied from the IRP), or directly from the
1279 // IRP itself (we will need a pointer to the stack location to do that),
1280 // Then, switch based on the value on the Major Function code
1281 switch (PtrIrpContext
->MajorFunction
)
1284 // Invoke the common create routine
1285 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_CREATE request asynchronously .", 0);
1286 (void)Ext2CommonCreate(PtrIrpContext
, PtrIrp
, FALSE
);
1289 // Invoke the common read routine
1290 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_READ request asynchronously .", 0);
1291 (void)Ext2CommonRead(PtrIrpContext
, PtrIrp
, FALSE
);
1294 // Invoke the common write routine
1295 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_WRITE request asynchronously .", 0);
1296 (void)Ext2CommonWrite(PtrIrpContext
, PtrIrp
);
1299 case IRP_MJ_CLEANUP
:
1300 // Invoke the common read routine
1301 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_CLEANUP request asynchronously .", 0);
1302 (void)Ext2CommonCleanup(PtrIrpContext
, PtrIrp
, FALSE
);
1305 // Invoke the common read routine
1306 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_CLOSE request asynchronously .", 0);
1307 (void)Ext2CommonClose ( PtrIrpContext
, PtrIrp
, FALSE
);
1310 // Continue with the remaining possible dispatch routines below ...
1312 // This is the case where we have an invalid major function
1313 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing asynchronous request. \nUnable to recoganise the IRP!!! How can this be!!!", 0);
1314 PtrIrp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1315 PtrIrp
->IoStatus
.Information
= 0;
1319 IoCompleteRequest(PtrIrp
, IO_NO_INCREMENT
);
1323 except (Ext2ExceptionFilter(PtrIrpContext
, GetExceptionInformation()))
1325 RC
= Ext2ExceptionHandler(PtrIrpContext
, PtrIrp
);
1326 Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR
, RC
);
1329 // Enable preemption
1330 FsRtlExitFileSystem();
1332 // Ensure that the "top-level" field is cleared
1333 IoSetTopLevelIrp(NULL
);
1335 PsTerminateSystemThread( RC
);
1341 /*************************************************************************
1343 * Function: Ext2InitializeVCB()
1346 * Perform the initialization for a VCB structure.
1348 * Expected Interrupt Level (for execution) :
1350 * IRQL PASSIVE_LEVEL
1352 * Return Value: None
1354 *************************************************************************/
1355 void NTAPI
Ext2InitializeVCB(
1356 PDEVICE_OBJECT PtrVolumeDeviceObject
,
1357 PDEVICE_OBJECT PtrTargetDeviceObject
,
1359 PLARGE_INTEGER AllocationSize
)
1361 NTSTATUS RC
= STATUS_SUCCESS
;
1362 PtrExt2VCB PtrVCB
= NULL
;
1363 BOOLEAN VCBResourceInitialized
= FALSE
;
1365 PtrVCB
= (PtrExt2VCB
)(PtrVolumeDeviceObject
->DeviceExtension
);
1367 // Zero it out (typically this has already been done by the I/O
1368 // Manager but it does not hurt to do it again)!
1369 RtlZeroMemory(PtrVCB
, sizeof(Ext2VCB
));
1371 // Initialize the signature fields
1372 PtrVCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_VCB
;
1373 PtrVCB
->NodeIdentifier
.NodeSize
= sizeof(Ext2VCB
);
1375 // Initialize the ERESOURCE objects.
1376 RC
= ExInitializeResourceLite(&(PtrVCB
->VCBResource
));
1377 RC
= ExInitializeResourceLite(&(PtrVCB
->PagingIoResource
));
1379 ASSERT(NT_SUCCESS(RC
));
1380 VCBResourceInitialized
= TRUE
;
1382 PtrVCB
->TargetDeviceObject
= PtrTargetDeviceObject
;
1384 PtrVCB
->VCBDeviceObject
= PtrVolumeDeviceObject
;
1386 PtrVCB
->PtrVPB
= PtrVPB
;
1388 // Initialize the list anchor (head) for some lists in this VCB.
1389 InitializeListHead(&(PtrVCB
->FCBListHead
));
1390 InitializeListHead(&(PtrVCB
->NextNotifyIRP
));
1391 InitializeListHead(&(PtrVCB
->VolumeOpenListHead
));
1392 InitializeListHead(&(PtrVCB
->ClosableFCBs
.ClosableFCBListHead
));
1393 PtrVCB
->ClosableFCBs
.Count
= 0;
1395 // Initialize the notify IRP list mutex
1396 KeInitializeMutex(&(PtrVCB
->NotifyIRPMutex
), 0);
1398 // Set the initial file size values appropriately. Note that your FSD may
1399 // wish to guess at the initial amount of information you would like to
1400 // read from the disk until you have really determined that this a valid
1401 // logical volume (on disk) that you wish to mount.
1402 PtrVCB
->CommonVCBHeader
.AllocationSize
.QuadPart
= AllocationSize
->QuadPart
;
1404 PtrVCB
->CommonVCBHeader
.FileSize
.QuadPart
= AllocationSize
->QuadPart
;
1405 // You typically do not want to bother with valid data length callbacks
1406 // from the Cache Manager for the file stream opened for volume metadata
1408 PtrVCB
->CommonVCBHeader
.ValidDataLength
.LowPart
= 0xFFFFFFFF;
1409 PtrVCB
->CommonVCBHeader
.ValidDataLength
.HighPart
= 0x7FFFFFFF;
1411 PtrVCB
->CommonVCBHeader
.IsFastIoPossible
= FastIoIsNotPossible
;
1413 PtrVCB
->CommonVCBHeader
.Resource
= &(PtrVCB
->VCBResource
);
1414 PtrVCB
->CommonVCBHeader
.PagingIoResource
= &(PtrVCB
->PagingIoResource
);
1416 // Create a stream file object for this volume.
1417 PtrVCB
->PtrStreamFileObject
= IoCreateStreamFileObject(NULL
,
1418 PtrVCB
->PtrVPB
->RealDevice
);
1419 ASSERT(PtrVCB
->PtrStreamFileObject
);
1421 // Initialize some important fields in the newly created file object.
1422 PtrVCB
->PtrStreamFileObject
->FsContext
= (void *)(&PtrVCB
->CommonVCBHeader
);
1423 PtrVCB
->PtrStreamFileObject
->FsContext2
= NULL
;
1424 PtrVCB
->PtrStreamFileObject
->SectionObjectPointer
= &(PtrVCB
->SectionObject
);
1426 PtrVCB
->PtrStreamFileObject
->Vpb
= PtrVPB
;
1427 PtrVCB
->PtrStreamFileObject
->ReadAccess
= TRUE
;
1428 PtrVCB
->PtrStreamFileObject
->WriteAccess
= TRUE
;
1430 // Link this chap onto the global linked list of all VCB structures.
1431 DebugTrace(DEBUG_TRACE_MISC
, "*** Attempting to acquire Global Resource Exclusively [FileInfo]", 0);
1432 ExAcquireResourceExclusiveLite(&(Ext2GlobalData
.GlobalDataResource
), TRUE
);
1433 InsertTailList(&(Ext2GlobalData
.NextVCB
), &(PtrVCB
->NextVCB
));
1434 DebugTrace(DEBUG_TRACE_MISC
, "*** Global Resource Acquired [FileInfo]", 0);
1438 // Initialize caching for the stream file object.
1439 CcInitializeCacheMap(PtrVCB
->PtrStreamFileObject
, (PCC_FILE_SIZES
)(&(PtrVCB
->CommonVCBHeader
.AllocationSize
)),
1440 TRUE
, // We will use pinned access.
1441 &(Ext2GlobalData
.CacheMgrCallBacks
), PtrVCB
);
1444 Ext2ReleaseResource(&(Ext2GlobalData
.GlobalDataResource
));
1445 DebugTrace(DEBUG_TRACE_MISC
, "*** Global Resource Released[FileInfo]", 0);
1447 // Mark the fact that this VCB structure is initialized.
1448 Ext2SetFlag(PtrVCB
->VCBFlags
, EXT2_VCB_FLAGS_VCB_INITIALIZED
);
1449 PtrVCB
->PtrGroupDescriptors
= NULL
;
1450 PtrVCB
->NoOfGroups
= 0;
1456 /*************************************************************************
1458 * Function: Ext2CompleteRequest()
1461 * This routine completes a Irp.
1463 * Expected Interrupt Level (for execution) :
1469 * Irp - Supplies the Irp being processed
1471 * Status - Supplies the status to complete the Irp with
1473 * Return Value: none
1475 *************************************************************************/
1476 void NTAPI
Ext2CompleteRequest(
1477 IN PIRP Irp OPTIONAL
,
1482 // If we have an Irp then complete the irp.
1489 // We got an error, so zero out the information field before
1490 // completing the request if this was an input operation.
1491 // Otherwise IopCompleteRequest will try to copy to the user's buffer.
1494 if ( NT_ERROR(Status
) &&
1495 FlagOn(Irp
->Flags
, IRP_INPUT_OPERATION
) ) {
1497 Irp
->IoStatus
.Information
= 0;
1500 Irp
->IoStatus
.Status
= Status
;
1502 IoCompleteRequest( Irp
, IO_DISK_INCREMENT
);
1508 /*************************************************************************
1510 * Function: Ext2CreateNewCCB()
1513 * We want to create a new CCB.
1515 * Expected Interrupt Level (for execution) :
1517 * IRQL_PASSIVE_LEVEL
1519 * Return Value: A pointer to the CCB structure OR NULL.
1521 *************************************************************************/
1522 NTSTATUS NTAPI
Ext2CreateNewCCB(
1523 PtrExt2CCB
*ReturnedCCB
,
1525 PFILE_OBJECT PtrFileObject
)
1528 NTSTATUS RC
= STATUS_SUCCESS
;
1533 PtrCCB
= Ext2AllocateCCB();
1536 // Assume lack of memory.
1537 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
1539 PtrCCB
->PtrFCB
= PtrFCB
;
1541 PtrCCB
->PtrFileObject
= PtrFileObject
;
1542 PtrCCB
->CurrentByteOffset
.QuadPart
= 0;
1544 if( PtrFCB
->ClosableFCBs
.OnClosableFCBList
)
1546 // This FCB was on the Closable List...
1547 // Taking it off the list...
1549 RemoveEntryList( &PtrFCB
->ClosableFCBs
.ClosableFCBList
);
1550 PtrFCB
->ClosableFCBs
.OnClosableFCBList
= FALSE
;
1551 PtrFCB
->PtrVCB
->ClosableFCBs
.Count
--;
1554 InterlockedIncrement( &PtrFCB
->ReferenceCount
);
1555 InterlockedIncrement( &PtrFCB
->OpenHandleCount
);
1557 InsertTailList( &( PtrFCB
->CCBListHead
), &(PtrCCB
->NextCCB
));
1559 *ReturnedCCB
= PtrCCB
;
1571 /*************************************************************************
1573 * Function: Ext2DenyAccess()
1576 * We want to deny access to an IRP
1578 * Expected Interrupt Level (for execution) :
1580 * IRQL_PASSIVE_LEVEL
1582 * Return Value: NTSTATUS - STATUS_ACCESS_DENIED (always)
1584 *************************************************************************/
1585 NTSTATUS NTAPI
Ext2DenyAccess( IN PIRP Irp
)
1589 // Just return Access Denied
1590 Irp
->IoStatus
.Information
= 0;
1591 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
1592 IoCompleteRequest( Irp
, IO_DISK_INCREMENT
);
1594 DebugTrace(DEBUG_TRACE_MISC
, "DENYING ACCESS (this will do for now!)...", 0);
1596 return STATUS_ACCESS_DENIED
;
1601 /*************************************************************************
1603 * Function: Ext2GetFCB_CCB_VCB_FromFileObject()
1606 * This routine retrieves the FCB, CCB and VCB from the File Object...
1608 * Expected Interrupt Level (for execution) :
1612 * Return Value: NTSTATUS - STATUS_SUCCESS(always)
1614 *************************************************************************/
1615 NTSTATUS NTAPI
Ext2GetFCB_CCB_VCB_FromFileObject (
1616 IN PFILE_OBJECT PtrFileObject
,
1617 OUT PtrExt2FCB
*PPtrFCB
,
1618 OUT PtrExt2CCB
*PPtrCCB
,
1619 OUT PtrExt2VCB
*PPtrVCB
)
1621 (*PPtrCCB
) = (PtrExt2CCB
)(PtrFileObject
->FsContext2
);
1624 ASSERT((*PPtrCCB
)->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_CCB
);
1625 (*PPtrFCB
) = (*PPtrCCB
)->PtrFCB
;
1629 if ((*PPtrFCB
)->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_VCB
)
1631 (*PPtrVCB
) = (PtrExt2VCB
)(*PPtrFCB
);
1632 AssertVCB( (*PPtrVCB
) );
1640 AssertFCB( (*PPtrFCB
) );
1641 (*PPtrVCB
) = (*PPtrFCB
)->PtrVCB
;
1642 AssertVCB( (*PPtrVCB
) );
1648 // PtrFileObject->FsContext points to NTRequiredFCB
1649 (*PPtrFCB
) = CONTAINING_RECORD( PtrFileObject
->FsContext
, Ext2FCB
, NTRequiredFCB
);
1651 //(*PPtrFCB) = PtrFileObject->FsContext;
1653 if ((*PPtrFCB
)->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_FCB
)
1655 // Making sure I got it right...
1656 AssertFCB( *PPtrFCB
);
1657 (*PPtrVCB
) = (*PPtrFCB
)->PtrVCB
;
1658 AssertVCB( *PPtrVCB
);
1662 // This should be a VCB
1664 (*PPtrVCB
) = CONTAINING_RECORD( PtrFileObject
->FsContext
, Ext2VCB
, CommonVCBHeader
);
1665 AssertVCB( *PPtrVCB
);
1673 return STATUS_SUCCESS
;
1677 void NTAPI
Ext2CopyUnicodeString( PUNICODE_STRING PtrDestinationString
, PUNICODE_STRING PtrSourceString
)
1680 // Allcating space for Destination...
1681 PtrDestinationString
->Length
= PtrSourceString
->Length
;
1682 PtrDestinationString
->MaximumLength
= Ext2QuadAlign( PtrSourceString
->Length
+ 2 );
1683 PtrDestinationString
->Buffer
= Ext2AllocatePool( NonPagedPool
, PtrDestinationString
->MaximumLength
);
1685 // RtlCopyUnicodeString( PtrDestinationString, PtrSourceString );
1687 for( Count
= 0 ; Count
< (PtrSourceString
->Length
/2) ; Count
++ )
1689 PtrDestinationString
->Buffer
[Count
] = PtrSourceString
->Buffer
[Count
];
1691 PtrDestinationString
->Buffer
[Count
] = 0;
1695 void NTAPI
Ext2CopyWideCharToUnicodeString(
1696 PUNICODE_STRING PtrDestinationString
,
1697 PCWSTR PtrSourceString
)
1702 // Determining length...
1703 for( Count
= 0 ; PtrSourceString
[Count
] != 0 ; Count
++ );
1705 // Allcating space for Destination...
1706 PtrDestinationString
->Length
= Count
* 2;
1707 PtrDestinationString
->MaximumLength
= Ext2QuadAlign( Count
* 2 + 2 );
1708 PtrDestinationString
->Buffer
= Ext2AllocatePool( NonPagedPool
, PtrDestinationString
->MaximumLength
);
1710 // Copying the string over...
1711 for( Count
= 0 ; ; Count
++ )
1713 PtrDestinationString
->Buffer
[Count
] = PtrSourceString
[Count
];
1714 if( PtrSourceString
[Count
] == 0 )
1720 void NTAPI
Ext2CopyCharToUnicodeString(
1721 PUNICODE_STRING PtrDestinationString
,
1722 PCSTR PtrSourceString
,
1723 USHORT SourceStringLength
)
1726 // Allcating space for Destination...
1727 PtrDestinationString
->Length
= SourceStringLength
* 2;
1728 PtrDestinationString
->MaximumLength
= Ext2QuadAlign( SourceStringLength
* 2 + 2 );
1729 PtrDestinationString
->Buffer
= Ext2AllocatePool( NonPagedPool
, PtrDestinationString
->MaximumLength
);
1731 // Copying the string over...
1732 for( Count
= 0 ; Count
< SourceStringLength
; Count
++ )
1734 PtrDestinationString
->Buffer
[Count
] = PtrSourceString
[Count
];
1736 PtrDestinationString
->Buffer
[Count
] = 0;
1740 void NTAPI
Ext2CopyZCharToUnicodeString( PUNICODE_STRING PtrDestinationString
, PCSTR PtrSourceString
)
1745 // Determining length...
1746 for( Count
= 0 ; PtrSourceString
[Count
] != 0 ; Count
++ );
1748 // Allcating space for Destination...
1749 PtrDestinationString
->Length
= Count
* 2;
1750 PtrDestinationString
->MaximumLength
= Ext2QuadAlign( Count
* 2 + 2 );
1751 PtrDestinationString
->Buffer
= Ext2AllocatePool( NonPagedPool
, PtrDestinationString
->MaximumLength
);
1753 // Copying the string over...
1754 for( Count
= 0 ; ; Count
++ )
1756 PtrDestinationString
->Buffer
[Count
] = PtrSourceString
[Count
];
1757 if( PtrSourceString
[Count
] == 0 )
1762 void NTAPI
Ext2ZerooutUnicodeString( PUNICODE_STRING PtrUnicodeString
)
1764 PtrUnicodeString
->Length
= 0;
1765 PtrUnicodeString
->MaximumLength
=0;
1766 PtrUnicodeString
->Buffer
= 0;
1769 void NTAPI
Ext2DeallocateUnicodeString( PUNICODE_STRING PtrUnicodeString
)
1771 if( PtrUnicodeString
&& PtrUnicodeString
->Buffer
)
1773 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrUnicodeString
->Buffer
);
1774 ExFreePool( PtrUnicodeString
->Buffer
);
1776 PtrUnicodeString
->Length
= 0;
1777 PtrUnicodeString
->MaximumLength
=0;
1778 PtrUnicodeString
->Buffer
= 0;
1781 PtrExt2FCB NTAPI
Ext2GetUsedFCB(
1785 BOOLEAN AllocatedFromZone
= FALSE
;
1786 PLIST_ENTRY PtrEntry
= NULL
;
1787 PtrExt2FCB PtrFCB
= NULL
;
1790 if( PtrVCB
->ClosableFCBs
.Count
< EXT2_MAXCLOSABLE_FCBS_LL
)
1793 // Too few Closable FCBs
1794 // Will not reuse any FCBs
1795 // Allocating a new one
1797 return Ext2AllocateFCB();
1800 // Obtaining a used FCB...
1803 // Retrieving the first entry in the closable FCB list...
1805 PtrEntry
= RemoveHeadList( &PtrVCB
->ClosableFCBs
.ClosableFCBListHead
);
1807 PtrFCB
= CONTAINING_RECORD( PtrEntry
, Ext2FCB
, ClosableFCBs
.ClosableFCBList
);
1809 // Remembering if the FCB was allocated from the Zone...
1810 AllocatedFromZone
= Ext2IsFlagOn( PtrFCB
->FCBFlags
, EXT2_FCB_NOT_FROM_ZONE
);
1815 if( !Ext2CloseClosableFCB( PtrFCB
) )
1817 // Couldn't close the FCB!!
1819 InsertHeadList( &PtrVCB
->ClosableFCBs
.ClosableFCBListHead
,
1820 &PtrFCB
->ClosableFCBs
.ClosableFCBList
);
1821 return Ext2AllocateFCB();
1824 PtrVCB
->ClosableFCBs
.Count
--;
1825 DebugTrace( DEBUG_TRACE_SPECIAL
, "Count = %ld [Ext2GetUsedFCB]", PtrVCB
->ClosableFCBs
.Count
);
1828 // Getting the FCB ready for reuse by
1829 // zeroing it out...
1831 RtlZeroMemory(PtrFCB
, Ext2QuadAlign(sizeof(Ext2FCB
)));
1833 // set up some fields ...
1834 PtrFCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FCB
;
1835 PtrFCB
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2FCB
));
1838 if (!AllocatedFromZone
)
1840 Ext2SetFlag(PtrFCB
->FCBFlags
, EXT2_FCB_NOT_FROM_ZONE
);
1846 BOOLEAN NTAPI
Ext2CloseClosableFCB(
1850 PFILE_OBJECT PtrFileObject
= NULL
;
1852 AssertFCB( PtrFCB
);
1854 // Attempting to acquire the FCB Exclusively...
1855 if(! ExAcquireResourceExclusiveLite( &(PtrFCB
->NTRequiredFCB
.MainResource
), FALSE
) )
1861 Irql
= KeGetCurrentIrql( );
1863 if( PtrFCB
->ReferenceCount
)
1865 // How the hell can this happen!!!
1868 if( PtrFCB
->OpenHandleCount
)
1870 // How the hell can this happen!!!
1874 // Deleting entry from VCB's FCB list...
1875 RemoveEntryList( &PtrFCB
->NextFCB
);
1877 PtrFCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FREED
;
1879 PtrFileObject
= PtrFCB
->DcbFcb
.Dcb
.PtrDirFileObject
;
1881 if ( PtrFileObject
)
1884 // Clear the Cache Map...
1886 if( PtrFileObject
->PrivateCacheMap
!= NULL
)
1888 IO_STATUS_BLOCK Status
;
1889 DebugTrace( DEBUG_TRACE_SPECIAL
, ">>.........Flushing cache.........<<", 0 );
1890 CcFlushCache( PtrFileObject
->SectionObjectPointer
, NULL
, 0, &Status
);
1891 CcUninitializeCacheMap( PtrFileObject
, NULL
, NULL
);
1894 // The File Object is no longer required...
1895 // Close it by dereferenceing it!!!
1897 PtrFileObject
->FsContext
= NULL
;
1898 PtrFileObject
->FsContext2
= NULL
;
1899 ObDereferenceObject( PtrFileObject
);
1901 PtrFCB
->DcbFcb
.Dcb
.PtrDirFileObject
= NULL
;
1902 PtrFileObject
= NULL
;
1905 // Uninitialize the Resources...
1906 ExDeleteResourceLite( &PtrFCB
->NTRequiredFCB
.MainResource
);
1907 ExDeleteResourceLite( &PtrFCB
->NTRequiredFCB
.PagingIoResource
);
1910 // Releasing the FCB Name Object...
1912 if( PtrFCB
->FCBName
)
1914 DebugTrace( DEBUG_TRACE_SPECIAL
, "Reusing FCB - File Name %S", PtrFCB
->FCBName
->ObjectName
.Buffer
);
1915 Ext2ReleaseObjectName( PtrFCB
->FCBName
);
1919 DebugTrace( DEBUG_TRACE_SPECIAL
, "Reusing FCB - File Name *Unknown*", 0 );
1925 BOOLEAN NTAPI
Ext2SaveBCB(
1926 PtrExt2IrpContext PtrIrpContext
,
1928 PFILE_OBJECT PtrFileObject
)
1930 PEXT2_SAVED_BCBS PtrSavedBCB
;
1931 PLIST_ENTRY PtrEntry
= NULL
;
1933 if( !PtrIrpContext
)
1936 // NULL passed instead of the IRP Context
1937 // This call should be ignored...
1942 if( !AssertBCB( PtrBCB
) )
1944 DebugTrace( DEBUG_TRACE_MISC
, "Not saving BCB!!! [Ext2SaveBCB]", 0 );
1949 DebugTrace( DEBUG_TRACE_SPECIAL
, "Saving BCB [Ext2SaveBCB]", 0 );
1951 // Has the BCB been saved already?
1952 for( PtrEntry
= PtrIrpContext
->SavedBCBsListHead
.Flink
;
1953 PtrEntry
!= &PtrIrpContext
->SavedBCBsListHead
;
1954 PtrEntry
= PtrEntry
->Flink
)
1956 PtrSavedBCB
= CONTAINING_RECORD( PtrEntry
, EXT2_SAVED_BCBS
, SavedBCBsListEntry
);
1957 ASSERT( PtrSavedBCB
);
1958 if( PtrSavedBCB
->PtrBCB
== PtrBCB
)
1961 // A BCB for this file has already been saved for flushing...
1962 // Won't resave this one...
1968 // Reference the BCB
1969 CcRepinBcb( PtrBCB
);
1971 // Now allocate a EXT2_SAVED_BCBS
1972 PtrSavedBCB
= Ext2AllocatePool( NonPagedPool
,
1973 Ext2QuadAlign( sizeof( EXT2_SAVED_BCBS
) ) );
1976 PtrSavedBCB
->NodeIdentifier
.NodeSize
= sizeof( EXT2_SAVED_BCBS
);
1977 PtrSavedBCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_SAVED_BCB
;
1979 PtrSavedBCB
->PtrBCB
= PtrBCB
;
1980 // PtrSavedBCB->PtrFileObject = PtrFileObject;
1982 // Now save it in the IRP Context
1983 InsertHeadList( &PtrIrpContext
->SavedBCBsListHead
, &PtrSavedBCB
->SavedBCBsListEntry
);
1985 PtrIrpContext
->SavedCount
++;
1986 // Return success...
1992 BOOLEAN NTAPI
Ext2FlushSavedBCBs(
1993 PtrExt2IrpContext PtrIrpContext
)
1996 PLIST_ENTRY PtrEntry
= NULL
;
1997 PEXT2_SAVED_BCBS PtrSavedBCB
= NULL
;
1998 IO_STATUS_BLOCK Status
;
2001 if( !IsListEmpty( &PtrIrpContext
->SavedBCBsListHead
) )
2003 DebugTrace( DEBUG_TRACE_SPECIAL
, "Flushing cache... - Ext2FlushSavedBCBs", 0 );
2005 while( !IsListEmpty( &PtrIrpContext
->SavedBCBsListHead
) )
2008 PtrEntry
= RemoveTailList( &PtrIrpContext
->SavedBCBsListHead
);
2011 // No more entries left...
2015 // Get the Saved BCB
2016 PtrSavedBCB
= CONTAINING_RECORD( PtrEntry
, EXT2_SAVED_BCBS
, SavedBCBsListEntry
);
2017 if( PtrSavedBCB
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_SAVED_BCB
)
2019 // Something is wrong...
2024 if( !AssertBCB( PtrSavedBCB
->PtrBCB
) )
2026 // This BCB shouldn't have been saved in the first place...
2027 DebugTrace( DEBUG_TRACE_ERROR
, "Unable to flush BCB - Skipping!!! [Ext2SaveBCB]", 0 );
2031 // Unpin and Flush the cache...
2032 CcUnpinRepinnedBcb( PtrSavedBCB
->PtrBCB
, TRUE
, &Status
);
2034 if( !NT_SUCCESS( Status
.Status
) )
2036 // Failure in flushing...
2037 DebugTrace( DEBUG_TRACE_SPECIAL
, "Failure flushing cache - Ext2FlushSavedBCBs", 0 );
2041 // Release the Saved BCB
2042 PtrSavedBCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_INVALID
;
2044 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrSavedBCB
);
2045 ExFreePool( PtrSavedBCB
);
2047 PtrIrpContext
->SavedCount
--;
2053 BOOLEAN NTAPI
AssertBCB( PBCB PtrBCB
)
2055 PFILE_OBJECT PtrFileObject
= NULL
;
2058 * This routine is simplified version of the original
2059 * AssertBCB and doesn't make any assumptions about
2060 * the layout of undocumented BCB structure.
2061 * -- Filip Navara, 18/08/2004
2064 PtrFileObject
= CcGetFileObjectFromBcb ( PtrBCB
);
2065 if( !PtrFileObject
)
2077 ULONG NTAPI
Ext2Align( ULONG NumberToBeAligned
, ULONG Alignment
)
2079 if( Alignment
& ( Alignment
- 1 ) )
2082 // Alignment not a power of 2
2085 return NumberToBeAligned
;
2087 if( ( NumberToBeAligned
& ( Alignment
- 1 ) ) != 0 )
2089 NumberToBeAligned
= NumberToBeAligned
+ Alignment
;
2090 NumberToBeAligned
= NumberToBeAligned
& ( ~ (Alignment
-1) );
2092 return NumberToBeAligned
;
2095 LONGLONG NTAPI
Ext2Align64( LONGLONG NumberToBeAligned
, LONGLONG Alignment
)
2097 if( Alignment
& ( Alignment
- 1 ) )
2100 // Alignment not a power of 2
2103 return NumberToBeAligned
;
2105 if( ( NumberToBeAligned
& ( Alignment
- 1 ) ) != 0 )
2107 NumberToBeAligned
= NumberToBeAligned
+ Alignment
;
2108 NumberToBeAligned
= NumberToBeAligned
& ( ~ (Alignment
-1) );
2110 return NumberToBeAligned
;
2114 ULONG
Ext2GetCurrentTime()
2116 LARGE_INTEGER CurrentTime
;
2118 KeQuerySystemTime( &CurrentTime
);
2119 Time
= (ULONG
) ( (CurrentTime
.QuadPart
- Ext2GlobalData
.TimeDiff
.QuadPart
) / 10000000 );