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