ReactOS  0.4.14-dev-358-gbef841c
create.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2002, 2014 ReactOS Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * COPYRIGHT: See COPYING in the top level directory
20  * PROJECT: ReactOS kernel
21  * FILE: drivers/filesystem/ntfs/create.c
22  * PURPOSE: NTFS filesystem driver
23  * PROGRAMMERS: Eric Kohl
24  * Pierre Schweitzer (pierre@reactos.org)
25  */
26 
27 /* INCLUDES *****************************************************************/
28 
29 #include "ntfs.h"
30 
31 #define NDEBUG
32 #include <debug.h>
33 
34 static PCWSTR MftIdToName[] = {
35  L"$MFT",
36  L"$MFTMirr",
37  L"$LogFile",
38  L"$Volume",
39  L"AttrDef",
40  L".",
41  L"$Bitmap",
42  L"$Boot",
43  L"$BadClus",
44  L"$Quota",
45  L"$UpCase",
46  L"$Extended",
47 };
48 
49 /* FUNCTIONS ****************************************************************/
50 
51 static
54  PWSTR pRelativeFileName,
55  PWSTR *pAbsoluteFilename)
56 {
57  PWSTR rcName;
58  PNTFS_FCB Fcb;
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 \. */
78  if (NtfsFCBIsDirectory(Fcb) == FALSE ||
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 }
100 
101 
102 static
103 NTSTATUS
105  ULONGLONG Id,
106  PUNICODE_STRING OutPath)
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 }
172 
173 static
174 NTSTATUS
177  ULONGLONG MftId,
178  PNTFS_FCB * FoundFCB)
179 {
181  PNTFS_FCB FCB;
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 
229  Status = NtfsAttachFCBToFileObject(DeviceExt,
230  FCB,
231  FileObject);
232  *FoundFCB = FCB;
233 
234  return Status;
235 }
236 
237 /*
238  * FUNCTION: Opens a file
239  */
240 static
241 NTSTATUS
244  PWSTR FileName,
245  BOOLEAN CaseSensitive,
246  PNTFS_FCB * FoundFCB)
247 {
249  PNTFS_FCB Fcb;
251  PWSTR AbsFileName = NULL;
252 
253  DPRINT("NtfsOpenFile(%p, %p, %S, %s, %p)\n",
254  DeviceExt,
255  FileObject,
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");
310  Status = NtfsAttachFCBToFileObject(DeviceExt,
311  Fcb,
312  FileObject);
313 
314  if (AbsFileName)
315  ExFreePool(AbsFileName);
316 
317  *FoundFCB = Fcb;
318 
319  return Status;
320 }
321 
322 
323 /*
324  * FUNCTION: Opens a file
325  */
326 static
327 NTSTATUS
329  PNTFS_IRP_CONTEXT IrpContext)
330 {
331  PDEVICE_EXTENSION DeviceExt;
332  PIO_STACK_LOCATION Stack;
334  ULONG RequestedDisposition;
335  ULONG RequestedOptions;
336  PNTFS_FCB Fcb = NULL;
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  {
361  return STATUS_ACCESS_DENIED;
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 
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  {
398  return STATUS_ACCESS_DENIED;
399  }
400 
401  if (RequestedOptions & FILE_DIRECTORY_FILE)
402  {
403  return STATUS_NOT_A_DIRECTORY;
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,
416  FileObject,
417  ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
419  &Fcb);
420 
421  if (RequestedOptions & FILE_OPEN_BY_FILE_ID)
422  {
423  ExFreePoolWithTag(FullPath.Buffer, TAG_NTFS);
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);
447  return STATUS_NOT_A_DIRECTORY;
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  */
456  if (NtfsFCBIsReparsePoint(Fcb) &&
457  ((RequestedOptions & FILE_OPEN_REPARSE_POINT) != FILE_OPEN_REPARSE_POINT))
458  {
459  PREPARSE_DATA_BUFFER ReparseData = NULL;
460 
461  Status = NtfsReadFCBAttribute(DeviceExt, Fcb,
462  AttributeReparsePoint, L"", 0,
463  (PVOID *)&Irp->Tail.Overlay.AuxiliaryBuffer);
464  if (NT_SUCCESS(Status))
465  {
466  ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
467  if (ReparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
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);
498  return STATUS_ACCESS_DENIED;
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);
563  return STATUS_ACCESS_DENIED;
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,
571  FileObject,
573  BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT));
574  }
575  else
576  {
577  // Create the file record on disk
578  Status = NtfsCreateFileRecord(DeviceExt,
579  FileObject,
581  BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT));
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  {
607  Fcb->OpenHandleCount++;
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 }
619 
620 
621 NTSTATUS
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 }
652 
680 NTSTATUS
683  BOOLEAN CaseSensitive,
684  BOOLEAN CanWait)
685 {
686 
688  PFILE_RECORD_HEADER FileRecord;
689  PNTFS_ATTR_RECORD NextAttribute;
690  PFILENAME_ATTRIBUTE FilenameAttribute;
691  ULONGLONG ParentMftIndex;
692  ULONGLONG FileMftIndex;
693  PB_TREE Tree;
694  PINDEX_ROOT_ATTRIBUTE NewIndexRoot;
695  ULONG MaxIndexRootSize;
696  ULONG RootLength;
697 
698  DPRINT("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
699  DeviceExt,
700  FileObject,
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
748  Status = CreateIndexRootFromBTree(DeviceExt,
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 }
804 
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 }
860 
861 
885 NTSTATUS
888  BOOLEAN CaseSensitive,
889  BOOLEAN CanWait)
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,
900  FileObject,
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 }
962 
963 /* EOF */
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
VOID NtfsReleaseFCB(PNTFS_VCB Vcb, PNTFS_FCB Fcb)
Definition: fcb.c:171
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define NTFS_MFT_MASK
Definition: ntfs.h:198
#define FILE_EXISTS
Definition: nt_native.h:772
NTSTATUS NtfsCreateDirectory(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
Definition: create.c:681
PFILENAME_ATTRIBUTE GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:1985
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:484
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define SL_CASE_SENSITIVE
Definition: iotypes.h:1777
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define FILE_OPEN_IF
Definition: from_kernel.h:56
BOOLEAN NtfsFCBIsReparsePoint(PNTFS_FCB Fcb)
Definition: fcb.c:134
#define FILE_OVERWRITTEN
Definition: nt_native.h:771
static NTSTATUS NtfsOpenFileById(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, ULONGLONG MftId, PNTFS_FCB *FoundFCB)
Definition: create.c:175
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
USHORT MaximumLength
Definition: env_spec_w32.h:370
Iosb Status
Definition: create.c:4311
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
static NTSTATUS NtfsCreateFile(PDEVICE_OBJECT DeviceObject, PNTFS_IRP_CONTEXT IrpContext)
Definition: create.c:328
_In_ PIRP Irp
Definition: csq.h:116
Definition: cdstruc.h:908
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
uint16_t * PWSTR
Definition: typedefs.h:54
FORCEINLINE NTSTATUS NtfsMarkIrpContextForQueue(PNTFS_IRP_CONTEXT IrpContext)
Definition: ntfs.h:565
if(OpenRequiringOplock &&(Iosb.Status==STATUS_SUCCESS))
Definition: create.c:4324
NTSTATUS NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, ULONGLONG FileReferenceNumber, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
Definition: mft.c:2192
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
NTSTATUS AddStandardInformation(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:766
#define FILE_RECORD_END
Definition: ntfs.h:182
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_CREATE
Definition: from_kernel.h:55
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:378
#define FILE_OPENED
Definition: nt_native.h:769
#define FILE_SUPERSEDED
Definition: nt_native.h:768
ULONG BytesInUse
Definition: ntfs.h:253
PNTFS_FCB NtfsGrabFCBFromTable(PNTFS_VCB Vcb, PCWSTR FileName)
Definition: fcb.c:211
ULONG Type
Definition: ntfs.h:122
#define FILE_OVERWRITE
Definition: from_kernel.h:57
NTSTATUS NtfsCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
Definition: close.c:40
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
USHORT SequenceNumber
Definition: ntfs.h:249
WCHAR PathName[MAX_PATH]
Definition: ntfs.h:521
BOOLEAN NtfsFCBIsDirectory(PNTFS_FCB Fcb)
Definition: fcb.c:127
ULONGLONG MFTIndex
Definition: ntfs.h:535
static NTSTATUS NtfsOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PWSTR FileName, BOOLEAN CaseSensitive, PNTFS_FCB *FoundFCB)
Definition: create.c:242
NTSTATUS NtfsAttachFCBToFileObject(PNTFS_VCB Vcb, PNTFS_FCB Fcb, PFILE_OBJECT FileObject)
Definition: fcb.c:453
#define FILE_VALID_OPTION_FLAGS
Definition: nt_native.h:759
PNTFS_GLOBAL_DATA NtfsGlobalData
Definition: ntfs.c:41
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
static NTSTATUS NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject, PWSTR pRelativeFileName, PWSTR *pAbsoluteFilename)
Definition: create.c:53
DWORD Id
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:6875
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define FRH_IN_USE
Definition: ntfs.h:263
NTSTATUS NtfsGetFCBForFile(PNTFS_VCB Vcb, PNTFS_FCB *pParentFCB, PNTFS_FCB *pFCB, PCWSTR pFileName, BOOLEAN CaseSensitive)
Definition: fcb.c:592
NTSTATUS CreateEmptyBTree(PB_TREE *NewTree)
Definition: btree.c:348
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
NTSTATUS AddNewMftEntry(PFILE_RECORD_HEADER FileRecord, PDEVICE_EXTENSION DeviceExt, PULONGLONG DestinationIndex, BOOLEAN CanWait)
Definition: mft.c:2022
struct FILENAME_ATTRIBUTE * PFILENAME_ATTRIBUTE
ULONG Length
Definition: ntfs.h:123
USHORT AttributeOffset
Definition: ntfs.h:251
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT FileObject
Definition: create.c:4157
#define FRH_DIRECTORY
Definition: ntfs.h:264
struct NameRec_ * Name
Definition: cdprocs.h:464
NTSTATUS NtfsReadFCBAttribute(PNTFS_VCB Vcb, PNTFS_FCB pFCB, ULONG Type, PCWSTR Name, ULONG NameLength, PVOID *Data)
Definition: fcb.c:724
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
struct _FCB FCB
smooth NULL
Definition: ftsmooth.c:416
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define IRPCONTEXT_CANWAIT
Definition: vfat.h:569
void DPRINT(...)
Definition: polytest.cpp:61
NTSTATUS NtfsCreateFileRecord(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
Definition: create.c:886
NTSTATUS AddData(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:160
ULONG OpenHandleCount
Definition: ntfs.h:533
TCHAR Name[MAX_PATH]
Definition: filecomp.c:349
#define NTFS_FILE_FIRST_USER_FILE
Definition: ntfs.h:196
#define ATTR_RECORD_ALIGNMENT
Definition: ntfs.h:316
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static PCWSTR MftIdToName[]
Definition: create.c:34
ULONG BytesAllocated
Definition: ntfs.h:254
uint64_t ULONGLONG
Definition: typedefs.h:65
#define MAX_PATH
Definition: compat.h:26
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
CRegistryTree Tree
_In_ PFCB ParentFcb
Definition: cdprocs.h:741
#define TAG_NTFS
Definition: ntfs.h:12
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
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
ULONG Flags
Definition: ntfs.h:532
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSTATUS CreateIndexRootFromBTree(PDEVICE_EXTENSION DeviceExt, PB_TREE Tree, ULONG MaxIndexSize, PINDEX_ROOT_ATTRIBUTE *IndexRoot, ULONG *Length)
Definition: btree.c:910
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
VOID NtfsDumpFileRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:3334
static const WCHAR L[]
Definition: oid.c:1250
PUNICODE_STRING FileName
Definition: iotypes.h:2793
USHORT UsaCount
Definition: ntfs.h:237
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
ULONG Flags
Definition: ntfs.h:477
static NTSTATUS NtfsMoonWalkID(PDEVICE_EXTENSION DeviceExt, ULONGLONG Id, PUNICODE_STRING OutPath)
Definition: create.c:104
ERESOURCE MainResource
Definition: ntfs.h:524
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:148
Status
Definition: gdiplustypes.h:24
#define FILE_OPEN
Definition: from_kernel.h:54
VOID DestroyBTree(PB_TREE Tree)
Definition: btree.c:1542
#define FCB_IS_VOLUME
Definition: vfat.h:431
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord(PDEVICE_EXTENSION DeviceExt)
Definition: create.c:818
struct _FileName FileName
Definition: fatprocs.h:884
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
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 NtfsCreate(PNTFS_IRP_CONTEXT IrpContext)
Definition: create.c:622
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define STATUS_REPARSE
Definition: ntstatus.h:83
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
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
USHORT Flags
Definition: ntfs.h:252
Definition: ntfs.h:449
#define FILE_CREATED
Definition: nt_native.h:770
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:402
#define VCB_VOLUME_LOCKED
Definition: ext2fs.h:780
#define DPRINT1
Definition: precomp.h:8
NTSTATUS AddFileName(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, PULONGLONG ParentMftIndex)
Definition: attrib.c:230
#define NRH_FILE_TYPE
Definition: ntfs.h:242
NTFS_RECORD_HEADER Ntfs
Definition: ntfs.h:248
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
unsigned int ULONG
Definition: retypes.h:1
#define FILE_SUPERSEDE
Definition: from_kernel.h:53
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define ALIGN_UP_BY(size, align)
PVCB Vcb
Definition: cdstruc.h:939
USHORT UsaOffset
Definition: ntfs.h:236
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
_In_ PFCB Fcb
Definition: cdprocs.h:151
struct NTFS_ATTR_RECORD::@165::@167 Resident
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
BOOLEAN EnableWriteSupport
Definition: ntfs.h:155
HRESULT Create([out]ITransactionReceiver **ppReceiver)
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
BOOLEAN NtfsFCBIsRoot(PNTFS_FCB Fcb)
Definition: fcb.c:147
struct _REPARSE_DATA_BUFFER * PREPARSE_DATA_BUFFER
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NTFS_FILE_ROOT
Definition: ntfs.h:28