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

fileinfo.c
Go to the documentation of this file.
00001 /*************************************************************************
00002 *
00003 * File: fileinfo.c
00004 *
00005 * Module: Ext2 File System Driver (Kernel mode execution only)
00006 *
00007 * Description:
00008 *   Contains code to handle the "set/query file information" dispatch
00009 *   entry points.
00010 *
00011 * Author: Manoj Paul Joseph
00012 *
00013 *
00014 *************************************************************************/
00015 
00016 #include            "ext2fsd.h"
00017 
00018 // define the file specific bug-check id
00019 #define         EXT2_BUG_CHECK_ID               EXT2_FILE_INFORMATION
00020 #define         DEBUG_LEVEL                     (DEBUG_TRACE_FILEINFO)
00021 
00022 
00023 /*************************************************************************
00024 *
00025 * Function: Ext2FileInfo()
00026 *
00027 * Description:
00028 *   The I/O Manager will invoke this routine to handle a set/query file
00029 *   information 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 Ext2FileInfo(
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 = NULL;
00045     BOOLEAN             AreWeTopLevel = FALSE;
00046 
00047     DebugTrace(DEBUG_TRACE_IRP_ENTRY,   "File Info Control IRP received...", 0);
00048 
00049     FsRtlEnterFileSystem();
00050     
00051     ASSERT(DeviceObject);
00052     ASSERT(Irp);
00053 
00054     // set the top level context
00055     AreWeTopLevel = Ext2IsIrpTopLevel(Irp);
00056 
00057     try 
00058     {
00059 
00060         // get an IRP context structure and issue the request
00061         PtrIrpContext = Ext2AllocateIrpContext(Irp, DeviceObject);
00062         ASSERT(PtrIrpContext);
00063 
00064         RC = Ext2CommonFileInfo(PtrIrpContext, Irp);
00065 
00066     } 
00067     except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) 
00068     {
00069 
00070         RC = Ext2ExceptionHandler(PtrIrpContext, Irp);
00071 
00072         Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC);
00073     }
00074 
00075     if (AreWeTopLevel) 
00076     {
00077         IoSetTopLevelIrp(NULL);
00078     }
00079 
00080     FsRtlExitFileSystem();
00081 
00082     return(RC);
00083 }
00084 
00085 
00086 
00087 /*************************************************************************
00088 *
00089 * Function: Ext2CommonFileInfo()
00090 *
00091 * Description:
00092 *   The actual work is performed here. This routine may be invoked in one'
00093 *   of the two possible contexts:
00094 *   (a) in the context of a system worker thread
00095 *   (b) in the context of the original caller
00096 *
00097 * Expected Interrupt Level (for execution) :
00098 *
00099 *  IRQL_PASSIVE_LEVEL
00100 *
00101 * Return Value: STATUS_SUCCESS/Error
00102 *
00103 *************************************************************************/
00104 NTSTATUS NTAPI Ext2CommonFileInfo(
00105 PtrExt2IrpContext           PtrIrpContext,
00106 PIRP                            PtrIrp)
00107 {
00108     NTSTATUS                RC = STATUS_SUCCESS;
00109     PIO_STACK_LOCATION      PtrIoStackLocation = NULL;
00110     PFILE_OBJECT            PtrFileObject = NULL;
00111     PtrExt2FCB              PtrFCB = NULL;
00112     PtrExt2CCB              PtrCCB = NULL;
00113     PtrExt2VCB              PtrVCB = NULL;
00114     PtrExt2NTRequiredFCB    PtrReqdFCB = NULL;
00115     BOOLEAN                 MainResourceAcquired = FALSE;
00116     BOOLEAN                 VCBResourceAcquired = FALSE;
00117     BOOLEAN                 PagingIoResourceAcquired = FALSE;
00118     void                    *PtrSystemBuffer = NULL;
00119     long                    BufferLength = 0;
00120     FILE_INFORMATION_CLASS  FunctionalityRequested;
00121     BOOLEAN                 CanWait = FALSE;
00122     BOOLEAN                 PostRequest = FALSE;
00123 
00124     try 
00125     {
00126         // First, get a pointer to the current I/O stack location.
00127         PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp);
00128         ASSERT(PtrIoStackLocation);
00129 
00130         PtrFileObject = PtrIoStackLocation->FileObject;
00131         ASSERT(PtrFileObject);
00132 
00133         // Get the FCB and CCB pointers
00134         Ext2GetFCB_CCB_VCB_FromFileObject ( 
00135             PtrFileObject, &PtrFCB, &PtrCCB, &PtrVCB );
00136 
00137         PtrReqdFCB = &(PtrFCB->NTRequiredFCB);
00138 
00139         CanWait = ((PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
00140 
00141         // If the caller has opened a logical volume and is attempting to
00142         // query information for it as a file stream, return an error.
00143         if (PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) 
00144         {
00145             // This is not allowed. Caller must use get/set volume information instead.
00146             RC = STATUS_INVALID_PARAMETER;
00147             try_return();
00148         }
00149 
00150         //  ASSERT(PtrFCB->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB);
00151         AssertFCB( PtrFCB );
00152 
00153         PtrSystemBuffer = PtrIrp->AssociatedIrp.SystemBuffer;   
00154 
00155         if (PtrIoStackLocation->MajorFunction == IRP_MJ_QUERY_INFORMATION) 
00156         {
00157             //  ***********************
00158             //  Query File Information
00159             //  ***********************
00160 
00161             // Now, obtain some parameters.
00162             DebugTrace(DEBUG_TRACE_MISC,   "Buffer length = 0x%lX[FileInfo]", BufferLength );
00163 
00164             BufferLength = PtrIoStackLocation->Parameters.QueryFile.Length;
00165 
00166             FunctionalityRequested = PtrIoStackLocation->Parameters.QueryFile.FileInformationClass;
00167 
00168             //  Read in the file inode if it hasn't already been read...
00169             Ext2InitializeFCBInodeInfo( PtrFCB );
00170 
00171             //
00172             // Acquire the MainResource shared 
00173             // except for page files...
00174             //
00175             if (!(PtrFCB->FCBFlags & EXT2_FCB_PAGE_FILE)) 
00176             {
00177                 // Acquire the MainResource shared.
00178                 DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire FCB Shared [FileInfo]", 0);
00179                 DebugTraceState( "FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [FileInfo]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
00180                 if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait)) 
00181                 {
00182                     DebugTrace(DEBUG_TRACE_MISC,   "*** FCB acquisition FAILED [FileInfo]", 0);
00183                     PostRequest = TRUE;
00184                     try_return(RC = STATUS_PENDING);
00185                 }
00186                 MainResourceAcquired = TRUE;
00187                 DebugTrace(DEBUG_TRACE_MISC,   "*** FCB acquired [FileInfo]", 0);
00188             }
00189 
00190             // Do whatever the caller asked us to do
00191             switch (FunctionalityRequested) 
00192             {
00193             case FileBasicInformation:
00194                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileBasicInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00195                 RC = Ext2GetBasicInformation(PtrFCB, (PFILE_BASIC_INFORMATION)PtrSystemBuffer, &BufferLength);
00196                 break;
00197             case FileStandardInformation:
00198                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileStandardInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00199                 RC = Ext2GetStandardInformation(PtrFCB, (PFILE_STANDARD_INFORMATION)PtrSystemBuffer, &BufferLength);
00200                 break;
00201             // Similarly, implement all of the other query information routines
00202             // that your FSD can support.
00203 #if(_WIN32_WINNT >= 0x0400)
00204             case FileNetworkOpenInformation:
00205                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileNetworkOpenInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00206                 RC = Ext2GetNetworkOpenInformation(PtrFCB, (PFILE_NETWORK_OPEN_INFORMATION)PtrSystemBuffer, &BufferLength);
00207                 //  RC = STATUS_INVALID_PARAMETER;
00208                 //  try_return();
00209                 break;
00210 #endif  // _WIN32_WINNT >= 0x0400
00211             case FileInternalInformation:
00212                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileInternalInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00213                 // RC = Ext2GetInternalInformation(...);
00214                 RC = STATUS_INVALID_PARAMETER;
00215                 try_return();
00216                 break;
00217             case FileEaInformation:
00218                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileEaInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00219                 {   
00220                     PFILE_EA_INFORMATION EaInformation;
00221                     EaInformation = (PFILE_EA_INFORMATION) PtrSystemBuffer;
00222                     EaInformation->EaSize = 0;
00223                     BufferLength = sizeof( FILE_EA_INFORMATION );
00224                     break;
00225                 }
00226                 // RC = Ext2GetEaInformation(...);
00227                 break;
00228 
00229             case FilePositionInformation:
00230                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FilePositionInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00231                 // This is fairly simple. Copy over the information from the
00232                 // file object.
00233                 {
00234                     PFILE_POSITION_INFORMATION      PtrFileInfoBuffer;
00235 
00236                     PtrFileInfoBuffer = (PFILE_POSITION_INFORMATION)PtrSystemBuffer;
00237 
00238                     ASSERT(BufferLength >= sizeof(FILE_POSITION_INFORMATION));
00239                     PtrFileInfoBuffer->CurrentByteOffset = PtrFileObject->CurrentByteOffset;
00240                     // Modify the local variable for BufferLength appropriately.
00241                     BufferLength = sizeof(FILE_POSITION_INFORMATION);
00242                 }
00243                 break;
00244             case FileStreamInformation:
00245                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileStreamInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00246                 // RC = Ext2GetFileStreamInformation(...);
00247 
00248                 RC = STATUS_INVALID_PARAMETER;
00249                 try_return();
00250                 
00251                 break;
00252             case FileAllInformation:
00253                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileAllInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00254                 // The I/O Manager supplies the Mode, Access, and Alignment
00255                 // information. The rest is up to us to provide.
00256                 // Therefore, decrement the BufferLength appropriately (assuming
00257                 // that the above 3 types on information are already in the
00258                 // buffer)
00259                 {
00260 
00261                     PFILE_POSITION_INFORMATION      PtrFileInfoBuffer;
00262                     PFILE_ALL_INFORMATION           PtrAllInfo = (PFILE_ALL_INFORMATION)PtrSystemBuffer;
00263 
00264                     // Fill in the position information.
00265 
00266                     PtrFileInfoBuffer = (PFILE_POSITION_INFORMATION)&(PtrAllInfo->PositionInformation);
00267 
00268                     PtrFileInfoBuffer->CurrentByteOffset = PtrFileObject->CurrentByteOffset;
00269 
00270                     // Modify the local variable for BufferLength appropriately.
00271                     BufferLength = sizeof(FILE_ALL_INFORMATION);
00272 
00273                     // Get the remaining stuff.
00274                     if (!NT_SUCCESS(RC = Ext2GetBasicInformation(PtrFCB, (PFILE_BASIC_INFORMATION)&(PtrAllInfo->BasicInformation),
00275                                                                                     &BufferLength))) 
00276                     {
00277                         try_return();
00278                     }
00279                     if (!NT_SUCCESS(RC = Ext2GetStandardInformation(PtrFCB, &(PtrAllInfo->StandardInformation), &BufferLength))) 
00280                     {
00281                         try_return();
00282                     }
00283                     // Similarly, get all of the others ...
00284                 }
00285                 break;
00286             case FileNameInformation:
00287                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileNameInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00288                 //  RC = Ext2GetFullNameInformation(...);
00289                 RC = Ext2GetFullNameInformation(PtrFCB, PtrCCB, (PFILE_NAME_INFORMATION)PtrSystemBuffer, &BufferLength);
00290                 break;
00291             case FileAlternateNameInformation:
00292                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileAlternateNameInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00293                 RC = STATUS_INVALID_PARAMETER;
00294                 try_return();
00295                 // RC = Ext2GetAltNameInformation(...);
00296                 break;
00297             case FileCompressionInformation:
00298                 DebugTrace(DEBUG_TRACE_FILEINFO,   "FileCompressionInformation requested for %S", PtrFCB->FCBName->ObjectName.Buffer );
00299                 RC = STATUS_INVALID_PARAMETER;
00300                 try_return();
00301                 // RC = Ext2GetCompressionInformation(...);
00302                 break;
00303 
00304             default:
00305                 RC = STATUS_INVALID_PARAMETER;
00306                 try_return();
00307             }
00308 
00309             // If we completed successfully, the return the amount of information transferred.
00310             if (NT_SUCCESS(RC)) 
00311             {
00312                 PtrIrp->IoStatus.Information = BufferLength;
00313             }
00314             else 
00315             {
00316                 PtrIrp->IoStatus.Information = 0;
00317             }
00318 
00319         }
00320         else 
00321         {
00322             //  ***********************
00323             //  Set File Information
00324             //  ***********************
00325             ASSERT(PtrIoStackLocation->MajorFunction == IRP_MJ_SET_INFORMATION);
00326 
00327             DebugTrace(DEBUG_TRACE_FILEINFO,   ">>>>>>>> Set File Information <<<<<<<<< [FileInfo]", 0);
00328 
00329 
00330             // Now, obtain some parameters.
00331             FunctionalityRequested = PtrIoStackLocation->Parameters.SetFile.FileInformationClass;
00332 
00333             //  Check oplocks...
00334 
00335             //
00336             //  Acquire the VCB resource exclusively for 
00337             //  deletion, rename and link operations...
00338             //  To synchronize with create and cleanup operations
00339             //
00340             if ((FunctionalityRequested == FileDispositionInformation) || 
00341                 (FunctionalityRequested == FileRenameInformation) ||
00342                 (FunctionalityRequested == FileLinkInformation)) 
00343             {
00344                 DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire VCB Exclusively [FileInfo]", 0);
00345                 DebugTraceState( " VCB       AC:0x%LX   SW:0x%LX   EX:0x%LX   [FileInfo]", PtrVCB->VCBResource.ActiveCount, PtrVCB->VCBResource.NumberOfExclusiveWaiters, PtrVCB->VCBResource.NumberOfSharedWaiters );
00346                 if (!ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), CanWait)) 
00347                 {
00348                     DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Acquisition FAILED [FileInfo]", 0);
00349                     PostRequest = TRUE;
00350                     try_return(RC = STATUS_PENDING);
00351                 }
00352                 // We have the VCB acquired exclusively.
00353                 DebugTrace(DEBUG_TRACE_MISC,   "*** VCB Acquired [FileInfo]", 0);
00354                 VCBResourceAcquired = TRUE;
00355             }
00356 
00357 
00358             // Acquire the FCB exclusively at this time...
00359             if (!(PtrFCB->FCBFlags & EXT2_FCB_PAGE_FILE)) 
00360             {
00361                 // Acquire the MainResource shared.
00362                 DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire FCB Exclusively [FileInfo]", 0);
00363                 DebugTraceState( " FCBMain AC:0x%LX   SW:0x%LX   EX:0x%LX   [FileInfo]", PtrReqdFCB->MainResource.ActiveCount, PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, PtrReqdFCB->MainResource.NumberOfSharedWaiters );
00364                 if (!ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), CanWait)) 
00365                 {
00366                     DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquisition FAILED [FileInfo]", 0);
00367                     PostRequest = TRUE;
00368                     try_return(RC = STATUS_PENDING);
00369                 }
00370                 MainResourceAcquired = TRUE;
00371                 DebugTrace(DEBUG_TRACE_MISC,   "*** FCB Acquired [FileInfo]", 0);
00372             }
00373 
00374             //
00375             //  For delete link (rename),
00376             //  set allocation size, and set EOF, should also acquire the paging-IO
00377             //  resource, thereby synchronizing with paging-IO requests. 
00378             //
00379             if( PtrFileObject )
00380             {
00381                 DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [FileInfo]", PtrFileObject);
00382                 
00383             }
00384             DebugTrace(DEBUG_TRACE_MISC,   "*** Attempting to acquire FCBPaging Exclusively [FileInfo]", 0);
00385             DebugTraceState( " FCBPaging AC:0x%LX   SW:0x%LX   EX:0x%LX   [FileInfo]", PtrReqdFCB->PagingIoResource.ActiveCount, PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
00386             if (!ExAcquireResourceExclusiveLite(&(PtrReqdFCB->PagingIoResource), CanWait)) 
00387             {
00388                 DebugTrace(DEBUG_TRACE_MISC,   "*** Attempt to acquire FCBPaging FAILED [FileInfo]", 0);
00389                 PostRequest = TRUE;
00390                 try_return(RC = STATUS_PENDING);
00391             }
00392             PagingIoResourceAcquired = TRUE;
00393             DebugTrace(DEBUG_TRACE_MISC,   "*** Acquired FCBPaging [FileInfo]", 0);
00394 
00395             // Do whatever the caller asked us to do
00396             switch (FunctionalityRequested) 
00397             {
00398             case FileBasicInformation:
00399                 DebugTrace(DEBUG_TRACE_FILEINFO,   "Attempt to set FileBasicInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
00400                 RC = Ext2SetBasicInformation(PtrIrpContext, PtrFCB, PtrFileObject, (PFILE_BASIC_INFORMATION)PtrSystemBuffer);
00401                 //  RC = STATUS_ACCESS_DENIED;
00402                 break;
00403             case FileAllocationInformation:
00404                 DebugTrace(DEBUG_TRACE_FILEINFO,   "Attempt to set FileAllocationInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
00405                 RC = Ext2SetAllocationInformation(PtrFCB, PtrCCB, PtrVCB, PtrFileObject,
00406                                                                 PtrIrpContext, PtrIrp, PtrSystemBuffer);
00407                 break;
00408             case FileEndOfFileInformation:
00409                 DebugTrace(DEBUG_TRACE_FILEINFO,   "Attempt to set FileEndOfFileInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
00410                 // RC = Ext2SetEOF(...);
00411                 RC = STATUS_INVALID_PARAMETER;
00412                 try_return();
00413                 break;
00414 
00415             case FilePositionInformation:
00416                 DebugTrace(DEBUG_TRACE_FILEINFO,   "Attempt to set FilePositionInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
00417                 // Check    if no intermediate buffering has been specified.
00418                 // If it was specified, do not allow non-aligned set file
00419                 // position requests to succeed.
00420                 {
00421                     PFILE_POSITION_INFORMATION      PtrFileInfoBuffer;
00422 
00423                     PtrFileInfoBuffer = (PFILE_POSITION_INFORMATION)PtrSystemBuffer;
00424 
00425                     if (PtrFileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) 
00426                     {
00427                         if (PtrFileInfoBuffer->CurrentByteOffset.LowPart & PtrIoStackLocation->DeviceObject->AlignmentRequirement) 
00428                         {
00429                             // Invalid alignment.
00430                             try_return(RC = STATUS_INVALID_PARAMETER);
00431                         }
00432                     }
00433                     PtrFileObject->CurrentByteOffset = PtrFileInfoBuffer->CurrentByteOffset;
00434                 }
00435                 break;
00436 
00437             case FileDispositionInformation:
00438                 DebugTrace(DEBUG_TRACE_FILEINFO,   "Attempt to set FileDispositionInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
00439                 RC = Ext2SetDispositionInformation(PtrFCB, PtrCCB, PtrVCB, PtrFileObject, 
00440                     PtrIrpContext, PtrIrp,
00441                     (PFILE_DISPOSITION_INFORMATION)PtrSystemBuffer);
00442                 break;
00443 
00444             case FileRenameInformation:
00445                 DebugTrace(DEBUG_TRACE_FILEINFO,   "Attempt to set FileRenameInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
00446                 RC = Ext2RenameOrLinkFile( PtrFCB, PtrFileObject,   PtrIrpContext,
00447                                         PtrIrp, (PFILE_RENAME_INFORMATION)PtrSystemBuffer);
00448                 break;
00449             case FileLinkInformation:
00450                 DebugTrace(DEBUG_TRACE_FILEINFO,   "Attempt to set FileLinkInformation for %S", PtrFCB->FCBName->ObjectName.Buffer );
00451                 RC = STATUS_INVALID_PARAMETER;
00452                 try_return();
00453                 // When you implement your rename/link routine, be careful to
00454                 // check the following two arguments:
00455                 // TargetFileObject = PtrIoStackLocation->Parameters.SetFile.FileObject;
00456                 // ReplaceExistingFile = PtrIoStackLocation->Parameters.SetFile.ReplaceIfExists;
00457                 //
00458                 // The TargetFileObject argument is a pointer to the "target
00459                 // directory" file object obtained during the "create" routine
00460                 // invoked by the NT I/O Manager with the SL_OPEN_TARGET_DIRECTORY
00461                 // flag specified. Remember that it is quite possible that if the
00462                 // rename/link is contained within a single directory, the target
00463                 // and source directories will be the same.
00464                 // The ReplaceExistingFile argument should be used by you to
00465                 // determine if the caller wishes to replace the target (if it
00466                 // currently exists) with the new link/renamed file. If this
00467                 // value is FALSE, and if the target directory entry (being
00468                 // renamed-to, or the target of the link) exists, you should
00469                 // return a STATUS_OBJECT_NAME_COLLISION error to the caller.
00470 
00471                 // RC = Ext2RenameOrLinkFile(PtrFCB, PtrCCB, PtrFileObject, PtrIrpContext,
00472                 //                      PtrIrp, (PFILE_RENAME_INFORMATION)PtrSystemBuffer);
00473 
00474                 // Once you have completed the rename/link operation, do not
00475                 // forget to notify any "notify IRPs" about the actions you have
00476                 // performed.
00477                 // An example is if you renamed across directories, you should
00478                 // report that a new entry was added with the FILE_ACTION_ADDED
00479                 // action type. The actual modification would then be reported
00480                 // as either FILE_NOTIFY_CHANGE_FILE_NAME (if a file was renamed)
00481                 // or FILE_NOTIFY_CHANGE_DIR_NAME (if a directory was renamed).
00482                 
00483                 break;
00484             default:
00485                 DebugTrace(DEBUG_TRACE_FILEINFO,   "Unrecoganised SetFileInformation code for %S", PtrFCB->FCBName->ObjectName.Buffer );
00486                 RC = STATUS_INVALID_PARAMETER;
00487                 try_return();
00488             }
00489         }
00490 
00491         try_exit:   NOTHING;
00492     }
00493     finally
00494     {
00495         if (PagingIoResourceAcquired) 
00496         {
00497             Ext2ReleaseResource(&(PtrReqdFCB->PagingIoResource));
00498             DebugTrace(DEBUG_TRACE_MISC,  "*** FCBPaging Released [FileInfo]", 0);
00499             DebugTraceState( " FCBPaging AC:0x%LX   SW:0x%LX   EX:0x%LX   [FileInfo]", 
00500                 PtrReqdFCB->PagingIoResource.ActiveCount, 
00501                 PtrReqdFCB->PagingIoResource.NumberOfExclusiveWaiters, 
00502                 PtrReqdFCB->PagingIoResource.NumberOfSharedWaiters );
00503 
00504             if( PtrFileObject )
00505             {
00506                 DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [FileInfo]", PtrFileObject);
00507             }
00508 
00509             PagingIoResourceAcquired = FALSE;
00510         }
00511 
00512         if (MainResourceAcquired) 
00513         {
00514             Ext2ReleaseResource(&(PtrReqdFCB->MainResource));
00515             DebugTrace(DEBUG_TRACE_MISC,  "*** FCB Released [FileInfo]", 0);
00516             DebugTraceState( " FCBMain   AC:0x%LX   SW:0x%LX   EX:0x%LX   [FileInfo]", 
00517                 PtrReqdFCB->MainResource.ActiveCount, 
00518                 PtrReqdFCB->MainResource.NumberOfExclusiveWaiters, 
00519                 PtrReqdFCB->MainResource.NumberOfSharedWaiters );
00520             if( PtrFileObject )
00521             {
00522                 DebugTrace(DEBUG_TRACE_FILE_OBJ,  "###### File Pointer 0x%LX [FileInfo]", PtrFileObject);
00523             }
00524             
00525             MainResourceAcquired = FALSE;
00526         }
00527 
00528         if (VCBResourceAcquired) 
00529         {
00530             Ext2ReleaseResource(&(PtrVCB->VCBResource));
00531             DebugTrace(DEBUG_TRACE_MISC,  "*** VCB Released [FileInfo]", 0);
00532             DebugTraceState( " VCB       AC:0x%LX   SW:0x%LX   EX:0x%LX   [FileInfo]", 
00533                 PtrVCB->VCBResource.ActiveCount, 
00534                 PtrVCB->VCBResource.NumberOfExclusiveWaiters, 
00535                 PtrVCB->VCBResource.NumberOfSharedWaiters );
00536 
00537             VCBResourceAcquired = FALSE;
00538         }
00539 
00540         // Post IRP if required
00541         if (PostRequest) 
00542         {
00543 
00544             // Since, the I/O Manager gave us a system buffer, we do not
00545             // need to "lock" anything.
00546 
00547             // Perform the post operation which will mark the IRP pending
00548             // and will return STATUS_PENDING back to us
00549             RC = Ext2PostRequest(PtrIrpContext, PtrIrp);
00550 
00551         } 
00552         else 
00553         {
00554 
00555             // Can complete the IRP here if no exception was encountered
00556             if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_EXCEPTION)) {
00557                 PtrIrp->IoStatus.Status = RC;
00558 
00559                 // Free up the Irp Context
00560                 Ext2ReleaseIrpContext(PtrIrpContext);
00561     
00562                 // complete the IRP
00563                 IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT);
00564             }
00565         } // can we complete the IRP ?
00566     } // end of "finally" processing
00567     
00568     // DbgPrint( "\n    === File Info IRP returning --> RC : 0x%lX   Bytes: 0x%lX", PtrIrp->IoStatus.Status, PtrIrp->IoStatus.Information );
00569     
00570     return(RC);
00571 }
00572 
00573 
00574 /*************************************************************************
00575 *
00576 * Function: Ext2GetBasicInformation()
00577 *
00578 * Description:
00579 *   Return some time-stamps and file attributes to the caller.
00580 *
00581 * Expected Interrupt Level (for execution) :
00582 *
00583 *  IRQL_PASSIVE_LEVEL
00584 *
00585 * Return Value: STATUS_SUCCESS/Error
00586 *
00587 *************************************************************************/
00588 NTSTATUS NTAPI Ext2GetBasicInformation(
00589 PtrExt2FCB                  PtrFCB,
00590 PFILE_BASIC_INFORMATION     PtrBuffer,
00591 long                        *PtrReturnedLength )
00592 {
00593     NTSTATUS            RC = STATUS_SUCCESS;
00594 
00595     try 
00596     {
00597         if (*PtrReturnedLength < sizeof(FILE_BASIC_INFORMATION)) 
00598         {
00599             try_return(RC = STATUS_BUFFER_OVERFLOW);
00600         }
00601 
00602         // Zero out the supplied buffer.
00603         RtlZeroMemory(PtrBuffer, sizeof(FILE_BASIC_INFORMATION));
00604 
00605         // Get information from the FCB.
00606         PtrBuffer->CreationTime     = PtrFCB->CreationTime;
00607         PtrBuffer->LastAccessTime   = PtrFCB->LastAccessTime;
00608         PtrBuffer->LastWriteTime    = PtrFCB->LastWriteTime;
00609         PtrBuffer->ChangeTime       = PtrFCB->LastWriteTime;
00610         
00611         // Now fill in the attributes.
00612         PtrBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
00613         if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DIRECTORY ) )
00614         {
00615             PtrBuffer->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
00616         }
00617         else if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_SPECIAL_FILE ) )
00618         {
00619             //  Special File...
00620             //  Treated with respect... ;)
00621             //
00622             PtrBuffer->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY) ;
00623         }
00624 
00625         if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_HIDDEN_FILE  ) )
00626         {
00627             PtrBuffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
00628         }
00629         
00630         if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_READ_ONLY ) )
00631         {
00632             PtrBuffer->FileAttributes |= FILE_ATTRIBUTE_READONLY;
00633         }
00634         
00635         try_exit: NOTHING;
00636     } 
00637     finally 
00638     {
00639         if (NT_SUCCESS(RC)) 
00640         {
00641             // Return the amount of information filled in.
00642             *PtrReturnedLength = sizeof(FILE_BASIC_INFORMATION);
00643         }
00644     }
00645     return(RC);
00646 }
00647 
00648 NTSTATUS NTAPI Ext2GetStandardInformation(
00649 PtrExt2FCB                  PtrFCB,
00650 
00651 PFILE_STANDARD_INFORMATION  PtrStdInformation,
00652 long                        *PtrReturnedLength )
00653 {
00654 
00655     NTSTATUS            RC = STATUS_SUCCESS;
00656 
00657 
00658     try 
00659     {
00660         if (*PtrReturnedLength < sizeof( FILE_STANDARD_INFORMATION )) 
00661         {
00662             try_return(RC = STATUS_BUFFER_OVERFLOW);
00663         }
00664 
00665         // Zero out the supplied buffer.
00666         RtlZeroMemory(PtrStdInformation, sizeof(FILE_STANDARD_INFORMATION));
00667     
00668                 
00669         PtrStdInformation->AllocationSize   = PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize;
00670         PtrStdInformation->EndOfFile        = PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize;
00671         PtrStdInformation->DeletePending    = Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE);
00672         PtrStdInformation->Directory        = Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DIRECTORY );
00673         PtrStdInformation->NumberOfLinks    = PtrFCB->LinkCount;
00674 
00675         try_exit: NOTHING;
00676     } 
00677     finally 
00678     {
00679         if (NT_SUCCESS(RC)) 
00680         {
00681             // Return the amount of information filled in.
00682             *PtrReturnedLength = sizeof( FILE_STANDARD_INFORMATION );
00683         }
00684     }
00685     return(RC);
00686 }
00687 
00688 NTSTATUS NTAPI Ext2GetNetworkOpenInformation(
00689     PtrExt2FCB                      PtrFCB,
00690     PFILE_NETWORK_OPEN_INFORMATION  PtrNetworkOpenInformation,
00691     long                            *PtrReturnedLength )
00692 {
00693 
00694     NTSTATUS            RC = STATUS_SUCCESS;
00695 
00696     try 
00697     {
00698         if (*PtrReturnedLength < sizeof( FILE_NETWORK_OPEN_INFORMATION )) 
00699         {
00700             try_return(RC = STATUS_BUFFER_OVERFLOW);
00701         }
00702 
00703         // Zero out the supplied buffer.
00704         RtlZeroMemory(PtrNetworkOpenInformation, sizeof(FILE_NETWORK_OPEN_INFORMATION));
00705 
00706         PtrNetworkOpenInformation->CreationTime     = PtrFCB->CreationTime;
00707         PtrNetworkOpenInformation->LastAccessTime   = PtrFCB->LastAccessTime;
00708         PtrNetworkOpenInformation->LastWriteTime    = PtrFCB->LastWriteTime;
00709         PtrNetworkOpenInformation->ChangeTime       = PtrFCB->LastWriteTime;
00710         PtrNetworkOpenInformation->AllocationSize   = PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize;
00711         PtrNetworkOpenInformation->EndOfFile        = PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize;
00712 
00713         // Now fill in the attributes.
00714         PtrNetworkOpenInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
00715 
00716         if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_DIRECTORY ) )
00717         {
00718             PtrNetworkOpenInformation->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
00719         }
00720         else if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_SPECIAL_FILE ) )
00721         {
00722             //  Special File... 
00723             //  Treated with respect... ;)
00724             //
00725             PtrNetworkOpenInformation->FileAttributes |= ( FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY) ;
00726         }
00727         if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_HIDDEN_FILE  ) )
00728         {
00729             PtrNetworkOpenInformation->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
00730         }
00731         
00732         if ( Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_READ_ONLY ) )
00733         {
00734             PtrNetworkOpenInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
00735         }
00736         try_exit: NOTHING;
00737     } 
00738     finally 
00739     {
00740         if (NT_SUCCESS(RC)) 
00741         {
00742             // Return the amount of information filled in.
00743             *PtrReturnedLength = sizeof( FILE_NETWORK_OPEN_INFORMATION );
00744         }
00745     }
00746     return(RC);
00747 }
00748 
00749 
00750 NTSTATUS NTAPI Ext2GetFullNameInformation(
00751     PtrExt2FCB              PtrFCB,
00752     PtrExt2CCB              PtrCCB,
00753     PFILE_NAME_INFORMATION  PtrNameInformation,
00754     long                    *PtrReturnedLength )
00755 {
00756 
00757     NTSTATUS            RC = STATUS_SUCCESS;
00758 
00759     try 
00760     {
00761         if (*PtrReturnedLength < 
00762             (long)( sizeof(FILE_NAME_INFORMATION) + PtrCCB->AbsolutePathName.Length) ) 
00763         {
00764             try_return(RC = STATUS_BUFFER_OVERFLOW);
00765         }
00766 
00767         // Zero out the supplied buffer.
00768         RtlZeroMemory(PtrNameInformation, sizeof( FILE_NAME_INFORMATION ) );
00769         
00770         if( PtrCCB->AbsolutePathName.Length )
00771         {
00772             RtlCopyMemory(
00773                 PtrNameInformation->FileName,       //  Destination,
00774                 PtrCCB->AbsolutePathName.Buffer,    //  Source,
00775                 PtrCCB->AbsolutePathName.Length );  //  Length
00776 
00777             PtrNameInformation->FileNameLength = PtrCCB->AbsolutePathName.Length;
00778             try_return(RC = STATUS_SUCCESS);
00779         }
00780         else
00781         {
00782             try_return(RC = STATUS_INVALID_PARAMETER);
00783         }
00784         
00785         try_exit: NOTHING;
00786     } 
00787     finally 
00788     {
00789         if (NT_SUCCESS(RC)) 
00790         {
00791             // Return the amount of information filled in.
00792             *PtrReturnedLength =
00793                 sizeof( FILE_NAME_INFORMATION ) +
00794                 PtrCCB->AbsolutePathName.Length;
00795         }
00796     }
00797     return(RC);
00798 }
00799 /*************************************************************************
00800 *
00801 * Function: Ext2SetBasicInformation()
00802 *
00803 * Description:
00804 *   Set some time-stamps and file attributes supplied by the caller.
00805 *
00806 * Expected Interrupt Level (for execution) :
00807 *
00808 *  IRQL_PASSIVE_LEVEL
00809 *
00810 * Return Value: STATUS_SUCCESS/Error
00811 *
00812 *************************************************************************/
00813 NTSTATUS NTAPI Ext2SetBasicInformation(
00814     PtrExt2IrpContext           PtrIrpContext,
00815     PtrExt2FCB                  PtrFCB,
00816     PFILE_OBJECT                PtrFileObject,
00817     PFILE_BASIC_INFORMATION     PtrFileInformation )
00818 {
00819     NTSTATUS            RC = STATUS_SUCCESS;
00820 
00821     PtrExt2VCB          PtrVCB = PtrFCB->PtrVCB;
00822     AssertVCB( PtrVCB );
00823     
00824     //  BOOLEAN         CreationTimeChanged = FALSE;
00825     //  BOOLEAN         AttributesChanged = FALSE;
00826 
00827 //  return STATUS_INVALID_PARAMETER;
00828 
00829     try 
00830     {
00831         EXT2_INODE      Inode;
00832         RtlZeroMemory(&Inode, sizeof( EXT2_INODE ));
00833 
00834         if( NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) )
00835         {
00836             //
00837             //  Update time stamps in the inode
00838             //  and in the FCB...
00839             //
00840             if( PtrFileInformation->CreationTime.QuadPart )
00841             {
00842                 PtrFCB->CreationTime.QuadPart = PtrFileInformation->CreationTime.QuadPart;
00843                 Inode.i_ctime = (ULONG) ( (PtrFCB->CreationTime.QuadPart
00844                         - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
00845 
00846             }
00847             if( PtrFileInformation->LastAccessTime.QuadPart )
00848             {
00849                 PtrFCB->LastAccessTime.QuadPart = PtrFileInformation->LastAccessTime.QuadPart;
00850                 Inode.i_atime = (ULONG) ( (PtrFCB->LastAccessTime.QuadPart
00851                         - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
00852 
00853             }
00854             if( PtrFileInformation->LastWriteTime.QuadPart )
00855             {
00856                 PtrFCB->LastWriteTime.QuadPart = PtrFileInformation->LastWriteTime.QuadPart;
00857                 Inode.i_mtime = (ULONG) ( (PtrFCB->LastWriteTime.QuadPart
00858                         - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 );
00859             }
00860 
00861             // Now come the attributes.
00862             if (PtrFileInformation->FileAttributes) 
00863             {
00864                 if (PtrFileInformation->FileAttributes & FILE_ATTRIBUTE_READONLY ) 
00865                 {
00866                     //  Turn off the write bits...
00867                     Ext2SetModeReadOnly( Inode.i_mode );
00868                 }
00869                 if (PtrFileInformation->FileAttributes & FILE_ATTRIBUTE_HIDDEN ) 
00870                 {
00871                     //  Turn off the read and write bits...
00872                     Ext2SetModeHidden( Inode.i_mode );
00873 
00874                 }
00875                 if (PtrFileInformation->FileAttributes & FILE_ATTRIBUTE_SYSTEM ) 
00876                 {
00877                     //  Just turn off the read and write bits...
00878                     //  No special field to indicate that this is a system file...
00879                     Ext2SetModeReadOnly( Inode.i_mode );
00880                     Ext2SetModeHidden( Inode.i_mode );
00881                 }
00882             }
00883 
00884             //  Updating the inode...
00885             Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode );
00886         }
00887     
00888         if (PtrFileInformation->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) 
00889         {
00890             Ext2SetFlag(PtrFileObject->Flags, FO_TEMPORARY_FILE);
00891         } 
00892         else 
00893         {
00894             Ext2ClearFlag(PtrFileObject->Flags, FO_TEMPORARY_FILE);
00895         }
00896     } 
00897     finally 
00898     {
00899         ;
00900     }
00901     return(RC);
00902 }
00903 
00904 
00905 /*************************************************************************
00906 *
00907 * Function: Ext2SetDispositionInformation()
00908 *
00909 * Description:
00910 *   Mark/Unmark a file for deletion.
00911 *
00912 * Expected Interrupt Level (for execution) :
00913 *
00914 *  IRQL_PASSIVE_LEVEL
00915 *
00916 * Return Value: STATUS_SUCCESS/Error
00917 *
00918 *************************************************************************/
00919 NTSTATUS NTAPI Ext2SetDispositionInformation(
00920 PtrExt2FCB                  PtrFCB,
00921 PtrExt2CCB                  PtrCCB,
00922 PtrExt2VCB                  PtrVCB,
00923 PFILE_OBJECT                PtrFileObject,
00924 PtrExt2IrpContext           PtrIrpContext,
00925 PIRP                            PtrIrp,
00926 PFILE_DISPOSITION_INFORMATION   PtrBuffer)
00927 {
00928     NTSTATUS            RC = STATUS_SUCCESS;
00929 
00930     try 
00931     {
00932         if (!PtrBuffer->DeleteFile) 
00933         {
00934             // "un-delete" the file.
00935             Ext2ClearFlag(PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE);
00936             PtrFileObject->DeletePending = FALSE;
00937             try_return();
00938         }
00939 
00940         // Do some checking to see if the file can even be deleted.
00941 
00942         if (PtrFCB->FCBFlags & EXT2_FCB_DELETE_ON_CLOSE) 
00943         {
00944             // All done!
00945             try_return();
00946         }
00947 
00948         if (PtrFCB->FCBFlags & EXT2_FCB_READ_ONLY) 
00949         {
00950             try_return(RC = STATUS_CANNOT_DELETE);
00951         }
00952 
00953         if (PtrVCB->VCBFlags & EXT2_VCB_FLAGS_VOLUME_READ_ONLY) 
00954         {
00955             try_return(RC = STATUS_CANNOT_DELETE);
00956         }
00957 
00958         // An important step is to check if the file stream has been
00959         // mapped by any process. The delete cannot be allowed to proceed
00960         // in this case.
00961         if (!MmFlushImageSection(&(PtrFCB->NTRequiredFCB.SectionObject), MmFlushForDelete)) 
00962         {
00963             try_return(RC = STATUS_CANNOT_DELETE);
00964         }
00965 
00966         // Disallow deletion of either a root
00967         // directory or a directory that is not empty.
00968         if( PtrFCB->INodeNo == EXT2_ROOT_INO )
00969         {
00970             try_return(RC = STATUS_CANNOT_DELETE);
00971         }
00972 
00973         if (PtrFCB->FCBFlags & EXT2_FCB_DIRECTORY) 
00974         {
00975             if (!Ext2IsDirectoryEmpty(PtrFCB, PtrCCB, PtrIrpContext)) 
00976             {
00977                     try_return(RC = STATUS_DIRECTORY_NOT_EMPTY);
00978             }
00979         }
00980 
00981         // Set a flag to indicate that this directory entry will become history
00982         // at cleanup.
00983         Ext2SetFlag(PtrFCB->FCBFlags, EXT2_FCB_DELETE_ON_CLOSE);
00984         PtrFileObject->DeletePending = TRUE;
00985 
00986         try_exit: NOTHING;
00987     }
00988     finally 
00989     {
00990         ;
00991     }
00992     return(RC);
00993 }
00994 
00995 
00996 
00997 /*************************************************************************
00998 *
00999 * Function: Ext2SetAllocationInformation()
01000 *
01001 * Description:
01002 *   Mark/Unmark a file for deletion.
01003 *
01004 * Expected Interrupt Level (for execution) :
01005 *
01006 *  IRQL_PASSIVE_LEVEL
01007 *
01008 * Return Value: STATUS_SUCCESS/Error
01009 *
01010 *************************************************************************/
01011 NTSTATUS NTAPI Ext2SetAllocationInformation(
01012 PtrExt2FCB                  PtrFCB,
01013 PtrExt2CCB                  PtrCCB,
01014 PtrExt2VCB                  PtrVCB,
01015 PFILE_OBJECT                PtrFileObject,
01016 PtrExt2IrpContext           PtrIrpContext,
01017 PIRP                            PtrIrp,
01018 PFILE_ALLOCATION_INFORMATION    PtrBuffer)
01019 {
01020     NTSTATUS        RC = STATUS_SUCCESS;
01021     BOOLEAN         TruncatedFile = FALSE;
01022     BOOLEAN         ModifiedAllocSize = FALSE;
01023 
01024     try 
01025     {
01026             
01027         // Are we increasing the allocation size?
01028         if (RtlLargeIntegerLessThan(
01029                 PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize,
01030                 PtrBuffer->AllocationSize)) 
01031         {
01032             ULONG CurrentSize;
01033             ULONG LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;
01034             
01035             for( CurrentSize = 0; CurrentSize < PtrBuffer->AllocationSize.QuadPart; CurrentSize += LogicalBlockSize )
01036             {
01037                 Ext2AddBlockToFile( PtrIrpContext, PtrVCB, PtrFCB, PtrFileObject, FALSE );
01038             }
01039             ModifiedAllocSize = TRUE;
01040         } 
01041         else if (RtlLargeIntegerGreaterThan(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize,
01042                                                                 PtrBuffer->AllocationSize)) 
01043         {
01044             // This is the painful part. See if the VMM will allow us to proceed.
01045             // The VMM will deny the request if:
01046             // (a) any image section exists OR
01047             // (b) a data section exists and the size of the user mapped view
01048             //       is greater than the new size
01049             // Otherwise, the VMM should allow the request to proceed.
01050             if (!MmCanFileBeTruncated(&(PtrFCB->NTRequiredFCB.SectionObject), &(PtrBuffer->AllocationSize))) 
01051             {
01052                 // VMM said no way!
01053                 try_return(RC = STATUS_USER_MAPPED_FILE);
01054             }
01055 
01056             if( !Ext2TruncateFileAllocationSize( PtrIrpContext, PtrFCB, PtrFileObject, &PtrBuffer->AllocationSize) )
01057             {
01058                 //  This will do until I figure out a better error message code ;)
01059                 RC = STATUS_INSUFFICIENT_RESOURCES;
01060 
01061             }
01062 
01063             ModifiedAllocSize = TRUE;
01064             TruncatedFile = TRUE;
01065         }
01066 
01067         try_exit:
01068 
01069             // This is a good place to check if we have performed a truncate
01070             // operation. If we have perform a truncate (whether we extended
01071             // or reduced file size), you should update file time stamps.
01072 
01073             // Last, but not the lease, you must inform the Cache Manager of file size changes.
01074             if (ModifiedAllocSize && NT_SUCCESS(RC)) 
01075             {
01076                 // Update the FCB Header with the new allocation size.
01077                 PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize = PtrBuffer->AllocationSize;
01078 
01079                 // If we decreased the allocation size to less than the
01080                 // current file size, modify the file size value.
01081                 // Similarly, if we decreased the value to less than the
01082                 // current valid data length, modify that value as well.
01083                 if (TruncatedFile) 
01084                 {
01085                     if (RtlLargeIntegerLessThan(PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize, PtrBuffer->AllocationSize)) 
01086                     {
01087                         // Decrease the file size value.
01088                         PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize = PtrBuffer->AllocationSize;
01089                     }
01090 
01091                     if (RtlLargeIntegerLessThan(PtrFCB->NTRequiredFCB.CommonFCBHeader.ValidDataLength, PtrBuffer->AllocationSize)) 
01092                     {
01093                         // Decrease the valid data length value.
01094                         PtrFCB->NTRequiredFCB.CommonFCBHeader.ValidDataLength = PtrBuffer->AllocationSize;
01095                     }
01096                 }
01097 
01098 
01099                 // If the FCB has not had caching initiated, it is still valid
01100                 // for you to invoke the NT Cache Manager. It is possible in such
01101                 // situations for the call to be no'oped (unless some user has
01102                 // mapped in the file)
01103 
01104                 // NOTE: The invocation to CcSetFileSizes() will quite possibly
01105                 //  result in a recursive call back into the file system.
01106                 //  This is because the NT Cache Manager will typically
01107                 //  perform a flush before telling the VMM to purge pages
01108                 //  especially when caching has not been initiated on the
01109                 //  file stream, but the user has mapped the file into
01110                 //  the process' virtual address space.
01111                 CcSetFileSizes(PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize));
01112 
01113                 // Inform any pending IRPs (notify change directory).
01114             }
01115 
01116     } 
01117     finally 
01118     {
01119         ;
01120     }
01121     return(RC);
01122 }

Generated on Sat May 26 2012 04:22:57 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.