ReactOS 0.4.15-dev-7924-g5949c20
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
34static 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
51static
54 PWSTR pRelativeFileName,
55 PWSTR *pAbsoluteFilename)
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}
100
101
102static
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
173static
177 ULONGLONG MftId,
178 PNTFS_FCB * FoundFCB)
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}
236
237/*
238 * FUNCTION: Opens a file
239 */
240static
245 BOOLEAN CaseSensitive,
246 PNTFS_FCB * FoundFCB)
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}
321
322
323/*
324 * FUNCTION: Opens a file
325 */
326static
329 PNTFS_IRP_CONTEXT IrpContext)
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}
619
620
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
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;
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}
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
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,
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 */
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
DWORD Id
CRegistryTree Tree
#define ALIGN_UP_BY(size, align)
unsigned char BOOLEAN
struct NameRec_ * Name
Definition: cdprocs.h:460
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define DPRINT1
Definition: precomp.h:8
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
#define NTFS_MFT_MASK
Definition: ntfs.h:68
#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
_In_ PFCB ParentFcb
Definition: cdprocs.h:736
_In_ PFCB Fcb
Definition: cdprocs.h:159
struct _FCB FCB
_In_ PIRP Irp
Definition: csq.h:116
#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:32
#define MAX_PATH
Definition: compat.h:34
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 AddData(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:160
PFILENAME_ATTRIBUTE GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:1985
NTSTATUS AddStandardInformation(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:766
NTSTATUS NtfsCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
Definition: close.c:40
static NTSTATUS NtfsCreateFile(PDEVICE_OBJECT DeviceObject, PNTFS_IRP_CONTEXT IrpContext)
Definition: create.c:328
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
static NTSTATUS NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject, PWSTR pRelativeFileName, PWSTR *pAbsoluteFilename)
Definition: create.c:53
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
NTSTATUS NtfsCreate(PNTFS_IRP_CONTEXT IrpContext)
Definition: create.c:622
static PCWSTR MftIdToName[]
Definition: create.c:34
PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord(PDEVICE_EXTENSION DeviceExt)
Definition: create.c:818
PNTFS_GLOBAL_DATA NtfsGlobalData
Definition: ntfs.c:36
FORCEINLINE NTSTATUS NtfsMarkIrpContextForQueue(PNTFS_IRP_CONTEXT IrpContext)
Definition: ntfs.h:569
struct FILENAME_ATTRIBUTE * PFILENAME_ATTRIBUTE
#define NRH_FILE_TYPE
Definition: ntfs.h:246
#define FRH_DIRECTORY
Definition: ntfs.h:268
#define NTFS_FILE_FIRST_USER_FILE
Definition: ntfs.h:196
#define IRPCONTEXT_CANWAIT
Definition: ntfs.h:474
#define FILE_RECORD_END
Definition: ntfs.h:182
@ AttributeEnd
Definition: ntfs.h:177
@ AttributeReparsePoint
Definition: ntfs.h:172
@ AttributeData
Definition: ntfs.h:168
#define TAG_NTFS
Definition: ntfs.h:12
#define ATTR_RECORD_ALIGNMENT
Definition: ntfs.h:320
#define FCB_IS_VOLUME
Definition: ntfs.h:510
#define FRH_IN_USE
Definition: ntfs.h:267
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define NonPagedPool
Definition: env_spec_w32.h:307
#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
struct _FileName FileName
Definition: fatprocs.h:896
#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
Status
Definition: gdiplustypes.h:25
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
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 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
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 ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#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
#define FILE_OPENED
Definition: nt_native.h:769
__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
PNTFS_FCB NtfsGrabFCBFromTable(PNTFS_VCB Vcb, PCWSTR FileName)
Definition: fcb.c:222
BOOLEAN NtfsFCBIsRoot(PNTFS_FCB Fcb)
Definition: fcb.c:158
BOOLEAN NtfsFCBIsReparsePoint(PNTFS_FCB Fcb)
Definition: fcb.c:139
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
NTSTATUS NtfsAttachFCBToFileObject(PNTFS_VCB Vcb, PNTFS_FCB Fcb, PFILE_OBJECT FileObject)
Definition: fcb.c:464
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
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define L(x)
Definition: ntvdm.h:50
_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)
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _REPARSE_DATA_BUFFER * PREPARSE_DATA_BUFFER
#define DPRINT
Definition: sndvol32.h:71
Definition: ntfs.h:454
ULONG Length
Definition: ntfs.h:127
struct NTFS_ATTR_RECORD::@175::@177 Resident
ULONG Type
Definition: ntfs.h:126
BOOLEAN EnableWriteSupport
Definition: ntfs.h:155
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:148
ULONG Flags
Definition: ntfs.h:481
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:488
USHORT UsaCount
Definition: ntfs.h:241
USHORT UsaOffset
Definition: ntfs.h:240
Definition: cdstruc.h:902
ULONG Flags
Definition: ntfs.h:536
PVCB Vcb
Definition: cdstruc.h:933
ULONGLONG MFTIndex
Definition: ntfs.h:539
WCHAR PathName[MAX_PATH]
Definition: ntfs.h:525
ULONG OpenHandleCount
Definition: ntfs.h:537
ERESOURCE MainResource
Definition: ntfs.h:528
USHORT SequenceNumber
Definition: ntfs.h:253
USHORT Flags
Definition: ntfs.h:256
NTFS_RECORD_HEADER Ntfs
Definition: ntfs.h:252
USHORT AttributeOffset
Definition: ntfs.h:255
ULONG BytesInUse
Definition: ntfs.h:257
ULONG BytesAllocated
Definition: ntfs.h:258
TCHAR Name[MAX_PATH]
Definition: filecomp.c:349
IO_STATUS_BLOCK IoStatus
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#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_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_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
__wchar_t WCHAR
Definition: xmlstorage.h:180