[REISERFS] Don't leak on failure
[reactos.git] / drivers / filesystems / reiserfs / src / create.c
1 /*
2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
4 * FILE: create.c
5 * PURPOSE:
6 * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
7 * HOMEPAGE:
8 * UPDATE HISTORY:
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include "rfsd.h"
14
15 /* GLOBALS *****************************************************************/
16
17 extern PRFSD_GLOBAL RfsdGlobal;
18
19 /* DEFINITIONS *************************************************************/
20
21 NTSTATUS
22 RfsdScanDirCallback(
23 ULONG BlockNumber,
24 PVOID pContext );
25
26 typedef struct _RFSD_SCANDIR_CALLBACK_CONTEXT {
27 IN PRFSD_VCB Vcb;
28 IN PRFSD_KEY_IN_MEMORY pDirectoryKey;
29 IN PUNICODE_STRING pTargetFilename;
30
31 ULONG idxCurrentDentry; /// Running count of the dentries processed, so that MatchingIndex will be relative to all dentry spans
32
33 OUT PRFSD_DENTRY_HEAD pMatchingDentry; /// If a matching dentry is found, the callback will fill this structure with it
34 OUT PULONG pMatchingIndex; /// Index of the matching entry (relative to all dentry spans for the directory)
35 } RFSD_SCANDIR_CALLBACK_CONTEXT, *PRFSD_SCANDIR_CALLBACK_CONTEXT;
36
37 #ifdef ALLOC_PRAGMA
38 #pragma alloc_text(PAGE, RfsdLookupFileName)
39 #pragma alloc_text(PAGE, RfsdScanDir)
40 #pragma alloc_text(PAGE, RfsdCreateFile)
41 #pragma alloc_text(PAGE, RfsdCreateVolume)
42 #pragma alloc_text(PAGE, RfsdCreate)
43 #if !RFSD_READ_ONLY
44 #pragma alloc_text(PAGE, RfsdCreateInode)
45 #pragma alloc_text(PAGE, RfsdSupersedeOrOverWriteFile)
46 #endif // !RFSD_READ_ONLY
47 #pragma alloc_text(PAGE, RfsdScanDirCallback)
48 #endif
49
50 NTSTATUS
51 RfsdLookupFileName (IN PRFSD_VCB Vcb,
52 IN PUNICODE_STRING FullFileName,
53 IN PRFSD_MCB ParentMcb,
54 OUT PRFSD_MCB * RfsdMcb,
55 IN OUT PRFSD_INODE Inode) // An allocated, but unfilled inode, to which the matching file's information will be put
56 {
57 NTSTATUS Status;
58 UNICODE_STRING FileName;
59 PRFSD_MCB Mcb = 0;
60
61 RFSD_DENTRY_HEAD DirectoryEntry;
62 int i = 0;
63 BOOLEAN bRun = TRUE;
64 BOOLEAN bParent = FALSE;
65 RFSD_INODE in;
66 ULONG off = 0;
67
68 PAGED_CODE();
69
70 Status = STATUS_OBJECT_NAME_NOT_FOUND;
71
72 *RfsdMcb = NULL;
73
74
75 // Determine the parent node
76 if (ParentMcb) {
77 // Looking up a file in the tree, starting at an arbitrary parent node.
78 bParent = TRUE;
79 } else if (FullFileName->Buffer[0] == L'\\') {
80 // Looking up from the root (so there was no parent). Assign the root node parent from the VCB.
81 ParentMcb = Vcb->McbTree;
82 } else {
83 // Otherwise, fail attempt to lookup non-rooted filename
84 return STATUS_OBJECT_PATH_NOT_FOUND;
85 }
86
87 RtlZeroMemory(&DirectoryEntry, sizeof(RFSD_DENTRY_HEAD));
88
89 // Sanity check that the filename is valid
90 if (FullFileName->Length == 0) {
91 return Status;
92 }
93
94 // Only if we're looking up *exactly* the root node, load it, and return it
95 if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\') {
96 if (!RfsdLoadInode(Vcb, &(ParentMcb->Key), Inode)) {
97 return Status;
98 }
99
100 *RfsdMcb = Vcb->McbTree;
101
102 return STATUS_SUCCESS;
103 }
104
105 // Begin lookup from the parent node
106 while (bRun && i < FullFileName->Length/2) {
107 int Length;
108 ULONG FileAttr = FILE_ATTRIBUTE_NORMAL;
109
110 if (bParent) {
111 bParent = FALSE;
112 } else {
113 // Advance through the (potentially) consecutive '\' path seperators in the filename
114 while(i < FullFileName->Length/2 && FullFileName->Buffer[i] == L'\\') i++;
115 }
116
117 Length = i;
118
119 // Advance to the next '\' path seperator
120 while(i < FullFileName->Length/2 && (FullFileName->Buffer[i] != L'\\')) i++;
121
122 if ( (i - Length) <= 0) {
123 // All of the tokens have been parsed...
124 break;
125 }
126 else {
127 // There remains a token between the path seperators...
128
129 // FileName is a (non-null-terminated) view into the FullFileName structure
130 FileName = *FullFileName;
131 FileName.Buffer += Length;
132 FileName.Length = (USHORT)((i - Length) * 2);
133
134 // Check to see if the parent MCB already contains a child MCB matching the target FileName
135 Mcb = RfsdSearchMcb(Vcb, ParentMcb, &FileName);
136
137 if (Mcb) {
138 ParentMcb = Mcb;
139
140 Status = STATUS_SUCCESS;
141
142 if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
143 if (i < FullFileName->Length/2) {
144 Status = STATUS_OBJECT_PATH_NOT_FOUND;
145 }
146
147 break;
148 }
149 } else {
150 // The parent has no child MCB, or there was no child MCB sibling named FileName. Check the disk using ScanDir...
151
152 // Load the parent directory's inode / stat data structure
153 // For ReiserFS, I'd need the parent's key. This has to be a key leading to a directory... I'm just getting it to pass it to scan.
154 if (!RfsdLoadInode(Vcb, &(ParentMcb->Key), &in)) {
155 Status = STATUS_OBJECT_NAME_NOT_FOUND;
156 break;
157 }
158
159 // Sanity check that we loaded a directory (unless we loaded the last token, in which case it's ok that we loaded something else??)
160 if (!S_ISDIR(in.i_mode)) {
161 if (i < FullFileName->Length/2) {
162 Status = STATUS_OBJECT_NAME_NOT_FOUND;
163 break;
164 }
165 }
166
167
168 Status = RfsdScanDir (
169 Vcb,
170 ParentMcb,
171 &FileName,
172 &off, // <
173 &(DirectoryEntry) ); // <
174
175 if (!NT_SUCCESS(Status)) {
176 // No such file (or an error occurred), so drop out.
177 bRun = FALSE;
178 /*
179 if (i >= FullFileName->Length/2)
180 {
181 *RfsdMcb = ParentMcb;
182 }
183 */
184 } else {
185 // We've found what we were looking for...
186 #if 0 // disabled by ffs too
187 if (IsFlagOn( SUPER_BLOCK->s_feature_incompat,
188 RFSD_FEATURE_INCOMPAT_FILETYPE)) {
189 if (rfsd_dir.file_type == RFSD_FT_DIR)
190 SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
191 } else
192 #endif
193 {
194 RFSD_KEY_IN_MEMORY key;
195 key.k_dir_id = DirectoryEntry.deh_dir_id;
196 key.k_objectid = DirectoryEntry.deh_objectid;
197
198 if (!RfsdLoadInode(Vcb, &key, &in)) {
199 Status = STATUS_OBJECT_NAME_NOT_FOUND;
200 break;
201 }
202 if (S_ISDIR(in.i_mode)) {
203 SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
204 }
205 }
206
207 SetFlag(ParentMcb->Flags, MCB_IN_USE);
208 Mcb = RfsdAllocateMcb(Vcb, &FileName, FileAttr);
209 ClearFlag(ParentMcb->Flags, MCB_IN_USE);
210
211 if (!Mcb) {
212 Status = STATUS_OBJECT_NAME_NOT_FOUND;
213 break;
214 }
215
216 // NOTE: It should be OK to leave off the 3rd / 4th part of key, because (AFAIK) the only place this is used is ScanDir
217 Mcb->Key.k_dir_id = DirectoryEntry.deh_dir_id;
218 Mcb->Key.k_objectid = DirectoryEntry.deh_objectid;
219 Mcb->Key.k_offset = Mcb->Key.k_type = 0;
220
221 Mcb->DeOffset = off;
222 RfsdAddMcbNode(Vcb, ParentMcb, Mcb);
223 ParentMcb = Mcb;
224 }
225 }
226 }
227 }
228
229 if (NT_SUCCESS(Status)) {
230 // If the name has been found, load it according to the inode number in the MCB...
231 // The result will be returned to the caller via Inode
232 *RfsdMcb = Mcb;
233 if (Inode) {
234 if (!RfsdLoadInode(Vcb, &(Mcb->Key), Inode)) {
235 RfsdPrint((DBG_ERROR, "RfsdLookupFileName: error loading Inode %x,%xh\n",
236 Mcb->Key.k_dir_id, Mcb->Key.k_objectid));
237 Status = STATUS_INSUFFICIENT_RESOURCES;
238 }
239 }
240 }
241
242 return Status;
243 }
244
245 /** (This function is only called by LookupFileName.)
246 NOTE: The offset and type of the key passed are irrelevant, as the function will always open a a directory for searching, and will search for the contents by file name -- not key.
247
248 STATUS_INSUFFICIENT_RESOURCES if the filename or diskreading buffer could not be allocated
249 STATUS_UNSUCCESSFUL if the buffer could not be read from disk
250 STATUS_NO_SUCH_FILE if the FileName given was not found in the directory scanned
251 */
252 NTSTATUS
253 RfsdScanDir (IN PRFSD_VCB Vcb,
254 IN PRFSD_MCB ParentMcb, // Mcb of the directory to be scanned (which holds the ->Key of the directory)
255 IN PUNICODE_STRING FileName, // Short file name (not necisarilly null-terminated!)
256 IN OUT PULONG Index, // Offset (in bytes) of the dentry relative to the start of the directory listing
257 IN OUT PRFSD_DENTRY_HEAD rfsd_dir) // Directory entry of the found item
258 {
259 NTSTATUS Status = STATUS_UNSUCCESSFUL;
260 RFSD_KEY_IN_MEMORY DirectoryKey;
261
262 PAGED_CODE();
263
264 // Construct the key (for the directory to be searched), by copying the structure
265 DirectoryKey = ParentMcb->Key;
266 DirectoryKey.k_offset = 0x1;
267 DirectoryKey.k_type = RFSD_KEY_TYPE_v2_DIRENTRY;
268
269 // Request that the filesystem tree be parsed, looking for FileName in directory spans belonging to DirectoryKey
270 {
271 RFSD_SCANDIR_CALLBACK_CONTEXT CallbackContext;
272
273 CallbackContext.Vcb = Vcb;
274 CallbackContext.pDirectoryKey = &DirectoryKey;
275 CallbackContext.pTargetFilename = FileName;
276
277 CallbackContext.idxCurrentDentry = 0;
278
279 CallbackContext.pMatchingDentry = rfsd_dir;
280 CallbackContext.pMatchingIndex = Index;
281
282 Status = RfsdParseFilesystemTree(Vcb, &DirectoryKey, Vcb->SuperBlock->s_root_block, &RfsdScanDirCallback, &CallbackContext);
283
284 if (Status == STATUS_EVENT_DONE)
285 {
286 Status = STATUS_SUCCESS;
287 }
288 else if (Status == STATUS_SUCCESS)
289 {
290 Status = STATUS_NO_SUCH_FILE;
291 }
292 else
293 {
294 Status = STATUS_UNSUCCESSFUL;
295 }
296 }
297
298 RfsdPrint((DBG_TRACE, /*__FUNCTION__*/ " returning %s\n", RfsdNtStatusToString(Status)));
299 return Status;
300 }
301
302 __drv_mustHoldCriticalRegion
303 NTSTATUS
304 RfsdCreateFile(PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb)
305 {
306 NTSTATUS Status = STATUS_UNSUCCESSFUL;
307 PIO_STACK_LOCATION IrpSp;
308 PRFSD_FCB Fcb = NULL;
309 PRFSD_MCB RfsdMcb = NULL;
310
311 PRFSD_FCB ParentFcb = NULL;
312 PRFSD_MCB ParentMcb = NULL;
313
314 BOOLEAN bParentFcbCreated = FALSE;
315
316 PRFSD_CCB Ccb = NULL;
317 PRFSD_INODE Inode = 0;
318 BOOLEAN VcbResourceAcquired = FALSE;
319 #if DISABLED
320 BOOLEAN bDir = FALSE;
321 #endif
322 BOOLEAN bFcbAllocated = FALSE;
323 BOOLEAN bCreated = FALSE;
324 UNICODE_STRING FileName;
325 PIRP Irp;
326
327 ULONG Options;
328 ULONG CreateDisposition;
329
330 BOOLEAN OpenDirectory;
331 BOOLEAN OpenTargetDirectory;
332 BOOLEAN CreateDirectory;
333 BOOLEAN SequentialOnly;
334 BOOLEAN NoIntermediateBuffering;
335 BOOLEAN IsPagingFile;
336 BOOLEAN DirectoryFile;
337 BOOLEAN NonDirectoryFile;
338 BOOLEAN NoEaKnowledge;
339 BOOLEAN DeleteOnClose;
340 BOOLEAN TemporaryFile;
341 BOOLEAN CaseSensitive;
342
343 ACCESS_MASK DesiredAccess;
344 ULONG ShareAccess;
345
346 PAGED_CODE();
347
348 Irp = IrpContext->Irp;
349 IrpSp = IoGetCurrentIrpStackLocation(Irp);
350
351 Options = IrpSp->Parameters.Create.Options;
352
353 DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
354 OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
355
356 NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
357 SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
358 NoIntermediateBuffering = IsFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
359 NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
360 DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
361
362 CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);
363
364 TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
365 FILE_ATTRIBUTE_TEMPORARY );
366
367 CreateDisposition = (Options >> 24) & 0x000000ff;
368
369 IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
370
371 CreateDirectory = (BOOLEAN)(DirectoryFile &&
372 ((CreateDisposition == FILE_CREATE) ||
373 (CreateDisposition == FILE_OPEN_IF)));
374
375 OpenDirectory = (BOOLEAN)(DirectoryFile &&
376 ((CreateDisposition == FILE_OPEN) ||
377 (CreateDisposition == FILE_OPEN_IF)));
378
379 DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
380 ShareAccess = IrpSp->Parameters.Create.ShareAccess;
381
382 FileName.Buffer = NULL;
383
384 _SEH2_TRY {
385
386 ExAcquireResourceExclusiveLite(
387 &Vcb->MainResource, TRUE );
388
389 VcbResourceAcquired = TRUE;
390
391 if (Irp->Overlay.AllocationSize.HighPart) {
392 Status = STATUS_INVALID_PARAMETER;
393 _SEH2_LEAVE;
394 }
395
396 if (!(Inode = ExAllocatePoolWithTag(
397 PagedPool, sizeof(RFSD_INODE), RFSD_POOL_TAG) )) {
398 _SEH2_LEAVE;
399 }
400
401 RtlZeroMemory(Inode, sizeof(RFSD_INODE));
402
403 FileName.MaximumLength = IrpSp->FileObject->FileName.MaximumLength;
404 FileName.Length = IrpSp->FileObject->FileName.Length;
405
406 FileName.Buffer = ExAllocatePoolWithTag(PagedPool, FileName.MaximumLength, RFSD_POOL_TAG);
407 if (!FileName.Buffer) {
408 Status = STATUS_INSUFFICIENT_RESOURCES;
409 _SEH2_LEAVE;
410 }
411
412 RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
413 RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
414
415 if (IrpSp->FileObject->RelatedFileObject) {
416 ParentFcb = (PRFSD_FCB)(IrpSp->FileObject->RelatedFileObject->FsContext);
417 }
418
419 if ((FileName.Length > sizeof(WCHAR)) &&
420 (FileName.Buffer[1] == L'\\') &&
421 (FileName.Buffer[0] == L'\\')) {
422
423 FileName.Length -= sizeof(WCHAR);
424
425 RtlMoveMemory( &FileName.Buffer[0],
426 &FileName.Buffer[1],
427 FileName.Length );
428
429 //
430 // Bad Name if there are still beginning backslashes.
431 //
432
433 if ((FileName.Length > sizeof(WCHAR)) &&
434 (FileName.Buffer[1] == L'\\') &&
435 (FileName.Buffer[0] == L'\\')) {
436
437 Status = STATUS_OBJECT_NAME_INVALID;
438
439 _SEH2_LEAVE;
440 }
441 }
442
443 if (IsFlagOn(Options, FILE_OPEN_BY_FILE_ID)) {
444 Status = STATUS_NOT_IMPLEMENTED;
445 _SEH2_LEAVE;
446 }
447
448 RfsdPrint((DBG_INFO, "RfsdCreateFile: %S (NameLen=%xh) Paging=%xh Option: %xh.\n",
449 FileName.Buffer, FileName.Length, IsPagingFile, IrpSp->Parameters.Create.Options));
450
451 if (ParentFcb) {
452 ParentMcb = ParentFcb->RfsdMcb;
453 }
454
455 Status = RfsdLookupFileName(
456 Vcb,
457 &FileName,
458 ParentMcb,
459 &RfsdMcb,
460 Inode );
461
462 if (!NT_SUCCESS(Status)) {
463 UNICODE_STRING PathName;
464 UNICODE_STRING RealName;
465 UNICODE_STRING RemainName;
466
467 #if DISABLED
468 LONG i = 0;
469 #endif
470
471 PathName = FileName;
472
473 RfsdPrint((DBG_INFO, "RfsdCreateFile: File %S will be created.\n", PathName.Buffer));
474
475 RfsdMcb = NULL;
476
477 if (PathName.Buffer[PathName.Length/2 - 1] == L'\\') {
478 if (DirectoryFile) {
479 PathName.Length -=2;
480 PathName.Buffer[PathName.Length/2] = 0;
481 } else {
482 Status = STATUS_NOT_A_DIRECTORY;
483 _SEH2_LEAVE;
484 }
485 }
486
487 if (!ParentMcb) {
488 if (PathName.Buffer[0] != L'\\') {
489 Status = STATUS_OBJECT_PATH_NOT_FOUND;
490 _SEH2_LEAVE;
491 } else {
492 ParentMcb = Vcb->McbTree;
493 }
494 }
495
496 Dissecting:
497
498 FsRtlDissectName(PathName, &RealName, &RemainName);
499
500 if (((RemainName.Length != 0) && (RemainName.Buffer[0] == L'\\')) ||
501 (RealName.Length >= 256*sizeof(WCHAR))) {
502 Status = STATUS_OBJECT_NAME_INVALID;
503 _SEH2_LEAVE;
504 }
505
506 if (RemainName.Length != 0) {
507
508 PRFSD_MCB RetMcb;
509
510 Status = RfsdLookupFileName (
511 Vcb,
512 &RealName,
513 ParentMcb,
514 &RetMcb,
515 Inode );
516
517 if (!NT_SUCCESS(Status)) {
518 Status = STATUS_OBJECT_PATH_NOT_FOUND;
519 _SEH2_LEAVE;
520 }
521
522 ParentMcb = RetMcb;
523 PathName = RemainName;
524
525 goto Dissecting;
526 }
527
528 if (FsRtlDoesNameContainWildCards(&RealName)) {
529 Status = STATUS_OBJECT_NAME_INVALID;
530 _SEH2_LEAVE;
531 }
532
533 ParentFcb = ParentMcb->RfsdFcb;
534
535 if (!ParentFcb) {
536
537 PRFSD_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool,
538 sizeof(RFSD_INODE), RFSD_POOL_TAG);
539 if (!pTmpInode) {
540 Status = STATUS_INSUFFICIENT_RESOURCES;
541 _SEH2_LEAVE;
542 }
543
544 if(!RfsdLoadInode(Vcb, &(ParentMcb->Key), pTmpInode)) {
545 #ifdef __REACTOS__
546 ExFreePool(pTmpInode);
547 #endif
548 Status = STATUS_OBJECT_PATH_NOT_FOUND;
549 _SEH2_LEAVE;
550 }
551
552 ParentFcb = RfsdAllocateFcb(Vcb, ParentMcb, pTmpInode);
553
554 if (!ParentFcb) {
555 ExFreePool(pTmpInode);
556 Status = STATUS_INSUFFICIENT_RESOURCES;
557 _SEH2_LEAVE;
558 }
559
560 bParentFcbCreated = TRUE;
561 ParentFcb->ReferenceCount++;
562 }
563
564 // We need to create a new one ?
565 if ((CreateDisposition == FILE_CREATE ) ||
566 (CreateDisposition == FILE_OPEN_IF) ||
567 (CreateDisposition == FILE_OVERWRITE_IF)) {
568
569 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
570 Status = STATUS_MEDIA_WRITE_PROTECTED;
571 _SEH2_LEAVE;
572 }
573
574 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
575 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
576 Vcb->Vpb->RealDevice );
577 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
578
579 RfsdRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
580 }
581
582 if (DirectoryFile) {
583 if (TemporaryFile) {
584 Status = STATUS_INVALID_PARAMETER;
585 _SEH2_LEAVE;
586 }
587 }
588
589 if (!ParentFcb) {
590 Status = STATUS_OBJECT_PATH_NOT_FOUND;
591 _SEH2_LEAVE;
592 }
593
594 if (DirectoryFile) {
595 if ( RFSD_IS_ROOT_KEY(ParentFcb->RfsdMcb->Key) ) {
596 if ( (RealName.Length == 0x10) &&
597 memcmp(RealName.Buffer, L"Recycled\0", 0x10) == 0) {
598 SetFlag( IrpSp->Parameters.Create.FileAttributes,
599 FILE_ATTRIBUTE_READONLY );
600 }
601 }
602
603 Status = STATUS_UNSUCCESSFUL;
604 #if DISABLED
605 Status = RfsdCreateInode( IrpContext,
606 Vcb,
607 ParentFcb,
608 RFSD_FT_DIR,
609 IrpSp->Parameters.Create.FileAttributes,
610 &RealName);
611 #endif
612 } else {
613 Status = STATUS_UNSUCCESSFUL;
614 #if DISABLED
615 Status = RfsdCreateInode( IrpContext,
616 Vcb,
617 ParentFcb,
618 RFSD_FT_REG_FILE,
619 IrpSp->Parameters.Create.FileAttributes,
620 &RealName);
621 #endif
622 }
623
624 if (NT_SUCCESS(Status)) {
625
626 bCreated = TRUE;
627
628 Irp->IoStatus.Information = FILE_CREATED;
629 Status = RfsdLookupFileName (
630 Vcb,
631 &RealName,
632 ParentMcb,
633 &RfsdMcb,
634 Inode );
635
636 if (NT_SUCCESS(Status)) {
637
638 if (DirectoryFile) {
639 DbgBreak();
640 #if DISABLED // dirctl.c [ see also in cleanup.c ]
641 RfsdNotifyReportChange(
642 IrpContext,
643 Vcb,
644 ParentFcb,
645 FILE_NOTIFY_CHANGE_DIR_NAME,
646 FILE_ACTION_ADDED );
647 } else {
648 RfsdNotifyReportChange(
649 IrpContext,
650 Vcb,
651 ParentFcb,
652 FILE_NOTIFY_CHANGE_FILE_NAME,
653 FILE_ACTION_ADDED );
654 #endif
655 }
656 } else {
657 DbgBreak();
658 }
659 } else {
660 DbgBreak();
661 }
662 } else if (OpenTargetDirectory) {
663 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
664 Status = STATUS_MEDIA_WRITE_PROTECTED;
665 _SEH2_LEAVE;
666 }
667
668 if (!ParentFcb) {
669 Status = STATUS_OBJECT_PATH_NOT_FOUND;
670 _SEH2_LEAVE;
671 }
672
673 RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
674 IrpSp->FileObject->FileName.MaximumLength);
675 IrpSp->FileObject->FileName.Length = RealName.Length;
676
677 RtlCopyMemory( IrpSp->FileObject->FileName.Buffer,
678 RealName.Buffer,
679 RealName.Length );
680
681 Fcb = ParentFcb;
682
683 Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
684 Status = STATUS_SUCCESS;
685 } else {
686 Status = STATUS_OBJECT_NAME_NOT_FOUND;
687 _SEH2_LEAVE;
688 }
689
690 } else { // File / Dir already exists.
691
692 if (OpenTargetDirectory) {
693
694 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
695 Status = STATUS_MEDIA_WRITE_PROTECTED;
696 _SEH2_LEAVE;
697 }
698
699 Irp->IoStatus.Information = FILE_EXISTS;
700 Status = STATUS_SUCCESS;
701
702 RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
703 IrpSp->FileObject->FileName.MaximumLength);
704 IrpSp->FileObject->FileName.Length = RfsdMcb->ShortName.Length;
705
706 RtlCopyMemory( IrpSp->FileObject->FileName.Buffer,
707 RfsdMcb->ShortName.Buffer,
708 RfsdMcb->ShortName.Length );
709
710 //Let Mcb pointer to it's parent
711 RfsdMcb = RfsdMcb->Parent;
712
713 goto Openit;
714 }
715
716 // We can not create if one exists
717 if (CreateDisposition == FILE_CREATE) {
718 Irp->IoStatus.Information = FILE_EXISTS;
719 Status = STATUS_OBJECT_NAME_COLLISION;
720 _SEH2_LEAVE;
721 }
722
723 if(IsFlagOn(RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
724
725 if ((CreateDisposition != FILE_OPEN) &&
726 (CreateDisposition != FILE_OPEN_IF)) {
727
728 Status = STATUS_OBJECT_NAME_COLLISION;
729 _SEH2_LEAVE;
730 }
731
732 if (NonDirectoryFile) {
733 Status = STATUS_FILE_IS_A_DIRECTORY;
734 _SEH2_LEAVE;
735 }
736
737 if (RFSD_IS_ROOT_KEY(RfsdMcb->Key)) {
738
739 if (DeleteOnClose) {
740 Status = STATUS_CANNOT_DELETE;
741 _SEH2_LEAVE;
742 }
743
744 if (OpenTargetDirectory) {
745 Status = STATUS_INVALID_PARAMETER;
746 _SEH2_LEAVE;
747 }
748 }
749 }
750
751 Irp->IoStatus.Information = FILE_OPENED;
752 }
753
754 Openit:
755
756 if (RfsdMcb) {
757
758 Fcb = RfsdMcb->RfsdFcb;
759
760 if (!Fcb) {
761 Fcb = RfsdAllocateFcb (Vcb, RfsdMcb, Inode);
762 bFcbAllocated = TRUE;
763 }
764 }
765
766 if (Fcb) {
767
768 if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
769 Status = STATUS_FILE_DELETED;
770 _SEH2_LEAVE;
771 }
772
773 if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
774 Status = STATUS_DELETE_PENDING;
775 _SEH2_LEAVE;
776 }
777
778 if (bCreated) {
779 DbgBreak();
780 #if DISABLED // ONLY FOR WRITE SUPPORT?
781
782 //
783 // This file is just created.
784 //
785
786 if (DirectoryFile) {
787 UNICODE_STRING EntryName;
788 USHORT NameBuf[6];
789
790 RtlZeroMemory(&NameBuf, 6 * sizeof(USHORT));
791
792 EntryName.Length = EntryName.MaximumLength = 2;
793 EntryName.Buffer = &NameBuf[0];
794 NameBuf[0] = (USHORT)'.';
795
796 RfsdAddEntry( IrpContext, Vcb, Fcb,
797 RFSD_FT_DIR,
798 Fcb->RfsdMcb->Key,
799 &EntryName );
800
801 RfsdSaveInode( IrpContext, Vcb,
802 Fcb->RfsdMcb->Key,
803 Fcb->Inode );
804
805 EntryName.Length = EntryName.MaximumLength = 4;
806 EntryName.Buffer = &NameBuf[0];
807 NameBuf[0] = NameBuf[1] = (USHORT)'.';
808
809 RfsdAddEntry( IrpContext, Vcb, Fcb,
810 RFSD_FT_DIR,
811 Fcb->RfsdMcb->Parent->Inode,
812 &EntryName );
813
814 RfsdSaveInode( IrpContext, Vcb,
815 Fcb->RfsdMcb->Parent->Inode,
816 ParentFcb->Inode );
817 } else {
818 DbgBreak();
819 #if DISABLED
820 Status = RfsdExpandFile(
821 IrpContext, Vcb, Fcb,
822 &(Irp->Overlay.AllocationSize));
823 #endif
824
825 if (!NT_SUCCESS(Status)) {
826
827 DbgBreak();
828
829 _SEH2_LEAVE;
830 }
831 }
832 #endif
833 } else {
834
835 //
836 // This file alreayd exists.
837 //
838
839 if (DeleteOnClose) {
840
841 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
842 Status = STATUS_MEDIA_WRITE_PROTECTED;
843 _SEH2_LEAVE;
844 }
845
846 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
847 Status = STATUS_MEDIA_WRITE_PROTECTED;
848
849 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
850 Vcb->Vpb->RealDevice );
851
852 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
853
854 RfsdRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
855 }
856
857 SetFlag(Fcb->Flags, FCB_DELETE_ON_CLOSE);
858
859 } else {
860
861 //
862 // Just to Open file (Open/OverWrite ...)
863 //
864
865 if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags,
866 FO_NO_INTERMEDIATE_BUFFERING))) {
867 Fcb->Header.IsFastIoPossible = FastIoIsPossible;
868
869 if (IsFlagOn(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED) &&
870 (Fcb->SectionObject.DataSectionObject != NULL)) {
871
872 if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) {
873 /* IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) */
874
875 if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
876 CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
877 ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
878 }
879
880 CcPurgeCacheSection(&Fcb->SectionObject,
881 NULL,
882 0,
883 FALSE );
884 }
885 }
886 }
887 }
888 }
889
890 if (!IsDirectory(Fcb)) {
891 if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
892 if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile){
893 DesiredAccess |= DELETE;
894 } else if (((CreateDisposition == FILE_OVERWRITE) ||
895 (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) {
896 DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA |
897 FILE_WRITE_ATTRIBUTES );
898 }
899 }
900 }
901
902 if (Fcb->OpenHandleCount > 0) {
903 Status = IoCheckShareAccess( DesiredAccess,
904 ShareAccess,
905 IrpSp->FileObject,
906 &(Fcb->ShareAccess),
907 TRUE );
908
909 if (!NT_SUCCESS(Status)) {
910 _SEH2_LEAVE;
911 }
912 } else {
913 IoSetShareAccess( DesiredAccess,
914 ShareAccess,
915 IrpSp->FileObject,
916 &(Fcb->ShareAccess) );
917 }
918
919 Ccb = RfsdAllocateCcb();
920
921 Fcb->OpenHandleCount++;
922 Fcb->ReferenceCount++;
923
924 if (IsFlagOn(IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) {
925 Fcb->NonCachedOpenCount++;
926 }
927
928 Vcb->OpenFileHandleCount++;
929 Vcb->ReferenceCount++;
930
931 IrpSp->FileObject->FsContext = (void*)Fcb;
932 IrpSp->FileObject->FsContext2 = (void*) Ccb;
933 IrpSp->FileObject->PrivateCacheMap = NULL;
934 IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
935 IrpSp->FileObject->Vpb = Vcb->Vpb;
936
937 Status = STATUS_SUCCESS;
938
939 RfsdPrint((DBG_INFO, "RfsdCreateFile: %s OpenCount: %u ReferCount: %u\n",
940 Fcb->AnsiFileName.Buffer, Fcb->OpenHandleCount, Fcb->ReferenceCount));
941
942 if (!IsDirectory(Fcb) && !NoIntermediateBuffering ) {
943 IrpSp->FileObject->Flags |= FO_CACHE_SUPPORTED;
944 }
945
946 if (!bCreated && !IsDirectory(Fcb)) {
947 if ( DeleteOnClose ||
948 IsFlagOn(DesiredAccess, FILE_WRITE_DATA) ||
949 (CreateDisposition == FILE_OVERWRITE) ||
950 (CreateDisposition == FILE_OVERWRITE_IF)) {
951 if (!MmFlushImageSection( &Fcb->SectionObject,
952 MmFlushForWrite )) {
953
954 Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
955 STATUS_SHARING_VIOLATION;
956 _SEH2_LEAVE;
957 }
958 }
959
960 if ((CreateDisposition == FILE_SUPERSEDE) ||
961 (CreateDisposition == FILE_OVERWRITE) ||
962 (CreateDisposition == FILE_OVERWRITE_IF)) {
963
964 #if RFSD_READ_ONLY
965 Status = STATUS_MEDIA_WRITE_PROTECTED;
966 _SEH2_LEAVE;
967 #endif
968
969
970 #if DISABLED
971 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
972 Status = STATUS_MEDIA_WRITE_PROTECTED;
973 _SEH2_LEAVE;
974 }
975
976 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
977
978 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
979 Vcb->Vpb->RealDevice );
980 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
981
982 RfsdRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
983 }
984
985 Status = RfsdSupersedeOrOverWriteFile( IrpContext,
986 Vcb,
987 Fcb,
988 CreateDisposition );
989
990 if (NT_SUCCESS(Status)) {
991 _SEH2_LEAVE;
992 }
993
994 DbgBreak();
995 #if DISABLED
996 Status = RfsdExpandFile(
997 IrpContext,
998 Vcb,
999 Fcb,
1000 &(Irp->Overlay.AllocationSize));
1001 #endif
1002
1003 if (!(NT_SUCCESS(Status))) {
1004 _SEH2_LEAVE;
1005 }
1006
1007 DbgBreak();
1008 #if DISABLED // dirctl.c
1009 RfsdNotifyReportChange(
1010 IrpContext,
1011 Vcb,
1012 Fcb,
1013 FILE_NOTIFY_CHANGE_LAST_WRITE |
1014 FILE_NOTIFY_CHANGE_ATTRIBUTES |
1015 FILE_NOTIFY_CHANGE_SIZE,
1016 FILE_ACTION_MODIFIED );
1017 #endif
1018
1019 if (CreateDisposition == FILE_SUPERSEDE) {
1020 Irp->IoStatus.Information = FILE_SUPERSEDED;
1021 } else {
1022 Irp->IoStatus.Information = FILE_OVERWRITTEN;
1023 }
1024 #endif
1025 }
1026 }
1027 }
1028 } _SEH2_FINALLY {
1029
1030 if (FileName.Buffer)
1031 ExFreePool(FileName.Buffer);
1032
1033 if (bParentFcbCreated) {
1034 ParentFcb->ReferenceCount--;
1035 }
1036
1037 if (VcbResourceAcquired) {
1038 ExReleaseResourceForThreadLite(
1039 &Vcb->MainResource,
1040 ExGetCurrentResourceThread() );
1041 }
1042
1043 if (!bFcbAllocated) {
1044 if (Inode)
1045 ExFreePool(Inode);
1046 } else {
1047 if (!Fcb && Inode)
1048 ExFreePool(Inode);
1049 }
1050 } _SEH2_END;
1051
1052 return Status;
1053 }
1054
1055 __drv_mustHoldCriticalRegion
1056 NTSTATUS
1057 RfsdCreateVolume(PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb)
1058 {
1059 PIO_STACK_LOCATION IrpSp;
1060 PIRP Irp;
1061
1062 NTSTATUS Status;
1063
1064 ACCESS_MASK DesiredAccess;
1065 ULONG ShareAccess;
1066
1067 ULONG Options;
1068 BOOLEAN DirectoryFile;
1069 BOOLEAN OpenTargetDirectory;
1070
1071 ULONG CreateDisposition;
1072
1073 PAGED_CODE();
1074
1075 RfsdPrint((DBG_FUNC, "Entering CreateVolume\n"));
1076
1077 Irp = IrpContext->Irp;
1078 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1079
1080 Options = IrpSp->Parameters.Create.Options;
1081
1082 DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
1083 OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
1084
1085 CreateDisposition = (Options >> 24) & 0x000000ff;
1086
1087 DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
1088 ShareAccess = IrpSp->Parameters.Create.ShareAccess;
1089
1090 if (DirectoryFile) {
1091 return STATUS_NOT_A_DIRECTORY;
1092 }
1093
1094 if (OpenTargetDirectory) {
1095 return STATUS_INVALID_PARAMETER;
1096 }
1097
1098 if ( (CreateDisposition != FILE_OPEN) &&
1099 (CreateDisposition != FILE_OPEN_IF) ) {
1100 return STATUS_ACCESS_DENIED;
1101 }
1102
1103 Status = STATUS_SUCCESS;
1104
1105 if (Vcb->OpenHandleCount > 0) {
1106 Status = IoCheckShareAccess( DesiredAccess, ShareAccess,
1107 IrpSp->FileObject,
1108 &(Vcb->ShareAccess), TRUE);
1109
1110 if (!NT_SUCCESS(Status)) {
1111 goto errorout;
1112 }
1113 } else {
1114 IoSetShareAccess( DesiredAccess, ShareAccess,
1115 IrpSp->FileObject,
1116 &(Vcb->ShareAccess) );
1117 }
1118
1119 if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)) {
1120 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
1121
1122 RfsdFlushFiles(Vcb, FALSE);
1123 RfsdFlushVolume(Vcb, FALSE);
1124
1125 ExReleaseResourceLite(&Vcb->MainResource);
1126 }
1127
1128 {
1129 PRFSD_CCB Ccb = RfsdAllocateCcb();
1130
1131 if (Ccb == NULL) {
1132 Status = STATUS_INSUFFICIENT_RESOURCES;
1133 goto errorout;
1134 }
1135
1136 IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
1137 IrpSp->FileObject->FsContext = Vcb;
1138 IrpSp->FileObject->FsContext2 = Ccb;
1139
1140 Vcb->ReferenceCount++;
1141 Vcb->OpenHandleCount++;
1142
1143 Irp->IoStatus.Information = FILE_OPENED;
1144 }
1145
1146 errorout:
1147
1148 return Status;
1149 }
1150
1151 __drv_mustHoldCriticalRegion
1152 NTSTATUS
1153 RfsdCreate (IN PRFSD_IRP_CONTEXT IrpContext)
1154 {
1155 PDEVICE_OBJECT DeviceObject;
1156 PIRP Irp;
1157 PIO_STACK_LOCATION IrpSp;
1158 PRFSD_VCB Vcb = 0;
1159 NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
1160 PRFSD_FCBVCB Xcb = NULL;
1161
1162 PAGED_CODE();
1163
1164 DeviceObject = IrpContext->DeviceObject;
1165
1166 Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
1167
1168 ASSERT(IsMounted(Vcb));
1169
1170 Irp = IrpContext->Irp;
1171
1172 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1173
1174 Xcb = (PRFSD_FCBVCB) (IrpSp->FileObject->FsContext);
1175
1176 if (DeviceObject == RfsdGlobal->DeviceObject) {
1177 RfsdPrint((DBG_INFO, "RfsdCreate: Create on main device object.\n"));
1178
1179 Status = STATUS_SUCCESS;
1180
1181 Irp->IoStatus.Information = FILE_OPENED;
1182
1183 RfsdUnpinRepinnedBcbs(IrpContext);
1184
1185 RfsdCompleteIrpContext(IrpContext, Status);
1186
1187 return Status;
1188 }
1189
1190 _SEH2_TRY {
1191
1192 if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
1193 Status = STATUS_ACCESS_DENIED;
1194
1195 if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
1196 Status = STATUS_VOLUME_DISMOUNTED;
1197 }
1198
1199 _SEH2_LEAVE;
1200 }
1201
1202 if ( ((IrpSp->FileObject->FileName.Length == 0) &&
1203 (IrpSp->FileObject->RelatedFileObject == NULL)) ||
1204 (Xcb && Xcb->Identifier.Type == RFSDVCB) ) {
1205 Status = RfsdCreateVolume(IrpContext, Vcb);
1206 } else {
1207 Status = RfsdCreateFile(IrpContext, Vcb);
1208 }
1209
1210 } _SEH2_FINALLY {
1211
1212 if (!IrpContext->ExceptionInProgress) {
1213 RfsdUnpinRepinnedBcbs(IrpContext);
1214
1215 RfsdCompleteIrpContext(IrpContext, Status);
1216 }
1217 } _SEH2_END;
1218
1219 return Status;
1220 }
1221
1222 #if !RFSD_READ_ONLY
1223
1224 NTSTATUS
1225 RfsdCreateInode(
1226 PRFSD_IRP_CONTEXT IrpContext,
1227 PRFSD_VCB Vcb,
1228 PRFSD_FCB ParentFcb,
1229 ULONG Type,
1230 ULONG FileAttr,
1231 PUNICODE_STRING FileName)
1232 {
1233 NTSTATUS Status;
1234 ULONG Inode;
1235 ULONG Group;
1236 RFSD_INODE RfsdIno;
1237
1238 PAGED_CODE();
1239 #if 0
1240 RtlZeroMemory(&RfsdIno, sizeof(RFSD_INODE));
1241
1242 DbgBreak();
1243 #if DISABLED
1244 Group = (ParentFcb->RfsdMcb->Inode - 1) / BLOCKS_PER_GROUP;
1245 #endif
1246
1247 RfsdPrint(( DBG_INFO,
1248 "RfsdCreateInode: %S in %S(Key=%x,%xh)\n",
1249 FileName->Buffer,
1250 ParentFcb->RfsdMcb->ShortName.Buffer,
1251 ParentFcb->RfsdMcb->Key.k_dir_id, ParentFcb->RfsdMcb->Key.k_objectid));
1252
1253 Status = RfsdNewInode(IrpContext, Vcb, Group,Type, &Inode);
1254
1255 if (!NT_SUCCESS(Status)) {
1256 goto errorout;
1257 }
1258
1259 Status = RfsdAddEntry(IrpContext, Vcb, ParentFcb, Type, Inode, FileName);
1260
1261 if (!NT_SUCCESS(Status)) {
1262 DbgBreak();
1263 RfsdFreeInode(IrpContext, Vcb, Inode, Type);
1264
1265 goto errorout;
1266 }
1267
1268 RfsdSaveInode(IrpContext, Vcb, ParentFcb->RfsdMcb->Inode, ParentFcb->Inode);
1269
1270 RfsdIno.i_ctime = ParentFcb->Inode->i_mtime;
1271 RfsdIno.i_mode = ( S_IPERMISSION_MASK &
1272 ParentFcb->Inode->i_mode );
1273 RfsdIno.i_uid = ParentFcb->Inode->i_uid;
1274 RfsdIno.i_gid = ParentFcb->Inode->i_gid;
1275
1276 //~ RfsdIno.i_dir_acl = ParentFcb->Inode->i_dir_acl;
1277 //~ RfsdIno.i_file_acl = ParentFcb->Inode->i_file_acl;
1278 RfsdIno.u.i_generation = ParentFcb->Inode->u.i_generation;
1279
1280 //~ RfsdIno.osd2 = ParentFcb->Inode->osd2;
1281
1282 if (IsFlagOn(FileAttr, FILE_ATTRIBUTE_READONLY)) {
1283 RfsdSetReadOnly(RfsdIno.i_mode);
1284 }
1285
1286 if (Type == RFSD_FT_DIR) {
1287 RfsdIno.i_mode |= S_IFDIR;
1288 RfsdIno.i_links_count = 2;
1289 } else if (Type == RFSD_FT_REG_FILE) {
1290 RfsdIno.i_mode |= S_IFREG;
1291 RfsdIno.i_links_count = 1;
1292 } else {
1293 DbgBreak();
1294 RfsdIno.i_links_count = 1;
1295 }
1296
1297 RfsdSaveInode(IrpContext, Vcb, Inode, &RfsdIno);
1298
1299 RfsdPrint((DBG_INFO, "RfsdCreateInode: New Inode = %xh (Type=%xh)\n", Inode, Type));
1300
1301 errorout:
1302 #endif // 0
1303 return 0;//Status;
1304 }
1305
1306 NTSTATUS
1307 RfsdSupersedeOrOverWriteFile(
1308 PRFSD_IRP_CONTEXT IrpContext,
1309 PRFSD_VCB Vcb,
1310 PRFSD_FCB Fcb,
1311 ULONG Disposition)
1312 {
1313 LARGE_INTEGER CurrentTime;
1314 LARGE_INTEGER AllocationSize;
1315 NTSTATUS Status = STATUS_SUCCESS;
1316
1317 PAGED_CODE();
1318 #if 0
1319 KeQuerySystemTime(&CurrentTime);
1320
1321 AllocationSize.QuadPart = (LONGLONG)0;
1322
1323 if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(AllocationSize))) {
1324 Status = STATUS_USER_MAPPED_FILE;
1325 return Status;
1326 }
1327
1328 DbgBreak();
1329 #if DISABLED
1330 Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
1331 #endif
1332
1333 if (NT_SUCCESS(Status)) {
1334 Fcb->Header.AllocationSize.QuadPart =
1335 Fcb->Header.FileSize.QuadPart = (LONGLONG) 0;
1336
1337 Fcb->Inode->i_size = 0;
1338
1339 if (S_ISREG(Fcb->Inode->i_mode)) {
1340 KdPrint(("Reminder: Fcb->Inode->i_size_high = 0;\n"));
1341 //~Fcb->Inode->i_size_high = 0;
1342 }
1343
1344 if (Disposition == FILE_SUPERSEDE)
1345 Fcb->Inode->i_ctime = RfsdInodeTime(CurrentTime);
1346
1347 Fcb->Inode->i_atime =
1348 Fcb->Inode->i_mtime = RfsdInodeTime(CurrentTime);
1349 } else {
1350 LARGE_INTEGER iSize;
1351
1352 iSize.QuadPart = (LONGLONG) Fcb->Inode->i_size;
1353
1354 if (S_ISREG(Fcb->Inode->i_mode))
1355 KdPrint(("Reminder: Fcb->Inode->i_size_high = 0;\n"));
1356 //~ iSize.HighPart = (LONG)(Fcb->Inode->i_size_high);
1357
1358 if (iSize.QuadPart > Fcb->Header.AllocationSize.QuadPart)
1359 iSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
1360
1361 Fcb->Header.FileSize.QuadPart = iSize.QuadPart;
1362
1363 Fcb->Inode->i_size = iSize.LowPart;
1364 //~ Fcb->Inode->i_size_high = (ULONG) iSize.HighPart;
1365 }
1366
1367 RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
1368 #endif // 0
1369 return Status;
1370 }
1371
1372 #endif // !RFSD_READ_ONLY
1373
1374 /**
1375 Searches to find if the name if is located in the dentry span within the block.
1376
1377 STATUS_SUCCESS if the name was not found, but processing should continue
1378 STATUS_EVENT_DONE if the name was found, and processing should stop
1379 */
1380 NTSTATUS
1381 RfsdScanDirCallback(
1382 ULONG BlockNumber,
1383 PVOID pContext )
1384 {
1385 PRFSD_SCANDIR_CALLBACK_CONTEXT pCallbackContext = (PRFSD_SCANDIR_CALLBACK_CONTEXT) pContext;
1386 RFSD_KEY_IN_MEMORY DirectoryKey;
1387 PUCHAR pBlockBuffer = NULL;
1388 PRFSD_ITEM_HEAD pDirectoryItemHeader = NULL;
1389 PUCHAR pDirectoryItemBuffer = NULL;
1390 NTSTATUS Status;
1391 BOOLEAN bFound = FALSE;
1392 PRFSD_DENTRY_HEAD pPrevDentry = NULL;
1393 ULONG idxDentryInSpan = 0;
1394 UNICODE_STRING InodeFileName;
1395 USHORT InodeFileNameLength;
1396
1397 PAGED_CODE();
1398
1399 InodeFileName.Buffer = NULL;
1400
1401 RfsdPrint((DBG_FUNC, /*__FUNCTION__*/ " invoked on block %i\n", BlockNumber));
1402
1403
1404 _SEH2_TRY {
1405
1406 // Load the block
1407 pBlockBuffer = RfsdAllocateAndLoadBlock(pCallbackContext->Vcb, BlockNumber);
1408 if (!pBlockBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
1409
1410 // Construct the item key to search for
1411 DirectoryKey = *(pCallbackContext->pDirectoryKey);
1412 DirectoryKey.k_type = RFSD_KEY_TYPE_v2_DIRENTRY;
1413
1414 // Get the item header and its information
1415 Status = RfsdFindItemHeaderInBlock(
1416 pCallbackContext->Vcb, &DirectoryKey, pBlockBuffer,
1417 ( &pDirectoryItemHeader ), //<
1418 &CompareKeysWithoutOffset
1419 );
1420
1421 // If this block doesn't happen to contain a directory item, skip it.
1422 if ( (Status == STATUS_NO_SUCH_MEMBER) || !pDirectoryItemHeader )
1423 {
1424 KdPrint(("Block %i did not contain the appropriate diritem header\n", BlockNumber));
1425 Status = STATUS_SUCCESS; _SEH2_LEAVE;
1426 }
1427
1428 // Setup the item buffer
1429 pDirectoryItemBuffer = (PUCHAR) pBlockBuffer + pDirectoryItemHeader->ih_item_location;
1430
1431
1432
1433 // Allocate the unicode filename buffer
1434 InodeFileName.Buffer = ExAllocatePoolWithTag(PagedPool, (RFSD_NAME_LEN + 1) * 2, RFSD_POOL_TAG);
1435 if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
1436
1437
1438 while (!bFound && (idxDentryInSpan < pDirectoryItemHeader->u.ih_entry_count) ) {
1439 OEM_STRING OemName;
1440
1441 //
1442 // reading dir entries from Dcb
1443 //
1444
1445 PRFSD_DENTRY_HEAD pCurrentDentry = (PRFSD_DENTRY_HEAD) (pDirectoryItemBuffer + (idxDentryInSpan * sizeof(RFSD_DENTRY_HEAD)));
1446
1447 // Skip the directory entry for the parent of the root directory (because it should not be shown, and has no stat data)
1448 // (NOTE: Any change made here should also be mirrored in RfsdDirControlCallback)
1449 if (pCurrentDentry->deh_dir_id == 0 /*&& pCurrentDentry->deh_objectid == 1*/)
1450 { goto ProcessNextEntry; }
1451
1452 // Retrieve the filename of the loaded directory entry from the buffer (encoded with the codepage)
1453 // NOTE: The filename is not gauranteed to be null-terminated, and so the end may implicitly be the start of the previous entry.
1454 OemName.Buffer = (PUCHAR) pDirectoryItemBuffer + pCurrentDentry->deh_location;
1455 OemName.MaximumLength = (pPrevDentry ? pPrevDentry->deh_location : // The end of this entry is the start of the previous
1456 pDirectoryItemHeader->ih_item_len // Otherwise this is the first entry, the end of which is the end of the item.
1457 ) - pCurrentDentry->deh_location;
1458 OemName.Length = RfsdStringLength(OemName.Buffer, OemName.MaximumLength);
1459
1460
1461
1462 // Convert that name to unicode
1463 {
1464 InodeFileNameLength = (USHORT) RfsdOEMToUnicodeSize(&OemName) + 2;
1465
1466 // If the unicode InodeFileName.Buffer is not large enough, expand it
1467 if (InodeFileName.MaximumLength < InodeFileNameLength)
1468 {
1469 // Free the existing buffer
1470 if (InodeFileName.Buffer) { ExFreePool(InodeFileName.Buffer); }
1471
1472 // Allocate a new larger buffer
1473 InodeFileName.Buffer = ExAllocatePoolWithTag(PagedPool, InodeFileNameLength, RFSD_POOL_TAG);
1474 if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
1475 InodeFileName.MaximumLength = InodeFileNameLength;
1476 }
1477
1478 InodeFileName.Length = 0;
1479
1480 RtlZeroMemory( InodeFileName.Buffer, InodeFileNameLength);
1481
1482 Status = RfsdOEMToUnicode(
1483 &InodeFileName,
1484 &OemName );
1485
1486 if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
1487 }
1488
1489
1490 // Compare it to the name we are searching for
1491 if (!RtlCompareUnicodeString(
1492 pCallbackContext->pTargetFilename,
1493 &InodeFileName,
1494 TRUE )) {
1495 // This entry MATCHED! Copy the matching dentry into the output field on the context
1496 bFound = TRUE;
1497
1498 *(pCallbackContext->pMatchingIndex) = (pCallbackContext->idxCurrentDentry * sizeof(RFSD_DENTRY_HEAD));
1499 RtlCopyMemory(pCallbackContext->pMatchingDentry, pCurrentDentry, sizeof(RFSD_DENTRY_HEAD));
1500
1501 RfsdPrint(( DBG_INFO, /*__FUNCTION__*/ ": Found: Name=%S Key=%xh,%xh\n",
1502 InodeFileName.Buffer, pCurrentDentry->deh_dir_id, pCurrentDentry->deh_objectid ));
1503
1504 Status = STATUS_EVENT_DONE;
1505 break;
1506 }
1507
1508 ProcessNextEntry:
1509 // Advance to the next directory entry
1510 pPrevDentry = pCurrentDentry;
1511 ++idxDentryInSpan;
1512 ++(pCallbackContext->idxCurrentDentry);
1513 }
1514
1515 if (!bFound) {
1516 // Indicate success, so that parsing will continue with subsequent blocks.
1517 Status = STATUS_SUCCESS;
1518 }
1519 } _SEH2_FINALLY {
1520 if (pBlockBuffer) ExFreePool(pBlockBuffer);
1521 if (InodeFileName.Buffer) ExFreePool(InodeFileName.Buffer);
1522 } _SEH2_END;
1523
1524
1525 return Status;
1526
1527 }