ReactOS 0.4.16-dev-340-g0540c21
dirwr.c File Reference
#include "vfat.h"
#include <debug.h>
Include dependency graph for dirwr.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

NTSTATUS vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb)
 
NTSTATUS VfatUpdateEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb)
 
NTSTATUS vfatRenameEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN BOOLEAN CaseChangeOnly)
 
BOOLEAN vfatFindDirSpace (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pDirFcb, IN ULONG nbSlots, OUT PULONG start)
 
static NTSTATUS FATAddEntry (IN PDEVICE_EXTENSION DeviceExt, IN PUNICODE_STRING NameU, IN PVFATFCB *Fcb, IN PVFATFCB ParentFcb, IN ULONG RequestedOptions, IN UCHAR ReqAttr, IN PVFAT_MOVE_CONTEXT MoveContext)
 
static NTSTATUS FATXAddEntry (IN PDEVICE_EXTENSION DeviceExt, IN PUNICODE_STRING NameU, IN PVFATFCB *Fcb, IN PVFATFCB ParentFcb, IN ULONG RequestedOptions, IN UCHAR ReqAttr, IN PVFAT_MOVE_CONTEXT MoveContext)
 
static NTSTATUS FATDelEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
 
static NTSTATUS FATXDelEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
 
NTSTATUS VfatMoveEntry (IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN PVFATFCB ParentFcb)
 
BOOLEAN FATXIsDirectoryEmpty (PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
 
BOOLEAN FATIsDirectoryEmpty (PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
 
NTSTATUS FATGetNextDirEntry (PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
 
NTSTATUS FATXGetNextDirEntry (PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
 

Variables

VFAT_DISPATCH FatXDispatch
 
VFAT_DISPATCH FatDispatch
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file dirwr.c.

Function Documentation

◆ FATAddEntry()

static NTSTATUS FATAddEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PUNICODE_STRING  NameU,
IN PVFATFCB Fcb,
IN PVFATFCB  ParentFcb,
IN ULONG  RequestedOptions,
IN UCHAR  ReqAttr,
IN PVFAT_MOVE_CONTEXT  MoveContext 
)
static

Definition at line 403 of file dirwr.c.

411{
413 PFAT_DIR_ENTRY pFatEntry;
414 slot *pSlots;
415 USHORT nbSlots = 0, j;
417 BOOLEAN needTilde = FALSE, needLong = FALSE;
418 BOOLEAN BaseAllLower, BaseAllUpper;
419 BOOLEAN ExtensionAllLower, ExtensionAllUpper;
420 BOOLEAN InExtension;
422 WCHAR c;
423 ULONG CurrentCluster;
424 LARGE_INTEGER SystemTime, FileOffset;
426 ULONG size;
427 long i;
428
429 OEM_STRING NameA;
430 CHAR aName[13];
431 BOOLEAN IsNameLegal;
432 BOOLEAN SpacesFound;
433
435 WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1];
436 WCHAR ShortNameBuffer[13];
437
438 DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU);
439
440 DirContext.LongNameU = *NameU;
441 IsDirectory = BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE);
442
443 /* nb of entry needed for long name+normal entry */
444 nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1;
445 DPRINT("NameLen= %u, nbSlots =%u\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
447 if (Buffer == NULL)
448 {
450 }
451 RtlZeroMemory(Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
452 pSlots = (slot *) Buffer;
453
454 NameA.Buffer = aName;
455 NameA.Length = 0;
456 NameA.MaximumLength = sizeof(aName);
457
458 DirContext.DeviceExt = DeviceExt;
459 DirContext.ShortNameU.Buffer = ShortNameBuffer;
460 DirContext.ShortNameU.Length = 0;
461 DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
462
463 RtlZeroMemory(&DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
464
465 IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU, &NameA, &SpacesFound);
466
467 if (!IsNameLegal || SpacesFound)
468 {
469 GENERATE_NAME_CONTEXT NameContext;
470 VFAT_DIRENTRY_CONTEXT SearchContext;
471 WCHAR ShortSearchName[13];
472 needTilde = TRUE;
473 needLong = TRUE;
474 RtlZeroMemory(&NameContext, sizeof(GENERATE_NAME_CONTEXT));
475 SearchContext.DeviceExt = DeviceExt;
476 SearchContext.LongNameU.Buffer = LongNameBuffer;
477 SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
478 SearchContext.ShortNameU.Buffer = ShortSearchName;
479 SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName);
480
481 for (i = 0; i < 100; i++)
482 {
483 RtlGenerate8dot3Name(&DirContext.LongNameU, FALSE, &NameContext, &DirContext.ShortNameU);
484 DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
485 SearchContext.DirIndex = 0;
486 Status = FindFile(DeviceExt, ParentFcb, &DirContext.ShortNameU, &SearchContext, TRUE);
487 if (!NT_SUCCESS(Status))
488 {
489 break;
490 }
491 else if (MoveContext)
492 {
493 ASSERT(*Fcb);
494 if (strncmp((char *)SearchContext.DirEntry.Fat.ShortName, (char *)(*Fcb)->entry.Fat.ShortName, 11) == 0)
495 {
496 if (MoveContext->InPlace)
497 {
498 ASSERT(SearchContext.DirEntry.Fat.FileSize == MoveContext->FileSize);
499 break;
500 }
501 }
502 }
503 }
504 if (i == 100) /* FIXME : what to do after this ? */
505 {
507 return STATUS_UNSUCCESSFUL;
508 }
509 IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound);
510 }
511 else
512 {
513 BaseAllLower = BaseAllUpper = TRUE;
514 ExtensionAllLower = ExtensionAllUpper = TRUE;
515 InExtension = FALSE;
516 for (i = 0; i < DirContext.LongNameU.Length / sizeof(WCHAR); i++)
517 {
518 c = DirContext.LongNameU.Buffer[i];
519 if (c >= L'A' && c <= L'Z')
520 {
521 if (InExtension)
522 ExtensionAllLower = FALSE;
523 else
524 BaseAllLower = FALSE;
525 }
526 else if (c >= L'a' && c <= L'z')
527 {
528 if (InExtension)
529 ExtensionAllUpper = FALSE;
530 else
531 BaseAllUpper = FALSE;
532 }
533 else if (c > 0x7f)
534 {
535 needLong = TRUE;
536 break;
537 }
538
539 if (c == L'.')
540 {
541 InExtension = TRUE;
542 }
543 }
544
545 if ((!BaseAllLower && !BaseAllUpper) ||
546 (!ExtensionAllLower && !ExtensionAllUpper))
547 {
548 needLong = TRUE;
549 }
550
551 RtlUpcaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);
552 DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
553 }
554 aName[NameA.Length] = 0;
555 DPRINT("'%s', '%wZ', needTilde=%u, needLong=%u\n",
556 aName, &DirContext.LongNameU, needTilde, needLong);
557 memset(DirContext.DirEntry.Fat.ShortName, ' ', 11);
558 for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)
559 {
560 DirContext.DirEntry.Fat.Filename[i] = aName[i];
561 }
562 if (aName[i] == '.')
563 {
564 i++;
565 for (j = 0; j < 3 && aName[i]; j++, i++)
566 {
567 DirContext.DirEntry.Fat.Ext[j] = aName[i];
568 }
569 }
570 if (DirContext.DirEntry.Fat.Filename[0] == 0xe5)
571 {
572 DirContext.DirEntry.Fat.Filename[0] = 0x05;
573 }
574
575 if (needLong)
576 {
577 RtlCopyMemory(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length);
578 DirContext.LongNameU.Buffer = LongNameBuffer;
579 DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
580 DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
581 memset(DirContext.LongNameU.Buffer + DirContext.LongNameU.Length / sizeof(WCHAR) + 1, 0xff,
582 DirContext.LongNameU.MaximumLength - DirContext.LongNameU.Length - sizeof(WCHAR));
583 }
584 else
585 {
586 nbSlots = 1;
587 if (BaseAllLower && !BaseAllUpper)
588 {
589 DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_BASE;
590 }
591 if (ExtensionAllLower && !ExtensionAllUpper)
592 {
593 DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_EXT;
594 }
595 }
596
597 DPRINT ("dos name=%11.11s\n", DirContext.DirEntry.Fat.Filename);
598
599 /* set attributes */
600 DirContext.DirEntry.Fat.Attrib = ReqAttr;
601 if (IsDirectory)
602 {
603 DirContext.DirEntry.Fat.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
604 }
605 /* set dates and times */
606 KeQuerySystemTime(&SystemTime);
607 FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.Fat.CreationDate,
608 &DirContext.DirEntry.Fat.CreationTime);
609 DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;
610 DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;
611 DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;
612 /* If it's moving, preserve creation time and file size */
613 if (MoveContext != NULL)
614 {
615 DirContext.DirEntry.Fat.CreationDate = MoveContext->CreationDate;
616 DirContext.DirEntry.Fat.CreationTime = MoveContext->CreationTime;
617 DirContext.DirEntry.Fat.FileSize = MoveContext->FileSize;
618 }
619
620 if (needLong)
621 {
622 /* calculate checksum for 8.3 name */
623 for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++)
624 {
625 pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
626 | ((pSlots[0].alias_checksum & 0xfe) >> 1))
627 + DirContext.DirEntry.Fat.ShortName[i]);
628 }
629 /* construct slots and entry */
630 for (i = nbSlots - 2; i >= 0; i--)
631 {
632 DPRINT("construct slot %d\n", i);
633 pSlots[i].attr = 0xf;
634 if (i)
635 {
636 pSlots[i].id = (unsigned char)(nbSlots - i - 1);
637 }
638 else
639 {
640 pSlots[i].id = (unsigned char)(nbSlots - i - 1 + 0x40);
641 }
642 pSlots[i].alias_checksum = pSlots[0].alias_checksum;
643 RtlCopyMemory(pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
644 RtlCopyMemory(pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
645 RtlCopyMemory(pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
646 }
647 }
648 /* try to find nbSlots contiguous entries frees in directory */
649 if (!vfatFindDirSpace(DeviceExt, ParentFcb, nbSlots, &DirContext.StartIndex))
650 {
652 return STATUS_DISK_FULL;
653 }
654 DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
655 if (IsDirectory)
656 {
657 /* If we aren't moving, use next */
658 if (MoveContext == NULL)
659 {
660 CurrentCluster = 0;
661 Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE);
662 if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
663 {
665 if (!NT_SUCCESS(Status))
666 {
667 return Status;
668 }
669 return STATUS_DISK_FULL;
670 }
671
672 if (DeviceExt->FatInfo.FatType == FAT32)
673 {
675 }
676 }
677 else
678 {
679 CurrentCluster = MoveContext->FirstCluster;
680 }
681
682 if (DeviceExt->FatInfo.FatType == FAT32)
683 {
684 DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
685 }
686 DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
687 }
688 else if (MoveContext != NULL)
689 {
690 CurrentCluster = MoveContext->FirstCluster;
691
692 if (DeviceExt->FatInfo.FatType == FAT32)
693 {
694 DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
695 }
696 DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
697 }
698
699 /* No need to init cache here, vfatFindDirSpace() will have done it for us */
701
702 i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY);
703 FileOffset.u.HighPart = 0;
704 FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY);
705 if (DirContext.StartIndex / i == DirContext.DirIndex / i)
706 {
707 /* one cluster */
709 {
710 CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY), PIN_WAIT, &Context, (PVOID*)&pFatEntry);
711 }
713 {
716 }
717 _SEH2_END;
718
719 if (nbSlots > 1)
720 {
721 RtlCopyMemory(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
722 }
723 RtlCopyMemory(pFatEntry + (nbSlots - 1), &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
724 }
725 else
726 {
727 /* two clusters */
728 size = DeviceExt->FatInfo.BytesPerCluster -
729 (DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster;
730 i = size / sizeof(FAT_DIR_ENTRY);
732 {
734 }
736 {
739 }
740 _SEH2_END;
741 RtlCopyMemory(pFatEntry, Buffer, size);
744 FileOffset.u.LowPart += size;
746 {
747 CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY) - size, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
748 }
750 {
753 }
754 _SEH2_END;
755 if (nbSlots - 1 > i)
756 {
757 RtlCopyMemory(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY));
758 }
759 RtlCopyMemory(pFatEntry + nbSlots - 1 - i, &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
760 }
763
764 if (MoveContext != NULL)
765 {
766 /* We're modifying an existing FCB - likely rename/move */
767 Status = vfatUpdateFCB(DeviceExt, *Fcb, &DirContext, ParentFcb);
768 }
769 else
770 {
772 }
773 if (!NT_SUCCESS(Status))
774 {
776 return Status;
777 }
778
779 DPRINT("new : entry=%11.11s\n", (*Fcb)->entry.Fat.Filename);
780 DPRINT("new : entry=%11.11s\n", DirContext.DirEntry.Fat.Filename);
781
782 if (IsDirectory)
783 {
785 if (!NT_SUCCESS(Status))
786 {
788 return Status;
789 }
790
791 FileOffset.QuadPart = 0;
793 {
794 CcPinRead((*Fcb)->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
795 }
797 {
800 }
801 _SEH2_END;
802 /* clear the new directory cluster if not moving */
803 if (MoveContext == NULL)
804 {
805 RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
806 /* create '.' and '..' */
807 pFatEntry[0] = DirContext.DirEntry.Fat;
808 RtlCopyMemory(pFatEntry[0].ShortName, ". ", 11);
809 pFatEntry[1] = DirContext.DirEntry.Fat;
810 RtlCopyMemory(pFatEntry[1].ShortName, ".. ", 11);
811 }
812
813 pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;
814 pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;
816 {
817 pFatEntry[1].FirstCluster = 0;
818 pFatEntry[1].FirstClusterHigh = 0;
819 }
822 }
824 DPRINT("addentry ok\n");
825 return STATUS_SUCCESS;
826}
unsigned char BOOLEAN
NTSYSAPI VOID NTAPI RtlGenerate8dot3Name(_In_ PCUNICODE_STRING Name, _In_ BOOLEAN AllowExtendedCharacters, _Inout_ PGENERATE_NAME_CONTEXT Context, _Inout_ PUNICODE_STRING Name8dot3)
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FAT32
Definition: fat.h:169
VOID NTAPI CcSetDirtyPinnedData(IN PVOID BcbVoid, IN OPTIONAL PLARGE_INTEGER Lsn)
Definition: cachesub.c:121
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PFCB ParentFcb
Definition: cdprocs.h:736
_In_ PFCB Fcb
Definition: cdprocs.h:159
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:425
Definition: bufpool.h:45
BOOLEAN vfatFindDirSpace(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pDirFcb, IN ULONG nbSlots, OUT PULONG start)
Definition: dirwr.c:258
NTSTATUS vfatFCBInitializeCacheFromVolume(PVCB vcb, PVFATFCB fcb)
Definition: dirwr.c:22
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
@ FindFile
Definition: find.c:28
unsigned char
Definition: typeof.h:29
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
#define TAG_DIRENT
Definition: nodetype.h:158
#define FCB_CACHE_INITIALIZED
Definition: ntfs.h:508
BOOLEAN FsdSystemTimeToDosDateTime(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, PUSHORT pDosDate, PUSHORT pDosTime)
Definition: dir.c:52
NTSTATUS FAT32UpdateFreeClustersCount(PDEVICE_EXTENSION DeviceExt)
Definition: fat.c:1215
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define NonPagedPool
Definition: env_spec_w32.h:307
#define IsDirectory(Fcb)
Definition: ext2fs.h:283
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1307
Status
Definition: gdiplustypes.h:25
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
BOOLEAN NTAPI RtlIsNameLegalDOS8Dot3(_In_ PUNICODE_STRING Name, _Inout_opt_ POEM_STRING OemName, _Inout_opt_ PBOOLEAN NameContainsSpaces)
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define c
Definition: ke_i.h:80
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define PIN_WAIT
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
BOOLEAN NTAPI CcPinRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer)
Definition: pinsup.c:802
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
unsigned char ShortName[11]
Definition: vfat.h:115
unsigned long FileSize
Definition: vfat.h:129
unsigned short FirstCluster
Definition: vfat.h:128
unsigned short FirstClusterHigh
Definition: vfat.h:123
LONGLONG CreationTime
Definition: cdstruc.h:1030
ULONG Flags
Definition: ntfs.h:536
ULONG DirIndex
Definition: ntfs.h:533
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
PFILE_OBJECT FileObject
Definition: ntfs.h:520
USHORT MaximumLength
Definition: env_spec_w32.h:370
UNICODE_STRING ShortNameU
Definition: vfat.h:603
UNICODE_STRING LongNameU
Definition: vfat.h:602
DIR_ENTRY DirEntry
Definition: vfat.h:601
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:604
Definition: vfat.h:185
unsigned char id
Definition: vfat.h:186
unsigned char alias_checksum
Definition: vfat.h:190
unsigned char attr
Definition: vfat.h:188
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
STRING OEM_STRING
Definition: umtypes.h:203
FAT_DIR_ENTRY Fat
Definition: vfat.h:226
struct _FATDirEntry FAT_DIR_ENTRY
Definition: vfat.h:167
#define VFAT_CASE_LOWER_EXT
Definition: vfat.h:201
#define LONGNAME_MAX_LENGTH
Definition: vfat.h:203
#define VFAT_CASE_LOWER_BASE
Definition: vfat.h:200
NTSTATUS vfatUpdateFCB(PDEVICE_EXTENSION pVCB, PVFATFCB Fcb, PVFAT_DIRENTRY_CONTEXT DirContext, PVFATFCB ParentFcb)
Definition: fcb.c:539
BOOLEAN vfatFCBIsRoot(PVFATFCB FCB)
Definition: fcb.c:293
NTSTATUS vfatMakeFCBFromDirEntry(PVCB vcb, PVFATFCB directoryFCB, PVFAT_DIRENTRY_CONTEXT DirContext, PVFATFCB *fileFCB)
Definition: fcb.c:725
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175

◆ FATDelEntry()

static NTSTATUS FATDelEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb,
OUT PVFAT_MOVE_CONTEXT  MoveContext 
)
static

Definition at line 956 of file dirwr.c.

960{
961 ULONG CurrentCluster = 0, NextCluster, i;
964 PFAT_DIR_ENTRY pDirEntry = NULL;
966
967 ASSERT(pFcb);
968 ASSERT(pFcb->parentFcb);
969
970 Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
971 if (!NT_SUCCESS(Status))
972 {
973 return Status;
974 }
975
976 DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
977 DPRINT("delete entry: %u to %u\n", pFcb->startIndex, pFcb->dirIndex);
978 Offset.u.HighPart = 0;
979 for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
980 {
981 if (Context == NULL || ((i * sizeof(FAT_DIR_ENTRY)) % PAGE_SIZE) == 0)
982 {
983 if (Context)
984 {
987 }
988 Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
990 {
991 CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
992 }
994 {
996 }
997 _SEH2_END;
998 }
999 pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5;
1000 if (i == pFcb->dirIndex)
1001 {
1002 CurrentCluster =
1004 (PDIR_ENTRY)&pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))]);
1005 }
1006 }
1007
1008 /* In case of moving, save properties */
1009 if (MoveContext != NULL)
1010 {
1011 pDirEntry = &pDirEntry[pFcb->dirIndex % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))];
1012 MoveContext->FirstCluster = CurrentCluster;
1013 MoveContext->FileSize = pDirEntry->FileSize;
1014 MoveContext->CreationTime = pDirEntry->CreationTime;
1015 MoveContext->CreationDate = pDirEntry->CreationDate;
1016 }
1017
1018 if (Context)
1019 {
1022 }
1023
1024 /* In case of moving, don't delete data */
1025 if (MoveContext == NULL)
1026 {
1027 while (CurrentCluster && CurrentCluster != 0xffffffff)
1028 {
1029 GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
1030 /* FIXME: check status */
1031 WriteCluster(DeviceExt, CurrentCluster, 0);
1032 CurrentCluster = NextCluster;
1033 }
1034
1035 if (DeviceExt->FatInfo.FatType == FAT32)
1036 {
1038 }
1039 }
1040
1041 return STATUS_SUCCESS;
1042}
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:18
NTSTATUS GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:744
NTSTATUS WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue)
Definition: fat.c:705
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
unsigned char Filename[8]
Definition: vfat.h:114
unsigned short CreationDate
Definition: vfat.h:120
unsigned short CreationTime
Definition: vfat.h:120
Definition: vfat.h:225

◆ FATGetNextDirEntry()

NTSTATUS FATGetNextDirEntry ( PVOID pContext,
PVOID pPage,
PVFATFCB  pDirFcb,
PVFAT_DIRENTRY_CONTEXT  DirContext,
BOOLEAN  First 
)

◆ FATIsDirectoryEmpty()

BOOLEAN FATIsDirectoryEmpty ( PDEVICE_EXTENSION  DeviceExt,
PVFATFCB  Fcb 
)

Definition at line 42 of file direntry.c.

45{
48 PFAT_DIR_ENTRY FatDirEntry;
49 ULONG Index, MaxIndex;
51
52 if (vfatFCBIsRoot(Fcb))
53 {
54 Index = 0;
55 }
56 else
57 {
58 Index = 2;
59 }
60
61 FileOffset.QuadPart = 0;
62 MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FAT_DIR_ENTRY);
63
65 if (!NT_SUCCESS(Status))
66 {
67 return FALSE;
68 }
69
70 while (Index < MaxIndex)
71 {
72 if (Context == NULL || (Index % FAT_ENTRIES_PER_PAGE) == 0)
73 {
74 if (Context != NULL)
75 {
77 }
78
80 {
81 CcMapData(Fcb->FileObject, &FileOffset, sizeof(FAT_DIR_ENTRY), MAP_WAIT, &Context, (PVOID*)&FatDirEntry);
82 }
84 {
85 _SEH2_YIELD(return TRUE);
86 }
88
89 FatDirEntry += Index % FAT_ENTRIES_PER_PAGE;
90 FileOffset.QuadPart += PAGE_SIZE;
91 }
92
93 if (FAT_ENTRY_END(FatDirEntry))
94 {
96 return TRUE;
97 }
98
99 if (!FAT_ENTRY_DELETED(FatDirEntry))
100 {
102 return FALSE;
103 }
104
105 Index++;
106 FatDirEntry++;
107 }
108
109 if (Context)
110 {
112 }
113
114 return TRUE;
115}
#define MAP_WAIT
BOOLEAN NTAPI CcMapData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *BcbResult, OUT PVOID *Buffer)
Definition: pinsup.c:694
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
struct _LARGE_INTEGER::@2304 u
#define FAT_ENTRY_DELETED(DirEntry)
Definition: vfat.h:209
#define FAT_ENTRY_END(DirEntry)
Definition: vfat.h:210
#define FAT_ENTRIES_PER_PAGE
Definition: vfat.h:219
_In_ WDFCOLLECTION _In_ ULONG Index

◆ FATXAddEntry()

static NTSTATUS FATXAddEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PUNICODE_STRING  NameU,
IN PVFATFCB Fcb,
IN PVFATFCB  ParentFcb,
IN ULONG  RequestedOptions,
IN UCHAR  ReqAttr,
IN PVFAT_MOVE_CONTEXT  MoveContext 
)
static

Definition at line 832 of file dirwr.c.

840{
842 LARGE_INTEGER SystemTime, FileOffset;
843 OEM_STRING NameA;
845 PFATX_DIR_ENTRY pFatXDirEntry;
846 ULONG Index;
847
848 DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU);
849
850 DirContext.LongNameU = *NameU;
851
852 if (DirContext.LongNameU.Length / sizeof(WCHAR) > 42)
853 {
854 /* name too long */
856 }
857
858 /* try to find 1 entry free in directory */
859 if (!vfatFindDirSpace(DeviceExt, ParentFcb, 1, &DirContext.StartIndex))
860 {
861 return STATUS_DISK_FULL;
862 }
863 Index = DirContext.DirIndex = DirContext.StartIndex;
865 {
866 DirContext.DirIndex += 2;
867 DirContext.StartIndex += 2;
868 }
869
870 DirContext.ShortNameU.Buffer = 0;
871 DirContext.ShortNameU.Length = 0;
872 DirContext.ShortNameU.MaximumLength = 0;
873 DirContext.DeviceExt = DeviceExt;
874 RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
875 memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
876 /* Use cluster, if moving */
877 if (MoveContext != NULL)
878 {
879 DirContext.DirEntry.FatX.FirstCluster = MoveContext->FirstCluster;
880 }
881 else
882 {
883 DirContext.DirEntry.FatX.FirstCluster = 0;
884 }
885 DirContext.DirEntry.FatX.FileSize = 0;
886
887 /* set file name */
888 NameA.Buffer = (PCHAR)DirContext.DirEntry.FatX.Filename;
889 NameA.Length = 0;
890 NameA.MaximumLength = 42;
891 RtlUnicodeStringToOemString(&NameA, &DirContext.LongNameU, FALSE);
892 DirContext.DirEntry.FatX.FilenameLength = (unsigned char)NameA.Length;
893
894 /* set attributes */
895 DirContext.DirEntry.FatX.Attrib = ReqAttr;
896 if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE))
897 {
898 DirContext.DirEntry.FatX.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
899 }
900
901 /* set dates and times */
902 KeQuerySystemTime(&SystemTime);
903 FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.FatX.CreationDate,
904 &DirContext.DirEntry.FatX.CreationTime);
905 DirContext.DirEntry.FatX.UpdateDate = DirContext.DirEntry.FatX.CreationDate;
906 DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime;
907 DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate;
908 DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime;
909 /* If it's moving, preserve creation time and file size */
910 if (MoveContext != NULL)
911 {
912 DirContext.DirEntry.FatX.CreationDate = MoveContext->CreationDate;
913 DirContext.DirEntry.FatX.CreationTime = MoveContext->CreationTime;
914 DirContext.DirEntry.FatX.FileSize = MoveContext->FileSize;
915 }
916
917 /* No need to init cache here, vfatFindDirSpace() will have done it for us */
919
920 /* add entry into parent directory */
921 FileOffset.u.HighPart = 0;
922 FileOffset.u.LowPart = Index * sizeof(FATX_DIR_ENTRY);
924 {
926 }
928 {
930 }
931 _SEH2_END;
932 RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
935
936 if (MoveContext != NULL)
937 {
938 /* We're modifying an existing FCB - likely rename/move */
939 /* FIXME: check status */
940 vfatUpdateFCB(DeviceExt, *Fcb, &DirContext, ParentFcb);
941 }
942 else
943 {
944 /* FIXME: check status */
946 }
947
948 DPRINT("addentry ok\n");
949 return STATUS_SUCCESS;
950}
if(dx< 0)
Definition: linetemp.h:194
#define PCHAR
Definition: match.c:90
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222

◆ FATXDelEntry()

static NTSTATUS FATXDelEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb,
OUT PVFAT_MOVE_CONTEXT  MoveContext 
)
static

Definition at line 1048 of file dirwr.c.

1052{
1053 ULONG CurrentCluster = 0, NextCluster;
1054 PVOID Context = NULL;
1056 PFATX_DIR_ENTRY pDirEntry;
1057 ULONG StartIndex;
1059
1060 ASSERT(pFcb);
1061 ASSERT(pFcb->parentFcb);
1062 ASSERT(vfatVolumeIsFatX(DeviceExt));
1063
1064 StartIndex = pFcb->startIndex;
1065
1066 Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
1067 if (!NT_SUCCESS(Status))
1068 {
1069 return Status;
1070 }
1071
1072 DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
1073 DPRINT("delete entry: %u\n", StartIndex);
1074 Offset.u.HighPart = 0;
1075 Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
1076 _SEH2_TRY
1077 {
1078 CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
1079 }
1081 {
1082 DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
1084 }
1085 _SEH2_END;
1086 pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
1087 pDirEntry->FilenameLength = 0xe5;
1088 CurrentCluster = vfatDirEntryGetFirstCluster(DeviceExt,
1089 (PDIR_ENTRY)pDirEntry);
1090
1091 /* In case of moving, save properties */
1092 if (MoveContext != NULL)
1093 {
1094 MoveContext->FirstCluster = CurrentCluster;
1095 MoveContext->FileSize = pDirEntry->FileSize;
1096 MoveContext->CreationTime = pDirEntry->CreationTime;
1097 MoveContext->CreationDate = pDirEntry->CreationDate;
1098 }
1099
1102
1103 /* In case of moving, don't delete data */
1104 if (MoveContext == NULL)
1105 {
1106 while (CurrentCluster && CurrentCluster != 0xffffffff)
1107 {
1108 GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
1109 /* FIXME: check status */
1110 WriteCluster(DeviceExt, CurrentCluster, 0);
1111 CurrentCluster = NextCluster;
1112 }
1113 }
1114
1115 return STATUS_SUCCESS;
1116}
#define DPRINT1
Definition: precomp.h:8
unsigned long FileSize
Definition: vfat.h:175
unsigned short CreationDate
Definition: vfat.h:179
unsigned char FilenameLength
Definition: vfat.h:171
unsigned short CreationTime
Definition: vfat.h:178
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651

◆ FATXGetNextDirEntry()

NTSTATUS FATXGetNextDirEntry ( PVOID pContext,
PVOID pPage,
PVFATFCB  pDirFcb,
PVFAT_DIRENTRY_CONTEXT  DirContext,
BOOLEAN  First 
)

◆ FATXIsDirectoryEmpty()

BOOLEAN FATXIsDirectoryEmpty ( PDEVICE_EXTENSION  DeviceExt,
PVFATFCB  Fcb 
)

Definition at line 118 of file direntry.c.

121{
124 PFATX_DIR_ENTRY FatXDirEntry;
125 ULONG Index = 0, MaxIndex;
127
128 FileOffset.QuadPart = 0;
129 MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FATX_DIR_ENTRY);
130
132 if (!NT_SUCCESS(Status))
133 {
134 return FALSE;
135 }
136
137 while (Index < MaxIndex)
138 {
139 if (Context == NULL || (Index % FATX_ENTRIES_PER_PAGE) == 0)
140 {
141 if (Context != NULL)
142 {
144 }
145
147 {
148 CcMapData(Fcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), MAP_WAIT, &Context, (PVOID*)&FatXDirEntry);
149 }
151 {
152 _SEH2_YIELD(return TRUE);
153 }
154 _SEH2_END;
155
156 FatXDirEntry += Index % FATX_ENTRIES_PER_PAGE;
157 FileOffset.QuadPart += PAGE_SIZE;
158 }
159
160 if (FATX_ENTRY_END(FatXDirEntry))
161 {
163 return TRUE;
164 }
165
166 if (!FATX_ENTRY_DELETED(FatXDirEntry))
167 {
169 return FALSE;
170 }
171
172 Index++;
173 FatXDirEntry++;
174 }
175
176 if (Context)
177 {
179 }
180
181 return TRUE;
182}
#define FATX_ENTRY_END(DirEntry)
Definition: vfat.h:215
#define FATX_ENTRIES_PER_PAGE
Definition: vfat.h:220
#define FATX_ENTRY_DELETED(DirEntry)
Definition: vfat.h:214

◆ vfatFCBInitializeCacheFromVolume()

NTSTATUS vfatFCBInitializeCacheFromVolume ( PVCB  vcb,
PVFATFCB  fcb 
)

Definition at line 22 of file dirwr.c.

25{
26 PFILE_OBJECT fileObject;
27 PVFATCCB newCCB;
29 BOOLEAN Acquired;
30
31 /* Don't re-initialize if already done */
33 {
34 return STATUS_SUCCESS;
35 }
36
38 ASSERT(fcb->FileObject == NULL);
39
40 Acquired = FALSE;
41 if (!ExIsResourceAcquiredExclusive(&vcb->DirResource))
42 {
43 ExAcquireResourceExclusiveLite(&vcb->DirResource, TRUE);
44 Acquired = TRUE;
45 }
46
47 fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
48 if (fileObject == NULL)
49 {
51 goto Quit;
52 }
53
54#ifdef KDBG
55 if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &fcb->LongNameU, FALSE, NULL))
56 {
57 DPRINT1("Attaching %p to %p (%d)\n", fcb, fileObject, fcb->RefCount);
58 }
59#endif
60
61 newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
62 if (newCCB == NULL)
63 {
65 ObDereferenceObject(fileObject);
66 goto Quit;
67 }
68 RtlZeroMemory(newCCB, sizeof (VFATCCB));
69
70 fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
71 fileObject->FsContext = fcb;
72 fileObject->FsContext2 = newCCB;
73 fileObject->Vpb = vcb->IoVPB;
74 fcb->FileObject = fileObject;
75
77 {
78 CcInitializeCacheMap(fileObject,
79 (PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize),
80 TRUE,
82 fcb);
83 }
85 {
87 fcb->FileObject = NULL;
88 ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, newCCB);
89 ObDereferenceObject(fileObject);
90 if (Acquired)
91 {
92 ExReleaseResourceLite(&vcb->DirResource);
93 }
94 return status;
95 }
97
98 vfatGrabFCB(vcb, fcb);
101
102Quit:
103 if (Acquired)
104 {
105 ExReleaseResourceLite(&vcb->DirResource);
106 }
107
108 return status;
109}
struct _fcb fcb
Definition: btrfs_drv.h:1364
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:18
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI FsRtlIsNameInExpression(IN PUNICODE_STRING Expression, IN PUNICODE_STRING Name, IN BOOLEAN IgnoreCase, IN PWCHAR UpcaseTable OPTIONAL)
Definition: name.c:514
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3187
NPAGED_LOOKASIDE_LIST CcbLookasideList
Definition: vfat.h:418
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
Definition: vfat.h:537
Definition: ps.c:97
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:637
VOID vfatGrabFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
Definition: fcb.c:301
#define ExIsResourceAcquiredExclusive
Definition: exfuncs.h:347
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by FATAddEntry(), FATDelEntry(), FATGetNextDirEntry(), FATIsDirectoryEmpty(), FATXDelEntry(), FATXGetNextDirEntry(), FATXIsDirectoryEmpty(), FsdSetFsLabelInformation(), vfatFindDirSpace(), vfatMakeRootFCB(), vfatRenameEntry(), and VfatUpdateEntry().

◆ vfatFindDirSpace()

BOOLEAN vfatFindDirSpace ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pDirFcb,
IN ULONG  nbSlots,
OUT PULONG  start 
)

Definition at line 258 of file dirwr.c.

263{
265 ULONG i, count, size, nbFree = 0;
266 PDIR_ENTRY pFatEntry = NULL;
269 ULONG SizeDirEntry;
270 BOOLEAN IsFatX = vfatVolumeIsFatX(DeviceExt);
271 FileOffset.QuadPart = 0;
272
273 if (IsFatX)
274 SizeDirEntry = sizeof(FATX_DIR_ENTRY);
275 else
276 SizeDirEntry = sizeof(FAT_DIR_ENTRY);
277
278 Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pDirFcb);
279 if (!NT_SUCCESS(Status))
280 {
281 return FALSE;
282 }
283
284 count = pDirFcb->RFCB.FileSize.u.LowPart / SizeDirEntry;
285 size = DeviceExt->FatInfo.BytesPerCluster / SizeDirEntry;
286 for (i = 0; i < count; i++, pFatEntry = (PDIR_ENTRY)((ULONG_PTR)pFatEntry + SizeDirEntry))
287 {
288 if (Context == NULL || (i % size) == 0)
289 {
290 if (Context)
291 {
293 }
295 {
296 CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
297 }
299 {
300 _SEH2_YIELD(return FALSE);
301 }
302 _SEH2_END;
303
304 FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
305 }
306 if (ENTRY_END(IsFatX, pFatEntry))
307 {
308 break;
309 }
310 if (ENTRY_DELETED(IsFatX, pFatEntry))
311 {
312 nbFree++;
313 }
314 else
315 {
316 nbFree = 0;
317 }
318 if (nbFree == nbSlots)
319 {
320 break;
321 }
322 }
323 if (Context)
324 {
326 Context = NULL;
327 }
328 if (nbFree == nbSlots)
329 {
330 /* found enough contiguous free slots */
331 *start = i - nbSlots + 1;
332 }
333 else
334 {
335 *start = i - nbFree;
336 if (*start + nbSlots > count)
337 {
339 /* extend the directory */
340 if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32)
341 {
342 /* We can't extend a root directory on a FAT12/FAT16/FATX partition */
343 return FALSE;
344 }
345 AllocationSize.QuadPart = pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster;
346 Status = VfatSetAllocationSizeInformation(pDirFcb->FileObject, pDirFcb,
347 DeviceExt, &AllocationSize);
348 if (!NT_SUCCESS(Status))
349 {
350 return FALSE;
351 }
352 /* clear the new dir cluster */
353 FileOffset.u.LowPart = (ULONG)(pDirFcb->RFCB.FileSize.QuadPart -
354 DeviceExt->FatInfo.BytesPerCluster);
356 {
357 CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
358 }
360 {
361 _SEH2_YIELD(return FALSE);
362 }
363 _SEH2_END;
364
365 if (IsFatX)
366 memset(pFatEntry, 0xff, DeviceExt->FatInfo.BytesPerCluster);
367 else
368 RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
369 }
370 else if (*start + nbSlots < count)
371 {
372 /* clear the entry after the last new entry */
373 FileOffset.u.LowPart = (*start + nbSlots) * SizeDirEntry;
375 {
376 CcPinRead(pDirFcb->FileObject, &FileOffset, SizeDirEntry, PIN_WAIT, &Context, (PVOID*)&pFatEntry);
377 }
379 {
380 _SEH2_YIELD(return FALSE);
381 }
382 _SEH2_END;
383
384 if (IsFatX)
385 memset(pFatEntry, 0xff, SizeDirEntry);
386 else
387 RtlZeroMemory(pFatEntry, SizeDirEntry);
388 }
389 if (Context)
390 {
393 }
394 }
395 DPRINT("nbSlots %u nbFree %u, entry number %u\n", nbSlots, nbFree, *start);
396 return TRUE;
397}
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:323
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define ENTRY_DELETED(IsFatX, DirEntry)
Definition: vfat.h:205
union _DIR_ENTRY * PDIR_ENTRY
Definition: vfat.h:230
#define ENTRY_END(IsFatX, DirEntry)
Definition: vfat.h:207
NTSTATUS VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, PVFATFCB Fcb, PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER AllocationSize)
Definition: finfo.c:1211

Referenced by FATAddEntry(), FATXAddEntry(), and FsdSetFsLabelInformation().

◆ VfatMoveEntry()

NTSTATUS VfatMoveEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb,
IN PUNICODE_STRING  FileName,
IN PVFATFCB  ParentFcb 
)

Definition at line 1122 of file dirwr.c.

1127{
1129 PVFATFCB OldParent;
1130 VFAT_MOVE_CONTEXT MoveContext;
1131
1132 DPRINT("VfatMoveEntry(%p, %p, %wZ, %p)\n", DeviceExt, pFcb, FileName, ParentFcb);
1133
1134 /* Delete old entry while keeping data */
1135 Status = VfatDelEntry(DeviceExt, pFcb, &MoveContext);
1136 if (!NT_SUCCESS(Status))
1137 {
1138 return Status;
1139 }
1140
1141 OldParent = pFcb->parentFcb;
1142 CcFlushCache(&OldParent->SectionObjectPointers, NULL, 0, NULL);
1143 MoveContext.InPlace = (OldParent == ParentFcb);
1144
1145 /* Add our new entry with our cluster */
1146 Status = VfatAddEntry(DeviceExt,
1147 FileName,
1148 &pFcb,
1149 ParentFcb,
1151 *pFcb->Attributes,
1152 &MoveContext);
1153
1154 CcFlushCache(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, NULL);
1155
1156 return Status;
1157}
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
Definition: vfat.h:448
struct _VFATFCB * parentFcb
Definition: vfat.h:490
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: vfat.h:451
BOOLEAN InPlace
Definition: vfat.h:613
FORCEINLINE NTSTATUS VfatAddEntry(PDEVICE_EXTENSION DeviceExt, PUNICODE_STRING NameU, struct _VFATFCB **Fcb, struct _VFATFCB *ParentFcb, ULONG RequestedOptions, UCHAR ReqAttr, struct _VFAT_MOVE_CONTEXT *MoveContext)
Definition: vfat.h:375
FORCEINLINE NTSTATUS VfatDelEntry(PDEVICE_EXTENSION DeviceExt, struct _VFATFCB *Fcb, struct _VFAT_MOVE_CONTEXT *MoveContext)
Definition: vfat.h:388

Referenced by vfatRenameEntry(), and VfatSetRenameInformation().

◆ vfatRenameEntry()

NTSTATUS vfatRenameEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb,
IN PUNICODE_STRING  FileName,
IN BOOLEAN  CaseChangeOnly 
)

Definition at line 178 of file dirwr.c.

183{
184 OEM_STRING NameA;
185 ULONG StartIndex;
188 PFATX_DIR_ENTRY pDirEntry;
190
191 DPRINT("vfatRenameEntry(%p, %p, %wZ, %d)\n", DeviceExt, pFcb, FileName, CaseChangeOnly);
192
193 Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
194 if (!NT_SUCCESS(Status))
195 {
196 return Status;
197 }
198
199 if (vfatVolumeIsFatX(DeviceExt))
200 {
202
203 /* Open associated dir entry */
204 StartIndex = pFcb->startIndex;
205 Offset.u.HighPart = 0;
206 Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
208 {
209 CcPinRead(pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, PIN_WAIT, &Context, (PVOID*)&pDirEntry);
210 }
212 {
213 DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
215 }
216 _SEH2_END;
217
218 pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
219
220 /* Set file name */
221 NameA.Buffer = (PCHAR)pDirEntry->Filename;
222 NameA.Length = 0;
223 NameA.MaximumLength = 42;
225 pDirEntry->FilenameLength = (unsigned char)NameA.Length;
226
227 /* Update FCB */
228 DirContext.DeviceExt = DeviceExt;
229 DirContext.ShortNameU.Length = 0;
230 DirContext.ShortNameU.MaximumLength = 0;
231 DirContext.ShortNameU.Buffer = NULL;
232 DirContext.LongNameU = *FileName;
233 DirContext.DirEntry.FatX = *pDirEntry;
234
237
238 Status = vfatUpdateFCB(DeviceExt, pFcb, &DirContext, pFcb->parentFcb);
239 if (NT_SUCCESS(Status))
240 {
241 CcFlushCache(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, NULL);
242 }
243
244 return Status;
245 }
246 else
247 {
248 /* This we cannot handle properly, move file - would likely need love */
249 return VfatMoveEntry(DeviceExt, pFcb, FileName, pFcb->parentFcb);
250 }
251}
NTSTATUS VfatMoveEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, IN PUNICODE_STRING FileName, IN PVFATFCB ParentFcb)
Definition: dirwr.c:1122
unsigned char Filename[42]
Definition: vfat.h:173

Referenced by VfatSetRenameInformation().

◆ VfatUpdateEntry()

NTSTATUS VfatUpdateEntry ( IN PDEVICE_EXTENSION  DeviceExt,
IN PVFATFCB  pFcb 
)

Definition at line 115 of file dirwr.c.

118{
120 PDIR_ENTRY PinEntry;
122 ULONG SizeDirEntry;
123 ULONG dirIndex;
125
126 ASSERT(pFcb);
127
128 if (vfatVolumeIsFatX(DeviceExt))
129 {
130 SizeDirEntry = sizeof(FATX_DIR_ENTRY);
131 dirIndex = pFcb->startIndex;
132 }
133 else
134 {
135 SizeDirEntry = sizeof(FAT_DIR_ENTRY);
136 dirIndex = pFcb->dirIndex;
137 }
138
139 DPRINT("updEntry dirIndex %u, PathName \'%wZ\'\n", dirIndex, &pFcb->PathNameU);
140
141 if (vfatFCBIsRoot(pFcb) || BooleanFlagOn(pFcb->Flags, FCB_IS_FAT | FCB_IS_VOLUME))
142 {
143 return STATUS_SUCCESS;
144 }
145
146 ASSERT(pFcb->parentFcb);
147
148 Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
149 if (!NT_SUCCESS(Status))
150 {
151 return Status;
152 }
153
154 Offset.u.HighPart = 0;
155 Offset.u.LowPart = dirIndex * SizeDirEntry;
157 {
158 CcPinRead(pFcb->parentFcb->FileObject, &Offset, SizeDirEntry, PIN_WAIT, &Context, (PVOID*)&PinEntry);
159 }
161 {
162 DPRINT1("Failed write to \'%wZ\'.\n", &pFcb->parentFcb->PathNameU);
164 }
165 _SEH2_END;
166
167 pFcb->Flags &= ~FCB_IS_DIRTY;
168 RtlCopyMemory(PinEntry, &pFcb->entry, SizeDirEntry);
171 return STATUS_SUCCESS;
172}
#define FCB_IS_VOLUME
Definition: ntfs.h:510
#define FCB_IS_FAT
Definition: vfat.h:435

Referenced by VfatCleanupFile(), VfatCreateFile(), VfatFlushFile(), VfatSetAllocationSizeInformation(), and VfatSetBasicInformation().

Variable Documentation

◆ FatDispatch

VFAT_DISPATCH FatDispatch
Initial value:
= {
}
BOOLEAN FATIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
Definition: direntry.c:42
static NTSTATUS FATAddEntry(IN PDEVICE_EXTENSION DeviceExt, IN PUNICODE_STRING NameU, IN PVFATFCB *Fcb, IN PVFATFCB ParentFcb, IN ULONG RequestedOptions, IN UCHAR ReqAttr, IN PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:403
NTSTATUS FATGetNextDirEntry(PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
static NTSTATUS FATDelEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:956

Definition at line 1171 of file dirwr.c.

Referenced by VfatMount().

◆ FatXDispatch

VFAT_DISPATCH FatXDispatch
Initial value:
= {
}
BOOLEAN FATXIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
Definition: direntry.c:118
NTSTATUS FATXGetNextDirEntry(PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First)
static NTSTATUS FATXDelEntry(IN PDEVICE_EXTENSION DeviceExt, IN PVFATFCB pFcb, OUT PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:1048
static NTSTATUS FATXAddEntry(IN PDEVICE_EXTENSION DeviceExt, IN PUNICODE_STRING NameU, IN PVFATFCB *Fcb, IN PVFATFCB ParentFcb, IN ULONG RequestedOptions, IN UCHAR ReqAttr, IN PVFAT_MOVE_CONTEXT MoveContext)
Definition: dirwr.c:832

Definition at line 1164 of file dirwr.c.

Referenced by VfatMount().