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