VOID Secondary_ChangeFcbFileName( IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PUNICODE_STRING FullFileName ) { RtlInitEmptyUnicodeString( &Fcb->FullFileName, Fcb->FullFileNameBuffer, sizeof(Fcb->FullFileNameBuffer) ); RtlCopyUnicodeString( &Fcb->FullFileName, FullFileName ); RtlInitEmptyUnicodeString( &Fcb->CaseInSensitiveFullFileName, Fcb->CaseInSensitiveFullFileNameBuffer, sizeof(Fcb->CaseInSensitiveFullFileNameBuffer) ); RtlDowncaseUnicodeString( &Fcb->CaseInSensitiveFullFileName, &Fcb->FullFileName, FALSE ); if (FullFileName->Length && FullFileName->Buffer[0] != L'\\') ASSERT( NDFAT_BUG ); return; }
PXIXFS_LCB xixfs_FCBTLBInsertPrefix ( IN PXIXFS_IRPCONTEXT IrpContext, IN PXIXFS_FCB Fcb, IN PUNICODE_STRING Name, IN PXIXFS_FCB ParentFcb ) { PXIXFS_LCB Lcb; PRTL_SPLAY_LINKS *TreeRoot; PLIST_ENTRY ListLinks; PWCHAR NameBuffer; PAGED_CODE(); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CREATE|DEBUG_TARGET_CLOSE| DEBUG_TARGET_FCB), ("Enter xixfs_FCBTLBInsertPrefix \n" )); // // Check inputs. // ASSERT_IRPCONTEXT( IrpContext ); ASSERT_FCB( Fcb ); ASSERT_EXCLUSIVE_FCB( Fcb ); ASSERT_EXCLUSIVE_FCB( ParentFcb ); ASSERT( ParentFcb->XixcoreFcb.FCBType == FCB_TYPE_DIR); // // It must be the case that an index Fcb is only referenced by a single index. Now // we walk the child's Lcb queue to insure that if any prefixes have already been // inserted, they all refer to the index Fcb we are linking to. This is the only way // we can detect directory cross-linkage. // if (Fcb->XixcoreFcb.FCBType == FCB_TYPE_DIR) { for (ListLinks = Fcb->ParentLcbQueue.Flink; ListLinks != &Fcb->ParentLcbQueue; ListLinks = ListLinks->Flink) { Lcb = CONTAINING_RECORD( ListLinks, XIXFS_LCB, ChildFcbLinks ); if (Lcb->ParentFcb != ParentFcb) { XifsdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR ); } } } // // Allocate space for the Lcb. // Lcb = xixfs_AllocateLCB(Name->Length); // // Initialize the name-based file attributes. // Lcb->FileAttributes = 0; // // Set up the filename in the Lcb. // RtlCopyMemory( Lcb->FileName.Buffer, Name->Buffer, Name->Length ); // // Capture the separate cases. // TreeRoot = &ParentFcb->Root; // // Insert the Lcb into the prefix tree. // if (!xixfs_NLInsertNameLink( IrpContext, TreeRoot, Lcb )) { // // This will very rarely occur. // xixfs_FreeLCB( Lcb ); Lcb = xixfs_NLFindNameLink( IrpContext, TreeRoot, Name ); if (Lcb == NULL) { // // Even worse. // XifsdRaiseStatus( IrpContext, STATUS_DRIVER_INTERNAL_ERROR ); } if(!XIXCORE_TEST_FLAGS(Lcb->LCBFlags, XIFSD_LCB_STATE_IGNORE_CASE_SET)){ XifsdRaiseStatus( IrpContext, STATUS_DRIVER_INTERNAL_ERROR ); } return Lcb; } // // Capture the separate cases. // TreeRoot = &ParentFcb->IgnoreCaseRoot; // // Set up the filename in the Lcb. // RtlDowncaseUnicodeString(&(Lcb->IgnoreCaseFileName), Name, FALSE); if(!xixfs_NLInsertNameLinkIgnoreCase( IrpContext, TreeRoot, Lcb )){ XifsdRaiseStatus( IrpContext, STATUS_DRIVER_INTERNAL_ERROR ); } XIXCORE_SET_FLAGS(Lcb->LCBFlags, XIFSD_LCB_STATE_IGNORE_CASE_SET); // // Link the Fcbs together through the Lcb. // Lcb->ParentFcb = ParentFcb; Lcb->ChildFcb = Fcb; InsertHeadList( &ParentFcb->ChildLcbQueue, &Lcb->ParentFcbLinks ); InsertHeadList( &Fcb->ParentLcbQueue, &Lcb->ChildFcbLinks ); // // Initialize the reference count. // Lcb->Reference = 0; //DbgPrint(" !!!Insert LCB FileName(%wZ) IgnoreFileName(%wZ) .\n", &Lcb->FileName, &Lcb->IgnoreCaseFileName); DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_CREATE|DEBUG_TARGET_CLOSE| DEBUG_TARGET_FCB), ("Exit xixfs_FCBTLBInsertPrefix \n" )); return Lcb; }
PNDAS_FCB ReadonlyAllocateFcb ( IN PFILESPY_DEVICE_EXTENSION DevExt, IN PUNICODE_STRING FullFileName, IN BOOLEAN IsPagingFile ) { PNDAS_FCB fcb; fcb = FsRtlAllocatePoolWithTag( NonPagedPool, sizeof(NDAS_FCB), LFS_FCB_TAG ); if (fcb == NULL) { SPY_LOG_PRINT( LFS_DEBUG_READONLY_ERROR, ("ReadonlyAllocateFcb: failed to allocate fcb\n") ); return NULL; } RtlZeroMemory( fcb, sizeof(NDAS_FCB) ); fcb->NonPaged = LfsAllocateNonPagedFcb(); if (fcb->NonPaged == NULL) { SPY_LOG_PRINT( LFS_DEBUG_READONLY_ERROR, ("ReadonlyAllocateFcb: failed to allocate fcb->NonPaged\n") ); ExFreePool( fcb ); return NULL; } RtlZeroMemory( fcb->NonPaged, sizeof(NON_PAGED_FCB) ); #define FAT_NTC_FCB (0x0502) fcb->Header.NodeTypeCode = FAT_NTC_FCB; fcb->Header.IsFastIoPossible = FastIoIsPossible; fcb->Header.Resource = LfsAllocateResource(); fcb->Header.PagingIoResource = NULL; //fcb->Header.Resource; if (fcb->Header.Resource == NULL) { SPY_LOG_PRINT( LFS_DEBUG_READONLY_ERROR, ("ReadonlyAllocateFcb: failed to allocate fcb->Header.Resource\n") ); ExFreePool( fcb->NonPaged ); ExFreePool( fcb ); return NULL; } if (LfsFsRtlTeardownPerStreamContexts) { ExInitializeFastMutex( &fcb->NonPaged->AdvancedFcbHeaderMutex ); FsRtlSetupAdvancedHeader( &fcb->Header, &fcb->NonPaged->AdvancedFcbHeaderMutex ); if (IsPagingFile) { ClearFlag( fcb->Header.Flags2, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS ); } } FsRtlInitializeFileLock( &fcb->FileLock, NULL, NULL ); fcb->ReferenceCount = 1; InitializeListHead( &fcb->ListEntry ); fcb->Readonly = DevExt->LfsDeviceExt.Readonly; RtlInitEmptyUnicodeString( &fcb->FullFileName, fcb->FullFileNameBuffer, sizeof(fcb->FullFileNameBuffer) ); RtlCopyUnicodeString( &fcb->FullFileName, FullFileName ); RtlInitEmptyUnicodeString( &fcb->CaseInSensitiveFullFileName, fcb->CaseInSensitiveFullFileNameBuffer, sizeof(fcb->CaseInSensitiveFullFileNameBuffer) ); RtlDowncaseUnicodeString( &fcb->CaseInSensitiveFullFileName, &fcb->FullFileName, FALSE ); if(FullFileName->Length) if(FullFileName->Buffer[0] != L'\\') ASSERT( LFS_BUG ); return fcb; }
PNDAS_FCB ReadonlyLookUpFcb ( IN PFILESPY_DEVICE_EXTENSION DevExt, IN PUNICODE_STRING FullFileName, IN BOOLEAN CaseInSensitive ) { PNDAS_FCB fcb = NULL; PLIST_ENTRY listEntry; KIRQL oldIrql; UNICODE_STRING caseInSensitiveFullFileName; PWCHAR caseInSensitiveFullFileNameBuffer; NTSTATUS downcaseStatus; // // Allocate a name buffer // caseInSensitiveFullFileNameBuffer = ExAllocatePoolWithTag(NonPagedPool, NDFS_MAX_PATH, LFS_ALLOC_TAG); if (caseInSensitiveFullFileNameBuffer == NULL) { ASSERT( LFS_REQUIRED ); return NULL; } ASSERT( FullFileName->Length <= NDFS_MAX_PATH*sizeof(WCHAR) ); if (CaseInSensitive == TRUE) { RtlInitEmptyUnicodeString( &caseInSensitiveFullFileName, caseInSensitiveFullFileNameBuffer, NDFS_MAX_PATH ); downcaseStatus = RtlDowncaseUnicodeString( &caseInSensitiveFullFileName, FullFileName, FALSE ); if (downcaseStatus != STATUS_SUCCESS) { ExFreePool( caseInSensitiveFullFileNameBuffer ); ASSERT( LFS_UNEXPECTED ); return NULL; } } KeAcquireSpinLock( &DevExt->LfsDeviceExt.Readonly->FcbQSpinLock, &oldIrql ); for (listEntry = DevExt->LfsDeviceExt.Readonly->FcbQueue.Flink; listEntry != &DevExt->LfsDeviceExt.Readonly->FcbQueue; listEntry = listEntry->Flink) { fcb = CONTAINING_RECORD( listEntry, NDAS_FCB, ListEntry ); if (fcb->FullFileName.Length != FullFileName->Length) { fcb = NULL; continue; } if (CaseInSensitive == TRUE) { if (RtlEqualMemory(fcb->CaseInSensitiveFullFileName.Buffer, caseInSensitiveFullFileName.Buffer, fcb->CaseInSensitiveFullFileName.Length)) { InterlockedIncrement( &fcb->ReferenceCount ); break; } } else { if (RtlEqualMemory(fcb->FullFileName.Buffer, FullFileName->Buffer, fcb->FullFileName.Length)) { InterlockedIncrement( &fcb->ReferenceCount ); break; } } fcb = NULL; } KeReleaseSpinLock( &DevExt->LfsDeviceExt.Readonly->FcbQSpinLock, oldIrql ); ExFreePool( caseInSensitiveFullFileNameBuffer ); return fcb; }
VOID NTAPI FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext, IN PFCB Fcb) { FF_DIRENT DirEnt; FF_ERROR Err; POEM_STRING ShortName; CHAR ShortNameRaw[13]; UCHAR EntryBuffer[32]; UCHAR NumLFNs; PUNICODE_STRING UnicodeName; OEM_STRING LongNameOem; NTSTATUS Status; /* Get the dir entry */ Err = FF_GetEntry(Fcb->Vcb->Ioman, Fcb->FatHandle->DirEntry, Fcb->FatHandle->DirCluster, &DirEnt); if (Err != FF_ERR_NONE) { DPRINT1("Error %d getting dirent of a file\n", Err); return; } /* Read the dirent to fetch the raw short name */ FF_FetchEntry(Fcb->Vcb->Ioman, Fcb->FatHandle->DirCluster, Fcb->FatHandle->DirEntry, EntryBuffer); NumLFNs = (UCHAR)(EntryBuffer[0] & ~0x40); RtlCopyMemory(ShortNameRaw, EntryBuffer, 11); /* Initialize short name string */ ShortName = &Fcb->ShortName.Name.Ansi; ShortName->Buffer = Fcb->ShortNameBuffer; ShortName->Length = 0; ShortName->MaximumLength = sizeof(Fcb->ShortNameBuffer); /* Convert raw short name to a proper string */ Fati8dot3ToString(ShortNameRaw, FALSE, ShortName); /* Add the short name link */ FatInsertName(IrpContext, &Fcb->ParentFcb->Dcb.SplayLinksAnsi, &Fcb->ShortName); Fcb->ShortName.Fcb = Fcb; /* Get the long file name (if any) */ if (NumLFNs > 0) { /* Prepare the oem string */ LongNameOem.Buffer = DirEnt.FileName; LongNameOem.MaximumLength = FF_MAX_FILENAME; LongNameOem.Length = strlen(DirEnt.FileName); /* Prepare the unicode string */ UnicodeName = &Fcb->LongName.Name.String; UnicodeName->Length = (LongNameOem.Length + 1) * sizeof(WCHAR); UnicodeName->MaximumLength = UnicodeName->Length; UnicodeName->Buffer = FsRtlAllocatePool(PagedPool, UnicodeName->Length); /* Convert it to unicode */ Status = RtlOemStringToUnicodeString(UnicodeName, &LongNameOem, FALSE); if (!NT_SUCCESS(Status)) { ASSERT(FALSE); } /* Set its length */ Fcb->FileNameLength = UnicodeName->Length; /* Save case-preserved copy */ Fcb->ExactCaseLongName.Length = UnicodeName->Length; Fcb->ExactCaseLongName.MaximumLength = UnicodeName->Length; Fcb->ExactCaseLongName.Buffer = FsRtlAllocatePoolWithTag(PagedPool, UnicodeName->Length, TAG_FILENAME); RtlCopyMemory(Fcb->ExactCaseLongName.Buffer, UnicodeName->Buffer, UnicodeName->Length); /* Perform a trick which is done by MS's FASTFAT driver to monocase the filename */ RtlDowncaseUnicodeString(UnicodeName, UnicodeName, FALSE); RtlUpcaseUnicodeString(UnicodeName, UnicodeName, FALSE); DPRINT("Converted long name: %wZ\n", UnicodeName); /* Add the long unicode name link */ FatInsertName(IrpContext, &Fcb->ParentFcb->Dcb.SplayLinksUnicode, &Fcb->LongName); Fcb->LongName.Fcb = Fcb; /* Indicate that this FCB has a unicode long name */ SetFlag(Fcb->State, FCB_STATE_HAS_UNICODE_NAME); } else { /* No LFN, set exact case name to 0 length */ Fcb->ExactCaseLongName.Length = 0; Fcb->ExactCaseLongName.MaximumLength = 0; /* Set the length based on the short name */ Fcb->FileNameLength = RtlOemStringToCountedUnicodeSize(ShortName); } /* Mark the fact that names were added to splay trees*/ SetFlag(Fcb->State, FCB_STATE_HAS_NAMES); }