Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfileinfo.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
1.7.6.1
|