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
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 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
);
214 Ext2ClearFlag(Ext2GlobalData
.Ext2Flags
, EXT2_DATA_FLAGS_ZONES_INITIALIZED
);
221 /*************************************************************************
223 * Function: Ext2IsIrpTopLevel()
226 * Helps the FSD determine who the "top level" caller is for this
227 * request. A request can originate directly from a user process
228 * (in which case, the "top level" will be NULL when this routine
229 * is invoked), OR the user may have originated either from the NT
230 * Cache Manager/VMM ("top level" may be set), or this could be a
231 * recursion into our code in which we would have set the "top level"
232 * field the last time around.
234 * Expected Interrupt Level (for execution) :
236 * whatever level a particular dispatch routine is invoked at.
238 * Return Value: TRUE/FALSE (TRUE if top level was NULL when routine invoked)
240 *************************************************************************/
241 BOOLEAN
Ext2IsIrpTopLevel(
242 PIRP Irp
) // the IRP sent to our dispatch routine
244 BOOLEAN ReturnCode
= FALSE
;
246 if (IoGetTopLevelIrp() == NULL
)
248 // OK, so we can set ourselves to become the "top level" component
249 IoSetTopLevelIrp( Irp
);
257 /*************************************************************************
259 * Function: Ext2ExceptionFilter()
262 * This routines allows the driver to determine whether the exception
263 * is an "allowed" exception i.e. one we should not-so-quietly consume
264 * ourselves, or one which should be propagated onwards in which case
265 * we will most likely bring down the machine.
267 * This routine employs the services of FsRtlIsNtstatusExpected(). This
268 * routine returns a BOOLEAN result. A RC of FALSE will cause us to return
269 * EXCEPTION_CONTINUE_SEARCH which will probably cause a panic.
270 * The FsRtl.. routine returns FALSE iff exception values are (currently) :
271 * STATUS_DATATYPE_MISALIGNMENT || STATUS_ACCESS_VIOLATION ||
272 * STATUS_ILLEGAL_INSTRUCTION || STATUS_INSTRUCTION_MISALIGNMENT
274 * Expected Interrupt Level (for execution) :
278 * Return Value: EXCEPTION_EXECUTE_HANDLER/EXECEPTION_CONTINUE_SEARCH
280 *************************************************************************/
281 long Ext2ExceptionFilter(
282 PtrExt2IrpContext PtrIrpContext
,
283 PEXCEPTION_POINTERS PtrExceptionPointers
)
285 long ReturnCode
= EXCEPTION_EXECUTE_HANDLER
;
286 NTSTATUS ExceptionCode
= STATUS_SUCCESS
;
288 // figure out the exception code
289 ExceptionCode
= PtrExceptionPointers
->ExceptionRecord
->ExceptionCode
;
291 if ((ExceptionCode
== STATUS_IN_PAGE_ERROR
) && (PtrExceptionPointers
->ExceptionRecord
->NumberParameters
>= 3))
293 ExceptionCode
= PtrExceptionPointers
->ExceptionRecord
->ExceptionInformation
[2];
298 PtrIrpContext
->SavedExceptionCode
= ExceptionCode
;
299 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_EXCEPTION
);
302 // check if we should propagate this exception or not
303 if (!(FsRtlIsNtstatusExpected(ExceptionCode
)))
305 // we are not ok, propagate this exception.
306 // NOTE: we will bring down the machine ...
307 ReturnCode
= EXCEPTION_CONTINUE_SEARCH
;
309 // better free up the IrpContext now ...
312 Ext2ReleaseIrpContext(PtrIrpContext
);
316 // if you wish to perform some special processing when
317 // not propagating the exception, set up the state for
318 // special processing now ...
320 // return the appropriate code
324 /*************************************************************************
326 * Function: Ext2ExceptionHandler()
329 * One of the routines in the FSD or in the modules we invoked encountered
330 * an exception. We have decided that we will "handle" the exception.
331 * Therefore we will prevent the machine from a panic ...
332 * You can do pretty much anything you choose to in your commercial
333 * driver at this point to ensure a graceful exit. In the sample
334 * driver, I will simply free up the IrpContext (if any), set the
335 * error code in the IRP and complete the IRP at this time ...
337 * Expected Interrupt Level (for execution) :
341 * Return Value: Error code
343 *************************************************************************/
344 NTSTATUS
Ext2ExceptionHandler(
345 PtrExt2IrpContext PtrIrpContext
,
354 RC
= PtrIrpContext
->SavedExceptionCode
;
355 // Free irp context here
356 Ext2ReleaseIrpContext(PtrIrpContext
);
360 // must be insufficient resources ...?
361 RC
= STATUS_INSUFFICIENT_RESOURCES
;
364 // set the error code in the IRP
365 Irp
->IoStatus
.Status
= RC
;
366 Irp
->IoStatus
.Information
= 0;
369 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
374 /*************************************************************************
376 * Function: Ext2LogEvent()
379 * Log a message in the NT Event Log. This is a rather simplistic log
380 * methodology since you can potentially utilize the event log to
381 * provide a lot of information to the user (and you should too!)
383 * Expected Interrupt Level (for execution) :
389 *************************************************************************/
391 NTSTATUS Ext2EventLogId
, // the Ext2 private message id
392 NTSTATUS RC
) // any NT error code we wish to log ...
397 // Implement a call to IoAllocateErrorLogEntry() followed by a call
398 // to IoWriteErrorLogEntry(). You should note that the call to IoWriteErrorLogEntry()
399 // will free memory for the entry once the write completes (which in actuality
400 // is an asynchronous operation).
403 except (EXCEPTION_EXECUTE_HANDLER
)
405 // nothing really we can do here, just do not wish to crash ...
412 /*************************************************************************
414 * Function: Ext2AllocateObjectName()
417 * Allocate a new ObjectName structure to represent an open on-disk object.
418 * Also initialize the ObjectName structure to NULL.
420 * Expected Interrupt Level (for execution) :
424 * Return Value: A pointer to the ObjectName structure OR NULL.
426 *************************************************************************/
427 PtrExt2ObjectName
Ext2AllocateObjectName(
430 PtrExt2ObjectName PtrObjectName
= NULL
;
431 BOOLEAN AllocatedFromZone
= TRUE
;
434 // first, try to allocate out of the zone
435 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
436 if (!ExIsFullZone(&(Ext2GlobalData.ObjectNameZoneHeader))) {
437 // we have enough memory
438 PtrObjectName = (PtrExt2ObjectName)ExAllocateFromZone(&(Ext2GlobalData.ObjectNameZoneHeader));
440 // release the spinlock
441 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
443 // release the spinlock
444 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
446 // if we failed to obtain from the zone, get it directly from the VMM
448 PtrObjectName
= (PtrExt2ObjectName
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2ObjectName
)) );
449 AllocatedFromZone
= FALSE
;
453 // if we could not obtain the required memory, bug-check.
454 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
457 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2ObjectName
)), 0);
460 // zero out the allocated memory block
461 RtlZeroMemory( PtrObjectName
, Ext2QuadAlign(sizeof(Ext2ObjectName
)) );
463 // set up some fields ...
464 PtrObjectName
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_OBJECT_NAME
;
465 PtrObjectName
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2ObjectName
));
468 if (!AllocatedFromZone
)
470 Ext2SetFlag(PtrObjectName
->ObjectNameFlags
, EXT2_OB_NAME_NOT_FROM_ZONE
);
473 return(PtrObjectName
);
477 /*************************************************************************
479 * Function: Ext2ReleaseObjectName()
482 * Deallocate a previously allocated structure.
484 * Expected Interrupt Level (for execution) :
490 *************************************************************************/
491 void Ext2ReleaseObjectName(
492 PtrExt2ObjectName PtrObjectName
)
496 ASSERT(PtrObjectName
);
497 PtrObjectName
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FREED
;
500 // give back memory either to the zone or to the VMM
501 if (!(PtrObjectName
->ObjectNameFlags
& EXT2_OB_NAME_NOT_FROM_ZONE
))
504 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
505 ExFreeToZone(&(Ext2GlobalData
.ObjectNameZoneHeader
), PtrObjectName
);
506 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
512 Ext2DeallocateUnicodeString( & PtrObjectName
->ObjectName
);
514 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrObjectName
);
515 ExFreePool(PtrObjectName
);
523 /*************************************************************************
525 * Function: Ext2AllocateCCB()
528 * Allocate a new CCB structure to represent an open on-disk object.
529 * Also initialize the CCB structure to NULL.
531 * Expected Interrupt Level (for execution) :
535 * Return Value: A pointer to the CCB structure OR NULL.
537 *************************************************************************/
538 PtrExt2CCB
Ext2AllocateCCB(
541 PtrExt2CCB PtrCCB
= NULL
;
542 BOOLEAN AllocatedFromZone
= TRUE
;
547 // first, try to allocate out of the zone
548 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
549 if (!ExIsFullZone(&(Ext2GlobalData
.CCBZoneHeader
)))
551 // we have enough memory
552 PtrCCB
= (PtrExt2CCB
)ExAllocateFromZone(&(Ext2GlobalData
.CCBZoneHeader
));
554 // release the spinlock
555 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
559 // release the spinlock
560 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
561 // if we failed to obtain from the zone, get it directly from the VMM
564 PtrCCB
= (PtrExt2CCB
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2CCB
)) );
565 AllocatedFromZone
= FALSE
;
571 // if we could not obtain the required memory, bug-check.
572 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
575 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2CCB
)), 0);
578 // zero out the allocated memory block
579 RtlZeroMemory(PtrCCB
, Ext2QuadAlign(sizeof(Ext2CCB
)));
581 // set up some fields ...
582 PtrCCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_CCB
;
583 PtrCCB
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2CCB
));
586 if (!AllocatedFromZone
)
588 Ext2SetFlag(PtrCCB
->CCBFlags
, EXT2_CCB_NOT_FROM_ZONE
);
594 /*************************************************************************
596 * Function: Ext2ReleaseCCB()
599 * Deallocate a previously allocated structure.
601 * Expected Interrupt Level (for execution) :
607 *************************************************************************/
614 if(PtrCCB
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_CCB
)
616 Ext2Panic( PtrCCB
, PtrCCB
->NodeIdentifier
.NodeType
, EXT2_NODE_TYPE_CCB
) ;
619 Ext2DeallocateUnicodeString( &PtrCCB
->DirectorySearchPattern
);
620 Ext2DeallocateUnicodeString( &PtrCCB
->AbsolutePathName
);
621 Ext2DeallocateUnicodeString( &PtrCCB
->RenameLinkTargetFileName
);
626 // give back memory either to the zone or to the VMM
627 if (!(PtrCCB
->CCBFlags
& EXT2_CCB_NOT_FROM_ZONE
))
630 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
631 ExFreeToZone(&(Ext2GlobalData
.CCBZoneHeader
), PtrCCB
);
632 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
637 PtrCCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FREED
;
638 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrCCB
);
648 /*************************************************************************
650 * Function: Ext2AllocateFCB()
653 * Allocate a new FCB structure to represent an open on-disk object.
654 * Also initialize the FCB structure to NULL.
656 * Expected Interrupt Level (for execution) :
660 * Return Value: A pointer to the FCB structure OR NULL.
662 *************************************************************************/
663 PtrExt2FCB
Ext2AllocateFCB(
666 PtrExt2FCB PtrFCB
= NULL
;
667 BOOLEAN AllocatedFromZone
= TRUE
;
670 // first, try to allocate out of the zone
673 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
674 if (!ExIsFullZone(&(Ext2GlobalData
.FCBZoneHeader
))) {
675 // we have enough memory
676 PtrFCB
= (PtrExt2FCB
)ExAllocateFromZone(&(Ext2GlobalData
.FCBZoneHeader
));
678 // release the spinlock
679 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
681 // release the spinlock
682 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
684 // if we failed to obtain from the zone, get it directly from the VMM
685 PtrFCB
= (PtrExt2FCB
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2FCB
)) );
686 AllocatedFromZone
= FALSE
;
692 // if we could not obtain the required memory, bug-check.
693 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
696 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2FCB
)), 0);
699 // zero out the allocated memory block
700 RtlZeroMemory(PtrFCB
, Ext2QuadAlign(sizeof(Ext2FCB
)));
702 // set up some fields ...
703 PtrFCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FCB
;
704 PtrFCB
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2FCB
));
707 if (!AllocatedFromZone
)
709 Ext2SetFlag(PtrFCB
->FCBFlags
, EXT2_FCB_NOT_FROM_ZONE
);
716 /*************************************************************************
718 * Function: Ext2CreateNewFCB()
721 * We want to create a new FCB. We will also create a new CCB (presumably)
722 * later. Simply allocate a new FCB structure and initialize fields
724 * This function also takes the file size values that the caller must
725 * have obtained and will set the file size fields appropriately in the
727 * Finally, this routine will initialize the FileObject structure passed
728 * in to this function. If you decide to fail the call later, remember
729 * to uninitialize the fields.
731 * Expected Interrupt Level (for execution) :
735 * Return Value: A pointer to the FCB structure OR NULL.
737 *************************************************************************/
738 NTSTATUS
Ext2CreateNewFCB(
739 PtrExt2FCB
*ReturnedFCB
,
740 LARGE_INTEGER AllocationSize
,
741 LARGE_INTEGER EndOfFile
,
742 PFILE_OBJECT PtrFileObject
,
744 PtrExt2ObjectName PtrObjectName
)
746 NTSTATUS RC
= STATUS_SUCCESS
;
748 PtrExt2FCB PtrFCB
= NULL
;
749 PtrExt2NTRequiredFCB PtrReqdFCB
= NULL
;
750 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader
= NULL
;
758 PtrFCB
= Ext2GetUsedFCB( PtrVCB
);
763 // Obtain a new FCB structure.
764 // The function Ext2AllocateFCB() will obtain a new structure either
765 // from a zone or from memory requested directly from the VMM.
766 PtrFCB
= Ext2AllocateFCB();
770 // Assume lack of memory.
771 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
774 // Initialize fields required to interface with the NT Cache Manager.
775 // Note that the returned structure has already been zeroed. This means
776 // that the SectionObject structure has been zeroed which is a
777 // requirement for newly created FCB structures.
778 PtrReqdFCB
= &(PtrFCB
->NTRequiredFCB
);
780 // Initialize the MainResource and PagingIoResource structures now.
781 ExInitializeResourceLite(&(PtrReqdFCB
->MainResource
));
782 Ext2SetFlag(PtrFCB
->FCBFlags
, EXT2_INITIALIZED_MAIN_RESOURCE
);
784 ExInitializeResourceLite(&(PtrReqdFCB
->PagingIoResource
));
785 Ext2SetFlag(PtrFCB
->FCBFlags
, EXT2_INITIALIZED_PAGING_IO_RESOURCE
);
787 // Start initializing the fields contained in the CommonFCBHeader.
788 PtrCommonFCBHeader
= &(PtrReqdFCB
->CommonFCBHeader
);
790 // Disallow fast-IO for now.
791 PtrCommonFCBHeader
->IsFastIoPossible
= FastIoIsNotPossible
;
793 // Initialize the MainResource and PagingIoResource pointers in
794 // the CommonFCBHeader structure to point to the ERESOURCE structures we
795 // have allocated and already initialized above.
796 PtrCommonFCBHeader
->Resource
= &(PtrReqdFCB
->MainResource
);
797 PtrCommonFCBHeader
->PagingIoResource
= &(PtrReqdFCB
->PagingIoResource
);
799 // Ignore the Flags field in the CommonFCBHeader for now. Part 3
800 // of the book describes it in greater detail.
802 // Initialize the file size values here.
803 PtrCommonFCBHeader
->AllocationSize
= AllocationSize
;
804 PtrCommonFCBHeader
->FileSize
= EndOfFile
;
806 // The following will disable ValidDataLength support. However, your
807 // FSD may choose to support this concept.
808 PtrCommonFCBHeader
->ValidDataLength
.LowPart
= 0xFFFFFFFF;
809 PtrCommonFCBHeader
->ValidDataLength
.HighPart
= 0x7FFFFFFF;
811 // Initialize other fields for the FCB here ...
812 PtrFCB
->PtrVCB
= PtrVCB
;
814 // caller MUST ensure that VCB has been acquired exclusively
815 InsertTailList(&(PtrVCB
->FCBListHead
), &(PtrFCB
->NextFCB
));
818 InitializeListHead(&(PtrFCB
->CCBListHead
));
820 // Initialize fields contained in the file object now.
823 PtrFileObject
->PrivateCacheMap
= NULL
;
824 // Note that we could have just as well taken the value of PtrReqdFCB
825 // directly below. The bottom line however is that the FsContext
826 // field must point to a FSRTL_COMMON_FCB_HEADER structure.
827 PtrFileObject
->FsContext
= (void *)(PtrCommonFCBHeader
);
828 PtrFileObject
->SectionObjectPointer
= &(PtrFCB
->NTRequiredFCB
.SectionObject
) ;
831 // Initialising the object name...
832 PtrFCB
->FCBName
= PtrObjectName
;
834 // Returning the FCB...
835 *ReturnedFCB
= PtrFCB
;
848 /*************************************************************************
850 * Function: Ext2ReleaseFCB()
853 * Deallocate a previously allocated structure.
855 * Expected Interrupt Level (for execution) :
861 *************************************************************************/
869 if( PtrFCB
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_FCB
)
871 Ext2Panic( PtrFCB
, PtrFCB
->NodeIdentifier
.NodeType
, EXT2_NODE_TYPE_FCB
) ;
875 PtrFCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FREED
;
878 // give back memory either to the zone or to the VMM
879 if (!(PtrFCB->FCBFlags & EXT2_FCB_NOT_FROM_ZONE))
882 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
883 ExFreeToZone(&(Ext2GlobalData.FCBZoneHeader), PtrFCB);
884 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
890 ExDeleteResourceLite( &PtrFCB
->NTRequiredFCB
.MainResource
);
891 ExDeleteResourceLite( &PtrFCB
->NTRequiredFCB
.PagingIoResource
);
893 if( PtrFCB
->FCBName
)
895 Ext2ReleaseObjectName( PtrFCB
->FCBName
);
898 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrFCB
);
908 /*************************************************************************
910 * Function: Ext2AllocateByteLocks()
913 * Allocate a new byte range lock structure and initialize it to NULL.
915 * Expected Interrupt Level (for execution) :
919 * Return Value: A pointer to the Ext2ByteLocks structure OR NULL.
921 *************************************************************************/
922 PtrExt2FileLockInfo
Ext2AllocateByteLocks(
925 PtrExt2FileLockInfo PtrByteLocks
= NULL
;
926 BOOLEAN AllocatedFromZone
= TRUE
;
929 // first, try to allocate out of the zone
930 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
931 if (!ExIsFullZone(&(Ext2GlobalData
.ByteLockZoneHeader
)))
933 // we have enough memory
934 PtrByteLocks
= (PtrExt2FileLockInfo
)ExAllocateFromZone(&(Ext2GlobalData
.ByteLockZoneHeader
));
936 // release the spinlock
937 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
941 // release the spinlock
942 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
944 // if we failed to obtain from the zone, get it directly from the VMM
945 PtrByteLocks
= (PtrExt2FileLockInfo
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2FileLockInfo
)) );
946 AllocatedFromZone
= FALSE
;
949 // if we could not obtain the required memory, bug-check.
950 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
953 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2FileLockInfo
)), 0);
956 // zero out the allocated memory block
957 RtlZeroMemory(PtrByteLocks
, Ext2QuadAlign(sizeof(PtrExt2FileLockInfo
)));
959 if (!AllocatedFromZone
)
961 Ext2SetFlag(PtrByteLocks
->FileLockFlags
, EXT2_BYTE_LOCK_NOT_FROM_ZONE
);
964 return(PtrByteLocks
);
967 /*************************************************************************
969 * Function: Ext2ReleaseByteLocks()
972 * Deallocate a previously allocated structure.
974 * Expected Interrupt Level (for execution) :
980 *************************************************************************/
981 void Ext2ReleaseByteLocks(
982 PtrExt2FileLockInfo PtrByteLocks
)
986 ASSERT(PtrByteLocks
);
988 // give back memory either to the zone or to the VMM
989 if (!(PtrByteLocks
->FileLockFlags
& EXT2_BYTE_LOCK_NOT_FROM_ZONE
)) {
991 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
992 ExFreeToZone(&(Ext2GlobalData
.ByteLockZoneHeader
), PtrByteLocks
);
993 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
997 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrByteLocks
);
998 ExFreePool(PtrByteLocks
);
1005 /*************************************************************************
1007 * Function: Ext2AllocateIrpContext()
1010 * The sample FSD creates an IRP context for each request received. This
1011 * routine simply allocates (and initializes to NULL) a Ext2IrpContext
1013 * Most of the fields in the context structure are then initialized here.
1015 * Expected Interrupt Level (for execution) :
1017 * IRQL_PASSIVE_LEVEL
1019 * Return Value: A pointer to the IrpContext structure OR NULL.
1021 *************************************************************************/
1022 PtrExt2IrpContext
Ext2AllocateIrpContext(
1024 PDEVICE_OBJECT PtrTargetDeviceObject
)
1026 PtrExt2IrpContext PtrIrpContext
= NULL
;
1027 BOOLEAN AllocatedFromZone
= TRUE
;
1029 PIO_STACK_LOCATION PtrIoStackLocation
= NULL
;
1032 // Allocation from zone not done at present...
1034 // first, try to allocate out of the zone
1035 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql);
1036 if (!ExIsFullZone(&(Ext2GlobalData.IrpContextZoneHeader))) {
1037 // we have enough memory
1038 PtrIrpContext = (PtrExt2IrpContext)ExAllocateFromZone(&(Ext2GlobalData.IrpContextZoneHeader));
1040 // release the spinlock
1041 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
1043 // release the spinlock
1044 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql);
1049 // if we failed to obtain from the zone, get it directly from the VMM
1050 PtrIrpContext = (PtrExt2IrpContext)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2IrpContext)) );
1051 AllocatedFromZone = FALSE;
1054 //No Zone handling for now
1057 PtrIrpContext
= (PtrExt2IrpContext
)Ext2AllocatePool(NonPagedPool
, Ext2QuadAlign(sizeof(Ext2IrpContext
)) );
1058 AllocatedFromZone
= FALSE
;
1060 // if we could not obtain the required memory, bug-check.
1061 // Do NOT do this in your commercial driver, instead handle the error gracefully ...
1064 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES
, Ext2QuadAlign(sizeof(Ext2IrpContext
)), 0);
1067 // zero out the allocated memory block
1068 RtlZeroMemory(PtrIrpContext
, Ext2QuadAlign(sizeof(Ext2IrpContext
)));
1070 // set up some fields ...
1071 PtrIrpContext
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_IRP_CONTEXT
;
1072 PtrIrpContext
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2IrpContext
));
1075 PtrIrpContext
->Irp
= Irp
;
1076 PtrIrpContext
->TargetDeviceObject
= PtrTargetDeviceObject
;
1078 // copy over some fields from the IRP and set appropriate flag values
1081 PtrIoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1082 ASSERT(PtrIoStackLocation
);
1084 PtrIrpContext
->MajorFunction
= PtrIoStackLocation
->MajorFunction
;
1085 PtrIrpContext
->MinorFunction
= PtrIoStackLocation
->MinorFunction
;
1087 // Often, a FSD cannot honor a request for asynchronous processing
1088 // of certain critical requests. For example, a "close" request on
1089 // a file object can typically never be deferred. Therefore, do not
1090 // be surprised if sometimes your FSD (just like all other FSD
1091 // implementations on the Windows NT system) has to override the flag
1093 if( PtrIoStackLocation
->FileObject
)
1095 if (IoIsOperationSynchronous(Irp
) )
1097 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_CAN_BLOCK
);
1102 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_CAN_BLOCK
);
1106 if (!AllocatedFromZone
)
1108 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_NOT_FROM_ZONE
);
1111 // Are we top-level ? This information is used by the dispatching code
1112 // later (and also by the FSD dispatch routine)
1113 if (IoGetTopLevelIrp() != Irp
)
1115 // We are not top-level. Note this fact in the context structure
1116 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_NOT_TOP_LEVEL
);
1119 InitializeListHead( &PtrIrpContext
->SavedBCBsListHead
);
1121 return(PtrIrpContext
);
1125 /*************************************************************************
1127 * Function: Ext2ReleaseIrpContext()
1130 * Deallocate a previously allocated structure.
1132 * Expected Interrupt Level (for execution) :
1134 * IRQL_PASSIVE_LEVEL
1136 * Return Value: None
1138 *************************************************************************/
1139 void Ext2ReleaseIrpContext(
1140 PtrExt2IrpContext PtrIrpContext
)
1144 ASSERT(PtrIrpContext
);
1146 // Flush the saved BCBs...
1147 Ext2FlushSavedBCBs( PtrIrpContext
);
1149 // give back memory either to the zone or to the VMM
1150 if (!(PtrIrpContext
->IrpContextFlags
& EXT2_IRP_CONTEXT_NOT_FROM_ZONE
))
1153 KeAcquireSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), &CurrentIrql
);
1154 ExFreeToZone(&(Ext2GlobalData
.IrpContextZoneHeader
), PtrIrpContext
);
1155 KeReleaseSpinLock(&(Ext2GlobalData
.ZoneAllocationSpinLock
), CurrentIrql
);
1159 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrIrpContext
);
1160 ExFreePool(PtrIrpContext
);
1166 /*************************************************************************
1168 * Function: Ext2PostRequest()
1171 * Queue up a request for deferred processing (in the context of a system
1172 * worker thread). The caller must have locked the user buffer (if required)
1174 * Expected Interrupt Level (for execution) :
1176 * IRQL_PASSIVE_LEVEL
1178 * Return Value: STATUS_PENDING
1180 *************************************************************************/
1181 NTSTATUS
Ext2PostRequest(
1182 PtrExt2IrpContext PtrIrpContext
,
1185 NTSTATUS RC
= STATUS_PENDING
;
1187 DebugTrace(DEBUG_TRACE_ASYNC
, " === Asynchronous request. Deferring processing", 0);
1189 // mark the IRP pending
1190 IoMarkIrpPending(PtrIrp
);
1192 // queue up the request
1193 ExInterlockedInsertTailList(
1194 &Ext2GlobalData
.ThreadQueue
.ThreadQueueListHead
,
1195 &PtrIrpContext
->ThreadQueueListEntry
,
1196 &Ext2GlobalData
.ThreadQueue
.SpinLock
);
1198 KeSetEvent( &Ext2GlobalData
.ThreadQueue
.QueueEvent
, 0, FALSE
);
1201 /***************** not using system worker threads *****************
1202 ExInitializeWorkItem(&(PtrIrpContext->WorkQueueItem), Ext2CommonDispatch, PtrIrpContext);
1203 ExQueueWorkItem( &( PtrIrpContext->WorkQueueItem ), DelayedWorkQueue );
1204 // CriticalWorkQueue
1205 *****************************************************************************/
1207 // return status pending
1212 /*************************************************************************
1214 * Function: Ext2CommonDispatch()
1217 * The common dispatch routine invoked in the context of a system worker
1218 * thread. All we do here is pretty much case off the major function
1219 * code and invoke the appropriate FSD dispatch routine for further
1222 * Expected Interrupt Level (for execution) :
1224 * IRQL PASSIVE_LEVEL
1226 * Return Value: None
1228 *************************************************************************/
1229 void Ext2CommonDispatch(
1230 void *Context
) // actually an IRPContext structure
1232 NTSTATUS RC
= STATUS_SUCCESS
;
1233 PtrExt2IrpContext PtrIrpContext
= NULL
;
1236 // The context must be a pointer to an IrpContext structure
1237 PtrIrpContext
= (PtrExt2IrpContext
)Context
;
1238 ASSERT(PtrIrpContext
);
1240 // Assert that the Context is legitimate
1241 if ((PtrIrpContext
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_IRP_CONTEXT
) || (PtrIrpContext
->NodeIdentifier
.NodeSize
!= Ext2QuadAlign(sizeof(Ext2IrpContext
))))
1243 // This does not look good
1244 Ext2Panic(EXT2_ERROR_INTERNAL_ERROR
, PtrIrpContext
->NodeIdentifier
.NodeType
, PtrIrpContext
->NodeIdentifier
.NodeSize
);
1247 // Get a pointer to the IRP structure
1248 PtrIrp
= PtrIrpContext
->Irp
;
1251 // Now, check if the FSD was top level when the IRP was originally invoked
1252 // and set the thread context (for the worker thread) appropriately
1253 if (PtrIrpContext
->IrpContextFlags
& EXT2_IRP_CONTEXT_NOT_TOP_LEVEL
)
1255 // The FSD is not top level for the original request
1256 // Set a constant value in TLS to reflect this fact
1257 IoSetTopLevelIrp((PIRP
)FSRTL_FSP_TOP_LEVEL_IRP
);
1260 // Since the FSD routine will now be invoked in the context of this worker
1261 // thread, we should inform the FSD that it is perfectly OK to block in
1262 // the context of this thread
1263 Ext2SetFlag(PtrIrpContext
->IrpContextFlags
, EXT2_IRP_CONTEXT_CAN_BLOCK
);
1265 FsRtlEnterFileSystem();
1270 // Pre-processing has been completed; check the Major Function code value
1271 // either in the IrpContext (copied from the IRP), or directly from the
1272 // IRP itself (we will need a pointer to the stack location to do that),
1273 // Then, switch based on the value on the Major Function code
1274 switch (PtrIrpContext
->MajorFunction
)
1277 // Invoke the common create routine
1278 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_CREATE request asynchronously .", 0);
1279 (void)Ext2CommonCreate(PtrIrpContext
, PtrIrp
, FALSE
);
1282 // Invoke the common read routine
1283 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_READ request asynchronously .", 0);
1284 (void)Ext2CommonRead(PtrIrpContext
, PtrIrp
, FALSE
);
1287 // Invoke the common write routine
1288 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_WRITE request asynchronously .", 0);
1289 (void)Ext2CommonWrite(PtrIrpContext
, PtrIrp
);
1292 case IRP_MJ_CLEANUP
:
1293 // Invoke the common read routine
1294 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_CLEANUP request asynchronously .", 0);
1295 (void)Ext2CommonCleanup(PtrIrpContext
, PtrIrp
, FALSE
);
1298 // Invoke the common read routine
1299 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing IRP_MJ_CLOSE request asynchronously .", 0);
1300 (void)Ext2CommonClose ( PtrIrpContext
, PtrIrp
, FALSE
);
1303 // Continue with the remaining possible dispatch routines below ...
1305 // This is the case where we have an invalid major function
1306 DebugTrace(DEBUG_TRACE_ASYNC
, " === Serviceing asynchronous request. \nUnable to recoganise the IRP!!! How can this be!!!", 0);
1307 PtrIrp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1308 PtrIrp
->IoStatus
.Information
= 0;
1312 IoCompleteRequest(PtrIrp
, IO_NO_INCREMENT
);
1316 except (Ext2ExceptionFilter(PtrIrpContext
, GetExceptionInformation()))
1318 RC
= Ext2ExceptionHandler(PtrIrpContext
, PtrIrp
);
1319 Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR
, RC
);
1322 // Enable preemption
1323 FsRtlExitFileSystem();
1325 // Ensure that the "top-level" field is cleared
1326 IoSetTopLevelIrp(NULL
);
1328 PsTerminateSystemThread( RC
);
1334 /*************************************************************************
1336 * Function: Ext2InitializeVCB()
1339 * Perform the initialization for a VCB structure.
1341 * Expected Interrupt Level (for execution) :
1343 * IRQL PASSIVE_LEVEL
1345 * Return Value: None
1347 *************************************************************************/
1348 void Ext2InitializeVCB(
1349 PDEVICE_OBJECT PtrVolumeDeviceObject
,
1350 PDEVICE_OBJECT PtrTargetDeviceObject
,
1352 PLARGE_INTEGER AllocationSize
)
1354 NTSTATUS RC
= STATUS_SUCCESS
;
1355 PtrExt2VCB PtrVCB
= NULL
;
1356 BOOLEAN VCBResourceInitialized
= FALSE
;
1358 PtrVCB
= (PtrExt2VCB
)(PtrVolumeDeviceObject
->DeviceExtension
);
1360 // Zero it out (typically this has already been done by the I/O
1361 // Manager but it does not hurt to do it again)!
1362 RtlZeroMemory(PtrVCB
, sizeof(Ext2VCB
));
1364 // Initialize the signature fields
1365 PtrVCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_VCB
;
1366 PtrVCB
->NodeIdentifier
.NodeSize
= sizeof(Ext2VCB
);
1368 // Initialize the ERESOURCE objects.
1369 RC
= ExInitializeResourceLite(&(PtrVCB
->VCBResource
));
1370 RC
= ExInitializeResourceLite(&(PtrVCB
->PagingIoResource
));
1372 ASSERT(NT_SUCCESS(RC
));
1373 VCBResourceInitialized
= TRUE
;
1375 PtrVCB
->TargetDeviceObject
= PtrTargetDeviceObject
;
1377 PtrVCB
->VCBDeviceObject
= PtrVolumeDeviceObject
;
1379 PtrVCB
->PtrVPB
= PtrVPB
;
1381 // Initialize the list anchor (head) for some lists in this VCB.
1382 InitializeListHead(&(PtrVCB
->FCBListHead
));
1383 InitializeListHead(&(PtrVCB
->NextNotifyIRP
));
1384 InitializeListHead(&(PtrVCB
->VolumeOpenListHead
));
1385 InitializeListHead(&(PtrVCB
->ClosableFCBs
.ClosableFCBListHead
));
1386 PtrVCB
->ClosableFCBs
.Count
= 0;
1388 // Initialize the notify IRP list mutex
1389 KeInitializeMutex(&(PtrVCB
->NotifyIRPMutex
), 0);
1391 // Set the initial file size values appropriately. Note that your FSD may
1392 // wish to guess at the initial amount of information you would like to
1393 // read from the disk until you have really determined that this a valid
1394 // logical volume (on disk) that you wish to mount.
1395 PtrVCB
->CommonVCBHeader
.AllocationSize
.QuadPart
= AllocationSize
->QuadPart
;
1397 PtrVCB
->CommonVCBHeader
.FileSize
.QuadPart
= AllocationSize
->QuadPart
;
1398 // You typically do not want to bother with valid data length callbacks
1399 // from the Cache Manager for the file stream opened for volume metadata
1401 PtrVCB
->CommonVCBHeader
.ValidDataLength
.LowPart
= 0xFFFFFFFF;
1402 PtrVCB
->CommonVCBHeader
.ValidDataLength
.HighPart
= 0x7FFFFFFF;
1404 PtrVCB
->CommonVCBHeader
.IsFastIoPossible
= FastIoIsNotPossible
;
1406 PtrVCB
->CommonVCBHeader
.Resource
= &(PtrVCB
->VCBResource
);
1407 PtrVCB
->CommonVCBHeader
.PagingIoResource
= &(PtrVCB
->PagingIoResource
);;
1409 // Create a stream file object for this volume.
1410 PtrVCB
->PtrStreamFileObject
= IoCreateStreamFileObject(NULL
,
1411 PtrVCB
->PtrVPB
->RealDevice
);
1412 ASSERT(PtrVCB
->PtrStreamFileObject
);
1414 // Initialize some important fields in the newly created file object.
1415 PtrVCB
->PtrStreamFileObject
->FsContext
= (void *)(&PtrVCB
->CommonVCBHeader
);
1416 PtrVCB
->PtrStreamFileObject
->FsContext2
= NULL
;
1417 PtrVCB
->PtrStreamFileObject
->SectionObjectPointer
= &(PtrVCB
->SectionObject
);
1419 PtrVCB
->PtrStreamFileObject
->Vpb
= PtrVPB
;
1420 PtrVCB
->PtrStreamFileObject
->ReadAccess
= TRUE
;
1421 PtrVCB
->PtrStreamFileObject
->WriteAccess
= TRUE
;
1423 // Link this chap onto the global linked list of all VCB structures.
1424 DebugTrace(DEBUG_TRACE_MISC
, "*** Attempting to acquire Global Resource Exclusively [FileInfo]", 0);
1425 ExAcquireResourceExclusiveLite(&(Ext2GlobalData
.GlobalDataResource
), TRUE
);
1426 InsertTailList(&(Ext2GlobalData
.NextVCB
), &(PtrVCB
->NextVCB
));
1427 DebugTrace(DEBUG_TRACE_MISC
, "*** Global Resource Acquired [FileInfo]", 0);
1431 // Initialize caching for the stream file object.
1432 CcInitializeCacheMap(PtrVCB
->PtrStreamFileObject
, (PCC_FILE_SIZES
)(&(PtrVCB
->CommonVCBHeader
.AllocationSize
)),
1433 TRUE
, // We will use pinned access.
1434 &(Ext2GlobalData
.CacheMgrCallBacks
), PtrVCB
);
1437 Ext2ReleaseResource(&(Ext2GlobalData
.GlobalDataResource
));
1438 DebugTrace(DEBUG_TRACE_MISC
, "*** Global Resource Released[FileInfo]", 0);
1440 // Mark the fact that this VCB structure is initialized.
1441 Ext2SetFlag(PtrVCB
->VCBFlags
, EXT2_VCB_FLAGS_VCB_INITIALIZED
);
1442 PtrVCB
->PtrGroupDescriptors
= NULL
;
1443 PtrVCB
->NoOfGroups
= 0;
1449 /*************************************************************************
1451 * Function: Ext2CompleteRequest()
1454 * This routine completes a Irp.
1456 * Expected Interrupt Level (for execution) :
1462 * Irp - Supplies the Irp being processed
1464 * Status - Supplies the status to complete the Irp with
1466 * Return Value: none
1468 *************************************************************************/
1469 void Ext2CompleteRequest(
1470 IN PIRP Irp OPTIONAL
,
1475 // If we have an Irp then complete the irp.
1482 // We got an error, so zero out the information field before
1483 // completing the request if this was an input operation.
1484 // Otherwise IopCompleteRequest will try to copy to the user's buffer.
1487 if ( NT_ERROR(Status
) &&
1488 FlagOn(Irp
->Flags
, IRP_INPUT_OPERATION
) ) {
1490 Irp
->IoStatus
.Information
= 0;
1493 Irp
->IoStatus
.Status
= Status
;
1495 IoCompleteRequest( Irp
, IO_DISK_INCREMENT
);
1501 /*************************************************************************
1503 * Function: Ext2CreateNewCCB()
1506 * We want to create a new CCB.
1508 * Expected Interrupt Level (for execution) :
1510 * IRQL_PASSIVE_LEVEL
1512 * Return Value: A pointer to the CCB structure OR NULL.
1514 *************************************************************************/
1515 NTSTATUS
Ext2CreateNewCCB(
1516 PtrExt2CCB
*ReturnedCCB
,
1518 PFILE_OBJECT PtrFileObject
)
1521 NTSTATUS RC
= STATUS_SUCCESS
;
1526 PtrCCB
= Ext2AllocateCCB();
1529 // Assume lack of memory.
1530 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
1532 PtrCCB
->PtrFCB
= PtrFCB
;
1534 PtrCCB
->PtrFileObject
= PtrFileObject
;
1535 PtrCCB
->CurrentByteOffset
.QuadPart
= 0;
1537 if( PtrFCB
->ClosableFCBs
.OnClosableFCBList
)
1539 // This FCB was on the Closable List...
1540 // Taking it off the list...
1542 RemoveEntryList( &PtrFCB
->ClosableFCBs
.ClosableFCBList
);
1543 PtrFCB
->ClosableFCBs
.OnClosableFCBList
= FALSE
;
1544 PtrFCB
->PtrVCB
->ClosableFCBs
.Count
--;
1547 InterlockedIncrement( &PtrFCB
->ReferenceCount
);
1548 InterlockedIncrement( &PtrFCB
->OpenHandleCount
);
1550 InsertTailList( &( PtrFCB
->CCBListHead
), &(PtrCCB
->NextCCB
));
1552 *ReturnedCCB
= PtrCCB
;
1564 /*************************************************************************
1566 * Function: Ext2DenyAccess()
1569 * We want to deny access to an IRP
1571 * Expected Interrupt Level (for execution) :
1573 * IRQL_PASSIVE_LEVEL
1575 * Return Value: NTSTATUS - STATUS_ACCESS_DENIED (always)
1577 *************************************************************************/
1578 NTSTATUS
Ext2DenyAccess( IN PIRP Irp
)
1582 // Just return Access Denied
1583 Irp
->IoStatus
.Information
= 0;
1584 Irp
->IoStatus
.Status
= STATUS_ACCESS_DENIED
;
1585 IoCompleteRequest( Irp
, IO_DISK_INCREMENT
);
1587 DebugTrace(DEBUG_TRACE_MISC
, "DENYING ACCESS (this will do for now!)...", 0);
1589 return STATUS_ACCESS_DENIED
;
1594 /*************************************************************************
1596 * Function: Ext2GetFCB_CCB_VCB_FromFileObject()
1599 * This routine retrieves the FCB, CCB and VCB from the File Object...
1601 * Expected Interrupt Level (for execution) :
1605 * Return Value: NTSTATUS - STATUS_SUCCESS(always)
1607 *************************************************************************/
1608 NTSTATUS
Ext2GetFCB_CCB_VCB_FromFileObject (
1609 IN PFILE_OBJECT PtrFileObject
,
1610 OUT PtrExt2FCB
*PPtrFCB
,
1611 OUT PtrExt2CCB
*PPtrCCB
,
1612 OUT PtrExt2VCB
*PPtrVCB
)
1616 (*PPtrCCB
) = (PtrExt2CCB
)(PtrFileObject
->FsContext2
);
1619 ASSERT((*PPtrCCB
)->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_CCB
);
1620 (*PPtrFCB
) = (*PPtrCCB
)->PtrFCB
;
1624 if ((*PPtrFCB
)->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_VCB
)
1626 (*PPtrVCB
) = (PtrExt2VCB
)(*PPtrFCB
);
1627 AssertVCB( (*PPtrVCB
) );
1635 AssertFCB( (*PPtrFCB
) );
1636 (*PPtrVCB
) = (*PPtrFCB
)->PtrVCB
;
1637 AssertVCB( (*PPtrVCB
) );
1643 // PtrFileObject->FsContext points to NTRequiredFCB
1644 (*PPtrFCB
) = CONTAINING_RECORD( PtrFileObject
->FsContext
, Ext2FCB
, NTRequiredFCB
);
1646 //(*PPtrFCB) = PtrFileObject->FsContext;
1648 if ((*PPtrFCB
)->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_FCB
)
1650 // Making sure I got it right...
1651 AssertFCB( *PPtrFCB
);
1652 (*PPtrVCB
) = (*PPtrFCB
)->PtrVCB
;
1653 AssertVCB( *PPtrVCB
);
1657 // This should be a VCB
1659 (*PPtrVCB
) = CONTAINING_RECORD( PtrFileObject
->FsContext
, Ext2VCB
, CommonVCBHeader
);
1660 AssertVCB( *PPtrVCB
);
1668 return STATUS_SUCCESS
;
1672 void Ext2CopyUnicodeString( PUNICODE_STRING PtrDestinationString
, PUNICODE_STRING PtrSourceString
)
1675 // Allcating space for Destination...
1676 PtrDestinationString
->Length
= PtrSourceString
->Length
;
1677 PtrDestinationString
->MaximumLength
= Ext2QuadAlign( PtrSourceString
->Length
+ 2 );
1678 PtrDestinationString
->Buffer
= Ext2AllocatePool( NonPagedPool
, PtrDestinationString
->MaximumLength
);
1680 // RtlCopyUnicodeString( PtrDestinationString, PtrSourceString );
1682 for( Count
= 0 ; Count
< (PtrSourceString
->Length
/2) ; Count
++ )
1684 PtrDestinationString
->Buffer
[Count
] = PtrSourceString
->Buffer
[Count
];
1686 PtrDestinationString
->Buffer
[Count
] = 0;
1690 void Ext2CopyWideCharToUnicodeString(
1691 PUNICODE_STRING PtrDestinationString
,
1692 PCWSTR PtrSourceString
)
1697 // Determining length...
1698 for( Count
= 0 ; PtrSourceString
[Count
] != 0 ; Count
++ );
1700 // Allcating space for Destination...
1701 PtrDestinationString
->Length
= Count
* 2;
1702 PtrDestinationString
->MaximumLength
= Ext2QuadAlign( Count
* 2 + 2 );
1703 PtrDestinationString
->Buffer
= Ext2AllocatePool( NonPagedPool
, PtrDestinationString
->MaximumLength
);
1705 // Copying the string over...
1706 for( Count
= 0 ; ; Count
++ )
1708 PtrDestinationString
->Buffer
[Count
] = PtrSourceString
[Count
];
1709 if( PtrSourceString
[Count
] == 0 )
1715 void Ext2CopyCharToUnicodeString(
1716 PUNICODE_STRING PtrDestinationString
,
1717 PCSTR PtrSourceString
,
1718 USHORT SourceStringLength
)
1721 // Allcating space for Destination...
1722 PtrDestinationString
->Length
= SourceStringLength
* 2;
1723 PtrDestinationString
->MaximumLength
= Ext2QuadAlign( SourceStringLength
* 2 + 2 );
1724 PtrDestinationString
->Buffer
= Ext2AllocatePool( NonPagedPool
, PtrDestinationString
->MaximumLength
);
1726 // Copying the string over...
1727 for( Count
= 0 ; Count
< SourceStringLength
; Count
++ )
1729 PtrDestinationString
->Buffer
[Count
] = PtrSourceString
[Count
];
1731 PtrDestinationString
->Buffer
[Count
] = 0;
1735 void Ext2CopyZCharToUnicodeString( PUNICODE_STRING PtrDestinationString
, PCSTR PtrSourceString
)
1740 // Determining length...
1741 for( Count
= 0 ; PtrSourceString
[Count
] != 0 ; Count
++ );
1743 // Allcating space for Destination...
1744 PtrDestinationString
->Length
= Count
* 2;
1745 PtrDestinationString
->MaximumLength
= Ext2QuadAlign( Count
* 2 + 2 );
1746 PtrDestinationString
->Buffer
= Ext2AllocatePool( NonPagedPool
, PtrDestinationString
->MaximumLength
);
1748 // Copying the string over...
1749 for( Count
= 0 ; ; Count
++ )
1751 PtrDestinationString
->Buffer
[Count
] = PtrSourceString
[Count
];
1752 if( PtrSourceString
[Count
] == 0 )
1757 void Ext2ZerooutUnicodeString( PUNICODE_STRING PtrUnicodeString
)
1759 PtrUnicodeString
->Length
= 0;
1760 PtrUnicodeString
->MaximumLength
=0;
1761 PtrUnicodeString
->Buffer
= 0;
1764 void Ext2DeallocateUnicodeString( PUNICODE_STRING PtrUnicodeString
)
1766 if( PtrUnicodeString
&& PtrUnicodeString
->Buffer
)
1768 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrUnicodeString
->Buffer
);
1769 ExFreePool( PtrUnicodeString
->Buffer
);
1771 PtrUnicodeString
->Length
= 0;
1772 PtrUnicodeString
->MaximumLength
=0;
1773 PtrUnicodeString
->Buffer
= 0;
1776 PtrExt2FCB
Ext2GetUsedFCB(
1780 BOOLEAN AllocatedFromZone
= FALSE
;
1781 PLIST_ENTRY PtrEntry
= NULL
;
1782 PtrExt2FCB PtrFCB
= NULL
;
1785 if( PtrVCB
->ClosableFCBs
.Count
< EXT2_MAXCLOSABLE_FCBS_LL
)
1788 // Too few Closable FCBs
1789 // Will not reuse any FCBs
1790 // Allocating a new one
1792 return Ext2AllocateFCB();
1795 // Obtaining a used FCB...
1798 // Retrieving the first entry in the closable FCB list...
1800 PtrEntry
= RemoveHeadList( &PtrVCB
->ClosableFCBs
.ClosableFCBListHead
);
1802 PtrFCB
= CONTAINING_RECORD( PtrEntry
, Ext2FCB
, ClosableFCBs
.ClosableFCBList
);
1804 // Remembering if the FCB was allocated from the Zone...
1805 AllocatedFromZone
= Ext2IsFlagOn( PtrFCB
->FCBFlags
, EXT2_FCB_NOT_FROM_ZONE
);
1810 if( !Ext2CloseClosableFCB( PtrFCB
) )
1812 // Couldn't close the FCB!!
1814 InsertHeadList( &PtrVCB
->ClosableFCBs
.ClosableFCBListHead
,
1815 &PtrFCB
->ClosableFCBs
.ClosableFCBList
);
1816 return Ext2AllocateFCB();
1819 PtrVCB
->ClosableFCBs
.Count
--;
1820 DebugTrace( DEBUG_TRACE_SPECIAL
, "Count = %ld [Ext2GetUsedFCB]", PtrVCB
->ClosableFCBs
.Count
);
1823 // Getting the FCB ready for reuse by
1824 // zeroing it out...
1826 RtlZeroMemory(PtrFCB
, Ext2QuadAlign(sizeof(Ext2FCB
)));
1828 // set up some fields ...
1829 PtrFCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FCB
;
1830 PtrFCB
->NodeIdentifier
.NodeSize
= Ext2QuadAlign(sizeof(Ext2FCB
));
1833 if (!AllocatedFromZone
)
1835 Ext2SetFlag(PtrFCB
->FCBFlags
, EXT2_FCB_NOT_FROM_ZONE
);
1841 BOOLEAN
Ext2CloseClosableFCB(
1845 PFILE_OBJECT PtrFileObject
= NULL
;
1847 AssertFCB( PtrFCB
);
1849 // Attempting to acquire the FCB Exclusively...
1850 if(! ExAcquireResourceExclusiveLite( &(PtrFCB
->NTRequiredFCB
.MainResource
), FALSE
) )
1856 Irql
= KeGetCurrentIrql( );
1858 if( PtrFCB
->ReferenceCount
)
1860 // How the hell can this happen!!!
1863 if( PtrFCB
->OpenHandleCount
)
1865 // How the hell can this happen!!!
1869 // Deleting entry from VCB's FCB list...
1870 RemoveEntryList( &PtrFCB
->NextFCB
);
1872 PtrFCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_FREED
;
1874 PtrFileObject
= PtrFCB
->DcbFcb
.Dcb
.PtrDirFileObject
;
1876 if ( PtrFileObject
)
1879 // Clear the Cache Map...
1881 if( PtrFileObject
->PrivateCacheMap
!= NULL
)
1883 IO_STATUS_BLOCK Status
;
1884 DebugTrace( DEBUG_TRACE_SPECIAL
, ">>.........Flushing cache.........<<", 0 );
1885 CcFlushCache( PtrFileObject
->SectionObjectPointer
, NULL
, 0, &Status
);
1886 CcUninitializeCacheMap( PtrFileObject
, NULL
, NULL
);
1889 // The File Object is no longer required...
1890 // Close it by dereferenceing it!!!
1892 PtrFileObject
->FsContext
= NULL
;
1893 PtrFileObject
->FsContext2
= NULL
;
1894 ObDereferenceObject( PtrFileObject
);
1896 PtrFCB
->DcbFcb
.Dcb
.PtrDirFileObject
= NULL
;
1897 PtrFileObject
= NULL
;
1900 // Uninitialize the Resources...
1901 ExDeleteResourceLite( &PtrFCB
->NTRequiredFCB
.MainResource
);
1902 ExDeleteResourceLite( &PtrFCB
->NTRequiredFCB
.PagingIoResource
);
1905 // Releasing the FCB Name Object...
1907 if( PtrFCB
->FCBName
)
1909 DebugTrace( DEBUG_TRACE_SPECIAL
, "Reusing FCB - File Name %S", PtrFCB
->FCBName
->ObjectName
.Buffer
);
1910 Ext2ReleaseObjectName( PtrFCB
->FCBName
);
1914 DebugTrace( DEBUG_TRACE_SPECIAL
, "Reusing FCB - File Name *Unknown*", 0 );
1920 BOOLEAN
Ext2SaveBCB(
1921 PtrExt2IrpContext PtrIrpContext
,
1923 PFILE_OBJECT PtrFileObject
)
1925 PEXT2_SAVED_BCBS PtrSavedBCB
;
1926 PLIST_ENTRY PtrEntry
= NULL
;
1928 if( !PtrIrpContext
)
1931 // NULL passed instead of the IRP Context
1932 // This call should be ignored...
1937 if( !AssertBCB( PtrBCB
) )
1939 DebugTrace( DEBUG_TRACE_MISC
, "Not saving BCB!!! [Ext2SaveBCB]", 0 );
1944 DebugTrace( DEBUG_TRACE_SPECIAL
, "Saving BCB [Ext2SaveBCB]", 0 );
1946 // Has the BCB been saved already?
1947 for( PtrEntry
= PtrIrpContext
->SavedBCBsListHead
.Flink
;
1948 PtrEntry
!= &PtrIrpContext
->SavedBCBsListHead
;
1949 PtrEntry
= PtrEntry
->Flink
)
1951 PtrSavedBCB
= CONTAINING_RECORD( PtrEntry
, EXT2_SAVED_BCBS
, SavedBCBsListEntry
);
1952 ASSERT( PtrSavedBCB
);
1953 if( PtrSavedBCB
->PtrBCB
== PtrBCB
)
1956 // A BCB for this file has already been saved for flushing...
1957 // Won't resave this one...
1963 // Reference the BCB
1964 CcRepinBcb( PtrBCB
);
1966 // Now allocate a EXT2_SAVED_BCBS
1967 PtrSavedBCB
= Ext2AllocatePool( NonPagedPool
,
1968 Ext2QuadAlign( sizeof( EXT2_SAVED_BCBS
) ) );
1971 PtrSavedBCB
->NodeIdentifier
.NodeSize
= sizeof( EXT2_SAVED_BCBS
);
1972 PtrSavedBCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_SAVED_BCB
;
1974 PtrSavedBCB
->PtrBCB
= PtrBCB
;
1975 // PtrSavedBCB->PtrFileObject = PtrFileObject;
1977 // Now save it in the IRP Context
1978 InsertHeadList( &PtrIrpContext
->SavedBCBsListHead
, &PtrSavedBCB
->SavedBCBsListEntry
);
1980 PtrIrpContext
->SavedCount
++;
1981 // Return success...
1987 BOOLEAN
Ext2FlushSavedBCBs(
1988 PtrExt2IrpContext PtrIrpContext
)
1991 PLIST_ENTRY PtrEntry
= NULL
;
1992 PEXT2_SAVED_BCBS PtrSavedBCB
= NULL
;
1993 IO_STATUS_BLOCK Status
;
1996 if( !IsListEmpty( &PtrIrpContext
->SavedBCBsListHead
) )
1998 DebugTrace( DEBUG_TRACE_SPECIAL
, "Flushing cache... - Ext2FlushSavedBCBs", 0 );
2000 while( !IsListEmpty( &PtrIrpContext
->SavedBCBsListHead
) )
2003 PtrEntry
= RemoveTailList( &PtrIrpContext
->SavedBCBsListHead
);
2006 // No more entries left...
2010 // Get the Saved BCB
2011 PtrSavedBCB
= CONTAINING_RECORD( PtrEntry
, EXT2_SAVED_BCBS
, SavedBCBsListEntry
);
2012 if( PtrSavedBCB
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_SAVED_BCB
)
2014 // Something is wrong...
2019 if( !AssertBCB( PtrSavedBCB
->PtrBCB
) )
2021 // This BCB shouldn't have been saved in the first place...
2022 DebugTrace( DEBUG_TRACE_ERROR
, "Unable to flush BCB - Skipping!!! [Ext2SaveBCB]", 0 );
2026 // Unpin and Flush the cache...
2027 CcUnpinRepinnedBcb( PtrSavedBCB
->PtrBCB
, TRUE
, &Status
);
2029 if( !NT_SUCCESS( Status
.Status
) )
2031 // Failure in flushing...
2032 DebugTrace( DEBUG_TRACE_SPECIAL
, "Failure flushing cache - Ext2FlushSavedBCBs", 0 );
2036 // Release the Saved BCB
2037 PtrSavedBCB
->NodeIdentifier
.NodeType
= EXT2_NODE_TYPE_INVALID
;
2039 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [misc]", PtrSavedBCB
);
2040 ExFreePool( PtrSavedBCB
);
2042 PtrIrpContext
->SavedCount
--;
2048 BOOLEAN
AssertBCB( PBCB PtrBCB
)
2050 PFILE_OBJECT PtrFileObject
= NULL
;
2053 * This routine is simplified version of the original
2054 * AssertBCB and doesn't make any assumptions about
2055 * the layout of undocumented BCB structure.
2056 * -- Filip Navara, 18/08/2004
2059 PtrFileObject
= CcGetFileObjectFromBcb ( PtrBCB
);
2060 if( !PtrFileObject
)
2072 ULONG
Ext2Align( ULONG NumberToBeAligned
, ULONG Alignment
)
2074 if( Alignment
& ( Alignment
- 1 ) )
2077 // Alignment not a power of 2
2080 return NumberToBeAligned
;
2082 if( ( NumberToBeAligned
& ( Alignment
- 1 ) ) != 0 )
2084 NumberToBeAligned
= NumberToBeAligned
+ Alignment
;
2085 NumberToBeAligned
= NumberToBeAligned
& ( ~ (Alignment
-1) );
2087 return NumberToBeAligned
;
2090 LONGLONG
Ext2Align64( LONGLONG NumberToBeAligned
, LONGLONG Alignment
)
2092 if( Alignment
& ( Alignment
- 1 ) )
2095 // Alignment not a power of 2
2098 return NumberToBeAligned
;
2100 if( ( NumberToBeAligned
& ( Alignment
- 1 ) ) != 0 )
2102 NumberToBeAligned
= NumberToBeAligned
+ Alignment
;
2103 NumberToBeAligned
= NumberToBeAligned
& ( ~ (Alignment
-1) );
2105 return NumberToBeAligned
;
2109 ULONG
Ext2GetCurrentTime()
2111 LARGE_INTEGER CurrentTime
;
2113 KeQuerySystemTime( &CurrentTime
);
2114 Time
= (ULONG
) ( (CurrentTime
.QuadPart
- Ext2GlobalData
.TimeDiff
.QuadPart
) / 10000000 );