ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

create.c
Go to the documentation of this file.
00001 /*************************************************************************
00002 *
00003 * File: create.c
00004 *
00005 * Module: Ext2 File System Driver (Kernel mode execution only)
00006 *
00007 * Description:
00008 *   Contains code to handle the "Create"/"Open" dispatch entry point.
00009 *
00010 * Author: Manoj Paul Joseph
00011 *
00012 *
00013 *************************************************************************/
00014 
00015 #include            "ext2fsd.h"
00016 
00017 // define the file specific bug-check id
00018 #define         EXT2_BUG_CHECK_ID               EXT2_FILE_CREATE
00019 
00020 #define         DEBUG_LEVEL                     (DEBUG_TRACE_CREATE)
00021  
00022 
00023 /*************************************************************************
00024 *
00025 * Function: Ext2Create()
00026 *
00027 * Description: 
00028 *   The I/O Manager will invoke this routine to handle a create/open
00029 *   request
00030 *
00031 * Expected Interrupt Level (for execution) :
00032 *
00033 *  IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
00034 *   to be deferred to a worker thread context)
00035 *
00036 * Return Value: STATUS_SUCCESS/Error
00037 *
00038 *************************************************************************/
00039 NTSTATUS NTAPI Ext2Create(
00040 PDEVICE_OBJECT      DeviceObject,       // the logical volume device object
00041 PIRP                    Irp)                    // I/O Request Packet
00042 {
00043     NTSTATUS                RC = STATUS_SUCCESS;
00044     PtrExt2IrpContext   PtrIrpContext;
00045     BOOLEAN             AreWeTopLevel = FALSE;
00046 
00047     DebugTrace( DEBUG_TRACE_IRP_ENTRY, "Create Control IRP received...", 0);
00048 
00049     FsRtlEnterFileSystem();
00050     
00051     //  Ext2BreakPoint();
00052 
00053     ASSERT(DeviceObject);
00054     ASSERT(Irp);
00055 
00056     // sometimes, we may be called here with the device object representing
00057     //  the file system (instead of the device object created for a logical
00058     //  volume. In this case, there is not much we wish to do (this create
00059     //  typically will happen 'cause some process has to open the FSD device
00060     //  object so as to be able to send an IOCTL to the FSD)
00061 
00062     //  All of the logical volume device objects we create have a device
00063     //  extension whereas the device object representing the FSD has no
00064     //  device extension. This seems like a good enough method to identify
00065     //  between the two device objects ...
00066     if (DeviceObject->Size == (unsigned short)(sizeof(DEVICE_OBJECT))) 
00067     {
00068         // this is an open of the FSD itself
00069         DebugTrace( DEBUG_TRACE_MISC, " === Open for the FSD itself", 0);
00070         Irp->IoStatus.Status = RC;
00071         Irp->IoStatus.Information = FILE_OPENED;
00072 
00073         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00074         return(RC);
00075     }
00076 
00077     // set the top level context
00078     AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
00079 
00080     try 
00081     {
00082 
00083         // get an IRP context structure and issue the request
00084         PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
00085         ASSERT(PtrIrpContext);
00086 
00087         RC = Ext2CommonCreate(PtrIrpContext, Irp, TRUE );
00088 
00089     } 
00090     except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) 
00091     {
00092 
00093         RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
00094 
00095         Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
00096     }
00097 
00098     if (AreWeTopLevel) 
00099     {
00100         IoSetTopLevelIrp(NULL);
00101     }
00102     
00103     FsRtlExitFileSystem();
00104 
00105     return(RC);
00106 }
00107 
00108 
00109 
00110 /*************************************************************************
00111 *
00112 * Function: Ext2CommonCreate()
00113 *
00114 * Description:
00115 *   The actual work is performed here. This routine may be invoked in one'
00116 *   of the two possible contexts:
00117 *   (a) in the context of a system worker thread
00118 *   (b) in the context of the original caller
00119 *
00120 * Expected Interrupt Level (for execution) :
00121 *
00122 *  IRQL_PASSIVE_LEVEL
00123 *
00124 * Return Value: STATUS_SUCCESS/Error
00125 *
00126 *************************************************************************/
00127 NTSTATUS NTAPI Ext2CommonCreate(
00128 PtrExt2IrpContext           PtrIrpContext,
00129 PIRP                        PtrIrp,
00130 BOOLEAN                     FirstAttempt)
00131 {
00132     NTSTATUS                RC = STATUS_SUCCESS;
00133     PIO_STACK_LOCATION      PtrIoStackLocation = NULL;
00134     PIO_SECURITY_CONTEXT    PtrSecurityContext = NULL;
00135     PFILE_OBJECT            PtrNewFileObject = NULL;
00136     PFILE_OBJECT            PtrRelatedFileObject = NULL;
00137     uint32                  AllocationSize = 0;     // if we create a new file
00138     PFILE_FULL_EA_INFORMATION   PtrExtAttrBuffer = NULL;
00139     unsigned long           RequestedOptions = 0;
00140     unsigned long           RequestedDisposition = 0;
00141     uint8                   FileAttributes = 0;
00142     unsigned short          ShareAccess = 0;
00143     unsigned long           ExtAttrLength = 0;
00144     ACCESS_MASK             DesiredAccess;
00145 
00146     BOOLEAN                 DeferredProcessing = FALSE;
00147 
00148     PtrExt2VCB              PtrVCB = NULL;
00149     BOOLEAN                 AcquiredVCB = FALSE;
00150 
00151     BOOLEAN                 DirectoryOnlyRequested = FALSE;
00152     BOOLEAN                 FileOnlyRequested = FALSE;
00153     BOOLEAN                 NoBufferingSpecified = FALSE;
00154     BOOLEAN                 WriteThroughRequested = FALSE;
00155     BOOLEAN                 DeleteOnCloseSpecified = FALSE;
00156     BOOLEAN                 NoExtAttrKnowledge = FALSE;
00157     BOOLEAN                 CreateTreeConnection = FALSE;
00158     BOOLEAN                 OpenByFileId    = FALSE;
00159 
00160     BOOLEAN                 SequentialOnly  = FALSE;
00161     BOOLEAN                 RandomAccess    = FALSE;
00162     
00163     // Are we dealing with a page file?
00164     BOOLEAN                 PageFileManipulation = FALSE;
00165 
00166     // Is this open for a target directory (used in rename operations)?
00167     BOOLEAN                 OpenTargetDirectory = FALSE;
00168 
00169     // Should we ignore case when attempting to locate the object?
00170     BOOLEAN                 IgnoreCaseWhenChecking = FALSE;
00171 
00172     PtrExt2CCB              PtrRelatedCCB = NULL, PtrNewCCB = NULL;
00173     PtrExt2FCB              PtrRelatedFCB = NULL, PtrNewFCB = NULL;
00174 
00175     unsigned long           ReturnedInformation = -1;
00176 
00177     UNICODE_STRING          TargetObjectName;
00178     UNICODE_STRING          RelatedObjectName;
00179 
00180     UNICODE_STRING          AbsolutePathName;
00181     UNICODE_STRING          RenameLinkTargetFileName;
00182 
00183     /* Silence GCC warnings */
00184     RtlZeroMemory(&RelatedObjectName, sizeof(UNICODE_STRING));
00185 
00186 
00187     ASSERT(PtrIrpContext);
00188     ASSERT(PtrIrp);
00189 
00190     try 
00191     {
00192 
00193         AbsolutePathName.Buffer = NULL;
00194         AbsolutePathName.Length = AbsolutePathName.MaximumLength = 0;
00195 
00196         // Getting a pointer to the current I/O stack location
00197         PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
00198         ASSERT(PtrIoStackLocation);
00199 
00200         // Can we block?
00201         if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK)) 
00202         {
00203             //  Asynchronous processing required...
00204             RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
00205             DeferredProcessing = TRUE;
00206             try_return();
00207         }
00208 
00209         // Obtaining the parameters specified by the user.
00210         PtrNewFileObject    = PtrIoStackLocation->FileObject;
00211         TargetObjectName    = PtrNewFileObject->FileName;
00212         PtrRelatedFileObject = PtrNewFileObject->RelatedFileObject;
00213 
00214         if( PtrNewFileObject->FileName.Length && PtrNewFileObject->FileName.Buffer )
00215         {
00216             if( PtrNewFileObject->FileName.Buffer[ PtrNewFileObject->FileName.Length/2 ] != 0 )
00217             {
00218                 DebugTrace(DEBUG_TRACE_MISC, "&&&&&&&&&  PtrFileObject->FileName not NULL terminated! [Create]", 0 );
00219             }
00220             DebugTrace( DEBUG_TRACE_FILE_NAME, " === Create/Open File Name : -%S- [Create]", PtrNewFileObject->FileName.Buffer );
00221         }
00222         else
00223         {
00224             DebugTrace( DEBUG_TRACE_FILE_NAME, " === Create/Open File Name : -null- [Create]", 0);
00225         }
00226 
00227         // Is this a Relative Create/Open?
00228         if (PtrRelatedFileObject) 
00229         {
00230             PtrRelatedCCB = (PtrExt2CCB)(PtrRelatedFileObject->FsContext2);
00231             ASSERT(PtrRelatedCCB);
00232             ASSERT(PtrRelatedCCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB);
00233             // each CCB in turn points to a FCB
00234             PtrRelatedFCB = PtrRelatedCCB->PtrFCB;
00235             ASSERT(PtrRelatedFCB);
00236             if( PtrRelatedFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB &&
00237                 PtrRelatedFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_VCB    )
00238             {
00239                 //  How the hell can this happen!!!
00240                 Ext2BreakPoint();
00241             }
00242 
00243             AssertFCBorVCB( PtrRelatedFCB );
00244 
00245             RelatedObjectName = PtrRelatedFileObject->FileName;
00246 
00247             if( PtrRelatedFileObject->FileName.Length && PtrRelatedFileObject->FileName.Buffer )
00248             {
00249                 DebugTrace( DEBUG_TRACE_FILE_NAME, " === Relative to : -%S-", PtrRelatedFileObject->FileName.Buffer );
00250             }
00251             else
00252             {
00253                 DebugTrace( DEBUG_TRACE_FILE_NAME, " === Relative to : -null-",0);
00254             }
00255 
00256         }
00257 
00258 
00259         AllocationSize    = PtrIrp->Overlay.AllocationSize.LowPart;
00260         //  Only 32 bit file sizes supported...
00261 
00262         if (PtrIrp->Overlay.AllocationSize.HighPart) 
00263         {
00264             RC = STATUS_INVALID_PARAMETER;
00265             try_return();
00266         }
00267 
00268         // Getting a pointer to the supplied security context
00269         PtrSecurityContext = PtrIoStackLocation->Parameters.Create.SecurityContext;
00270 
00271         // Obtaining the desired access 
00272         DesiredAccess = PtrSecurityContext->DesiredAccess;
00273 
00274         //  Getting the options supplied by the user...
00275         RequestedOptions = (PtrIoStackLocation->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS);
00276         RequestedDisposition = ((PtrIoStackLocation->Parameters.Create.Options >> 24) & 0xFF);
00277 
00278         FileAttributes  = (uint8)(PtrIoStackLocation->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS);
00279         ShareAccess = PtrIoStackLocation->Parameters.Create.ShareAccess;
00280         PtrExtAttrBuffer    = PtrIrp->AssociatedIrp.SystemBuffer;
00281 
00282         ExtAttrLength       = PtrIoStackLocation->Parameters.Create.EaLength;
00283 
00284         SequentialOnly      = ((RequestedOptions & FILE_SEQUENTIAL_ONLY ) ? TRUE : FALSE);
00285         RandomAccess        = ((RequestedOptions & FILE_RANDOM_ACCESS ) ? TRUE : FALSE);
00286         
00287 
00288         DirectoryOnlyRequested = ((RequestedOptions & FILE_DIRECTORY_FILE) ? TRUE : FALSE);
00289         FileOnlyRequested = ((RequestedOptions & FILE_NON_DIRECTORY_FILE) ? TRUE : FALSE);
00290         NoBufferingSpecified = ((RequestedOptions & FILE_NO_INTERMEDIATE_BUFFERING) ? TRUE : FALSE);
00291         WriteThroughRequested = ((RequestedOptions & FILE_WRITE_THROUGH) ? TRUE : FALSE);
00292         DeleteOnCloseSpecified = ((RequestedOptions & FILE_DELETE_ON_CLOSE) ? TRUE : FALSE);
00293         NoExtAttrKnowledge = ((RequestedOptions & FILE_NO_EA_KNOWLEDGE) ? TRUE : FALSE);
00294         CreateTreeConnection = ((RequestedOptions & FILE_CREATE_TREE_CONNECTION) ? TRUE : FALSE);
00295         OpenByFileId = ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? TRUE : FALSE);
00296         PageFileManipulation = ((PtrIoStackLocation->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE);
00297         OpenTargetDirectory = ((PtrIoStackLocation->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE);
00298         IgnoreCaseWhenChecking = ((PtrIoStackLocation->Flags & SL_CASE_SENSITIVE) ? TRUE : FALSE);
00299 
00300         // Ensure that the operation has been directed to a valid VCB ...
00301         PtrVCB =    (PtrExt2VCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
00302         ASSERT(PtrVCB);
00303         ASSERT(PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
00304 
00305         
00306         if( !PtrNewFileObject->Vpb )
00307         {
00308             PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
00309         }
00310 
00311         //  Acquiring the VCBResource Exclusively...
00312         //  This is done to synchronise with the close and cleanup routines...
00313         
00314         DebugTrace(DEBUG_TRACE_MISC,  "*** Going into a block to acquire VCB Exclusively [Create]", 0);
00315         
00316         DebugTraceState( "VCB       AC:0x%LX   SW:0x%LX   EX:0x%LX   [Create]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
00317         ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE);
00318                 
00319         AcquiredVCB = TRUE;
00320 
00321         DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Acquired in Create", 0);
00322         if( PtrNewFileObject )
00323         {
00324             DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Create]", PtrNewFileObject);
00325         }
00326 
00327         //  Verify Volume...
00328         //  if (!NT_SUCCESS(RC = Ext2VerifyVolume(PtrVCB))) 
00329         //  {
00330         //      try_return();
00331         //  }
00332 
00333         // If the volume has been locked, fail the request
00334 
00335         if (PtrVCB->VCBFlags & EXT2_VCB_FLAGS_VOLUME_LOCKED) 
00336         {
00337             DebugTrace(DEBUG_TRACE_MISC,   "Volume locked. Failing Create", 0 );
00338             RC = STATUS_ACCESS_DENIED;
00339             try_return();
00340         }
00341 
00342 
00343         if ((PtrNewFileObject->FileName.Length == 0) && ((PtrRelatedFileObject == NULL) ||
00344               (PtrRelatedFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB))) 
00345         {
00346             //
00347             //  >>>>>>>>>>>>>   Volume Open requested. <<<<<<<<<<<<<
00348             //
00349 
00350             //  Performing validity checks...
00351             if ((OpenTargetDirectory) || (PtrExtAttrBuffer)) 
00352             {
00353                 RC = STATUS_INVALID_PARAMETER;
00354                 try_return();
00355             }
00356 
00357             if (DirectoryOnlyRequested) 
00358             {
00359                 // a volume is not a directory
00360                 RC = STATUS_NOT_A_DIRECTORY;
00361                 try_return();
00362             }
00363 
00364             if ((RequestedDisposition != FILE_OPEN) && (RequestedDisposition != FILE_OPEN_IF)) 
00365             {
00366                 // cannot create a new volume, I'm afraid ...
00367                 RC = STATUS_ACCESS_DENIED;
00368                 try_return();
00369             }
00370             DebugTrace(DEBUG_TRACE_MISC,   "Volume open requested", 0 );
00371             RC = Ext2OpenVolume(PtrVCB, PtrIrpContext, PtrIrp, ShareAccess, PtrSecurityContext, PtrNewFileObject);
00372             ReturnedInformation = PtrIrp->IoStatus.Information;
00373 
00374             try_return();
00375         }
00376 
00377         if (OpenByFileId) 
00378         {
00379             DebugTrace(DEBUG_TRACE_MISC, "Open by File Id requested", 0 );
00380             RC = STATUS_ACCESS_DENIED;
00381             try_return();
00382         }
00383 
00384         // Relative path name specified...
00385         if (PtrRelatedFileObject)
00386         {
00387 
00388             if (!(PtrRelatedFCB->FCBFlags & EXT2_FCB_DIRECTORY)) 
00389             {
00390                 // we must have a directory as the "related" object
00391                 RC = STATUS_INVALID_PARAMETER;
00392                 try_return();
00393             }
00394 
00395             //  Performing validity checks...
00396             if ((RelatedObjectName.Length == 0) || (RelatedObjectName.Buffer[0] != L'\\')) 
00397             {
00398                 RC = STATUS_INVALID_PARAMETER;
00399                 try_return();
00400             }
00401 
00402             if ((TargetObjectName.Length != 0) && (TargetObjectName.Buffer[0] == L'\\')) 
00403             {
00404                 RC = STATUS_INVALID_PARAMETER;
00405                 try_return();
00406             }
00407 
00408             // Creating an absolute path-name.
00409             {
00410                 AbsolutePathName.MaximumLength = TargetObjectName.Length + RelatedObjectName.Length + sizeof(WCHAR);
00411                 if (!(AbsolutePathName.Buffer = Ext2AllocatePool(PagedPool, AbsolutePathName.MaximumLength ))) 
00412                 {
00413                     RC = STATUS_INSUFFICIENT_RESOURCES;
00414                     try_return();
00415                 }
00416 
00417                 RtlZeroMemory(AbsolutePathName.Buffer, AbsolutePathName.MaximumLength);
00418 
00419                 RtlCopyMemory((void *)(AbsolutePathName.Buffer), (void *)(RelatedObjectName.Buffer), RelatedObjectName.Length);
00420                 AbsolutePathName.Length = RelatedObjectName.Length;
00421                 RtlAppendUnicodeToString(&AbsolutePathName, L"\\");
00422                 RtlAppendUnicodeToString(&AbsolutePathName, TargetObjectName.Buffer);
00423             }
00424 
00425         }
00426         //  Absolute Path name specified...
00427         else 
00428         {
00429             
00430 
00431             // Validity Checks...
00432             if (TargetObjectName.Buffer[0] != L'\\') 
00433             {
00434                 RC = STATUS_INVALID_PARAMETER;
00435                 try_return();
00436             }
00437 
00438             {
00439                 AbsolutePathName.MaximumLength = TargetObjectName.Length;
00440                 if (!(AbsolutePathName.Buffer = Ext2AllocatePool(PagedPool, AbsolutePathName.MaximumLength ))) {
00441                     RC = STATUS_INSUFFICIENT_RESOURCES;
00442                     try_return();
00443                 }
00444 
00445                 RtlZeroMemory(AbsolutePathName.Buffer, AbsolutePathName.MaximumLength);
00446 
00447                 RtlCopyMemory((void *)(AbsolutePathName.Buffer), (void *)(TargetObjectName.Buffer), TargetObjectName.Length);
00448                 AbsolutePathName.Length = TargetObjectName.Length;
00449             }
00450         }
00451 
00452 
00453         //  Parsing the path...
00454         if (AbsolutePathName.Length == 2) 
00455         {
00456             
00457             // this is an open of the root directory, ensure that   the caller has not requested a file only
00458             if (FileOnlyRequested || (RequestedDisposition == FILE_SUPERSEDE) || (RequestedDisposition == FILE_OVERWRITE) ||
00459                  (RequestedDisposition == FILE_OVERWRITE_IF)) 
00460             {
00461                 RC = STATUS_FILE_IS_A_DIRECTORY;
00462                 try_return();
00463             }
00464 
00465             RC = Ext2OpenRootDirectory(PtrVCB, PtrIrpContext, PtrIrp, ShareAccess, PtrSecurityContext, PtrNewFileObject);
00466             DebugTrace(DEBUG_TRACE_MISC,   " === Root directory opened", 0 );
00467             try_return();
00468         }
00469 
00470 
00471         {
00472             //  Used during parsing the file path...
00473             UNICODE_STRING          RemainingName;
00474             UNICODE_STRING          CurrentName;
00475             UNICODE_STRING          NextRemainingName;
00476             ULONG                   CurrInodeNo = 0;
00477             PtrExt2FCB              PtrCurrFCB = NULL;
00478             PtrExt2FCB              PtrNextFCB = NULL;
00479             PFILE_OBJECT            PtrCurrFileObject = NULL;
00480             ULONG                   Type = 0;
00481             LARGE_INTEGER ZeroSize;
00482             BOOLEAN Found       = FALSE;
00483             
00484             ZeroSize.QuadPart = 0;
00485             if ( PtrRelatedFileObject ) 
00486             {
00487                 CurrInodeNo = PtrRelatedFCB->INodeNo;
00488                 PtrCurrFCB = PtrRelatedFCB;
00489             }
00490             else 
00491             {
00492                 CurrInodeNo = PtrVCB->PtrRootDirectoryFCB->INodeNo;
00493                 PtrCurrFCB = PtrVCB->PtrRootDirectoryFCB;
00494 
00495             }
00496 
00497             //  Ext2ZerooutUnicodeString( &RemainingName );
00498             Ext2ZerooutUnicodeString( &CurrentName );
00499             Ext2ZerooutUnicodeString( &NextRemainingName );
00500 
00501             RemainingName = TargetObjectName;
00502         
00503             while ( !Found && CurrInodeNo ) 
00504             {
00505                 FsRtlDissectName ( RemainingName, &CurrentName, &NextRemainingName );
00506 
00507                 RemainingName = NextRemainingName;
00508                 //  CurrInodeNo is the parent inode for the entry I am searching for
00509                 //  PtrCurrFCB  is the parent's FCB
00510                 //  Current Name is its name...
00511 
00512 
00513                 PtrNextFCB = Ext2LocateChildFCBInCore ( PtrVCB, &CurrentName, CurrInodeNo );
00514                 
00515                 if( PtrNextFCB )
00516                 {
00517                     CurrInodeNo = PtrNextFCB->INodeNo;
00518     
00519                     if( NextRemainingName.Length == 0 )
00520                     {
00521                         //
00522                         //  Done Parsing...
00523                         //  Found the file...
00524                         //
00525                         Found = TRUE;
00526                         
00527                         if( OpenTargetDirectory )
00528                         {
00529                             //
00530                             //  This is for a rename/move operation...
00531                             //
00532                             ReturnedInformation = FILE_EXISTS;
00533 
00534                             //  Now replace the file name field with that of the 
00535                             //  Target file name...
00536                             Ext2CopyUnicodeString( 
00537                                 &RenameLinkTargetFileName,
00538                                 &CurrentName );
00539                             /*
00540                             
00541                             for( i = 0; i < (CurrentName.Length/2); i++ )
00542                             {
00543                                 PtrNewFileObject->FileName.Buffer[i] = CurrentName.Buffer[i];
00544                             }
00545                             PtrNewFileObject->FileName.Length = CurrentName.Length;
00546                             */
00547                             //  Now open the Parent Directory...
00548                             PtrNextFCB = PtrCurrFCB;
00549                             CurrInodeNo = PtrNextFCB->INodeNo;
00550                         }
00551 
00552                         //  
00553                         //  Relating the FCB to the New File Object
00554                         //
00555                         PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
00556                         PtrNewFileObject->PrivateCacheMap = NULL;
00557                         PtrNewFileObject->FsContext = (void *)( &(PtrNextFCB->NTRequiredFCB.CommonFCBHeader) );
00558                         PtrNewFileObject->SectionObjectPointer = &(PtrNextFCB->NTRequiredFCB.SectionObject) ;
00559                         break;
00560                     }
00561 
00562                     else if( !Ext2IsFlagOn( PtrNextFCB->FCBFlags, EXT2_FCB_DIRECTORY ) )
00563                     {
00564                         //  Invalid path...
00565                         //  Can have only a directory in the middle of the path...
00566                         //
00567                         RC = STATUS_OBJECT_PATH_NOT_FOUND;
00568                         try_return();
00569                     }
00570                 }
00571                 else    //  searching on the disk...
00572                 {
00573                     CurrInodeNo = Ext2LocateFileInDisk( PtrVCB, &CurrentName, PtrCurrFCB, &Type );
00574                     if( !CurrInodeNo )
00575                     {
00576                         //
00577                         //  Not found...
00578                         //  Quit searching...
00579                         //  
00580                     
00581                         if( ( NextRemainingName.Length == 0 ) && (
00582                             ( RequestedDisposition == FILE_CREATE ) ||
00583                             ( RequestedDisposition == FILE_OPEN_IF) ||
00584                             ( RequestedDisposition == FILE_OVERWRITE_IF) ) )
00585 
00586                         {
00587                             //
00588                             //  Just the last component was not found...
00589                             //  A create was requested...
00590                             //
00591                             if( DirectoryOnlyRequested )
00592                             {
00593                                 Type = EXT2_FT_DIR;
00594                             }
00595                             else
00596                             {
00597                                 Type = EXT2_FT_REG_FILE;
00598                             }
00599 
00600                             CurrInodeNo = Ext2CreateFile( PtrIrpContext, PtrVCB, 
00601                                 &CurrentName, PtrCurrFCB, Type );
00602                             
00603                             if( !CurrInodeNo )
00604                             {
00605                                 RC = STATUS_OBJECT_PATH_NOT_FOUND;
00606                                 try_return();
00607                             }
00608                             // Set the allocation size for the object is specified
00609                             //IoSetShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject, &(PtrNewFCB->FCBShareAccess));
00610                             //  RC = STATUS_SUCCESS;
00611                             ReturnedInformation = FILE_CREATED;
00612                             
00613                             //  Should also create a CCB structure...
00614                             //  Doing that a little fathre down... ;)
00615 
00616                         }
00617                         else if( NextRemainingName.Length == 0 && OpenTargetDirectory )
00618                         { 
00619                             //
00620                             //  This is for a rename/move operation...
00621                             //  Just the last component was not found...
00622                             //
00623                             ReturnedInformation = FILE_DOES_NOT_EXIST;
00624 
00625                             //  Now replace the file name field with that of the 
00626                             //  Target file name...
00627                             Ext2CopyUnicodeString( 
00628                                 &RenameLinkTargetFileName,
00629                                 &CurrentName );
00630                             /*
00631                             for( i = 0; i < (CurrentName.Length/2); i++ )
00632                             {
00633                                 PtrNewFileObject->FileName.Buffer[i] = CurrentName.Buffer[i];
00634                             }
00635                             PtrNewFileObject->FileName.Length = CurrentName.Length;
00636                             */
00637 
00638                             //  Now open the Parent Directory...
00639                             PtrNextFCB = PtrCurrFCB;
00640                             CurrInodeNo = PtrNextFCB->INodeNo;
00641                             //  Initialize the FsContext
00642                             PtrNewFileObject->FsContext = &PtrNextFCB->NTRequiredFCB.CommonFCBHeader;
00643                             //  Initialize the section object pointer...
00644                             PtrNewFileObject->SectionObjectPointer = &(PtrNextFCB->NTRequiredFCB.SectionObject);
00645                             PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
00646                             PtrNewFileObject->PrivateCacheMap = NULL;                           
00647 
00648                             break;
00649                         }
00650                         else
00651                         {
00652                             RC = STATUS_OBJECT_PATH_NOT_FOUND;
00653                             try_return();
00654                         }
00655                     }
00656 
00657                     if( NextRemainingName.Length )
00658                     {
00659                         //  Should be a directory...
00660                         if( Type != EXT2_FT_DIR )
00661                         {
00662                             //  Invalid path...
00663                             //  Can have only a directory in the middle of the path...
00664                             //
00665                             RC = STATUS_OBJECT_PATH_NOT_FOUND;
00666                             try_return();
00667                         }
00668 
00669                         PtrCurrFileObject = NULL;
00670                     }
00671                     else
00672                     {
00673                         //
00674                         //  Done Parsing...
00675                         //  Found the file...
00676                         //
00677                         Found = TRUE;
00678                         
00679                         //
00680                         //  Was I supposed to create a new file?
00681                         //
00682                         if (RequestedDisposition == FILE_CREATE &&
00683                             ReturnedInformation != FILE_CREATED ) 
00684                         {
00685                             ReturnedInformation = FILE_EXISTS;
00686                             RC = STATUS_OBJECT_NAME_COLLISION;
00687                             try_return();
00688                         }
00689                         
00690                         //  Is this the type of file I was looking for?
00691                         //  Do some checking here...
00692 
00693                         if( Type != EXT2_FT_DIR && Type != EXT2_FT_REG_FILE )
00694                         {
00695                             //  Deny access!
00696                             //  Cannot open a special file...
00697                             RC = STATUS_ACCESS_DENIED;
00698                             try_return();
00699 
00700                         }
00701                         if( DirectoryOnlyRequested && Type != EXT2_FT_DIR )
00702                         {
00703                             RC = STATUS_NOT_A_DIRECTORY;
00704                             try_return();
00705                         }
00706                         if( FileOnlyRequested && Type == EXT2_FT_DIR )
00707                         {
00708                             RC = STATUS_FILE_IS_A_DIRECTORY;
00709                             try_return();
00710                         }
00711 
00712                         PtrCurrFileObject = PtrNewFileObject;
00713                         //  Things seem to be ok enough!
00714                         //  Proceeing with the Open/Create...
00715                         
00716                     }
00717 
00718                 
00719                     //
00720                     //  Create an FCB and initialise it...
00721                     //
00722                     {
00723                         PtrExt2ObjectName       PtrObjectName;
00724                         
00725                         //  Initialising the object name...
00726                         PtrObjectName = Ext2AllocateObjectName();
00727                         Ext2CopyUnicodeString( &PtrObjectName->ObjectName, &CurrentName ); 
00728                         //  RtlInitUnicodeString( &PtrObjectName->ObjectName, CurrentName.Buffer );
00729 
00730                         if( !NT_SUCCESS( Ext2CreateNewFCB( 
00731                             &PtrNextFCB,                //  the new FCB
00732                             ZeroSize,                   //  AllocationSize,
00733                             ZeroSize,                   //  EndOfFile,
00734                             PtrCurrFileObject,          //  The File Object
00735                             PtrVCB,
00736                             PtrObjectName  )  )  )
00737                         {
00738                             RC = STATUS_INSUFFICIENT_RESOURCES;
00739                             try_return();
00740                         }
00741 
00742                         if( Type == EXT2_FT_DIR )
00743                             PtrNextFCB->FCBFlags |= EXT2_FCB_DIRECTORY;
00744                         else if( Type != EXT2_FT_REG_FILE )
00745                             PtrNextFCB->FCBFlags |= EXT2_FCB_SPECIAL_FILE;
00746 
00747                         PtrNextFCB->INodeNo = CurrInodeNo ;
00748                         PtrNextFCB->ParentINodeNo = PtrCurrFCB->INodeNo;
00749 
00750                         if( PtrCurrFileObject == NULL && CurrInodeNo != EXT2_ROOT_INO )
00751                         {
00752                             //  This is an FCB created to cache the reads done while parsing
00753                             //  Put this FCB on the ClosableFCBList 
00754                             if( !PtrNextFCB->ClosableFCBs.OnClosableFCBList )
00755                             {
00756                                     InsertTailList( &PtrVCB->ClosableFCBs.ClosableFCBListHead,
00757                                         &PtrNextFCB->ClosableFCBs.ClosableFCBList );
00758                                     PtrVCB->ClosableFCBs.Count++;
00759                                     PtrNextFCB->ClosableFCBs.OnClosableFCBList = TRUE;
00760                             }
00761                         }
00762                     }
00763                 }
00764     
00765                 //
00766                 //  Still not done parsing...
00767                 //  miles to go before I open... ;)
00768                 //
00769                 PtrCurrFCB = PtrNextFCB;
00770             }
00771 
00772             PtrNewFCB = PtrNextFCB;
00773         }
00774         
00775 
00776         //  If I get this far...
00777         //  it means, I have located the file...
00778         //  I even have an FCB to represent it!!!
00779 
00780         if ( NT_SUCCESS (RC) ) 
00781         {
00782 
00783             if ((PtrNewFCB->FCBFlags & EXT2_FCB_DIRECTORY) && ((RequestedDisposition == FILE_SUPERSEDE) ||
00784                   (RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF ))) 
00785             {
00786                 RC = STATUS_FILE_IS_A_DIRECTORY;
00787                 try_return();
00788             }
00789         
00790             
00791             // Check share access and fail if the share conflicts with an existing
00792             // open.
00793             
00794             if (PtrNewFCB->OpenHandleCount > 0) 
00795             {
00796                 // The FCB is currently in use by some thread.
00797                 // We must check whether the requested access/share access
00798                 // conflicts with the existing open operations.
00799 
00800                 if (!NT_SUCCESS(RC = IoCheckShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject,
00801                                                 &(PtrNewFCB->FCBShareAccess), TRUE))) 
00802                 {
00803                     // Ext2CloseCCB(PtrNewCCB);
00804                     try_return();
00805                 }
00806             } 
00807             else 
00808             {
00809                 IoSetShareAccess(DesiredAccess, ShareAccess, PtrNewFileObject, &(PtrNewFCB->FCBShareAccess));
00810             }
00811 
00812             //
00813             //  Allocating a new CCB Structure...
00814             //  
00815             Ext2CreateNewCCB( &PtrNewCCB, PtrNewFCB, PtrNewFileObject);
00816             PtrNewFileObject->FsContext2 = (void *) PtrNewCCB;
00817             Ext2CopyUnicodeString( &(PtrNewCCB->AbsolutePathName), &AbsolutePathName );
00818 
00819             if( ReturnedInformation == -1 )
00820             {
00821                 //  
00822                 //  ReturnedInformation has not been set so far...
00823                 //
00824                 ReturnedInformation = FILE_OPENED;
00825             }
00826 
00827             // If a supersede or overwrite was requested, do so now ...
00828             if (RequestedDisposition == FILE_SUPERSEDE) 
00829             {
00830                 // Attempt the operation here ...
00831                 if( Ext2SupersedeFile( PtrNewFCB, PtrIrpContext) )
00832                 {
00833                     ReturnedInformation = FILE_SUPERSEDED;
00834                 }
00835             }
00836             
00837             else if ((RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF))
00838             {
00839                 // Attempt the overwrite operation...
00840                 if( Ext2OverwriteFile( PtrNewFCB, PtrIrpContext) )
00841                 {
00842                     ReturnedInformation = FILE_OVERWRITTEN;
00843                 }
00844             }
00845             if( AllocationSize )
00846             {
00847                 if( ReturnedInformation == FILE_CREATED ||
00848                     ReturnedInformation == FILE_SUPERSEDED )
00849                 {
00850                     ULONG CurrentSize;
00851                     ULONG LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
00852                     
00853                     for( CurrentSize = 0; CurrentSize < AllocationSize; CurrentSize += LogicalBlockSize )
00854                     {
00855                         Ext2AddBlockToFile( PtrIrpContext, PtrVCB, PtrNewFCB, PtrNewFileObject, FALSE );
00856                     }
00857                 }
00858             }
00859 
00860             if( ReturnedInformation == FILE_CREATED )
00861             {
00862                 //  Allocate some data blocks if 
00863                 //      1. initial file size has been specified...
00864                 //      2. if the file is a Directory...
00865                 //          In case of (2) make entries for '.' and '..'
00866                 //  Zero out the Blocks...
00867 
00868                 UNICODE_STRING      Name;
00869 
00870                 if( DirectoryOnlyRequested )
00871                 {
00872 
00873                     Ext2CopyCharToUnicodeString( &Name, ".", 1 );
00874                     Ext2MakeNewDirectoryEntry( PtrIrpContext, PtrNewFCB, PtrNewFileObject, &Name, EXT2_FT_DIR, PtrNewFCB->INodeNo);
00875 
00876                     Name.Buffer[1] = '.';
00877                     Name.Buffer[2] = '\0';
00878                     Name.Length += 2;
00879                     Ext2MakeNewDirectoryEntry( PtrIrpContext, PtrNewFCB, PtrNewFileObject, &Name, EXT2_FT_DIR, PtrNewFCB->ParentINodeNo );
00880                     Ext2DeallocateUnicodeString( &Name );
00881                 }
00882             }
00883             if( OpenTargetDirectory )
00884             {
00885                 //
00886                 //  Save the taget file name in the CCB...
00887                 //
00888                 Ext2CopyUnicodeString( 
00889                     &PtrNewCCB->RenameLinkTargetFileName,
00890                     &RenameLinkTargetFileName );
00891                 Ext2DeallocateUnicodeString( &RenameLinkTargetFileName );
00892             }
00893         }
00894 
00895         try_exit:   NOTHING;
00896 
00897     }
00898     finally 
00899     {
00900         if (AcquiredVCB) 
00901         {
00902             ASSERT(PtrVCB);
00903             Ext2ReleaseResource(&(PtrVCB->VCBResource));
00904 
00905             AcquiredVCB = FALSE;
00906             DebugTrace(DEBUG_TRACE_MISC,   "*** VCB released [Create]", 0);
00907 
00908             if( PtrNewFileObject )
00909             {
00910                 DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [Create]", PtrNewFileObject);
00911             }
00912         }
00913 
00914         if (AbsolutePathName.Buffer != NULL) 
00915         {
00916             DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Create]", AbsolutePathName.Buffer );
00917             ExFreePool(AbsolutePathName.Buffer);
00918         }
00919 
00920         // Complete the request unless we are here as part of unwinding
00921         //  when an exception condition was encountered, OR
00922         //  if the request has been deferred (i.e. posted for later handling)
00923         if (RC != STATUS_PENDING) 
00924         {
00925             // If we acquired any FCB resources, release them now ...
00926 
00927             // If any intermediate (directory) open operations were performed,
00928             //  implement the corresponding close (do *not* however close
00929             //  the target you have opened on behalf of the caller ...).
00930 
00931             if (NT_SUCCESS(RC)) 
00932             {
00933                 // Update the file object such that:
00934                 //  (a) the FsContext field points to the NTRequiredFCB field
00935                 //       in the FCB
00936                 //  (b) the FsContext2 field points to the CCB created as a
00937                 //       result of the open operation
00938 
00939                 // If write-through was requested, then mark the file object
00940                 //  appropriately
00941                 if (WriteThroughRequested) 
00942                 {
00943                     PtrNewFileObject->Flags |= FO_WRITE_THROUGH;
00944                 }
00945                 DebugTrace( DEBUG_TRACE_SPECIAL,   " === Create/Open successful", 0 );
00946             } 
00947             else 
00948             {
00949                 DebugTrace( DEBUG_TRACE_SPECIAL,   " === Create/Open failed", 0 );
00950                 // Perform failure related post-processing now
00951             }
00952 
00953             // As long as this unwinding is not being performed as a result of
00954             //  an exception condition, complete the IRP ...
00955             if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION)) 
00956             {
00957                 PtrIrp->IoStatus.Status = RC;
00958                 PtrIrp->IoStatus.Information = ReturnedInformation;
00959             
00960                 // Free up the Irp Context
00961                 Ext2ReleaseIrpContext(PtrIrpContext);
00962                 
00963                 // complete the IRP
00964                 IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
00965             }
00966         }
00967     }
00968     return(RC);
00969 }
00970 
00971 
00972 /*************************************************************************
00973 *
00974 * Function: Ext2OpenVolume()
00975 *
00976 * Description:
00977 *   Open a logical volume for the caller.
00978 *
00979 * Expected Interrupt Level (for execution) :
00980 *
00981 *  IRQL_PASSIVE_LEVEL
00982 *
00983 * Return Value: STATUS_SUCCESS/Error
00984 *
00985 *************************************************************************/
00986 NTSTATUS NTAPI Ext2OpenVolume(
00987 PtrExt2VCB              PtrVCB,                 // volume to be opened
00988 PtrExt2IrpContext       PtrIrpContext,          // IRP context
00989 PIRP                        PtrIrp,                 // original/user IRP
00990 unsigned short          ShareAccess,            // share access
00991 PIO_SECURITY_CONTEXT    PtrSecurityContext, // caller's context (incl access)
00992 PFILE_OBJECT            PtrNewFileObject)       // I/O Mgr. created file object
00993 {
00994     NTSTATUS                RC = STATUS_SUCCESS;
00995     PtrExt2CCB          PtrCCB = NULL;
00996 
00997     try {
00998         // check for exclusive open requests (using share modes supplied)
00999         //  and determine whether it is even possible to open the volume
01000         //  with the specified share modes (e.g. if caller does not
01001         //  wish to share read or share write ...)
01002     
01003         //  Use IoCheckShareAccess() and IoSetShareAccess() here ...    
01004         //  They are defined in the DDK.
01005 
01006         //  You might also wish to check the caller's security context
01007         //  to see whether you wish to allow the volume open or not.
01008         //  Use the SeAccessCheck() routine described in the DDK for    this purpose.
01009     
01010         // create a new CCB structure
01011         if (!(PtrCCB = Ext2AllocateCCB())) 
01012         {
01013             RC = STATUS_INSUFFICIENT_RESOURCES;
01014             try_return();
01015         }
01016 
01017         // initialize the CCB
01018         PtrCCB->PtrFCB = (PtrExt2FCB)(PtrVCB);
01019         InsertTailList(&(PtrVCB->VolumeOpenListHead), &(PtrCCB->NextCCB));
01020 
01021         // initialize the CCB to point to the file object
01022         PtrCCB->PtrFileObject = PtrNewFileObject;
01023 
01024         Ext2SetFlag(PtrCCB->CCBFlags, EXT2_CCB_VOLUME_OPEN);
01025 
01026         // initialize the file object appropriately
01027         PtrNewFileObject->FsContext = (void *)( &(PtrVCB->CommonVCBHeader) );
01028         PtrNewFileObject->FsContext2 = (void *)(PtrCCB);
01029 
01030         // increment the number of outstanding open operations on this
01031         //  logical volume (i.e. volume cannot be dismounted)
01032 
01033         //  You might be concerned about 32 bit wrap-around though I would
01034         //  argue that it is unlikely ... :-)
01035         (PtrVCB->VCBOpenCount)++;
01036     
01037         // now set the IoStatus Information value correctly in the IRP
01038         //  (caller will set the status field)
01039         PtrIrp->IoStatus.Information = FILE_OPENED;
01040     
01041         try_exit:   NOTHING;
01042     } 
01043     finally 
01044     {
01045         NOTHING;
01046     }
01047 
01048     return(RC);
01049 }
01050 
01051 /*************************************************************************
01052 *
01053 * Function: Ext2InitializeFCB()
01054 *
01055 * Description:
01056 *   Initialize a new FCB structure and also the sent-in file object
01057 *   (if supplied)
01058 *
01059 * Expected Interrupt Level (for execution) :
01060 *
01061 *  IRQL_PASSIVE_LEVEL
01062 *
01063 * Return Value: None
01064 *
01065 *************************************************************************
01066 void Ext2InitializeFCB(
01067 PtrExt2FCB              PtrNewFCB,      // FCB structure to be initialized
01068 PtrExt2VCB              PtrVCB,         // logical volume (VCB) pointer
01069 PtrExt2ObjectName       PtrObjectName,  // name of the object
01070 uint32                  Flags,          // is this a file/directory, etc.
01071 PFILE_OBJECT            PtrFileObject)  // optional file object to be initialized
01072 {
01073     // Initialize the disk dependent portion as you see fit
01074 
01075     // Initialize the two ERESOURCE objects
01076     ExInitializeResourceLite(&(PtrNewFCB->NTRequiredFCB.MainResource));
01077     ExInitializeResourceLite(&(PtrNewFCB->NTRequiredFCB.PagingIoResource));
01078 
01079     PtrNewFCB->FCBFlags |= EXT2_INITIALIZED_MAIN_RESOURCE | EXT2_INITIALIZED_PAGING_IO_RESOURCE | Flags;
01080 
01081     PtrNewFCB->PtrVCB = PtrVCB;
01082 
01083     // caller MUST ensure that VCB has been acquired exclusively
01084     InsertTailList(&(PtrVCB->FCBListHead), &(PtrNewFCB->NextFCB));
01085 
01086     // initialize the various list heads
01087     InitializeListHead(&(PtrNewFCB->CCBListHead));
01088 
01089 //  PtrNewFCB->ReferenceCount = 1;
01090 //  PtrNewFCB->OpenHandleCount = 1;
01091 
01092     if( PtrObjectName )
01093     {
01094         PtrNewFCB->FCBName = PtrObjectName;
01095     }
01096 
01097     if ( PtrFileObject )
01098     {
01099         PtrFileObject->FsContext = (void *)(&(PtrNewFCB->NTRequiredFCB));
01100     }
01101 
01102     return;
01103 }
01104 */
01105 
01106 /*************************************************************************
01107 *
01108 * Function: Ext2OpenRootDirectory()
01109 *
01110 * Description:
01111 *   Open the root directory for a volume
01112 *   
01113 *
01114 * Expected Interrupt Level (for execution) :
01115 *
01116 *  ???
01117 *
01118 * Return Value: None
01119 *
01120 *************************************************************************/
01121 NTSTATUS NTAPI Ext2OpenRootDirectory(
01122     PtrExt2VCB              PtrVCB,                 // volume 
01123     PtrExt2IrpContext       PtrIrpContext,          // IRP context
01124     PIRP                    PtrIrp,                 // original/user IRP
01125     unsigned short          ShareAccess,            // share access
01126     PIO_SECURITY_CONTEXT    PtrSecurityContext,     // caller's context (incl access)
01127     PFILE_OBJECT            PtrNewFileObject        // I/O Mgr. created file object
01128     )
01129 {
01130     //  Declerations...
01131     PtrExt2CCB PtrCCB;
01132     
01133     ASSERT( PtrVCB );
01134     ASSERT( PtrVCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB);
01135     ASSERT( PtrVCB->PtrRootDirectoryFCB );
01136     AssertFCB( PtrVCB->PtrRootDirectoryFCB );
01137         
01138     PtrVCB->PtrRootDirectoryFCB->INodeNo = EXT2_ROOT_INO;
01139     
01140     //  Create a new CCB...
01141     Ext2CreateNewCCB( &PtrCCB, PtrVCB->PtrRootDirectoryFCB, PtrNewFileObject);
01142     PtrNewFileObject->FsContext = (void *) &(PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.CommonFCBHeader);
01143     PtrVCB->PtrRootDirectoryFCB->FCBFlags |= EXT2_FCB_DIRECTORY;
01144     PtrNewFileObject->FsContext2 = (void *) PtrCCB;
01145     PtrNewFileObject->SectionObjectPointer = &PtrVCB->PtrRootDirectoryFCB->NTRequiredFCB.SectionObject;
01146     PtrNewFileObject->Vpb = PtrVCB->PtrVPB;
01147 
01148     Ext2CopyUnicodeString( &(PtrCCB->AbsolutePathName), &PtrVCB->PtrRootDirectoryFCB->FCBName->ObjectName );
01149 
01150 
01151     return STATUS_SUCCESS;
01152 }
01153 
01154 
01155 
01156 PtrExt2FCB NTAPI Ext2LocateChildFCBInCore(
01157     PtrExt2VCB              PtrVCB, 
01158     PUNICODE_STRING         PtrName, 
01159     ULONG                   ParentInodeNo )
01160 {
01161 
01162     PtrExt2FCB PtrFCB = NULL;
01163     PLIST_ENTRY PtrEntry;
01164 
01165     if( IsListEmpty( &(PtrVCB->FCBListHead) ) )
01166     {
01167         return NULL;    //  Failure;
01168     }
01169 
01170     for( PtrEntry = PtrVCB->FCBListHead.Flink; 
01171             PtrEntry != &PtrVCB->FCBListHead; 
01172             PtrEntry = PtrEntry->Flink )
01173     {
01174         PtrFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, NextFCB );
01175         ASSERT( PtrFCB );
01176         if( PtrFCB->ParentINodeNo == ParentInodeNo )
01177         {
01178             if( RtlCompareUnicodeString( &PtrFCB->FCBName->ObjectName, PtrName, TRUE ) == 0 )
01179                 return PtrFCB;
01180         }
01181     }
01182 
01183     return NULL;
01184 }
01185 
01186 PtrExt2FCB NTAPI Ext2LocateFCBInCore(
01187     PtrExt2VCB              PtrVCB, 
01188     ULONG                   InodeNo )
01189 {
01190     PtrExt2FCB PtrFCB = NULL;
01191     PLIST_ENTRY PtrEntry;
01192 
01193     if( IsListEmpty( &(PtrVCB->FCBListHead) ) )
01194     {
01195         return NULL;    //  Failure;
01196     }
01197 
01198     for( PtrEntry = PtrVCB->FCBListHead.Flink; 
01199             PtrEntry != &PtrVCB->FCBListHead; 
01200             PtrEntry = PtrEntry->Flink )
01201     {
01202         PtrFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, NextFCB );
01203         ASSERT( PtrFCB );
01204         if( PtrFCB->INodeNo == InodeNo )
01205         {
01206             return PtrFCB;
01207         }
01208     }
01209 
01210     return NULL;
01211 }
01212 
01213 
01214 ULONG NTAPI Ext2LocateFileInDisk (
01215     PtrExt2VCB              PtrVCB,
01216     PUNICODE_STRING         PtrCurrentName, 
01217     PtrExt2FCB              PtrParentFCB,
01218     ULONG                   *Type )
01219 {
01220 
01221     PFILE_OBJECT        PtrFileObject = NULL;
01222     ULONG               InodeNo = 0;
01223     
01224     *Type = EXT2_FT_UNKNOWN;
01225 
01226     //  1. 
01227     //  Initialize the Blocks in the FCB...
01228     //
01229     Ext2InitializeFCBInodeInfo( PtrParentFCB );
01230 
01231     
01232     //  2.
01233     //  Is there a file object I can use for caching??
01234     //  If not create one...
01235     //
01236     if( !PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject )
01237     {
01238         //
01239         //  No Directory File Object?
01240         //  No problem, will create one...
01241         //
01242 
01243         //  Acquire the MainResource first though...
01244             
01245             PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject = IoCreateStreamFileObject(NULL, PtrVCB->TargetDeviceObject );
01246             PtrFileObject = PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject;
01247             
01248             if( !PtrFileObject )
01249             {
01250                 Ext2BreakPoint();
01251                 return 0;
01252             }
01253             PtrFileObject->ReadAccess = TRUE;
01254             PtrFileObject->WriteAccess = TRUE;
01255 
01256             //  Associate the file stream with the Volume parameter block...
01257             PtrFileObject->Vpb = PtrVCB->PtrVPB;
01258 
01259             //  No caching as yet...
01260             PtrFileObject->PrivateCacheMap = NULL;
01261 
01262             //  this establishes the FCB - File Object connection...
01263             PtrFileObject->FsContext = (void *)( & (PtrParentFCB->NTRequiredFCB.CommonFCBHeader) );
01264 
01265             //  Initialize the section object pointer...
01266             PtrFileObject->SectionObjectPointer = &(PtrParentFCB->NTRequiredFCB.SectionObject);
01267     }
01268     else
01269     {
01270         //  
01271         //  I do have a file object... 
01272         //  I am using it now!
01273         //
01274         PtrFileObject = PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject;
01275     }
01276 
01277     //  3.
01278     //  Got hold of a file object? Good ;)
01279     //  Now initiating Caching, pinned access to be precise ...
01280     //
01281     if (PtrFileObject->PrivateCacheMap == NULL) 
01282     {
01283             CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrParentFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)),
01284                 TRUE,       // We utilize pin access for directories
01285                 &(Ext2GlobalData.CacheMgrCallBacks), // callbacks
01286                 PtrParentFCB );     // The context used in callbacks
01287     }
01288 
01289     //  4.
01290     //  Getting down to the real business now... ;)
01291     //  Read in the directory contents and do a search 
01292     //  a sequential search to be precise...
01293     //  Wish Mm'm Renuga were reading this
01294     //  Would feel proud... ;)
01295     //
01296     {
01297         LARGE_INTEGER   StartBufferOffset;
01298         ULONG           PinBufferLength;
01299         ULONG           BufferIndex;
01300         PBCB            PtrBCB = NULL;
01301         BYTE *          PtrPinnedBlockBuffer = NULL;
01302         PEXT2_DIR_ENTRY PtrDirEntry = NULL;
01303         BOOLEAN         Found;
01304         int             i;
01305 
01306 
01307         StartBufferOffset.QuadPart = 0;
01308 
01309         //
01310         //  Read in the whole damn directory
01311         //  **Bad programming**
01312         //  Will do for now.
01313         //
01314         PinBufferLength = PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.LowPart;
01315         if (!CcMapData( PtrFileObject,
01316                   &StartBufferOffset,
01317                   PinBufferLength,
01318                   TRUE,
01319                   &PtrBCB,
01320                   (PVOID*)&PtrPinnedBlockBuffer ) )
01321         {
01322 
01323             
01324         }
01325         //
01326         //  Walking through now...
01327         //
01328         
01329         for( BufferIndex = 0, Found = FALSE; !Found && BufferIndex < ( PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; BufferIndex += PtrDirEntry->rec_len )
01330         {
01331             PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ BufferIndex ];
01332             if( PtrDirEntry->name_len == 0 || PtrDirEntry->rec_len == 0 || PtrDirEntry->inode == 0)
01333             {
01334                 //  Invalid entry...
01335                 //  Ignore...
01336                 continue;
01337             }
01338             //
01339             //  Comparing ( case sensitive )
01340             //  Directory entry is not NULL terminated...
01341             //  nor is the CurrentName...
01342             //
01343             if( PtrDirEntry->name_len != (PtrCurrentName->Length / 2) )
01344                 continue;
01345             
01346             for( i = 0, Found = TRUE ; i < PtrDirEntry->name_len ; i++ )
01347             {
01348                 if( PtrDirEntry->name[ i ] != PtrCurrentName->Buffer[ i ] )
01349                 {
01350                     Found = FALSE;
01351                     break;
01352 
01353                 }
01354             }
01355             
01356         }
01357         if( Found )
01358         {
01359             InodeNo = PtrDirEntry->inode;
01360 
01361             if( PtrDirEntry->file_type == EXT2_FT_UNKNOWN )
01362             {
01363 
01364                 //  Old Fashioned Directory entries...
01365                 //  Will have to read in the Inode to determine the File Type...
01366                 EXT2_INODE  Inode;
01367                 //  PtrInode = Ext2AllocatePool( NonPagedPool, sizeof( EXT2_INODE )  );
01368                 Ext2ReadInode( PtrVCB, InodeNo, &Inode );   
01369 
01370                 if( Ext2IsModeRegularFile( Inode.i_mode ) )
01371                 {
01372                     *Type = EXT2_FT_REG_FILE;
01373                 }
01374                 else if ( Ext2IsModeDirectory( Inode.i_mode) )
01375                 {
01376                     //  Directory...
01377                     *Type = EXT2_FT_DIR;
01378                 }
01379                 else if( Ext2IsModeSymbolicLink(Inode.i_mode) )
01380                 {
01381                     *Type = EXT2_FT_SYMLINK;
01382                 }
01383                 else if( Ext2IsModePipe(Inode.i_mode) )
01384                 {
01385                     *Type = EXT2_FT_FIFO;
01386                 }
01387                 else if( Ext2IsModeCharacterDevice(Inode.i_mode) )
01388                 {
01389                     *Type = EXT2_FT_CHRDEV;
01390                 }
01391                 else if( Ext2IsModeBlockDevice(Inode.i_mode) )
01392                 {
01393                     *Type = EXT2_FT_BLKDEV;
01394                 }
01395                 else if( Ext2IsModeSocket(Inode.i_mode) )
01396                 {
01397                     *Type = EXT2_FT_SOCK;
01398                 }
01399                 else
01400                 {
01401                     *Type = EXT2_FT_UNKNOWN;
01402                 }
01403                 
01404                 //DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [Create]", PtrInode );
01405                 //ExFreePool( PtrInode );
01406             }
01407             else
01408             {
01409                 *Type = PtrDirEntry->file_type;
01410             }
01411         }
01412 
01413         CcUnpinData( PtrBCB );
01414         PtrBCB = NULL;
01415 
01416         return InodeNo;
01417     }
01418 }
01419 
01420 
01421 /*************************************************************************
01422 *
01423 * Function: Ext2CreateFile()
01424 *
01425 * Description:
01426 *   Creates a new file on the disk
01427 *   
01428 * Expected Interrupt Level (for execution) :
01429 *   IRQL_PASSIVE_LEVEL
01430 *
01431 * Restrictions:
01432 *   Expects the VCB to be acquired Exclusively before being invoked
01433 *
01434 * Return Value: None
01435 *
01436 *************************************************************************/
01437 ULONG NTAPI Ext2CreateFile( 
01438     PtrExt2IrpContext       PtrIrpContext,
01439     PtrExt2VCB              PtrVCB,
01440     PUNICODE_STRING         PtrName, 
01441     PtrExt2FCB              PtrParentFCB,
01442     ULONG                   Type)
01443 {
01444     EXT2_INODE  Inode, ParentInode;
01445 
01446     ULONG       NewInodeNo = 0;
01447     BOOLEAN     FCBAcquired = FALSE;
01448 
01449     ULONG       LogicalBlockSize = 0;
01450 
01451     try
01452     {
01453         
01454 
01455         //  0. Verify if the creation is possible,,,
01456         if( Type != EXT2_FT_DIR && Type != EXT2_FT_REG_FILE )
01457         {
01458             //
01459             //  Can create only a directory or a regular file...
01460             //
01461             return 0;
01462         }
01463         
01464         //  1. Allocate an i-node...
01465         
01466         NewInodeNo = Ext2AllocInode( PtrIrpContext, PtrVCB, PtrParentFCB->INodeNo );
01467         
01468         //  NewInodeNo = 12;
01469 
01470         if( !NewInodeNo )
01471         {
01472             return 0;
01473         }
01474         
01475         //  2. Acquire the Parent FCB Exclusively...
01476         if( !ExAcquireResourceExclusiveLite(&( PtrParentFCB->NTRequiredFCB.MainResource ), TRUE) )
01477         {
01478             Ext2DeallocInode( PtrIrpContext, PtrVCB, NewInodeNo );
01479             try_return( NewInodeNo = 0);
01480         }
01481         FCBAcquired = TRUE;
01482 
01483         //  3. Make an entry in the parent Directory...     
01484         ASSERT( PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject );
01485         
01486         Ext2MakeNewDirectoryEntry(
01487             PtrIrpContext,
01488             PtrParentFCB, 
01489             PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject, 
01490             PtrName, Type, NewInodeNo );
01491     
01492         
01493         //  4. Initialize an inode entry and  write it to disk...
01494         LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
01495 
01496         {
01497             //  To be deleted
01498             Ext2ReadInode( PtrVCB, NewInodeNo, &Inode );
01499         }
01500 
01501         RtlZeroMemory( &Inode, sizeof( EXT2_INODE ) );
01502         if( Type == EXT2_FT_DIR )
01503         {
01504             Inode.i_mode = 0x41ff;
01505 
01506             //  In addition to the usual link, 
01507             //  there will be an additional link in the directory itself - the '.' entry
01508             Inode.i_links_count = 2;
01509 
01510             //  Incrementing the link count for the parent as well...
01511             Ext2ReadInode( PtrVCB, PtrParentFCB->INodeNo, &ParentInode );
01512             ParentInode.i_links_count++;
01513             Ext2WriteInode( PtrIrpContext, PtrVCB, PtrParentFCB->INodeNo, &ParentInode );
01514 
01515         }
01516         else
01517         {
01518             Inode.i_mode = 0x81ff;
01519             Inode.i_links_count = 1;
01520         }
01521 
01522 
01523         {
01524             //
01525             //  Setting the time fields in the inode...
01526             //
01527             ULONG Time;
01528             Time = Ext2GetCurrentTime();
01529             Inode.i_ctime = Time;
01530             Inode.i_atime = Time;
01531             Inode.i_mtime = Time;
01532             Inode.i_dtime = 0;          //  Deleted time;
01533         }
01534 
01535         Ext2WriteInode( PtrIrpContext, PtrVCB, NewInodeNo, &Inode );
01536 
01537         try_exit:   NOTHING;
01538     }
01539     finally 
01540     {
01541         if( FCBAcquired )
01542         {
01543             Ext2ReleaseResource( &(PtrParentFCB->NTRequiredFCB.MainResource) );
01544         }
01545     }
01546 
01547     return NewInodeNo ;
01548 }
01549 
01550 /*************************************************************************
01551 *
01552 * Function: Ext2CreateFile()
01553 *
01554 * Description:
01555 *   Overwrites an existing file on the disk
01556 *   
01557 * Expected Interrupt Level (for execution) :
01558 *   IRQL_PASSIVE_LEVEL
01559 *
01560 * Restrictions:
01561 *   Expects the VCB to be acquired Exclusively before being invoked
01562 *
01563 * Return Value: None
01564 *
01565 *************************************************************************/
01566 BOOLEAN NTAPI Ext2OverwriteFile(
01567     PtrExt2FCB          PtrFCB,
01568     PtrExt2IrpContext   PtrIrpContext)
01569 {
01570     EXT2_INODE          Inode;
01571     PtrExt2VCB          PtrVCB = PtrFCB->PtrVCB;
01572     ULONG               i;
01573     ULONG   Time;
01574     Time = Ext2GetCurrentTime();
01575 
01576     Ext2InitializeFCBInodeInfo( PtrFCB );
01577     //  1.
01578     //  Update the inode...
01579     if( !NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
01580     {
01581         return FALSE;
01582     }
01583 
01584     Inode.i_size = 0;
01585     Inode.i_blocks = 0;
01586     Inode.i_atime = Time;
01587     Inode.i_mtime = Time;
01588     Inode.i_dtime = 0;
01589 
01590     for( i = 0; i < EXT2_N_BLOCKS; i++ )
01591     {
01592         Inode.i_block[ i ] = 0;
01593     }
01594 
01595     if( !NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
01596     {
01597         return FALSE;
01598     }
01599 
01600     //  2.
01601     //  Release all the data blocks...
01602     if( !Ext2ReleaseDataBlocks( PtrFCB, PtrIrpContext) )
01603     {
01604         return FALSE;
01605     }
01606     
01607     Ext2ClearFlag( PtrFCB->FCBFlags, EXT2_FCB_BLOCKS_INITIALIZED );
01608     Ext2InitializeFCBInodeInfo( PtrFCB );
01609     
01610     return TRUE;
01611 }
01612 
01613 /*************************************************************************
01614 *
01615 * Function: Ext2SupersedeFile()
01616 *
01617 * Description:
01618 *   Supersedes an existing file on the disk
01619 *   
01620 * Expected Interrupt Level (for execution) :
01621 *   IRQL_PASSIVE_LEVEL
01622 *
01623 * Restrictions:
01624 *   Expects the VCB to be acquired Exclusively before being invoked
01625 *
01626 * Return Value: None
01627 *
01628 *************************************************************************/
01629 BOOLEAN NTAPI Ext2SupersedeFile(
01630     PtrExt2FCB          PtrFCB,
01631     PtrExt2IrpContext   PtrIrpContext)
01632 {
01633     EXT2_INODE          Inode;
01634     PtrExt2VCB          PtrVCB = PtrFCB->PtrVCB;
01635 
01636     Ext2InitializeFCBInodeInfo( PtrFCB );
01637 
01638     //  1.
01639     //  Initialize the inode...
01640     RtlZeroMemory( &Inode, sizeof( EXT2_INODE ) );
01641 
01642     //  Setting the file mode...
01643     //  This operation is allowed only for a regular file...
01644     Inode.i_mode = 0x81ff;
01645 
01646     //  Maintaining the old link count...
01647     Inode.i_links_count = PtrFCB->LinkCount;
01648 
01649     //  Setting the time fields in the inode...
01650     {
01651         ULONG Time;
01652         Time = Ext2GetCurrentTime();
01653         Inode.i_ctime = Time;
01654         Inode.i_atime = Time;
01655         Inode.i_mtime = Time;
01656         Inode.i_dtime = 0;          //  Deleted time;
01657     }
01658 
01659     if( !NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
01660     {
01661         return FALSE;
01662     }
01663 
01664     //  2.
01665     //  Release all the data blocks...
01666     if( !Ext2ReleaseDataBlocks( PtrFCB, PtrIrpContext) )
01667     {
01668         return FALSE;
01669     }
01670     
01671     Ext2ClearFlag( PtrFCB->FCBFlags, EXT2_FCB_BLOCKS_INITIALIZED );
01672     Ext2InitializeFCBInodeInfo( PtrFCB );
01673     
01674     return TRUE;
01675 }

Generated on Sun May 27 2012 04:16:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.