ReactOS 0.4.15-dev-7942-gd23573b
create.c File Reference
#include "ntfs.h"
#include <debug.h>
Include dependency graph for create.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static NTSTATUS NtfsMakeAbsoluteFilename (PFILE_OBJECT pFileObject, PWSTR pRelativeFileName, PWSTR *pAbsoluteFilename)
 
static NTSTATUS NtfsMoonWalkID (PDEVICE_EXTENSION DeviceExt, ULONGLONG Id, PUNICODE_STRING OutPath)
 
static NTSTATUS NtfsOpenFileById (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, ULONGLONG MftId, PNTFS_FCB *FoundFCB)
 
static NTSTATUS NtfsOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PWSTR FileName, BOOLEAN CaseSensitive, PNTFS_FCB *FoundFCB)
 
static NTSTATUS NtfsCreateFile (PDEVICE_OBJECT DeviceObject, PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsCreate (PNTFS_IRP_CONTEXT IrpContext)
 
NtfsCreateDirectory()

@implemented

Creates a file record for a new directory and saves it to the MFT. Adds the filename attribute of the created directory to the parent directory's index.

Parameters
DeviceExtPoints to the target disk's DEVICE_EXTENSION
FileObjectPointer to a FILE_OBJECT describing the directory to be created
CaseSensitiveBoolean indicating if the function should operate in case-sensitive mode. This will be TRUE if an application created the folder with the FILE_FLAG_POSIX_SEMANTICS flag.
CanWaitBoolean indicating if the function is allowed to wait for exclusive access to the master file table. This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
Returns
STATUS_SUCCESS on success. STATUS_INSUFFICIENT_RESOURCES if unable to allocate memory for the file record. STATUS_CANT_WAIT if CanWait was FALSE and the function needed to resize the MFT but couldn't get immediate, exclusive access to it.
NTSTATUS NtfsCreateDirectory (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
 
NtfsCreateEmptyFileRecord

@implemented

Creates a new, empty file record, with no attributes.

Parameters
DeviceExtPointer to the DEVICE_EXTENSION of the target volume the file record will be stored on.
Returns
A pointer to the newly-created FILE_RECORD_HEADER if the function succeeds, NULL otherwise.
PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord (PDEVICE_EXTENSION DeviceExt)
 
NtfsCreateFileRecord()

@implemented

Creates a file record and saves it to the MFT. Adds the filename attribute of the created file to the parent directory's index.

Parameters
DeviceExtPoints to the target disk's DEVICE_EXTENSION
FileObjectPointer to a FILE_OBJECT describing the file to be created
CanWaitBoolean indicating if the function is allowed to wait for exclusive access to the master file table. This will only be relevant if the MFT doesn't have any free file records and needs to be enlarged.
Returns
STATUS_SUCCESS on success. STATUS_INSUFFICIENT_RESOURCES if unable to allocate memory for the file record. STATUS_CANT_WAIT if CanWait was FALSE and the function needed to resize the MFT but couldn't get immediate, exclusive access to it.
NTSTATUS NtfsCreateFileRecord (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
 

Variables

static PCWSTR MftIdToName []
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 31 of file create.c.

Function Documentation

◆ NtfsCreate()

NTSTATUS NtfsCreate ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 622 of file create.c.

623{
624 PDEVICE_EXTENSION DeviceExt;
627
628 DeviceObject = IrpContext->DeviceObject;
630 {
631 /* DeviceObject represents FileSystem instead of logical volume */
632 DPRINT("Opening file system\n");
633 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
634 return STATUS_SUCCESS;
635 }
636
637 DeviceExt = DeviceObject->DeviceExtension;
638
639 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
640 {
641 return NtfsMarkIrpContextForQueue(IrpContext);
642 }
643
644 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
645 TRUE);
647 IrpContext);
648 ExReleaseResourceLite(&DeviceExt->DirResource);
649
650 return Status;
651}
LONG NTSTATUS
Definition: precomp.h:26
#define TRUE
Definition: types.h:120
static NTSTATUS NtfsCreateFile(PDEVICE_OBJECT DeviceObject, PNTFS_IRP_CONTEXT IrpContext)
Definition: create.c:328
PNTFS_GLOBAL_DATA NtfsGlobalData
Definition: ntfs.c:36
FORCEINLINE NTSTATUS NtfsMarkIrpContextForQueue(PNTFS_IRP_CONTEXT IrpContext)
Definition: ntfs.h:569
#define IRPCONTEXT_CANWAIT
Definition: ntfs.h:474
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
Status
Definition: gdiplustypes.h:25
#define FILE_OPENED
Definition: nt_native.h:769
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:148
ULONG Flags
Definition: ntfs.h:481
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:488
IO_STATUS_BLOCK IoStatus
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055

Referenced by NtfsDispatch().

◆ NtfsCreateDirectory()

NTSTATUS NtfsCreateDirectory ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
BOOLEAN  CaseSensitive,
BOOLEAN  CanWait 
)

Definition at line 681 of file create.c.

685{
686
688 PFILE_RECORD_HEADER FileRecord;
689 PNTFS_ATTR_RECORD NextAttribute;
690 PFILENAME_ATTRIBUTE FilenameAttribute;
691 ULONGLONG ParentMftIndex;
692 ULONGLONG FileMftIndex;
694 PINDEX_ROOT_ATTRIBUTE NewIndexRoot;
695 ULONG MaxIndexRootSize;
696 ULONG RootLength;
697
698 DPRINT("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
699 DeviceExt,
701 CaseSensitive ? "TRUE" : "FALSE",
702 CanWait ? "TRUE" : "FALSE");
703
704 // Start with an empty file record
705 FileRecord = NtfsCreateEmptyFileRecord(DeviceExt);
706 if (!FileRecord)
707 {
708 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
710 }
711
712 // Set the directory flag
713 FileRecord->Flags |= FRH_DIRECTORY;
714
715 // find where the first attribute will be added
716 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
717
718 // add first attribute, $STANDARD_INFORMATION
719 AddStandardInformation(FileRecord, NextAttribute);
720
721 // advance NextAttribute pointer to the next attribute
722 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
723
724 // Add the $FILE_NAME attribute
725 AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject, CaseSensitive, &ParentMftIndex);
726
727 // save a pointer to the filename attribute
728 FilenameAttribute = (PFILENAME_ATTRIBUTE)((ULONG_PTR)NextAttribute + NextAttribute->Resident.ValueOffset);
729
730 // advance NextAttribute pointer to the next attribute
731 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
732
733 // Create an empty b-tree to represent our new index
735 if (!NT_SUCCESS(Status))
736 {
737 DPRINT1("ERROR: Failed to create empty B-Tree!\n");
738 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
739 return Status;
740 }
741
742 // Calculate maximum size of index root
743 MaxIndexRootSize = DeviceExt->NtfsInfo.BytesPerFileRecord
744 - ((ULONG_PTR)NextAttribute - (ULONG_PTR)FileRecord)
745 - sizeof(ULONG) * 2;
746
747 // Create a new index record from the tree
749 Tree,
750 MaxIndexRootSize,
751 &NewIndexRoot,
752 &RootLength);
753 if (!NT_SUCCESS(Status))
754 {
755 DPRINT1("ERROR: Unable to create empty index root!\n");
757 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
758 return Status;
759 }
760
761 // We're done with the B-Tree
763
764 // add the $INDEX_ROOT attribute
765 Status = AddIndexRoot(DeviceExt, FileRecord, NextAttribute, NewIndexRoot, RootLength, L"$I30", 4);
766 if (!NT_SUCCESS(Status))
767 {
768 DPRINT1("ERROR: Failed to add index root to new file record!\n");
769 ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
770 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
771 return Status;
772 }
773
774
775#ifndef NDEBUG
776 NtfsDumpFileRecord(DeviceExt, FileRecord);
777#endif
778
779 // Now that we've built the file record in memory, we need to store it in the MFT.
780 Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
781 if (NT_SUCCESS(Status))
782 {
783 // The highest 2 bytes should be the sequence number, unless the parent happens to be root
784 if (FileMftIndex == NTFS_FILE_ROOT)
785 FileMftIndex = FileMftIndex + ((ULONGLONG)NTFS_FILE_ROOT << 48);
786 else
787 FileMftIndex = FileMftIndex + ((ULONGLONG)FileRecord->SequenceNumber << 48);
788
789 DPRINT1("New File Reference: 0x%016I64x\n", FileMftIndex);
790
791 // Add the filename attribute to the filename-index of the parent directory
793 ParentMftIndex,
794 FileMftIndex,
795 FilenameAttribute,
796 CaseSensitive);
797 }
798
799 ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
800 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
801
802 return Status;
803}
CRegistryTree Tree
#define DPRINT1
Definition: precomp.h:8
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
#define NTFS_FILE_ROOT
Definition: ntfs.h:28
VOID DestroyBTree(PB_TREE Tree)
Definition: btree.c:1542
NTSTATUS CreateEmptyBTree(PB_TREE *NewTree)
Definition: btree.c:348
NTSTATUS CreateIndexRootFromBTree(PDEVICE_EXTENSION DeviceExt, PB_TREE Tree, ULONG MaxIndexSize, PINDEX_ROOT_ATTRIBUTE *IndexRoot, ULONG *Length)
Definition: btree.c:910
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS AddIndexRoot(PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PINDEX_ROOT_ATTRIBUTE NewIndexRoot, ULONG RootLength, PCWSTR Name, USHORT NameLength)
Definition: attrib.c:495
NTSTATUS AddFileName(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, PULONGLONG ParentMftIndex)
Definition: attrib.c:230
NTSTATUS AddStandardInformation(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:766
PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord(PDEVICE_EXTENSION DeviceExt)
Definition: create.c:818
struct FILENAME_ATTRIBUTE * PFILENAME_ATTRIBUTE
#define FRH_DIRECTORY
Definition: ntfs.h:268
#define TAG_NTFS
Definition: ntfs.h:12
#define ULONG_PTR
Definition: config.h:101
NTSTATUS NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, ULONGLONG FileReferenceNumber, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
Definition: mft.c:2192
NTSTATUS AddNewMftEntry(PFILE_RECORD_HEADER FileRecord, PDEVICE_EXTENSION DeviceExt, PULONGLONG DestinationIndex, BOOLEAN CanWait)
Definition: mft.c:2022
VOID NtfsDumpFileRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:3334
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define L(x)
Definition: ntvdm.h:50
Definition: ntfs.h:454
ULONG Length
Definition: ntfs.h:127
struct NTFS_ATTR_RECORD::@175::@177 Resident
USHORT SequenceNumber
Definition: ntfs.h:253
USHORT Flags
Definition: ntfs.h:256
USHORT AttributeOffset
Definition: ntfs.h:255
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550

Referenced by NtfsCreateFile().

◆ NtfsCreateEmptyFileRecord()

PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord ( PDEVICE_EXTENSION  DeviceExt)

Definition at line 818 of file create.c.

819{
820 PFILE_RECORD_HEADER FileRecord;
821 PNTFS_ATTR_RECORD NextAttribute;
822
823 DPRINT("NtfsCreateEmptyFileRecord(%p)\n", DeviceExt);
824
825 // allocate memory for file record
826 FileRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
827 if (!FileRecord)
828 {
829 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
830 return NULL;
831 }
832
833 RtlZeroMemory(FileRecord, DeviceExt->NtfsInfo.BytesPerFileRecord);
834
835 FileRecord->Ntfs.Type = NRH_FILE_TYPE;
836
837 // calculate USA offset and count
838 FileRecord->Ntfs.UsaOffset = FIELD_OFFSET(FILE_RECORD_HEADER, MFTRecordNumber) + sizeof(ULONG);
839
840 // size of USA (in ULONG's) will be 1 (for USA number) + 1 for every sector the file record uses
841 FileRecord->BytesAllocated = DeviceExt->NtfsInfo.BytesPerFileRecord;
842 FileRecord->Ntfs.UsaCount = (FileRecord->BytesAllocated / DeviceExt->NtfsInfo.BytesPerSector) + 1;
843
844 // setup other file record fields
845 FileRecord->SequenceNumber = 1;
846 FileRecord->AttributeOffset = FileRecord->Ntfs.UsaOffset + (2 * FileRecord->Ntfs.UsaCount);
848 FileRecord->Flags = FRH_IN_USE;
849 FileRecord->BytesInUse = FileRecord->AttributeOffset + sizeof(ULONG) * 2;
850
851 // find where the first attribute will be added
852 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
853
854 // mark the (temporary) end of the file-record
855 NextAttribute->Type = AttributeEnd;
856 NextAttribute->Length = FILE_RECORD_END;
857
858 return FileRecord;
859}
#define ALIGN_UP_BY(size, align)
#define NULL
Definition: types.h:112
#define NRH_FILE_TYPE
Definition: ntfs.h:246
#define FILE_RECORD_END
Definition: ntfs.h:182
@ AttributeEnd
Definition: ntfs.h:177
#define ATTR_RECORD_ALIGNMENT
Definition: ntfs.h:320
#define FRH_IN_USE
Definition: ntfs.h:267
ULONG Type
Definition: ntfs.h:126
USHORT UsaCount
Definition: ntfs.h:241
USHORT UsaOffset
Definition: ntfs.h:240
NTFS_RECORD_HEADER Ntfs
Definition: ntfs.h:252
ULONG BytesInUse
Definition: ntfs.h:257
ULONG BytesAllocated
Definition: ntfs.h:258
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by IncreaseMftSize(), NtfsCreateDirectory(), and NtfsCreateFileRecord().

◆ NtfsCreateFile()

static NTSTATUS NtfsCreateFile ( PDEVICE_OBJECT  DeviceObject,
PNTFS_IRP_CONTEXT  IrpContext 
)
static

Definition at line 328 of file create.c.

330{
331 PDEVICE_EXTENSION DeviceExt;
334 ULONG RequestedDisposition;
335 ULONG RequestedOptions;
337// PWSTR FileName;
339 UNICODE_STRING FullPath;
340 PIRP Irp = IrpContext->Irp;
341
342 DPRINT("NtfsCreateFile(%p, %p) called\n", DeviceObject, IrpContext);
343
344 DeviceExt = DeviceObject->DeviceExtension;
345 ASSERT(DeviceExt);
347 ASSERT(Stack);
348
349 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
350 RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
351// PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
352 if (RequestedOptions & FILE_DIRECTORY_FILE &&
353 RequestedDisposition == FILE_SUPERSEDE)
354 {
356 }
357
358 /* Deny create if the volume is locked */
359 if (DeviceExt->Flags & VCB_VOLUME_LOCKED)
360 {
362 }
363
364 FileObject = Stack->FileObject;
365
366 if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID)
367 {
368 ULONGLONG MFTId;
369
370 if (FileObject->FileName.Length != sizeof(ULONGLONG))
372
373 MFTId = (*(PULONGLONG)FileObject->FileName.Buffer) & NTFS_MFT_MASK;
374 if (MFTId < NTFS_FILE_FIRST_USER_FILE)
375 {
376 Status = NtfsOpenFileById(DeviceExt, FileObject, MFTId, &Fcb);
377 }
378 else
379 {
380 Status = NtfsMoonWalkID(DeviceExt, MFTId, &FullPath);
381 }
382
383 if (!NT_SUCCESS(Status))
384 {
385 return Status;
386 }
387
388 DPRINT1("Open by ID: %I64x -> %wZ\n", (*(PULONGLONG)FileObject->FileName.Buffer) & NTFS_MFT_MASK, &FullPath);
389 }
390
391 /* This a open operation for the volume itself */
392 if (FileObject->FileName.Length == 0 &&
393 (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
394 {
395 if (RequestedDisposition != FILE_OPEN &&
396 RequestedDisposition != FILE_OPEN_IF)
397 {
399 }
400
401 if (RequestedOptions & FILE_DIRECTORY_FILE)
402 {
404 }
405
406 NtfsAttachFCBToFileObject(DeviceExt, DeviceExt->VolumeFcb, FileObject);
407 DeviceExt->VolumeFcb->RefCount++;
408
409 Irp->IoStatus.Information = FILE_OPENED;
410 return STATUS_SUCCESS;
411 }
412
413 if (Fcb == NULL)
414 {
415 Status = NtfsOpenFile(DeviceExt,
417 ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
419 &Fcb);
420
421 if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
422 {
424 }
425 }
426
427 if (NT_SUCCESS(Status))
428 {
429 if (RequestedDisposition == FILE_CREATE)
430 {
431 Irp->IoStatus.Information = FILE_EXISTS;
432 NtfsCloseFile(DeviceExt, FileObject);
434 }
435
436 if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
438 {
439 NtfsCloseFile(DeviceExt, FileObject);
441 }
442
443 if (RequestedOptions & FILE_DIRECTORY_FILE &&
445 {
446 NtfsCloseFile(DeviceExt, FileObject);
448 }
449
450 /*
451 * If it is a reparse point & FILE_OPEN_REPARSE_POINT, then allow opening it
452 * as a normal file.
453 * Otherwise, attempt to read reparse data and hand them to the Io manager
454 * with status reparse to force a reparse.
455 */
457 ((RequestedOptions & FILE_OPEN_REPARSE_POINT) != FILE_OPEN_REPARSE_POINT))
458 {
459 PREPARSE_DATA_BUFFER ReparseData = NULL;
460
461 Status = NtfsReadFCBAttribute(DeviceExt, Fcb,
463 (PVOID *)&Irp->Tail.Overlay.AuxiliaryBuffer);
464 if (NT_SUCCESS(Status))
465 {
466 ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
468 {
470 }
471 else
472 {
474 ExFreePoolWithTag(ReparseData, TAG_NTFS);
475 }
476 }
477
478 Irp->IoStatus.Information = ((Status == STATUS_REPARSE) ? ReparseData->ReparseTag : 0);
479
480 NtfsCloseFile(DeviceExt, FileObject);
481 return Status;
482 }
483
484 if (RequestedDisposition == FILE_OVERWRITE ||
485 RequestedDisposition == FILE_OVERWRITE_IF ||
486 RequestedDisposition == FILE_SUPERSEDE)
487 {
488 PFILE_RECORD_HEADER fileRecord = NULL;
489 PNTFS_ATTR_CONTEXT dataContext = NULL;
490 ULONG DataAttributeOffset;
492 Zero.QuadPart = 0;
493
495 {
496 DPRINT1("NTFS write-support is EXPERIMENTAL and is disabled by default!\n");
497 NtfsCloseFile(DeviceExt, FileObject);
499 }
500
501 // TODO: check for appropriate access
502
504
505 fileRecord = ExAllocateFromNPagedLookasideList(&Fcb->Vcb->FileRecLookasideList);
506 if (fileRecord)
507 {
508
510 Fcb->MFTIndex,
511 fileRecord);
512 if (!NT_SUCCESS(Status))
513 goto DoneOverwriting;
514
515 // find the data attribute and set it's length to 0 (TODO: Handle Alternate Data Streams)
516 Status = FindAttribute(Fcb->Vcb, fileRecord, AttributeData, L"", 0, &dataContext, &DataAttributeOffset);
517 if (!NT_SUCCESS(Status))
518 goto DoneOverwriting;
519
520 Status = SetAttributeDataLength(FileObject, Fcb, dataContext, DataAttributeOffset, fileRecord, &Zero);
521 }
522 else
523 {
525 }
526
527 DoneOverwriting:
528 if (fileRecord)
529 ExFreeToNPagedLookasideList(&Fcb->Vcb->FileRecLookasideList, fileRecord);
530 if (dataContext)
531 ReleaseAttributeContext(dataContext);
532
534
535 if (!NT_SUCCESS(Status))
536 {
537 NtfsCloseFile(DeviceExt, FileObject);
538 return Status;
539 }
540
541 if (RequestedDisposition == FILE_SUPERSEDE)
542 {
543 Irp->IoStatus.Information = FILE_SUPERSEDED;
544 }
545 else
546 {
547 Irp->IoStatus.Information = FILE_OVERWRITTEN;
548 }
549 }
550 }
551 else
552 {
553 /* HUGLY HACK: Can't create new files yet... */
554 if (RequestedDisposition == FILE_CREATE ||
555 RequestedDisposition == FILE_OPEN_IF ||
556 RequestedDisposition == FILE_OVERWRITE_IF ||
557 RequestedDisposition == FILE_SUPERSEDE)
558 {
560 {
561 DPRINT1("NTFS write-support is EXPERIMENTAL and is disabled by default!\n");
562 NtfsCloseFile(DeviceExt, FileObject);
564 }
565
566 // Was the user trying to create a directory?
567 if (RequestedOptions & FILE_DIRECTORY_FILE)
568 {
569 // Create the directory on disk
570 Status = NtfsCreateDirectory(DeviceExt,
574 }
575 else
576 {
577 // Create the file record on disk
578 Status = NtfsCreateFileRecord(DeviceExt,
582 }
583
584 if (!NT_SUCCESS(Status))
585 {
586 DPRINT1("ERROR: Couldn't create file record!\n");
587 return Status;
588 }
589
590 // Before we open the file/directory we just created, we need to change the disposition (upper 8 bits of ULONG)
591 // from create to open, since we already created the file
592 Stack->Parameters.Create.Options = (ULONG)FILE_OPEN << 24 | RequestedOptions;
593
594 // Now we should be able to open the file using NtfsCreateFile()
595 Status = NtfsCreateFile(DeviceObject, IrpContext);
596 if (NT_SUCCESS(Status))
597 {
598 // We need to change Irp->IoStatus.Information to reflect creation
599 Irp->IoStatus.Information = FILE_CREATED;
600 }
601 return Status;
602 }
603 }
604
605 if (NT_SUCCESS(Status))
606 {
608 DeviceExt->OpenHandleCount++;
609 }
610
611 /*
612 * If the directory containing the file to open doesn't exist then
613 * fail immediately
614 */
615 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
616
617 return Status;
618}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define NTFS_MFT_MASK
Definition: ntfs.h:68
_In_ PFCB Fcb
Definition: cdprocs.h:159
_In_ PIRP Irp
Definition: csq.h:116
NTSTATUS NtfsCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
Definition: close.c:40
static NTSTATUS NtfsOpenFileById(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, ULONGLONG MftId, PNTFS_FCB *FoundFCB)
Definition: create.c:175
static NTSTATUS NtfsOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PWSTR FileName, BOOLEAN CaseSensitive, PNTFS_FCB *FoundFCB)
Definition: create.c:242
static NTSTATUS NtfsMoonWalkID(PDEVICE_EXTENSION DeviceExt, ULONGLONG Id, PUNICODE_STRING OutPath)
Definition: create.c:104
NTSTATUS NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
Definition: create.c:886
NTSTATUS NtfsCreateDirectory(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
Definition: create.c:681
#define NTFS_FILE_FIRST_USER_FILE
Definition: ntfs.h:196
@ AttributeReparsePoint
Definition: ntfs.h:172
@ AttributeData
Definition: ntfs.h:168
#define VCB_VOLUME_LOCKED
Definition: ext2fs.h:789
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:418
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_OVERWRITE
Definition: from_kernel.h:57
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SUPERSEDE
Definition: from_kernel.h:53
if(dx< 0)
Definition: linetemp.h:194
NTSTATUS ReadFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG index, PFILE_RECORD_HEADER file)
Definition: mft.c:1631
VOID ReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: mft.c:104
NTSTATUS FindAttribute(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, ULONG Type, PCWSTR Name, ULONG NameLength, PNTFS_ATTR_CONTEXT *AttrCtx, PULONG Offset)
Definition: mft.c:131
NTSTATUS SetAttributeDataLength(PFILE_OBJECT FileObject, PNTFS_FCB Fcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize)
Definition: mft.c:615
#define ASSERT(a)
Definition: mode.c:44
#define FILE_CREATED
Definition: nt_native.h:770
#define FILE_OVERWRITTEN
Definition: nt_native.h:771
#define FILE_SUPERSEDED
Definition: nt_native.h:768
#define FILE_EXISTS
Definition: nt_native.h:772
#define FILE_VALID_OPTION_FLAGS
Definition: nt_native.h:759
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
BOOLEAN NtfsFCBIsDirectory(PNTFS_FCB Fcb)
Definition: fcb.c:132
NTSTATUS NtfsReadFCBAttribute(PNTFS_VCB Vcb, PNTFS_FCB pFCB, ULONG Type, PCWSTR Name, ULONG NameLength, PVOID *Data)
Definition: fcb.c:735
BOOLEAN NtfsFCBIsReparsePoint(PNTFS_FCB Fcb)
Definition: fcb.c:139
NTSTATUS NtfsAttachFCBToFileObject(PNTFS_VCB Vcb, PNTFS_FCB Fcb, PFILE_OBJECT FileObject)
Definition: fcb.c:464
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
struct _REPARSE_DATA_BUFFER * PREPARSE_DATA_BUFFER
BOOLEAN EnableWriteSupport
Definition: ntfs.h:155
Definition: cdstruc.h:902
PVCB Vcb
Definition: cdstruc.h:933
ULONGLONG MFTIndex
Definition: ntfs.h:539
ULONG OpenHandleCount
Definition: ntfs.h:537
ERESOURCE MainResource
Definition: ntfs.h:528
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231
#define SL_CASE_SENSITIVE
Definition: iotypes.h:1820

Referenced by NtfsCreate(), and NtfsCreateFile().

◆ NtfsCreateFileRecord()

NTSTATUS NtfsCreateFileRecord ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
BOOLEAN  CaseSensitive,
BOOLEAN  CanWait 
)

Definition at line 886 of file create.c.

890{
892 PFILE_RECORD_HEADER FileRecord;
893 PNTFS_ATTR_RECORD NextAttribute;
894 PFILENAME_ATTRIBUTE FilenameAttribute;
895 ULONGLONG ParentMftIndex;
896 ULONGLONG FileMftIndex;
897
898 DPRINT("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
899 DeviceExt,
901 CaseSensitive ? "TRUE" : "FALSE",
902 CanWait ? "TRUE" : "FALSE");
903
904 // allocate memory for file record
905 FileRecord = NtfsCreateEmptyFileRecord(DeviceExt);
906 if (!FileRecord)
907 {
908 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
910 }
911
912 // find where the first attribute will be added
913 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
914
915 // add first attribute, $STANDARD_INFORMATION
916 AddStandardInformation(FileRecord, NextAttribute);
917
918 // advance NextAttribute pointer to the next attribute
919 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
920
921 // Add the $FILE_NAME attribute
922 AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject, CaseSensitive, &ParentMftIndex);
923
924 // save a pointer to the filename attribute
925 FilenameAttribute = (PFILENAME_ATTRIBUTE)((ULONG_PTR)NextAttribute + NextAttribute->Resident.ValueOffset);
926
927 // advance NextAttribute pointer to the next attribute
928 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
929
930 // add the $DATA attribute
931 AddData(FileRecord, NextAttribute);
932
933#ifndef NDEBUG
934 // dump file record in memory (for debugging)
935 NtfsDumpFileRecord(DeviceExt, FileRecord);
936#endif
937
938 // Now that we've built the file record in memory, we need to store it in the MFT.
939 Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
940 if (NT_SUCCESS(Status))
941 {
942 // The highest 2 bytes should be the sequence number, unless the parent happens to be root
943 if (FileMftIndex == NTFS_FILE_ROOT)
944 FileMftIndex = FileMftIndex + ((ULONGLONG)NTFS_FILE_ROOT << 48);
945 else
946 FileMftIndex = FileMftIndex + ((ULONGLONG)FileRecord->SequenceNumber << 48);
947
948 DPRINT1("New File Reference: 0x%016I64x\n", FileMftIndex);
949
950 // Add the filename attribute to the filename-index of the parent directory
952 ParentMftIndex,
953 FileMftIndex,
954 FilenameAttribute,
955 CaseSensitive);
956 }
957
958 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
959
960 return Status;
961}
NTSTATUS AddData(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:160

Referenced by NtfsCreateFile().

◆ NtfsMakeAbsoluteFilename()

static NTSTATUS NtfsMakeAbsoluteFilename ( PFILE_OBJECT  pFileObject,
PWSTR  pRelativeFileName,
PWSTR pAbsoluteFilename 
)
static

Definition at line 53 of file create.c.

56{
57 PWSTR rcName;
59
60 DPRINT("try related for %S\n", pRelativeFileName);
61 Fcb = pFileObject->FsContext;
62 ASSERT(Fcb);
63
64 if (Fcb->Flags & FCB_IS_VOLUME)
65 {
66 /* This is likely to be an opening by ID, return ourselves */
67 if (pRelativeFileName[0] == L'\\')
68 {
69 *pAbsoluteFilename = NULL;
70 return STATUS_SUCCESS;
71 }
72
74 }
75
76 /* verify related object is a directory and target name
77 don't start with \. */
79 pRelativeFileName[0] == L'\\')
80 {
82 }
83
84 /* construct absolute path name */
85 ASSERT(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 <= MAX_PATH);
87 if (!rcName)
88 {
90 }
91
92 wcscpy(rcName, Fcb->PathName);
93 if (!NtfsFCBIsRoot(Fcb))
94 wcscat (rcName, L"\\");
95 wcscat (rcName, pRelativeFileName);
96 *pAbsoluteFilename = rcName;
97
98 return STATUS_SUCCESS;
99}
#define FALSE
Definition: types.h:117
#define MAX_PATH
Definition: compat.h:34
#define FCB_IS_VOLUME
Definition: ntfs.h:510
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
BOOLEAN NtfsFCBIsRoot(PNTFS_FCB Fcb)
Definition: fcb.c:158
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
ULONG Flags
Definition: ntfs.h:536
WCHAR PathName[MAX_PATH]
Definition: ntfs.h:525
uint16_t * PWSTR
Definition: typedefs.h:56
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by NtfsOpenFile().

◆ NtfsMoonWalkID()

static NTSTATUS NtfsMoonWalkID ( PDEVICE_EXTENSION  DeviceExt,
ULONGLONG  Id,
PUNICODE_STRING  OutPath 
)
static

Definition at line 104 of file create.c.

107{
109 PFILE_RECORD_HEADER MftRecord;
111 WCHAR FullPath[MAX_PATH];
112 ULONG WritePosition = MAX_PATH - 1;
113
114 DPRINT("NtfsMoonWalkID(%p, %I64x, %p)\n", DeviceExt, Id, OutPath);
115
116 RtlZeroMemory(FullPath, sizeof(FullPath));
117 MftRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
118 if (MftRecord == NULL)
119 {
121 }
122
123 while (TRUE)
124 {
125 Status = ReadFileRecord(DeviceExt, Id, MftRecord);
126 if (!NT_SUCCESS(Status))
127 break;
128
129 ASSERT(MftRecord->Ntfs.Type == NRH_FILE_TYPE);
130 if (!(MftRecord->Flags & FRH_IN_USE))
131 {
133 break;
134 }
135
136 FileName = GetBestFileNameFromRecord(DeviceExt, MftRecord);
137 if (FileName == NULL)
138 {
139 DPRINT1("$FILE_NAME attribute not found for %I64x\n", Id);
141 break;
142 }
143
144 WritePosition -= FileName->NameLength;
145 ASSERT(WritePosition < MAX_PATH);
146 RtlCopyMemory(FullPath + WritePosition, FileName->Name, FileName->NameLength * sizeof(WCHAR));
147 WritePosition -= 1;
148 ASSERT(WritePosition < MAX_PATH);
149 FullPath[WritePosition] = L'\\';
150
151 Id = FileName->DirectoryFileReferenceNumber & NTFS_MFT_MASK;
152 if (Id == NTFS_FILE_ROOT)
153 break;
154 }
155
156 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
157
158 if (!NT_SUCCESS(Status))
159 return Status;
160
161 OutPath->Length = (MAX_PATH - WritePosition - 1) * sizeof(WCHAR);
162 OutPath->MaximumLength = (MAX_PATH - WritePosition) * sizeof(WCHAR);
164 if (OutPath->Buffer == NULL)
165 {
167 }
168 RtlCopyMemory(OutPath->Buffer, FullPath + WritePosition, OutPath->MaximumLength);
169
170 return Status;
171}
DWORD Id
PFILENAME_ATTRIBUTE GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:1985
struct _FileName FileName
Definition: fatprocs.h:896
TCHAR Name[MAX_PATH]
Definition: filecomp.c:349
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151

Referenced by NtfsCreateFile().

◆ NtfsOpenFile()

static NTSTATUS NtfsOpenFile ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
PWSTR  FileName,
BOOLEAN  CaseSensitive,
PNTFS_FCB FoundFCB 
)
static

Definition at line 242 of file create.c.

247{
251 PWSTR AbsFileName = NULL;
252
253 DPRINT("NtfsOpenFile(%p, %p, %S, %s, %p)\n",
254 DeviceExt,
256 FileName,
257 CaseSensitive ? "TRUE" : "FALSE",
258 FoundFCB);
259
260 *FoundFCB = NULL;
261
262 if (FileObject->RelatedFileObject)
263 {
264 DPRINT("Converting relative filename to absolute filename\n");
265
266 Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
267 FileName,
268 &AbsFileName);
269 if (AbsFileName) FileName = AbsFileName;
270 if (!NT_SUCCESS(Status))
271 {
272 return Status;
273 }
274 }
275
276 //FIXME: Get canonical path name (remove .'s, ..'s and extra separators)
277
278 DPRINT("PathName to open: %S\n", FileName);
279
280 /* try first to find an existing FCB in memory */
281 DPRINT("Checking for existing FCB in memory\n");
282 Fcb = NtfsGrabFCBFromTable(DeviceExt,
283 FileName);
284 if (Fcb == NULL)
285 {
286 DPRINT("No existing FCB found, making a new one if file exists.\n");
287 Status = NtfsGetFCBForFile(DeviceExt,
288 &ParentFcb,
289 &Fcb,
290 FileName,
291 CaseSensitive);
292 if (ParentFcb != NULL)
293 {
294 NtfsReleaseFCB(DeviceExt,
295 ParentFcb);
296 }
297
298 if (!NT_SUCCESS(Status))
299 {
300 DPRINT("Could not make a new FCB, status: %x\n", Status);
301
302 if (AbsFileName)
303 ExFreePoolWithTag(AbsFileName, TAG_NTFS);
304
305 return Status;
306 }
307 }
308
309 DPRINT("Attaching FCB to fileObject\n");
311 Fcb,
312 FileObject);
313
314 if (AbsFileName)
315 ExFreePool(AbsFileName);
316
317 *FoundFCB = Fcb;
318
319 return Status;
320}
_In_ PFCB ParentFcb
Definition: cdprocs.h:736
static NTSTATUS NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject, PWSTR pRelativeFileName, PWSTR *pAbsoluteFilename)
Definition: create.c:53
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
PNTFS_FCB NtfsGrabFCBFromTable(PNTFS_VCB Vcb, PCWSTR FileName)
Definition: fcb.c:222
NTSTATUS NtfsGetFCBForFile(PNTFS_VCB Vcb, PNTFS_FCB *pParentFCB, PNTFS_FCB *pFCB, PCWSTR pFileName, BOOLEAN CaseSensitive)
Definition: fcb.c:603
VOID NtfsReleaseFCB(PNTFS_VCB Vcb, PNTFS_FCB Fcb)
Definition: fcb.c:182

Referenced by NtfsCreateFile().

◆ NtfsOpenFileById()

static NTSTATUS NtfsOpenFileById ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
ULONGLONG  MftId,
PNTFS_FCB FoundFCB 
)
static

Definition at line 175 of file create.c.

179{
182 PFILE_RECORD_HEADER MftRecord;
183
184 DPRINT("NtfsOpenFileById(%p, %p, %I64x, %p)\n", DeviceExt, FileObject, MftId, FoundFCB);
185
187 if (MftId > 0xb) /* No entries are used yet beyond this */
188 {
190 }
191
192 MftRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
193 if (MftRecord == NULL)
194 {
196 }
197
198 Status = ReadFileRecord(DeviceExt, MftId, MftRecord);
199 if (!NT_SUCCESS(Status))
200 {
201 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
202 return Status;
203 }
204
205 if (!(MftRecord->Flags & FRH_IN_USE))
206 {
207 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
209 }
210
211 FCB = NtfsGrabFCBFromTable(DeviceExt, MftIdToName[MftId]);
212 if (FCB == NULL)
213 {
215
217 Status = NtfsMakeFCBFromDirEntry(DeviceExt, NULL, &Name, NULL, MftRecord, MftId, &FCB);
218 if (!NT_SUCCESS(Status))
219 {
220 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
221 return Status;
222 }
223 }
224
225 ASSERT(FCB != NULL);
226
227 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, MftRecord);
228
230 FCB,
231 FileObject);
232 *FoundFCB = FCB;
233
234 return Status;
235}
struct NameRec_ * Name
Definition: cdprocs.h:460
struct _FCB FCB
static PCWSTR MftIdToName[]
Definition: create.c:34
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb, PNTFS_FCB DirectoryFCB, PUNICODE_STRING Name, PCWSTR Stream, PFILE_RECORD_HEADER Record, ULONGLONG MFTIndex, PNTFS_FCB *fileFCB)
Definition: fcb.c:389
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149

Referenced by NtfsCreateFile().

Variable Documentation

◆ MftIdToName

PCWSTR MftIdToName[]
static
Initial value:
= {
L"$MFT",
L"$MFTMirr",
L"$LogFile",
L"$Volume",
L"AttrDef",
L".",
L"$Bitmap",
L"$Boot",
L"$BadClus",
L"$Quota",
L"$UpCase",
L"$Extended",
}

Definition at line 34 of file create.c.

Referenced by NtfsOpenFileById().