1 /*************************************************************************
5 * Module: Ext2 File System Driver (Kernel mode execution only)
8 * Contains code to handle the "Create"/"Open" dispatch entry point.
10 * Author: Manoj Paul Joseph
13 *************************************************************************/
17 // define the file specific bug-check id
18 #define EXT2_BUG_CHECK_ID EXT2_FILE_CREATE
20 #define DEBUG_LEVEL (DEBUG_TRACE_CREATE)
23 /*************************************************************************
25 * Function: Ext2Create()
28 * The I/O Manager will invoke this routine to handle a create/open
31 * Expected Interrupt Level (for execution) :
33 * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
34 * to be deferred to a worker thread context)
36 * Return Value: STATUS_SUCCESS/Error
38 *************************************************************************/
40 PDEVICE_OBJECT DeviceObject
, // the logical volume device object
41 PIRP Irp
) // I/O Request Packet
43 NTSTATUS RC
= STATUS_SUCCESS
;
44 PtrExt2IrpContext PtrIrpContext
;
45 BOOLEAN AreWeTopLevel
= FALSE
;
47 DebugTrace( DEBUG_TRACE_IRP_ENTRY
, "Create Control IRP received...", 0);
49 FsRtlEnterFileSystem();
56 // sometimes, we may be called here with the device object representing
57 // the file system (instead of the device object created for a logical
58 // volume. In this case, there is not much we wish to do (this create
59 // typically will happen 'cause some process has to open the FSD device
60 // object so as to be able to send an IOCTL to the FSD)
62 // All of the logical volume device objects we create have a device
63 // extension whereas the device object representing the FSD has no
64 // device extension. This seems like a good enough method to identify
65 // between the two device objects ...
66 if (DeviceObject
->Size
== (unsigned short)(sizeof(DEVICE_OBJECT
)))
68 // this is an open of the FSD itself
69 DebugTrace( DEBUG_TRACE_MISC
, " === Open for the FSD itself", 0);
70 Irp
->IoStatus
.Status
= RC
;
71 Irp
->IoStatus
.Information
= FILE_OPENED
;
73 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
77 // set the top level context
78 AreWeTopLevel
= Ext2IsIrpTopLevel(Irp
);
83 // get an IRP context structure and issue the request
84 PtrIrpContext
= Ext2AllocateIrpContext(Irp
, DeviceObject
);
85 ASSERT(PtrIrpContext
);
87 RC
= Ext2CommonCreate(PtrIrpContext
, Irp
, TRUE
);
90 except (Ext2ExceptionFilter(PtrIrpContext
, GetExceptionInformation()))
93 RC
= Ext2ExceptionHandler(PtrIrpContext
, Irp
);
95 Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR
, RC
);
100 IoSetTopLevelIrp(NULL
);
103 FsRtlExitFileSystem();
110 /*************************************************************************
112 * Function: Ext2CommonCreate()
115 * The actual work is performed here. This routine may be invoked in one'
116 * of the two possible contexts:
117 * (a) in the context of a system worker thread
118 * (b) in the context of the original caller
120 * Expected Interrupt Level (for execution) :
124 * Return Value: STATUS_SUCCESS/Error
126 *************************************************************************/
127 NTSTATUS
Ext2CommonCreate(
128 PtrExt2IrpContext PtrIrpContext
,
130 BOOLEAN FirstAttempt
)
132 NTSTATUS RC
= STATUS_SUCCESS
;
133 PIO_STACK_LOCATION PtrIoStackLocation
= NULL
;
134 PIO_SECURITY_CONTEXT PtrSecurityContext
= NULL
;
135 PFILE_OBJECT PtrNewFileObject
= NULL
;
136 PFILE_OBJECT PtrRelatedFileObject
= NULL
;
137 uint32 AllocationSize
= 0; // if we create a new file
138 PFILE_FULL_EA_INFORMATION PtrExtAttrBuffer
= NULL
;
139 unsigned long RequestedOptions
= 0;
140 unsigned long RequestedDisposition
= 0;
141 uint8 FileAttributes
= 0;
142 unsigned short ShareAccess
= 0;
143 unsigned long ExtAttrLength
= 0;
144 ACCESS_MASK DesiredAccess
;
146 BOOLEAN DeferredProcessing
= FALSE
;
148 PtrExt2VCB PtrVCB
= NULL
;
149 BOOLEAN AcquiredVCB
= FALSE
;
151 BOOLEAN DirectoryOnlyRequested
= FALSE
;
152 BOOLEAN FileOnlyRequested
= FALSE
;
153 BOOLEAN NoBufferingSpecified
= FALSE
;
154 BOOLEAN WriteThroughRequested
= FALSE
;
155 BOOLEAN DeleteOnCloseSpecified
= FALSE
;
156 BOOLEAN NoExtAttrKnowledge
= FALSE
;
157 BOOLEAN CreateTreeConnection
= FALSE
;
158 BOOLEAN OpenByFileId
= FALSE
;
160 BOOLEAN SequentialOnly
= FALSE
;
161 BOOLEAN RandomAccess
= FALSE
;
163 // Are we dealing with a page file?
164 BOOLEAN PageFileManipulation
= FALSE
;
166 // Is this open for a target directory (used in rename operations)?
167 BOOLEAN OpenTargetDirectory
= FALSE
;
169 // Should we ignore case when attempting to locate the object?
170 BOOLEAN IgnoreCaseWhenChecking
= FALSE
;
172 PtrExt2CCB PtrRelatedCCB
= NULL
, PtrNewCCB
= NULL
;
173 PtrExt2FCB PtrRelatedFCB
= NULL
, PtrNewFCB
= NULL
;
175 unsigned long ReturnedInformation
= -1;
177 UNICODE_STRING TargetObjectName
;
178 UNICODE_STRING RelatedObjectName
;
180 UNICODE_STRING AbsolutePathName
;
181 UNICODE_STRING RenameLinkTargetFileName
;
183 LARGE_INTEGER FileAllocationSize
, FileEndOfFile
;
186 ASSERT(PtrIrpContext
);
192 AbsolutePathName
.Buffer
= NULL
;
193 AbsolutePathName
.Length
= AbsolutePathName
.MaximumLength
= 0;
195 // Getting a pointer to the current I/O stack location
196 PtrIoStackLocation
= IoGetCurrentIrpStackLocation(PtrIrp
);
197 ASSERT(PtrIoStackLocation
);
200 if (!(PtrIrpContext
->IrpContextFlags
& EXT2_IRP_CONTEXT_CAN_BLOCK
))
202 // Asynchronous processing required...
203 RC
= Ext2PostRequest(PtrIrpContext
, PtrIrp
);
204 DeferredProcessing
= TRUE
;
208 // Obtaining the parameters specified by the user.
209 PtrNewFileObject
= PtrIoStackLocation
->FileObject
;
210 TargetObjectName
= PtrNewFileObject
->FileName
;
211 PtrRelatedFileObject
= PtrNewFileObject
->RelatedFileObject
;
213 if( PtrNewFileObject
->FileName
.Length
&& PtrNewFileObject
->FileName
.Buffer
)
215 if( PtrNewFileObject
->FileName
.Buffer
[ PtrNewFileObject
->FileName
.Length
/2 ] != 0 )
217 DebugTrace(DEBUG_TRACE_MISC
, "&&&&&&&&& PtrFileObject->FileName not NULL terminated! [Create]", 0 );
219 DebugTrace( DEBUG_TRACE_FILE_NAME
, " === Create/Open File Name : -%S- [Create]", PtrNewFileObject
->FileName
.Buffer
);
223 DebugTrace( DEBUG_TRACE_FILE_NAME
, " === Create/Open File Name : -null- [Create]", 0);
226 // Is this a Relative Create/Open?
227 if (PtrRelatedFileObject
)
229 PtrRelatedCCB
= (PtrExt2CCB
)(PtrRelatedFileObject
->FsContext2
);
230 ASSERT(PtrRelatedCCB
);
231 ASSERT(PtrRelatedCCB
->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_CCB
);
232 // each CCB in turn points to a FCB
233 PtrRelatedFCB
= PtrRelatedCCB
->PtrFCB
;
234 ASSERT(PtrRelatedFCB
);
235 if( PtrRelatedFCB
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_FCB
&&
236 PtrRelatedFCB
->NodeIdentifier
.NodeType
!= EXT2_NODE_TYPE_VCB
)
238 // How the hell can this happen!!!
242 AssertFCBorVCB( PtrRelatedFCB
);
244 RelatedObjectName
= PtrRelatedFileObject
->FileName
;
246 if( PtrRelatedFileObject
->FileName
.Length
&& PtrRelatedFileObject
->FileName
.Buffer
)
248 DebugTrace( DEBUG_TRACE_FILE_NAME
, " === Relative to : -%S-", PtrRelatedFileObject
->FileName
.Buffer
);
252 DebugTrace( DEBUG_TRACE_FILE_NAME
, " === Relative to : -null-",0);
258 AllocationSize
= PtrIrp
->Overlay
.AllocationSize
.LowPart
;
259 // Only 32 bit file sizes supported...
261 if (PtrIrp
->Overlay
.AllocationSize
.HighPart
)
263 RC
= STATUS_INVALID_PARAMETER
;
267 // Getting a pointer to the supplied security context
268 PtrSecurityContext
= PtrIoStackLocation
->Parameters
.Create
.SecurityContext
;
270 // Obtaining the desired access
271 DesiredAccess
= PtrSecurityContext
->DesiredAccess
;
273 // Getting the options supplied by the user...
274 RequestedOptions
= (PtrIoStackLocation
->Parameters
.Create
.Options
& FILE_VALID_OPTION_FLAGS
);
275 RequestedDisposition
= ((PtrIoStackLocation
->Parameters
.Create
.Options
>> 24) & 0xFF);
277 FileAttributes
= (uint8
)(PtrIoStackLocation
->Parameters
.Create
.FileAttributes
& FILE_ATTRIBUTE_VALID_FLAGS
);
278 ShareAccess
= PtrIoStackLocation
->Parameters
.Create
.ShareAccess
;
279 PtrExtAttrBuffer
= PtrIrp
->AssociatedIrp
.SystemBuffer
;
281 ExtAttrLength
= PtrIoStackLocation
->Parameters
.Create
.EaLength
;
283 SequentialOnly
= ((RequestedOptions
& FILE_SEQUENTIAL_ONLY
) ? TRUE
: FALSE
);
284 RandomAccess
= ((RequestedOptions
& FILE_RANDOM_ACCESS
) ? TRUE
: FALSE
);
287 DirectoryOnlyRequested
= ((RequestedOptions
& FILE_DIRECTORY_FILE
) ? TRUE
: FALSE
);
288 FileOnlyRequested
= ((RequestedOptions
& FILE_NON_DIRECTORY_FILE
) ? TRUE
: FALSE
);
289 NoBufferingSpecified
= ((RequestedOptions
& FILE_NO_INTERMEDIATE_BUFFERING
) ? TRUE
: FALSE
);
290 WriteThroughRequested
= ((RequestedOptions
& FILE_WRITE_THROUGH
) ? TRUE
: FALSE
);
291 DeleteOnCloseSpecified
= ((RequestedOptions
& FILE_DELETE_ON_CLOSE
) ? TRUE
: FALSE
);
292 NoExtAttrKnowledge
= ((RequestedOptions
& FILE_NO_EA_KNOWLEDGE
) ? TRUE
: FALSE
);
293 CreateTreeConnection
= ((RequestedOptions
& FILE_CREATE_TREE_CONNECTION
) ? TRUE
: FALSE
);
294 OpenByFileId
= ((RequestedOptions
& FILE_OPEN_BY_FILE_ID
) ? TRUE
: FALSE
);
295 PageFileManipulation
= ((PtrIoStackLocation
->Flags
& SL_OPEN_PAGING_FILE
) ? TRUE
: FALSE
);
296 OpenTargetDirectory
= ((PtrIoStackLocation
->Flags
& SL_OPEN_TARGET_DIRECTORY
) ? TRUE
: FALSE
);
297 IgnoreCaseWhenChecking
= ((PtrIoStackLocation
->Flags
& SL_CASE_SENSITIVE
) ? TRUE
: FALSE
);
299 // Ensure that the operation has been directed to a valid VCB ...
300 PtrVCB
= (PtrExt2VCB
)(PtrIrpContext
->TargetDeviceObject
->DeviceExtension
);
302 ASSERT(PtrVCB
->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_VCB
);
305 if( !PtrNewFileObject
->Vpb
)
307 PtrNewFileObject
->Vpb
= PtrVCB
->PtrVPB
;
310 // Acquiring the VCBResource Exclusively...
311 // This is done to synchronise with the close and cleanup routines...
313 DebugTrace(DEBUG_TRACE_MISC
, "*** Going into a block to acquire VCB Exclusively [Create]", 0);
315 DebugTraceState( "VCB AC:0x%LX SW:0x%LX EX:0x%LX [Create]", PtrVCB
->VCBResource
.ActiveCount
, PtrVCB
->VCBResource
.NumberOfExclusiveWaiters
, PtrVCB
->VCBResource
.NumberOfSharedWaiters
);
316 ExAcquireResourceExclusiveLite(&(PtrVCB
->VCBResource
), TRUE
);
320 DebugTrace(DEBUG_TRACE_MISC
, "*** VCB Acquired in Create", 0);
321 if( PtrNewFileObject
)
323 DebugTrace(DEBUG_TRACE_FILE_OBJ
, "###### File Pointer 0x%LX [Create]", PtrNewFileObject
);
327 // if (!NT_SUCCESS(RC = Ext2VerifyVolume(PtrVCB)))
332 // If the volume has been locked, fail the request
334 if (PtrVCB
->VCBFlags
& EXT2_VCB_FLAGS_VOLUME_LOCKED
)
336 DebugTrace(DEBUG_TRACE_MISC
, "Volume locked. Failing Create", 0 );
337 RC
= STATUS_ACCESS_DENIED
;
342 if ((PtrNewFileObject
->FileName
.Length
== 0) && ((PtrRelatedFileObject
== NULL
) ||
343 (PtrRelatedFCB
->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_VCB
)))
346 // >>>>>>>>>>>>> Volume Open requested. <<<<<<<<<<<<<
349 // Performing validity checks...
350 if ((OpenTargetDirectory
) || (PtrExtAttrBuffer
))
352 RC
= STATUS_INVALID_PARAMETER
;
356 if (DirectoryOnlyRequested
)
358 // a volume is not a directory
359 RC
= STATUS_NOT_A_DIRECTORY
;
363 if ((RequestedDisposition
!= FILE_OPEN
) && (RequestedDisposition
!= FILE_OPEN_IF
))
365 // cannot create a new volume, I'm afraid ...
366 RC
= STATUS_ACCESS_DENIED
;
369 DebugTrace(DEBUG_TRACE_MISC
, "Volume open requested", 0 );
370 RC
= Ext2OpenVolume(PtrVCB
, PtrIrpContext
, PtrIrp
, ShareAccess
, PtrSecurityContext
, PtrNewFileObject
);
371 ReturnedInformation
= PtrIrp
->IoStatus
.Information
;
378 DebugTrace(DEBUG_TRACE_MISC
, "Open by File Id requested", 0 );
379 RC
= STATUS_ACCESS_DENIED
;
383 // Relative path name specified...
384 if (PtrRelatedFileObject
)
387 if (!(PtrRelatedFCB
->FCBFlags
& EXT2_FCB_DIRECTORY
))
389 // we must have a directory as the "related" object
390 RC
= STATUS_INVALID_PARAMETER
;
394 // Performing validity checks...
395 if ((RelatedObjectName
.Length
== 0) || (RelatedObjectName
.Buffer
[0] != L
'\\'))
397 RC
= STATUS_INVALID_PARAMETER
;
401 if ((TargetObjectName
.Length
!= 0) && (TargetObjectName
.Buffer
[0] == L
'\\'))
403 RC
= STATUS_INVALID_PARAMETER
;
407 // Creating an absolute path-name.
409 AbsolutePathName
.MaximumLength
= TargetObjectName
.Length
+ RelatedObjectName
.Length
+ sizeof(WCHAR
);
410 if (!(AbsolutePathName
.Buffer
= Ext2AllocatePool(PagedPool
, AbsolutePathName
.MaximumLength
)))
412 RC
= STATUS_INSUFFICIENT_RESOURCES
;
416 RtlZeroMemory(AbsolutePathName
.Buffer
, AbsolutePathName
.MaximumLength
);
418 RtlCopyMemory((void *)(AbsolutePathName
.Buffer
), (void *)(RelatedObjectName
.Buffer
), RelatedObjectName
.Length
);
419 AbsolutePathName
.Length
= RelatedObjectName
.Length
;
420 RtlAppendUnicodeToString(&AbsolutePathName
, L
"\\");
421 RtlAppendUnicodeToString(&AbsolutePathName
, TargetObjectName
.Buffer
);
425 // Absolute Path name specified...
430 // Validity Checks...
431 if (TargetObjectName
.Buffer
[0] != L
'\\')
433 RC
= STATUS_INVALID_PARAMETER
;
438 AbsolutePathName
.MaximumLength
= TargetObjectName
.Length
;
439 if (!(AbsolutePathName
.Buffer
= Ext2AllocatePool(PagedPool
, AbsolutePathName
.MaximumLength
))) {
440 RC
= STATUS_INSUFFICIENT_RESOURCES
;
444 RtlZeroMemory(AbsolutePathName
.Buffer
, AbsolutePathName
.MaximumLength
);
446 RtlCopyMemory((void *)(AbsolutePathName
.Buffer
), (void *)(TargetObjectName
.Buffer
), TargetObjectName
.Length
);
447 AbsolutePathName
.Length
= TargetObjectName
.Length
;
452 // Parsing the path...
453 if (AbsolutePathName
.Length
== 2)
456 // this is an open of the root directory, ensure that the caller has not requested a file only
457 if (FileOnlyRequested
|| (RequestedDisposition
== FILE_SUPERSEDE
) || (RequestedDisposition
== FILE_OVERWRITE
) ||
458 (RequestedDisposition
== FILE_OVERWRITE_IF
))
460 RC
= STATUS_FILE_IS_A_DIRECTORY
;
464 RC
= Ext2OpenRootDirectory(PtrVCB
, PtrIrpContext
, PtrIrp
, ShareAccess
, PtrSecurityContext
, PtrNewFileObject
);
465 DebugTrace(DEBUG_TRACE_MISC
, " === Root directory opened", 0 );
471 // Used during parsing the file path...
472 UNICODE_STRING RemainingName
;
473 UNICODE_STRING CurrentName
;
474 UNICODE_STRING NextRemainingName
;
475 PEXT2_INODE PtrNextInode
= NULL
;
476 ULONG CurrInodeNo
= 0;
477 PtrExt2FCB PtrCurrFCB
= NULL
;
478 PtrExt2FCB PtrNextFCB
= NULL
;
479 PFILE_OBJECT PtrCurrFileObject
= NULL
;
480 UINT NameBufferIndex
;
482 LARGE_INTEGER ZeroSize
;
483 BOOLEAN Found
= FALSE
;
485 ZeroSize
.QuadPart
= 0;
486 if ( PtrRelatedFileObject
)
488 CurrInodeNo
= PtrRelatedFCB
->INodeNo
;
489 PtrCurrFCB
= PtrRelatedFCB
;
493 CurrInodeNo
= PtrVCB
->PtrRootDirectoryFCB
->INodeNo
;
494 PtrCurrFCB
= PtrVCB
->PtrRootDirectoryFCB
;
498 // Ext2ZerooutUnicodeString( &RemainingName );
499 Ext2ZerooutUnicodeString( &CurrentName
);
500 Ext2ZerooutUnicodeString( &NextRemainingName
);
502 RemainingName
= TargetObjectName
;
504 while ( !Found
&& CurrInodeNo
)
506 FsRtlDissectName ( RemainingName
, &CurrentName
, &NextRemainingName
);
508 RemainingName
= NextRemainingName
;
509 // CurrInodeNo is the parent inode for the entry I am searching for
510 // PtrCurrFCB is the parent's FCB
511 // Current Name is its name...
514 PtrNextFCB
= Ext2LocateChildFCBInCore ( PtrVCB
, &CurrentName
, CurrInodeNo
);
518 CurrInodeNo
= PtrNextFCB
->INodeNo
;
520 if( NextRemainingName
.Length
== 0 )
528 if( OpenTargetDirectory
)
532 // This is for a rename/move operation...
534 ReturnedInformation
= FILE_EXISTS
;
536 // Now replace the file name field with that of the
537 // Target file name...
538 Ext2CopyUnicodeString(
539 &RenameLinkTargetFileName
,
543 for( i = 0; i < (CurrentName.Length/2); i++ )
545 PtrNewFileObject->FileName.Buffer[i] = CurrentName.Buffer[i];
547 PtrNewFileObject->FileName.Length = CurrentName.Length;
549 // Now open the Parent Directory...
550 PtrNextFCB
= PtrCurrFCB
;
551 CurrInodeNo
= PtrNextFCB
->INodeNo
;
555 // Relating the FCB to the New File Object
557 PtrNewFileObject
->Vpb
= PtrVCB
->PtrVPB
;
558 PtrNewFileObject
->PrivateCacheMap
= NULL
;
559 PtrNewFileObject
->FsContext
= (void *)( &(PtrNextFCB
->NTRequiredFCB
.CommonFCBHeader
) );
560 PtrNewFileObject
->SectionObjectPointer
= &(PtrNextFCB
->NTRequiredFCB
.SectionObject
) ;
564 else if( !Ext2IsFlagOn( PtrNextFCB
->FCBFlags
, EXT2_FCB_DIRECTORY
) )
567 // Can have only a directory in the middle of the path...
569 RC
= STATUS_OBJECT_PATH_NOT_FOUND
;
573 else // searching on the disk...
575 CurrInodeNo
= Ext2LocateFileInDisk( PtrVCB
, &CurrentName
, PtrCurrFCB
, &Type
);
583 if( ( NextRemainingName
.Length
== 0 ) &&
584 ( RequestedDisposition
== FILE_CREATE
) ||
585 ( RequestedDisposition
== FILE_OPEN_IF
) ||
586 ( RequestedDisposition
== FILE_OVERWRITE_IF
) )
590 // Just the last component was not found...
591 // A create was requested...
593 if( DirectoryOnlyRequested
)
599 Type
= EXT2_FT_REG_FILE
;
602 CurrInodeNo
= Ext2CreateFile( PtrIrpContext
, PtrVCB
,
603 &CurrentName
, PtrCurrFCB
, Type
);
607 RC
= STATUS_OBJECT_PATH_NOT_FOUND
;
610 // Set the allocation size for the object is specified
611 //IoSetShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject, &(PtrNewFCB->FCBShareAccess));
612 // RC = STATUS_SUCCESS;
613 ReturnedInformation
= FILE_CREATED
;
615 // Should also create a CCB structure...
616 // Doing that a little fathre down... ;)
619 else if( NextRemainingName
.Length
== 0 && OpenTargetDirectory
)
623 // This is for a rename/move operation...
624 // Just the last component was not found...
626 ReturnedInformation
= FILE_DOES_NOT_EXIST
;
628 // Now replace the file name field with that of the
629 // Target file name...
630 Ext2CopyUnicodeString(
631 &RenameLinkTargetFileName
,
634 for( i = 0; i < (CurrentName.Length/2); i++ )
636 PtrNewFileObject->FileName.Buffer[i] = CurrentName.Buffer[i];
638 PtrNewFileObject->FileName.Length = CurrentName.Length;
641 // Now open the Parent Directory...
642 PtrNextFCB
= PtrCurrFCB
;
643 CurrInodeNo
= PtrNextFCB
->INodeNo
;
644 // Initialize the FsContext
645 PtrNewFileObject
->FsContext
= &PtrNextFCB
->NTRequiredFCB
.CommonFCBHeader
;
646 // Initialize the section object pointer...
647 PtrNewFileObject
->SectionObjectPointer
= &(PtrNextFCB
->NTRequiredFCB
.SectionObject
);
648 PtrNewFileObject
->Vpb
= PtrVCB
->PtrVPB
;
649 PtrNewFileObject
->PrivateCacheMap
= NULL
;
655 RC
= STATUS_OBJECT_PATH_NOT_FOUND
;
660 if( NextRemainingName
.Length
)
662 // Should be a directory...
663 if( Type
!= EXT2_FT_DIR
)
666 // Can have only a directory in the middle of the path...
668 RC
= STATUS_OBJECT_PATH_NOT_FOUND
;
672 PtrCurrFileObject
= NULL
;
683 // Was I supposed to create a new file?
685 if (RequestedDisposition
== FILE_CREATE
&&
686 ReturnedInformation
!= FILE_CREATED
)
688 ReturnedInformation
= FILE_EXISTS
;
689 RC
= STATUS_OBJECT_NAME_COLLISION
;
693 // Is this the type of file I was looking for?
694 // Do some checking here...
696 if( Type
!= EXT2_FT_DIR
&& Type
!= EXT2_FT_REG_FILE
)
699 // Cannot open a special file...
700 RC
= STATUS_ACCESS_DENIED
;
704 if( DirectoryOnlyRequested
&& Type
!= EXT2_FT_DIR
)
706 RC
= STATUS_NOT_A_DIRECTORY
;
709 if( FileOnlyRequested
&& Type
== EXT2_FT_DIR
)
711 RC
= STATUS_FILE_IS_A_DIRECTORY
;
715 PtrCurrFileObject
= PtrNewFileObject
;
716 // Things seem to be ok enough!
717 // Proceeing with the Open/Create...
723 // Create an FCB and initialise it...
726 PtrExt2ObjectName PtrObjectName
;
728 // Initialising the object name...
729 PtrObjectName
= Ext2AllocateObjectName();
730 Ext2CopyUnicodeString( &PtrObjectName
->ObjectName
, &CurrentName
);
731 // RtlInitUnicodeString( &PtrObjectName->ObjectName, CurrentName.Buffer );
733 if( !NT_SUCCESS( Ext2CreateNewFCB(
734 &PtrNextFCB
, // the new FCB
735 ZeroSize
, // AllocationSize,
736 ZeroSize
, // EndOfFile,
737 PtrCurrFileObject
, // The File Object
741 RC
= STATUS_INSUFFICIENT_RESOURCES
;
745 if( Type
== EXT2_FT_DIR
)
746 PtrNextFCB
->FCBFlags
|= EXT2_FCB_DIRECTORY
;
747 else if( Type
!= EXT2_FT_REG_FILE
)
748 PtrNextFCB
->FCBFlags
|= EXT2_FCB_SPECIAL_FILE
;
750 PtrNextFCB
->INodeNo
= CurrInodeNo
;
751 PtrNextFCB
->ParentINodeNo
= PtrCurrFCB
->INodeNo
;
753 if( PtrCurrFileObject
== NULL
&& CurrInodeNo
!= EXT2_ROOT_INO
)
755 // This is an FCB created to cache the reads done while parsing
756 // Put this FCB on the ClosableFCBList
757 if( !PtrNextFCB
->ClosableFCBs
.OnClosableFCBList
)
759 InsertTailList( &PtrVCB
->ClosableFCBs
.ClosableFCBListHead
,
760 &PtrNextFCB
->ClosableFCBs
.ClosableFCBList
);
761 PtrVCB
->ClosableFCBs
.Count
++;
762 PtrNextFCB
->ClosableFCBs
.OnClosableFCBList
= TRUE
;
769 // Still not done parsing...
770 // miles to go before I open... ;)
772 PtrCurrFCB
= PtrNextFCB
;
775 PtrNewFCB
= PtrNextFCB
;
779 // If I get this far...
780 // it means, I have located the file...
781 // I even have an FCB to represent it!!!
783 if ( NT_SUCCESS (RC
) )
786 if ((PtrNewFCB
->FCBFlags
& EXT2_FCB_DIRECTORY
) && ((RequestedDisposition
== FILE_SUPERSEDE
) ||
787 (RequestedDisposition
== FILE_OVERWRITE
) || (RequestedDisposition
== FILE_OVERWRITE_IF
)))
789 RC
= STATUS_FILE_IS_A_DIRECTORY
;
794 // Check share access and fail if the share conflicts with an existing
797 if (PtrNewFCB
->OpenHandleCount
> 0)
799 // The FCB is currently in use by some thread.
800 // We must check whether the requested access/share access
801 // conflicts with the existing open operations.
803 if (!NT_SUCCESS(RC
= IoCheckShareAccess(DesiredAccess
, ShareAccess
, PtrNewFileObject
,
804 &(PtrNewFCB
->FCBShareAccess
), TRUE
)))
806 // Ext2CloseCCB(PtrNewCCB);
812 IoSetShareAccess(DesiredAccess
, ShareAccess
, PtrNewFileObject
, &(PtrNewFCB
->FCBShareAccess
));
816 // Allocating a new CCB Structure...
818 Ext2CreateNewCCB( &PtrNewCCB
, PtrNewFCB
, PtrNewFileObject
);
819 PtrNewFileObject
->FsContext2
= (void *) PtrNewCCB
;
820 Ext2CopyUnicodeString( &(PtrNewCCB
->AbsolutePathName
), &AbsolutePathName
);
822 if( ReturnedInformation
== -1 )
825 // ReturnedInformation has not been set so far...
827 ReturnedInformation
= FILE_OPENED
;
830 // If a supersede or overwrite was requested, do so now ...
831 if (RequestedDisposition
== FILE_SUPERSEDE
)
833 // Attempt the operation here ...
834 if( Ext2SupersedeFile( PtrNewFCB
, PtrIrpContext
) )
836 ReturnedInformation
= FILE_SUPERSEDED
;
840 else if ((RequestedDisposition
== FILE_OVERWRITE
) || (RequestedDisposition
== FILE_OVERWRITE_IF
))
842 // Attempt the overwrite operation...
843 if( Ext2OverwriteFile( PtrNewFCB
, PtrIrpContext
) )
845 ReturnedInformation
= FILE_OVERWRITTEN
;
850 if( ReturnedInformation
== FILE_CREATED
||
851 ReturnedInformation
== FILE_SUPERSEDED
)
854 ULONG LogicalBlockSize
= EXT2_MIN_BLOCK_SIZE
<< PtrVCB
->LogBlockSize
;
856 for( CurrentSize
= 0; CurrentSize
< AllocationSize
; CurrentSize
+= LogicalBlockSize
)
858 Ext2AddBlockToFile( PtrIrpContext
, PtrVCB
, PtrNewFCB
, PtrNewFileObject
, FALSE
);
863 if( ReturnedInformation
== FILE_CREATED
)
865 // Allocate some data blocks if
866 // 1. initial file size has been specified...
867 // 2. if the file is a Directory...
868 // In case of (2) make entries for '.' and '..'
869 // Zero out the Blocks...
873 if( DirectoryOnlyRequested
)
876 Ext2CopyCharToUnicodeString( &Name
, ".", 1 );
877 Ext2MakeNewDirectoryEntry( PtrIrpContext
, PtrNewFCB
, PtrNewFileObject
, &Name
, EXT2_FT_DIR
, PtrNewFCB
->INodeNo
);
879 Name
.Buffer
[1] = '.';
880 Name
.Buffer
[2] = '\0';
882 Ext2MakeNewDirectoryEntry( PtrIrpContext
, PtrNewFCB
, PtrNewFileObject
, &Name
, EXT2_FT_DIR
, PtrNewFCB
->ParentINodeNo
);
883 Ext2DeallocateUnicodeString( &Name
);
886 if( OpenTargetDirectory
)
889 // Save the taget file name in the CCB...
891 Ext2CopyUnicodeString(
892 &PtrNewCCB
->RenameLinkTargetFileName
,
893 &RenameLinkTargetFileName
);
894 Ext2DeallocateUnicodeString( &RenameLinkTargetFileName
);
906 Ext2ReleaseResource(&(PtrVCB
->VCBResource
));
909 DebugTrace(DEBUG_TRACE_MISC
, "*** VCB released [Create]", 0);
911 if( PtrNewFileObject
)
913 DebugTrace(DEBUG_TRACE_FILE_OBJ
, "###### File Pointer 0x%LX [Create]", PtrNewFileObject
);
917 if (AbsolutePathName
.Buffer
!= NULL
)
919 DebugTrace( DEBUG_TRACE_FREE
, "Freeing = %lX [Create]", AbsolutePathName
.Buffer
);
920 ExFreePool(AbsolutePathName
.Buffer
);
923 // Complete the request unless we are here as part of unwinding
924 // when an exception condition was encountered, OR
925 // if the request has been deferred (i.e. posted for later handling)
926 if (RC
!= STATUS_PENDING
)
928 // If we acquired any FCB resources, release them now ...
930 // If any intermediate (directory) open operations were performed,
931 // implement the corresponding close (do *not* however close
932 // the target you have opened on behalf of the caller ...).
936 // Update the file object such that:
937 // (a) the FsContext field points to the NTRequiredFCB field
939 // (b) the FsContext2 field points to the CCB created as a
940 // result of the open operation
942 // If write-through was requested, then mark the file object
944 if (WriteThroughRequested
)
946 PtrNewFileObject
->Flags
|= FO_WRITE_THROUGH
;
948 DebugTrace( DEBUG_TRACE_SPECIAL
, " === Create/Open successful", 0 );
952 DebugTrace( DEBUG_TRACE_SPECIAL
, " === Create/Open failed", 0 );
953 // Perform failure related post-processing now
956 // As long as this unwinding is not being performed as a result of
957 // an exception condition, complete the IRP ...
958 if (!(PtrIrpContext
->IrpContextFlags
& EXT2_IRP_CONTEXT_EXCEPTION
))
960 PtrIrp
->IoStatus
.Status
= RC
;
961 PtrIrp
->IoStatus
.Information
= ReturnedInformation
;
963 // Free up the Irp Context
964 Ext2ReleaseIrpContext(PtrIrpContext
);
967 IoCompleteRequest(PtrIrp
, IO_DISK_INCREMENT
);
975 /*************************************************************************
977 * Function: Ext2OpenVolume()
980 * Open a logical volume for the caller.
982 * Expected Interrupt Level (for execution) :
986 * Return Value: STATUS_SUCCESS/Error
988 *************************************************************************/
989 NTSTATUS
Ext2OpenVolume(
990 PtrExt2VCB PtrVCB
, // volume to be opened
991 PtrExt2IrpContext PtrIrpContext
, // IRP context
992 PIRP PtrIrp
, // original/user IRP
993 unsigned short ShareAccess
, // share access
994 PIO_SECURITY_CONTEXT PtrSecurityContext
, // caller's context (incl access)
995 PFILE_OBJECT PtrNewFileObject
) // I/O Mgr. created file object
997 NTSTATUS RC
= STATUS_SUCCESS
;
998 PtrExt2CCB PtrCCB
= NULL
;
1001 // check for exclusive open requests (using share modes supplied)
1002 // and determine whether it is even possible to open the volume
1003 // with the specified share modes (e.g. if caller does not
1004 // wish to share read or share write ...)
1006 // Use IoCheckShareAccess() and IoSetShareAccess() here ...
1007 // They are defined in the DDK.
1009 // You might also wish to check the caller's security context
1010 // to see whether you wish to allow the volume open or not.
1011 // Use the SeAccessCheck() routine described in the DDK for this purpose.
1013 // create a new CCB structure
1014 if (!(PtrCCB
= Ext2AllocateCCB()))
1016 RC
= STATUS_INSUFFICIENT_RESOURCES
;
1020 // initialize the CCB
1021 PtrCCB
->PtrFCB
= (PtrExt2FCB
)(PtrVCB
);
1022 InsertTailList(&(PtrVCB
->VolumeOpenListHead
), &(PtrCCB
->NextCCB
));
1024 // initialize the CCB to point to the file object
1025 PtrCCB
->PtrFileObject
= PtrNewFileObject
;
1027 Ext2SetFlag(PtrCCB
->CCBFlags
, EXT2_CCB_VOLUME_OPEN
);
1029 // initialize the file object appropriately
1030 PtrNewFileObject
->FsContext
= (void *)( &(PtrVCB
->CommonVCBHeader
) );
1031 PtrNewFileObject
->FsContext2
= (void *)(PtrCCB
);
1033 // increment the number of outstanding open operations on this
1034 // logical volume (i.e. volume cannot be dismounted)
1036 // You might be concerned about 32 bit wrap-around though I would
1037 // argue that it is unlikely ... :-)
1038 (PtrVCB
->VCBOpenCount
)++;
1040 // now set the IoStatus Information value correctly in the IRP
1041 // (caller will set the status field)
1042 PtrIrp
->IoStatus
.Information
= FILE_OPENED
;
1054 /*************************************************************************
1056 * Function: Ext2InitializeFCB()
1059 * Initialize a new FCB structure and also the sent-in file object
1062 * Expected Interrupt Level (for execution) :
1064 * IRQL_PASSIVE_LEVEL
1066 * Return Value: None
1068 *************************************************************************
1069 void Ext2InitializeFCB(
1070 PtrExt2FCB PtrNewFCB, // FCB structure to be initialized
1071 PtrExt2VCB PtrVCB, // logical volume (VCB) pointer
1072 PtrExt2ObjectName PtrObjectName, // name of the object
1073 uint32 Flags, // is this a file/directory, etc.
1074 PFILE_OBJECT PtrFileObject) // optional file object to be initialized
1076 // Initialize the disk dependent portion as you see fit
1078 // Initialize the two ERESOURCE objects
1079 ExInitializeResourceLite(&(PtrNewFCB->NTRequiredFCB.MainResource));
1080 ExInitializeResourceLite(&(PtrNewFCB->NTRequiredFCB.PagingIoResource));
1082 PtrNewFCB->FCBFlags |= EXT2_INITIALIZED_MAIN_RESOURCE | EXT2_INITIALIZED_PAGING_IO_RESOURCE | Flags;
1084 PtrNewFCB->PtrVCB = PtrVCB;
1086 // caller MUST ensure that VCB has been acquired exclusively
1087 InsertTailList(&(PtrVCB->FCBListHead), &(PtrNewFCB->NextFCB));
1089 // initialize the various list heads
1090 InitializeListHead(&(PtrNewFCB->CCBListHead));
1092 // PtrNewFCB->ReferenceCount = 1;
1093 // PtrNewFCB->OpenHandleCount = 1;
1097 PtrNewFCB->FCBName = PtrObjectName;
1100 if ( PtrFileObject )
1102 PtrFileObject->FsContext = (void *)(&(PtrNewFCB->NTRequiredFCB));
1109 /*************************************************************************
1111 * Function: Ext2OpenRootDirectory()
1114 * Open the root directory for a volume
1117 * Expected Interrupt Level (for execution) :
1121 * Return Value: None
1123 *************************************************************************/
1124 NTSTATUS
Ext2OpenRootDirectory(
1125 PtrExt2VCB PtrVCB
, // volume
1126 PtrExt2IrpContext PtrIrpContext
, // IRP context
1127 PIRP PtrIrp
, // original/user IRP
1128 unsigned short ShareAccess
, // share access
1129 PIO_SECURITY_CONTEXT PtrSecurityContext
, // caller's context (incl access)
1130 PFILE_OBJECT PtrNewFileObject
// I/O Mgr. created file object
1137 ASSERT( PtrVCB
->NodeIdentifier
.NodeType
== EXT2_NODE_TYPE_VCB
);
1138 ASSERT( PtrVCB
->PtrRootDirectoryFCB
);
1139 AssertFCB( PtrVCB
->PtrRootDirectoryFCB
);
1141 PtrVCB
->PtrRootDirectoryFCB
->INodeNo
= EXT2_ROOT_INO
;
1143 // Create a new CCB...
1144 Ext2CreateNewCCB( &PtrCCB
, PtrVCB
->PtrRootDirectoryFCB
, PtrNewFileObject
);
1145 PtrNewFileObject
->FsContext
= (void *) &(PtrVCB
->PtrRootDirectoryFCB
->NTRequiredFCB
.CommonFCBHeader
);
1146 PtrVCB
->PtrRootDirectoryFCB
->FCBFlags
|= EXT2_FCB_DIRECTORY
;
1147 PtrNewFileObject
->FsContext2
= (void *) PtrCCB
;
1148 PtrNewFileObject
->SectionObjectPointer
= &PtrVCB
->PtrRootDirectoryFCB
->NTRequiredFCB
.SectionObject
;
1149 PtrNewFileObject
->Vpb
= PtrVCB
->PtrVPB
;
1151 Ext2CopyUnicodeString( &(PtrCCB
->AbsolutePathName
), &PtrVCB
->PtrRootDirectoryFCB
->FCBName
->ObjectName
);
1154 return STATUS_SUCCESS
;
1159 PtrExt2FCB
Ext2LocateChildFCBInCore(
1161 PUNICODE_STRING PtrName
,
1162 ULONG ParentInodeNo
)
1165 PtrExt2FCB PtrFCB
= NULL
;
1167 PLIST_ENTRY PtrEntry
;
1169 if( IsListEmpty( &(PtrVCB
->FCBListHead
) ) )
1171 return NULL
; // Failure;
1174 for( PtrEntry
= PtrVCB
->FCBListHead
.Flink
;
1175 PtrEntry
!= &PtrVCB
->FCBListHead
;
1176 PtrEntry
= PtrEntry
->Flink
)
1178 PtrFCB
= CONTAINING_RECORD( PtrEntry
, Ext2FCB
, NextFCB
);
1180 if( PtrFCB
->ParentINodeNo
== ParentInodeNo
)
1182 if( RtlCompareUnicodeString( &PtrFCB
->FCBName
->ObjectName
, PtrName
, TRUE
) == 0 )
1190 PtrExt2FCB
Ext2LocateFCBInCore(
1194 PtrExt2FCB PtrFCB
= NULL
;
1195 PLIST_ENTRY PtrEntry
;
1197 if( IsListEmpty( &(PtrVCB
->FCBListHead
) ) )
1199 return NULL
; // Failure;
1202 for( PtrEntry
= PtrVCB
->FCBListHead
.Flink
;
1203 PtrEntry
!= &PtrVCB
->FCBListHead
;
1204 PtrEntry
= PtrEntry
->Flink
)
1206 PtrFCB
= CONTAINING_RECORD( PtrEntry
, Ext2FCB
, NextFCB
);
1208 if( PtrFCB
->INodeNo
== InodeNo
)
1218 ULONG
Ext2LocateFileInDisk (
1220 PUNICODE_STRING PtrCurrentName
,
1221 PtrExt2FCB PtrParentFCB
,
1225 PtrExt2FCB PtrNewFCB
= NULL
;
1226 PFILE_OBJECT PtrFileObject
= NULL
;
1229 *Type
= EXT2_FT_UNKNOWN
;
1232 // Initialize the Blocks in the FCB...
1234 Ext2InitializeFCBInodeInfo( PtrParentFCB
);
1238 // Is there a file object I can use for caching??
1239 // If not create one...
1241 if( !PtrParentFCB
->DcbFcb
.Dcb
.PtrDirFileObject
)
1244 // No Directory File Object?
1245 // No problem, will create one...
1248 // Acquire the MainResource first though...
1250 PtrParentFCB
->DcbFcb
.Dcb
.PtrDirFileObject
= IoCreateStreamFileObject(NULL
, PtrVCB
->TargetDeviceObject
);
1251 PtrFileObject
= PtrParentFCB
->DcbFcb
.Dcb
.PtrDirFileObject
;
1253 if( !PtrFileObject
)
1258 PtrFileObject
->ReadAccess
= TRUE
;
1259 PtrFileObject
->WriteAccess
= TRUE
;
1261 // Associate the file stream with the Volume parameter block...
1262 PtrFileObject
->Vpb
= PtrVCB
->PtrVPB
;
1264 // No caching as yet...
1265 PtrFileObject
->PrivateCacheMap
= NULL
;
1267 // this establishes the FCB - File Object connection...
1268 PtrFileObject
->FsContext
= (void *)( & (PtrParentFCB
->NTRequiredFCB
.CommonFCBHeader
) );
1270 // Initialize the section object pointer...
1271 PtrFileObject
->SectionObjectPointer
= &(PtrParentFCB
->NTRequiredFCB
.SectionObject
);
1276 // I do have a file object...
1277 // I am using it now!
1279 PtrFileObject
= PtrParentFCB
->DcbFcb
.Dcb
.PtrDirFileObject
;
1283 // Got hold of a file object? Good ;)
1284 // Now initiating Caching, pinned access to be precise ...
1286 if (PtrFileObject
->PrivateCacheMap
== NULL
)
1288 CcInitializeCacheMap(PtrFileObject
, (PCC_FILE_SIZES
)(&(PtrParentFCB
->NTRequiredFCB
.CommonFCBHeader
.AllocationSize
)),
1289 TRUE
, // We utilize pin access for directories
1290 &(Ext2GlobalData
.CacheMgrCallBacks
), // callbacks
1291 PtrParentFCB
); // The context used in callbacks
1295 // Getting down to the real business now... ;)
1296 // Read in the directory contents and do a search
1297 // a sequential search to be precise...
1298 // Wish Mm'm Renuga were reading this
1299 // Would feel proud... ;)
1302 LARGE_INTEGER StartBufferOffset
;
1303 ULONG PinBufferLength
;
1306 BYTE
* PtrPinnedBlockBuffer
= NULL
;
1307 PEXT2_DIR_ENTRY PtrDirEntry
= NULL
;
1312 StartBufferOffset
.QuadPart
= 0;
1315 // Read in the whole damn directory
1316 // **Bad programming**
1319 PinBufferLength
= PtrParentFCB
->NTRequiredFCB
.CommonFCBHeader
.FileSize
.LowPart
;
1320 if (!CcMapData( PtrFileObject
,
1325 (PVOID
*)&PtrPinnedBlockBuffer
) )
1331 // Walking through now...
1334 for( BufferIndex
= 0, Found
= FALSE
; !Found
&& BufferIndex
< ( PtrParentFCB
->NTRequiredFCB
.CommonFCBHeader
.FileSize
.QuadPart
- 1) ; BufferIndex
+= PtrDirEntry
->rec_len
)
1336 PtrDirEntry
= (PEXT2_DIR_ENTRY
) &PtrPinnedBlockBuffer
[ BufferIndex
];
1337 if( PtrDirEntry
->name_len
== 0 || PtrDirEntry
->rec_len
== 0 || PtrDirEntry
->inode
== 0)
1344 // Comparing ( case sensitive )
1345 // Directory entry is not NULL terminated...
1346 // nor is the CurrentName...
1348 if( PtrDirEntry
->name_len
!= (PtrCurrentName
->Length
/ 2) )
1351 for( i
= 0, Found
= TRUE
; i
< PtrDirEntry
->name_len
; i
++ )
1353 if( PtrDirEntry
->name
[ i
] != PtrCurrentName
->Buffer
[ i
] )
1364 InodeNo
= PtrDirEntry
->inode
;
1366 if( PtrDirEntry
->file_type
== EXT2_FT_UNKNOWN
)
1369 // Old Fashioned Directory entries...
1370 // Will have to read in the Inode to determine the File Type...
1372 // PtrInode = Ext2AllocatePool( NonPagedPool, sizeof( EXT2_INODE ) );
1373 Ext2ReadInode( PtrVCB
, InodeNo
, &Inode
);
1375 if( Ext2IsModeRegularFile( Inode
.i_mode
) )
1377 *Type
= EXT2_FT_REG_FILE
;
1379 else if ( Ext2IsModeDirectory( Inode
.i_mode
) )
1382 *Type
= EXT2_FT_DIR
;
1384 else if( Ext2IsModeSymbolicLink(Inode
.i_mode
) )
1386 *Type
= EXT2_FT_SYMLINK
;
1388 else if( Ext2IsModePipe(Inode
.i_mode
) )
1390 *Type
= EXT2_FT_FIFO
;
1392 else if( Ext2IsModeCharacterDevice(Inode
.i_mode
) )
1394 *Type
= EXT2_FT_CHRDEV
;
1396 else if( Ext2IsModeBlockDevice(Inode
.i_mode
) )
1398 *Type
= EXT2_FT_BLKDEV
;
1400 else if( Ext2IsModeSocket(Inode
.i_mode
) )
1402 *Type
= EXT2_FT_SOCK
;
1406 *Type
= EXT2_FT_UNKNOWN
;
1409 //DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [Create]", PtrInode );
1410 //ExFreePool( PtrInode );
1414 *Type
= PtrDirEntry
->file_type
;
1418 CcUnpinData( PtrBCB
);
1426 /*************************************************************************
1428 * Function: Ext2CreateFile()
1431 * Creates a new file on the disk
1433 * Expected Interrupt Level (for execution) :
1434 * IRQL_PASSIVE_LEVEL
1437 * Expects the VCB to be acquired Exclusively before being invoked
1439 * Return Value: None
1441 *************************************************************************/
1442 ULONG
Ext2CreateFile(
1443 PtrExt2IrpContext PtrIrpContext
,
1445 PUNICODE_STRING PtrName
,
1446 PtrExt2FCB PtrParentFCB
,
1449 EXT2_INODE Inode
, ParentInode
;
1451 ULONG NewInodeNo
= 0;
1452 BOOLEAN FCBAcquired
= FALSE
;
1454 ULONG LogicalBlockSize
= 0;
1460 // 0. Verify if the creation is possible,,,
1461 if( Type
!= EXT2_FT_DIR
&& Type
!= EXT2_FT_REG_FILE
)
1464 // Can create only a directory or a regular file...
1469 // 1. Allocate an i-node...
1471 NewInodeNo
= Ext2AllocInode( PtrIrpContext
, PtrVCB
, PtrParentFCB
->INodeNo
);
1480 // 2. Acquire the Parent FCB Exclusively...
1481 if( !ExAcquireResourceExclusiveLite(&( PtrParentFCB
->NTRequiredFCB
.MainResource
), TRUE
) )
1483 Ext2DeallocInode( PtrIrpContext
, PtrVCB
, NewInodeNo
);
1484 try_return( NewInodeNo
= 0);
1488 // 3. Make an entry in the parent Directory...
1489 ASSERT( PtrParentFCB
->DcbFcb
.Dcb
.PtrDirFileObject
);
1491 Ext2MakeNewDirectoryEntry(
1494 PtrParentFCB
->DcbFcb
.Dcb
.PtrDirFileObject
,
1495 PtrName
, Type
, NewInodeNo
);
1498 // 4. Initialize an inode entry and write it to disk...
1499 LogicalBlockSize
= EXT2_MIN_BLOCK_SIZE
<< PtrVCB
->LogBlockSize
;
1503 Ext2ReadInode( PtrVCB
, NewInodeNo
, &Inode
);
1506 RtlZeroMemory( &Inode
, sizeof( EXT2_INODE
) );
1507 if( Type
== EXT2_FT_DIR
)
1509 Inode
.i_mode
= 0x41ff;
1511 // In addition to the usual link,
1512 // there will be an additional link in the directory itself - the '.' entry
1513 Inode
.i_links_count
= 2;
1515 // Incrementing the link count for the parent as well...
1516 Ext2ReadInode( PtrVCB
, PtrParentFCB
->INodeNo
, &ParentInode
);
1517 ParentInode
.i_links_count
++;
1518 Ext2WriteInode( PtrIrpContext
, PtrVCB
, PtrParentFCB
->INodeNo
, &ParentInode
);
1523 Inode
.i_mode
= 0x81ff;
1524 Inode
.i_links_count
= 1;
1530 // Setting the time fields in the inode...
1533 Time
= Ext2GetCurrentTime();
1534 Inode
.i_ctime
= Time
;
1535 Inode
.i_atime
= Time
;
1536 Inode
.i_mtime
= Time
;
1537 Inode
.i_dtime
= 0; // Deleted time;
1540 Ext2WriteInode( PtrIrpContext
, PtrVCB
, NewInodeNo
, &Inode
);
1548 Ext2ReleaseResource( &(PtrParentFCB
->NTRequiredFCB
.MainResource
) );
1555 /*************************************************************************
1557 * Function: Ext2CreateFile()
1560 * Overwrites an existing file on the disk
1562 * Expected Interrupt Level (for execution) :
1563 * IRQL_PASSIVE_LEVEL
1566 * Expects the VCB to be acquired Exclusively before being invoked
1568 * Return Value: None
1570 *************************************************************************/
1571 BOOLEAN
Ext2OverwriteFile(
1573 PtrExt2IrpContext PtrIrpContext
)
1576 PtrExt2VCB PtrVCB
= PtrFCB
->PtrVCB
;
1579 Time
= Ext2GetCurrentTime();
1581 Ext2InitializeFCBInodeInfo( PtrFCB
);
1583 // Update the inode...
1584 if( !NT_SUCCESS( Ext2ReadInode( PtrVCB
, PtrFCB
->INodeNo
, &Inode
) ) )
1591 Inode
.i_atime
= Time
;
1592 Inode
.i_mtime
= Time
;
1595 for( i
= 0; i
< EXT2_N_BLOCKS
; i
++ )
1597 Inode
.i_block
[ i
] = 0;
1600 if( !NT_SUCCESS( Ext2WriteInode( PtrIrpContext
, PtrVCB
, PtrFCB
->INodeNo
, &Inode
) ) )
1606 // Release all the data blocks...
1607 if( !Ext2ReleaseDataBlocks( PtrFCB
, PtrIrpContext
) )
1612 Ext2ClearFlag( PtrFCB
->FCBFlags
, EXT2_FCB_BLOCKS_INITIALIZED
);
1613 Ext2InitializeFCBInodeInfo( PtrFCB
);
1618 /*************************************************************************
1620 * Function: Ext2SupersedeFile()
1623 * Supersedes an existing file on the disk
1625 * Expected Interrupt Level (for execution) :
1626 * IRQL_PASSIVE_LEVEL
1629 * Expects the VCB to be acquired Exclusively before being invoked
1631 * Return Value: None
1633 *************************************************************************/
1634 BOOLEAN
Ext2SupersedeFile(
1636 PtrExt2IrpContext PtrIrpContext
)
1639 PtrExt2VCB PtrVCB
= PtrFCB
->PtrVCB
;
1642 Ext2InitializeFCBInodeInfo( PtrFCB
);
1645 // Initialize the inode...
1646 RtlZeroMemory( &Inode
, sizeof( EXT2_INODE
) );
1648 // Setting the file mode...
1649 // This operation is allowed only for a regular file...
1650 Inode
.i_mode
= 0x81ff;
1652 // Maintaining the old link count...
1653 Inode
.i_links_count
= PtrFCB
->LinkCount
;
1655 // Setting the time fields in the inode...
1658 Time
= Ext2GetCurrentTime();
1659 Inode
.i_ctime
= Time
;
1660 Inode
.i_atime
= Time
;
1661 Inode
.i_mtime
= Time
;
1662 Inode
.i_dtime
= 0; // Deleted time;
1665 if( !NT_SUCCESS( Ext2WriteInode( PtrIrpContext
, PtrVCB
, PtrFCB
->INodeNo
, &Inode
) ) )
1671 // Release all the data blocks...
1672 if( !Ext2ReleaseDataBlocks( PtrFCB
, PtrIrpContext
) )
1677 Ext2ClearFlag( PtrFCB
->FCBFlags
, EXT2_FCB_BLOCKS_INITIALIZED
);
1678 Ext2InitializeFCBInodeInfo( PtrFCB
);