Пример #1
0
/**
 *	@public
 *	@brief	Equivalent to fclose()
 *
 *	@param	pFile		FF_FILE object that was created by FF_Open().
 *
 *	@return 0 on sucess.
 *	@return -1 if a null pointer was provided.
 *
 **/
FF_ERROR FF_Close(FF_FILE *pFile) {

	FF_FILE		*pFileChain;
	FF_DIRENT	OriginalEntry;
	FF_ERROR	Error;

	if(!pFile) {
		return FF_ERR_NULL_POINTER;	
	}
	// UpDate Dirent if File-size has changed?

	// Update the Dirent!
	Error = FF_GetEntry(pFile->pIoman, pFile->DirEntry, pFile->DirCluster, &OriginalEntry);
	if(Error) {
		return Error;
	}
	
	if(!pFile->FileDeleted) {
		if(pFile->Filesize != OriginalEntry.Filesize) {
			OriginalEntry.Filesize = pFile->Filesize;
			Error = FF_PutEntry(pFile->pIoman, pFile->DirEntry, pFile->DirCluster, &OriginalEntry);
			if(Error) {
				return Error;
			}
		}
	}

	Error = FF_FlushCache(pFile->pIoman);		// Ensure all modfied blocks are flushed to disk!

	// Handle Linked list!
	FF_PendSemaphore(pFile->pIoman->pSemaphore);
	{	// Semaphore is required, or linked list could become corrupted.
		if(pFile->pIoman->FirstFile == pFile) {
			pFile->pIoman->FirstFile = pFile->Next;
		} else {
			pFileChain = (FF_FILE *) pFile->pIoman->FirstFile;
			while(pFileChain->Next != pFile) {
				pFileChain = pFileChain->Next;
			}
			pFileChain->Next = pFile->Next;
		}
	}	// Semaphore released, linked list was shortened!
	FF_ReleaseSemaphore(pFile->pIoman->pSemaphore);

	// If file written, flush to disk
	FF_FREE(pFile);

	if(Error) {
		return Error;
	}

	// Simply free the pointer!
	return FF_ERR_NONE;
}
Пример #2
0
static FF_ERROR FF_ExtendFile(FF_FILE *pFile, FF_T_UINT32 Size) {
	FF_IOMAN	*pIoman = pFile->pIoman;
	FF_T_UINT32 nBytesPerCluster = pIoman->pPartition->BlkSize * pIoman->pPartition->SectorsPerCluster;
	FF_T_UINT32 nTotalClustersNeeded = Size / nBytesPerCluster;
	FF_T_UINT32 nClusterToExtend; 
	FF_T_UINT32 CurrentCluster, NextCluster;
	FF_T_UINT32	i;
	FF_DIRENT	OriginalEntry;

	if((pFile->Mode & FF_MODE_WRITE) != FF_MODE_WRITE) {
		return FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE;
	}

	if(pFile->Filesize == 0 && pFile->ObjectCluster == 0) {	// No Allocated clusters.
		// Create a Cluster chain!
		pFile->AddrCurrentCluster = FF_CreateClusterChain(pFile->pIoman);
		if(!FF_GetEntry(pIoman, pFile->DirEntry, pFile->DirCluster, &OriginalEntry)) {
			OriginalEntry.ObjectCluster = pFile->AddrCurrentCluster;
			FF_PutEntry(pIoman, pFile->DirEntry, pFile->DirCluster, &OriginalEntry);
		} else {
			return FF_ERR_FILE_EXTEND_FAILED;
		}
		pFile->ObjectCluster = pFile->AddrCurrentCluster;
		pFile->iChainLength = 1;
		pFile->CurrentCluster = 0;
		pFile->iEndOfChain = pFile->AddrCurrentCluster;
	}
	
	if(Size % nBytesPerCluster) {
		nTotalClustersNeeded += 1;
	}

	if(pFile->iChainLength == 0) {	// First extension requiring the chain length, 
		pFile->iChainLength = FF_GetChainLength(pIoman, pFile->ObjectCluster, &pFile->iEndOfChain);
	}

	nClusterToExtend = (nTotalClustersNeeded - pFile->iChainLength);

	if(nTotalClustersNeeded > pFile->iChainLength) {

		NextCluster = pFile->AddrCurrentCluster;
		FF_lockFAT(pIoman);
		{
			for(i = 0; i <= nClusterToExtend; i++) {
				CurrentCluster = FF_FindEndOfChain(pIoman, NextCluster);
				NextCluster = FF_FindFreeCluster(pIoman);
				if(!NextCluster) {
					FF_unlockFAT(pIoman);
					return FF_ERR_FAT_NO_FREE_CLUSTERS;
				}
				FF_putFatEntry(pIoman, CurrentCluster, NextCluster);
				FF_putFatEntry(pIoman, NextCluster, 0xFFFFFFFF);
			}
			
			pFile->iEndOfChain = FF_FindEndOfChain(pIoman, NextCluster);
		}
		FF_unlockFAT(pIoman);
		
		pFile->iChainLength += i;
		FF_DecreaseFreeClusters(pIoman, i);	// Keep Tab of Numbers for fast FreeSize()
	}

	return FF_ERR_NONE;
}
Пример #3
0
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);
}
Пример #4
0
VOID
NTAPI
FatGetFcbUnicodeName(IN PFAT_IRP_CONTEXT IrpContext,
                     IN PFCB Fcb,
                     OUT PUNICODE_STRING LongName)
{
    FF_DIRENT DirEnt;
    FF_ERROR Err;
    OEM_STRING ShortName;
    CHAR ShortNameBuf[13];
    UCHAR EntryBuffer[32];
    UCHAR NumLFNs;
    OEM_STRING LongNameOem;
    NTSTATUS Status;

    /* Make sure this FCB has a FullFAT handle associated with it */
    if (Fcb->FatHandle == NULL &&
        FatNodeType(Fcb) == FAT_NTC_DCB)
    {
        /* Open the dir with FullFAT */
        Fcb->FatHandle = FF_OpenW(Fcb->Vcb->Ioman, &Fcb->FullFileName, FF_MODE_DIR, NULL);
        if (!Fcb->FatHandle)
        {
            ASSERT(FALSE);
        }
    }

    /* 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);

    /* Check if we only have a short name.
       Convert it to unicode and return if that's the case */
    if (NumLFNs == 0)
    {
        /* Initialize short name string */
        ShortName.Buffer = ShortNameBuf;
        ShortName.Length = 0;
        ShortName.MaximumLength = 12;

        /* Convert raw short name to a proper string */
        Fati8dot3ToString((PCHAR)EntryBuffer, FALSE, &ShortName);

        /* Convert it to unicode */
        Status = RtlOemStringToCountedUnicodeString(LongName,
                                                    &ShortName,
                                                    FALSE);

        /* Ensure conversion was successful */
        ASSERT(Status == STATUS_SUCCESS);

        /* Exit */
        return;
    }

    /* Convert LFN from OEM to unicode and return */
    LongNameOem.Buffer = DirEnt.FileName;
    LongNameOem.MaximumLength = FF_MAX_FILENAME;
    LongNameOem.Length = strlen(DirEnt.FileName);

    /* Convert it to unicode */
    Status = RtlOemStringToUnicodeString(LongName, &LongNameOem, FALSE);

    /* Ensure conversion was successful */
    ASSERT(Status == STATUS_SUCCESS);
}