Exemple #1
0
static
NTSTATUS
FsdSetFsLabelInformation(
    PDEVICE_OBJECT DeviceObject,
    PFILE_FS_LABEL_INFORMATION FsLabelInfo)
{
    PDEVICE_EXTENSION DeviceExt;
    PVOID Context = NULL;
    ULONG DirIndex = 0;
    PDIR_ENTRY Entry;
    PVFATFCB pRootFcb;
    LARGE_INTEGER FileOffset;
    BOOLEAN LabelFound = FALSE;
    DIR_ENTRY VolumeLabelDirEntry;
    ULONG VolumeLabelDirIndex;
    ULONG LabelLen;
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    OEM_STRING StringO;
    UNICODE_STRING StringW;
    CHAR cString[43];
    ULONG SizeDirEntry;
    ULONG EntriesPerPage;

    DPRINT("FsdSetFsLabelInformation()\n");

    DeviceExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

    if (sizeof(DeviceObject->Vpb->VolumeLabel) < FsLabelInfo->VolumeLabelLength)
    {
        return STATUS_NAME_TOO_LONG;
    }

    if (DeviceExt->Flags & VCB_IS_FATX)
    {
        if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 42)
            return STATUS_NAME_TOO_LONG;

        SizeDirEntry = sizeof(FATX_DIR_ENTRY);
        EntriesPerPage = FATX_ENTRIES_PER_PAGE;
    }
    else
    {
        if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 11)
            return STATUS_NAME_TOO_LONG;

        SizeDirEntry = sizeof(FAT_DIR_ENTRY);
        EntriesPerPage = FAT_ENTRIES_PER_PAGE;
    }

    /* Create Volume label dir entry */
    LabelLen = FsLabelInfo->VolumeLabelLength / sizeof(WCHAR);
    RtlZeroMemory(&VolumeLabelDirEntry, SizeDirEntry);
    StringW.Buffer = FsLabelInfo->VolumeLabel;
    StringW.Length = StringW.MaximumLength = (USHORT)FsLabelInfo->VolumeLabelLength;
    StringO.Buffer = cString;
    StringO.Length = 0;
    StringO.MaximumLength = 42;
    Status = RtlUnicodeStringToOemString(&StringO, &StringW, FALSE);
    if (!NT_SUCCESS(Status))
        return Status;

    if (DeviceExt->Flags & VCB_IS_FATX)
    {
        RtlCopyMemory(VolumeLabelDirEntry.FatX.Filename, cString, LabelLen);
        memset(&VolumeLabelDirEntry.FatX.Filename[LabelLen], ' ', 42 - LabelLen);
        VolumeLabelDirEntry.FatX.Attrib = _A_VOLID;
    }
    else
    {
        RtlCopyMemory(VolumeLabelDirEntry.Fat.Filename, cString, max(sizeof(VolumeLabelDirEntry.Fat.Filename), LabelLen));
        if (LabelLen > sizeof(VolumeLabelDirEntry.Fat.Filename))
        {
            memset(VolumeLabelDirEntry.Fat.Ext, ' ', sizeof(VolumeLabelDirEntry.Fat.Ext));
            RtlCopyMemory(VolumeLabelDirEntry.Fat.Ext, cString + sizeof(VolumeLabelDirEntry.Fat.Filename), LabelLen - sizeof(VolumeLabelDirEntry.Fat.Filename));
        }
        else
        {
            memset(&VolumeLabelDirEntry.Fat.Filename[LabelLen], ' ', sizeof(VolumeLabelDirEntry.Fat.Filename) - LabelLen);
        }
        VolumeLabelDirEntry.Fat.Attrib = _A_VOLID;
    }

    pRootFcb = vfatOpenRootFCB(DeviceExt);

    /* Search existing volume entry on disk */
    FileOffset.QuadPart = 0;
    if (CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
    {
        while (TRUE)
        {
            if (ENTRY_VOLUME(DeviceExt, Entry))
            {
                /* Update entry */
                LabelFound = TRUE;
                RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry);
                CcSetDirtyPinnedData(Context, NULL);
                Status = STATUS_SUCCESS;
                break;
            }

            if (ENTRY_END(DeviceExt, Entry))
            {
                break;
            }

            DirIndex++;
            Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
            if ((DirIndex % EntriesPerPage) == 0)
            {
                CcUnpinData(Context);
                FileOffset.u.LowPart += PAGE_SIZE;
                if (!CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
                {
                    Context = NULL;
                    break;
                }
            }
        }

        if (Context)
        {
            CcUnpinData(Context);
        }
    }

    if (!LabelFound)
    {
        /* Add new entry for label */
        if (!vfatFindDirSpace(DeviceExt, pRootFcb, 1, &VolumeLabelDirIndex))
            Status = STATUS_DISK_FULL;
        else
        {
            FileOffset.u.HighPart = 0;
            FileOffset.u.LowPart = VolumeLabelDirIndex * SizeDirEntry;
            if (!CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry,
                           TRUE, &Context, (PVOID*)&Entry))
            {
                Status = STATUS_UNSUCCESSFUL;
            }
            else
            {
                RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry);
                CcSetDirtyPinnedData(Context, NULL);
                CcUnpinData(Context);
                Status = STATUS_SUCCESS;
            }
        }
    }

    vfatReleaseFCB(DeviceExt, pRootFcb);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    /* Update volume label in memory */
    DeviceObject->Vpb->VolumeLabelLength = (USHORT)FsLabelInfo->VolumeLabelLength;
    RtlCopyMemory(DeviceObject->Vpb->VolumeLabel, FsLabelInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabelLength);

    return Status;
}
Exemple #2
0
/*
 * FUNCTION: Closes a file
 */
NTSTATUS
VfatCloseFile(
    PDEVICE_EXTENSION DeviceExt,
    PFILE_OBJECT FileObject)
{
    PVFATFCB pFcb;
    PVFATCCB pCcb;
    NTSTATUS Status = STATUS_SUCCESS;

    DPRINT("VfatCloseFile(DeviceExt %p, FileObject %p)\n",
            DeviceExt, FileObject);

    /* FIXME : update entry in directory? */
    pCcb = (PVFATCCB) (FileObject->FsContext2);
    pFcb = (PVFATFCB) (FileObject->FsContext);

    if (pFcb == NULL)
    {
        return STATUS_SUCCESS;
    }

    if (pFcb->Flags & FCB_IS_VOLUME)
    {
        DPRINT("Volume\n");
        FileObject->FsContext2 = NULL;
    }
    else
    {
        if (FileObject->DeletePending)
        {
            if (pFcb->Flags & FCB_DELETE_PENDING)
            {
                VfatDelEntry(DeviceExt, pFcb, NULL);

                FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
                                            &(DeviceExt->NotifyList),
                                            (PSTRING)&pFcb->PathNameU,
                                            pFcb->PathNameU.Length - pFcb->LongNameU.Length,
                                            NULL,
                                            NULL,
                                            ((*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
                                            FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
                                            FILE_ACTION_REMOVED,
                                            NULL);
            }
            else
            {
                Status = STATUS_DELETE_PENDING;
            }
        }

        vfatReleaseFCB(DeviceExt, pFcb);
    }

    FileObject->FsContext2 = NULL;
    FileObject->FsContext = NULL;
    FileObject->SectionObjectPointer = NULL;
    DeviceExt->OpenHandleCount--;

    if (pCcb)
    {
        vfatDestroyCCB(pCcb);
    }

    if (DeviceExt->OpenHandleCount == 0)
    {
        VfatCheckForDismount(DeviceExt, FALSE);
    }

    return Status;
}