[REISERFS] Don't allocate (and leak :-)) an unused event
[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 Status = STATUS_OBJECT_PATH_NOT_FOUND;
546 _SEH2_LEAVE;
547 }
548
549 ParentFcb = RfsdAllocateFcb(Vcb, ParentMcb, pTmpInode);
550
551 if (!ParentFcb) {
552 ExFreePool(pTmpInode);
553 Status = STATUS_INSUFFICIENT_RESOURCES;
554 _SEH2_LEAVE;
555 }
556
557 bParentFcbCreated = TRUE;
558 ParentFcb->ReferenceCount++;
559 }
560
561 // We need to create a new one ?
562 if ((CreateDisposition == FILE_CREATE ) ||
563 (CreateDisposition == FILE_OPEN_IF) ||
564 (CreateDisposition == FILE_OVERWRITE_IF)) {
565
566 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
567 Status = STATUS_MEDIA_WRITE_PROTECTED;
568 _SEH2_LEAVE;
569 }
570
571 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
572 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
573 Vcb->Vpb->RealDevice );
574 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
575
576 RfsdRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
577 }
578
579 if (DirectoryFile) {
580 if (TemporaryFile) {
581 Status = STATUS_INVALID_PARAMETER;
582 _SEH2_LEAVE;
583 }
584 }
585
586 if (!ParentFcb) {
587 Status = STATUS_OBJECT_PATH_NOT_FOUND;
588 _SEH2_LEAVE;
589 }
590
591 if (DirectoryFile) {
592 if ( RFSD_IS_ROOT_KEY(ParentFcb->RfsdMcb->Key) ) {
593 if ( (RealName.Length == 0x10) &&
594 memcmp(RealName.Buffer, L"Recycled\0", 0x10) == 0) {
595 SetFlag( IrpSp->Parameters.Create.FileAttributes,
596 FILE_ATTRIBUTE_READONLY );
597 }
598 }
599
600 Status = STATUS_UNSUCCESSFUL;
601 #if DISABLED
602 Status = RfsdCreateInode( IrpContext,
603 Vcb,
604 ParentFcb,
605 RFSD_FT_DIR,
606 IrpSp->Parameters.Create.FileAttributes,
607 &RealName);
608 #endif
609 } else {
610 Status = STATUS_UNSUCCESSFUL;
611 #if DISABLED
612 Status = RfsdCreateInode( IrpContext,
613 Vcb,
614 ParentFcb,
615 RFSD_FT_REG_FILE,
616 IrpSp->Parameters.Create.FileAttributes,
617 &RealName);
618 #endif
619 }
620
621 if (NT_SUCCESS(Status)) {
622
623 bCreated = TRUE;
624
625 Irp->IoStatus.Information = FILE_CREATED;
626 Status = RfsdLookupFileName (
627 Vcb,
628 &RealName,
629 ParentMcb,
630 &RfsdMcb,
631 Inode );
632
633 if (NT_SUCCESS(Status)) {
634
635 if (DirectoryFile) {
636 DbgBreak();
637 #if DISABLED // dirctl.c [ see also in cleanup.c ]
638 RfsdNotifyReportChange(
639 IrpContext,
640 Vcb,
641 ParentFcb,
642 FILE_NOTIFY_CHANGE_DIR_NAME,
643 FILE_ACTION_ADDED );
644 } else {
645 RfsdNotifyReportChange(
646 IrpContext,
647 Vcb,
648 ParentFcb,
649 FILE_NOTIFY_CHANGE_FILE_NAME,
650 FILE_ACTION_ADDED );
651 #endif
652 }
653 } else {
654 DbgBreak();
655 }
656 } else {
657 DbgBreak();
658 }
659 } else if (OpenTargetDirectory) {
660 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
661 Status = STATUS_MEDIA_WRITE_PROTECTED;
662 _SEH2_LEAVE;
663 }
664
665 if (!ParentFcb) {
666 Status = STATUS_OBJECT_PATH_NOT_FOUND;
667 _SEH2_LEAVE;
668 }
669
670 RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
671 IrpSp->FileObject->FileName.MaximumLength);
672 IrpSp->FileObject->FileName.Length = RealName.Length;
673
674 RtlCopyMemory( IrpSp->FileObject->FileName.Buffer,
675 RealName.Buffer,
676 RealName.Length );
677
678 Fcb = ParentFcb;
679
680 Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
681 Status = STATUS_SUCCESS;
682 } else {
683 Status = STATUS_OBJECT_NAME_NOT_FOUND;
684 _SEH2_LEAVE;
685 }
686
687 } else { // File / Dir already exists.
688
689 if (OpenTargetDirectory) {
690
691 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
692 Status = STATUS_MEDIA_WRITE_PROTECTED;
693 _SEH2_LEAVE;
694 }
695
696 Irp->IoStatus.Information = FILE_EXISTS;
697 Status = STATUS_SUCCESS;
698
699 RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
700 IrpSp->FileObject->FileName.MaximumLength);
701 IrpSp->FileObject->FileName.Length = RfsdMcb->ShortName.Length;
702
703 RtlCopyMemory( IrpSp->FileObject->FileName.Buffer,
704 RfsdMcb->ShortName.Buffer,
705 RfsdMcb->ShortName.Length );
706
707 //Let Mcb pointer to it's parent
708 RfsdMcb = RfsdMcb->Parent;
709
710 goto Openit;
711 }
712
713 // We can not create if one exists
714 if (CreateDisposition == FILE_CREATE) {
715 Irp->IoStatus.Information = FILE_EXISTS;
716 Status = STATUS_OBJECT_NAME_COLLISION;
717 _SEH2_LEAVE;
718 }
719
720 if(IsFlagOn(RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
721
722 if ((CreateDisposition != FILE_OPEN) &&
723 (CreateDisposition != FILE_OPEN_IF)) {
724
725 Status = STATUS_OBJECT_NAME_COLLISION;
726 _SEH2_LEAVE;
727 }
728
729 if (NonDirectoryFile) {
730 Status = STATUS_FILE_IS_A_DIRECTORY;
731 _SEH2_LEAVE;
732 }
733
734 if (RFSD_IS_ROOT_KEY(RfsdMcb->Key)) {
735
736 if (DeleteOnClose) {
737 Status = STATUS_CANNOT_DELETE;
738 _SEH2_LEAVE;
739 }
740
741 if (OpenTargetDirectory) {
742 Status = STATUS_INVALID_PARAMETER;
743 _SEH2_LEAVE;
744 }
745 }
746 }
747
748 Irp->IoStatus.Information = FILE_OPENED;
749 }
750
751 Openit:
752
753 if (RfsdMcb) {
754
755 Fcb = RfsdMcb->RfsdFcb;
756
757 if (!Fcb) {
758 Fcb = RfsdAllocateFcb (Vcb, RfsdMcb, Inode);
759 bFcbAllocated = TRUE;
760 }
761 }
762
763 if (Fcb) {
764
765 if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
766 Status = STATUS_FILE_DELETED;
767 _SEH2_LEAVE;
768 }
769
770 if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
771 Status = STATUS_DELETE_PENDING;
772 _SEH2_LEAVE;
773 }
774
775 if (bCreated) {
776 DbgBreak();
777 #if DISABLED // ONLY FOR WRITE SUPPORT?
778
779 //
780 // This file is just created.
781 //
782
783 if (DirectoryFile) {
784 UNICODE_STRING EntryName;
785 USHORT NameBuf[6];
786
787 RtlZeroMemory(&NameBuf, 6 * sizeof(USHORT));
788
789 EntryName.Length = EntryName.MaximumLength = 2;
790 EntryName.Buffer = &NameBuf[0];
791 NameBuf[0] = (USHORT)'.';
792
793 RfsdAddEntry( IrpContext, Vcb, Fcb,
794 RFSD_FT_DIR,
795 Fcb->RfsdMcb->Key,
796 &EntryName );
797
798 RfsdSaveInode( IrpContext, Vcb,
799 Fcb->RfsdMcb->Key,
800 Fcb->Inode );
801
802 EntryName.Length = EntryName.MaximumLength = 4;
803 EntryName.Buffer = &NameBuf[0];
804 NameBuf[0] = NameBuf[1] = (USHORT)'.';
805
806 RfsdAddEntry( IrpContext, Vcb, Fcb,
807 RFSD_FT_DIR,
808 Fcb->RfsdMcb->Parent->Inode,
809 &EntryName );
810
811 RfsdSaveInode( IrpContext, Vcb,
812 Fcb->RfsdMcb->Parent->Inode,
813 ParentFcb->Inode );
814 } else {
815 DbgBreak();
816 #if DISABLED
817 Status = RfsdExpandFile(
818 IrpContext, Vcb, Fcb,
819 &(Irp->Overlay.AllocationSize));
820 #endif
821
822 if (!NT_SUCCESS(Status)) {
823
824 DbgBreak();
825
826 _SEH2_LEAVE;
827 }
828 }
829 #endif
830 } else {
831
832 //
833 // This file alreayd exists.
834 //
835
836 if (DeleteOnClose) {
837
838 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
839 Status = STATUS_MEDIA_WRITE_PROTECTED;
840 _SEH2_LEAVE;
841 }
842
843 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
844 Status = STATUS_MEDIA_WRITE_PROTECTED;
845
846 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
847 Vcb->Vpb->RealDevice );
848
849 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
850
851 RfsdRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
852 }
853
854 SetFlag(Fcb->Flags, FCB_DELETE_ON_CLOSE);
855
856 } else {
857
858 //
859 // Just to Open file (Open/OverWrite ...)
860 //
861
862 if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags,
863 FO_NO_INTERMEDIATE_BUFFERING))) {
864 Fcb->Header.IsFastIoPossible = FastIoIsPossible;
865
866 if (IsFlagOn(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED) &&
867 (Fcb->SectionObject.DataSectionObject != NULL)) {
868
869 if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) {
870 /* IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) */
871
872 if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
873 CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
874 ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
875 }
876
877 CcPurgeCacheSection(&Fcb->SectionObject,
878 NULL,
879 0,
880 FALSE );
881 }
882 }
883 }
884 }
885 }
886
887 if (!IsDirectory(Fcb)) {
888 if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
889 if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile){
890 DesiredAccess |= DELETE;
891 } else if (((CreateDisposition == FILE_OVERWRITE) ||
892 (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) {
893 DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA |
894 FILE_WRITE_ATTRIBUTES );
895 }
896 }
897 }
898
899 if (Fcb->OpenHandleCount > 0) {
900 Status = IoCheckShareAccess( DesiredAccess,
901 ShareAccess,
902 IrpSp->FileObject,
903 &(Fcb->ShareAccess),
904 TRUE );
905
906 if (!NT_SUCCESS(Status)) {
907 _SEH2_LEAVE;
908 }
909 } else {
910 IoSetShareAccess( DesiredAccess,
911 ShareAccess,
912 IrpSp->FileObject,
913 &(Fcb->ShareAccess) );
914 }
915
916 Ccb = RfsdAllocateCcb();
917
918 Fcb->OpenHandleCount++;
919 Fcb->ReferenceCount++;
920
921 if (IsFlagOn(IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) {
922 Fcb->NonCachedOpenCount++;
923 }
924
925 Vcb->OpenFileHandleCount++;
926 Vcb->ReferenceCount++;
927
928 IrpSp->FileObject->FsContext = (void*)Fcb;
929 IrpSp->FileObject->FsContext2 = (void*) Ccb;
930 IrpSp->FileObject->PrivateCacheMap = NULL;
931 IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
932 IrpSp->FileObject->Vpb = Vcb->Vpb;
933
934 Status = STATUS_SUCCESS;
935
936 RfsdPrint((DBG_INFO, "RfsdCreateFile: %s OpenCount: %u ReferCount: %u\n",
937 Fcb->AnsiFileName.Buffer, Fcb->OpenHandleCount, Fcb->ReferenceCount));
938
939 if (!IsDirectory(Fcb) && !NoIntermediateBuffering ) {
940 IrpSp->FileObject->Flags |= FO_CACHE_SUPPORTED;
941 }
942
943 if (!bCreated && !IsDirectory(Fcb)) {
944 if ( DeleteOnClose ||
945 IsFlagOn(DesiredAccess, FILE_WRITE_DATA) ||
946 (CreateDisposition == FILE_OVERWRITE) ||
947 (CreateDisposition == FILE_OVERWRITE_IF)) {
948 if (!MmFlushImageSection( &Fcb->SectionObject,
949 MmFlushForWrite )) {
950
951 Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
952 STATUS_SHARING_VIOLATION;
953 _SEH2_LEAVE;
954 }
955 }
956
957 if ((CreateDisposition == FILE_SUPERSEDE) ||
958 (CreateDisposition == FILE_OVERWRITE) ||
959 (CreateDisposition == FILE_OVERWRITE_IF)) {
960
961 #if RFSD_READ_ONLY
962 Status = STATUS_MEDIA_WRITE_PROTECTED;
963 _SEH2_LEAVE;
964 #endif
965
966
967 #if DISABLED
968 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
969 Status = STATUS_MEDIA_WRITE_PROTECTED;
970 _SEH2_LEAVE;
971 }
972
973 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
974
975 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
976 Vcb->Vpb->RealDevice );
977 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
978
979 RfsdRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
980 }
981
982 Status = RfsdSupersedeOrOverWriteFile( IrpContext,
983 Vcb,
984 Fcb,
985 CreateDisposition );
986
987 if (NT_SUCCESS(Status)) {
988 _SEH2_LEAVE;
989 }
990
991 DbgBreak();
992 #if DISABLED
993 Status = RfsdExpandFile(
994 IrpContext,
995 Vcb,
996 Fcb,
997 &(Irp->Overlay.AllocationSize));
998 #endif
999
1000 if (!(NT_SUCCESS(Status))) {
1001 _SEH2_LEAVE;
1002 }
1003
1004 DbgBreak();
1005 #if DISABLED // dirctl.c
1006 RfsdNotifyReportChange(
1007 IrpContext,
1008 Vcb,
1009 Fcb,
1010 FILE_NOTIFY_CHANGE_LAST_WRITE |
1011 FILE_NOTIFY_CHANGE_ATTRIBUTES |
1012 FILE_NOTIFY_CHANGE_SIZE,
1013 FILE_ACTION_MODIFIED );
1014 #endif
1015
1016 if (CreateDisposition == FILE_SUPERSEDE) {
1017 Irp->IoStatus.Information = FILE_SUPERSEDED;
1018 } else {
1019 Irp->IoStatus.Information = FILE_OVERWRITTEN;
1020 }
1021 #endif
1022 }
1023 }
1024 }
1025 } _SEH2_FINALLY {
1026
1027 if (FileName.Buffer)
1028 ExFreePool(FileName.Buffer);
1029
1030 if (bParentFcbCreated) {
1031 ParentFcb->ReferenceCount--;
1032 }
1033
1034 if (VcbResourceAcquired) {
1035 ExReleaseResourceForThreadLite(
1036 &Vcb->MainResource,
1037 ExGetCurrentResourceThread() );
1038 }
1039
1040 if (!bFcbAllocated) {
1041 if (Inode)
1042 ExFreePool(Inode);
1043 } else {
1044 if (!Fcb && Inode)
1045 ExFreePool(Inode);
1046 }
1047 } _SEH2_END;
1048
1049 return Status;
1050 }
1051
1052 __drv_mustHoldCriticalRegion
1053 NTSTATUS
1054 RfsdCreateVolume(PRFSD_IRP_CONTEXT IrpContext, PRFSD_VCB Vcb)
1055 {
1056 PIO_STACK_LOCATION IrpSp;
1057 PIRP Irp;
1058
1059 NTSTATUS Status;
1060
1061 ACCESS_MASK DesiredAccess;
1062 ULONG ShareAccess;
1063
1064 ULONG Options;
1065 BOOLEAN DirectoryFile;
1066 BOOLEAN OpenTargetDirectory;
1067
1068 ULONG CreateDisposition;
1069
1070 PAGED_CODE();
1071
1072 RfsdPrint((DBG_FUNC, "Entering CreateVolume\n"));
1073
1074 Irp = IrpContext->Irp;
1075 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1076
1077 Options = IrpSp->Parameters.Create.Options;
1078
1079 DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
1080 OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
1081
1082 CreateDisposition = (Options >> 24) & 0x000000ff;
1083
1084 DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
1085 ShareAccess = IrpSp->Parameters.Create.ShareAccess;
1086
1087 if (DirectoryFile) {
1088 return STATUS_NOT_A_DIRECTORY;
1089 }
1090
1091 if (OpenTargetDirectory) {
1092 return STATUS_INVALID_PARAMETER;
1093 }
1094
1095 if ( (CreateDisposition != FILE_OPEN) &&
1096 (CreateDisposition != FILE_OPEN_IF) ) {
1097 return STATUS_ACCESS_DENIED;
1098 }
1099
1100 Status = STATUS_SUCCESS;
1101
1102 if (Vcb->OpenHandleCount > 0) {
1103 Status = IoCheckShareAccess( DesiredAccess, ShareAccess,
1104 IrpSp->FileObject,
1105 &(Vcb->ShareAccess), TRUE);
1106
1107 if (!NT_SUCCESS(Status)) {
1108 goto errorout;
1109 }
1110 } else {
1111 IoSetShareAccess( DesiredAccess, ShareAccess,
1112 IrpSp->FileObject,
1113 &(Vcb->ShareAccess) );
1114 }
1115
1116 if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)) {
1117 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
1118
1119 RfsdFlushFiles(Vcb, FALSE);
1120 RfsdFlushVolume(Vcb, FALSE);
1121
1122 ExReleaseResourceLite(&Vcb->MainResource);
1123 }
1124
1125 {
1126 PRFSD_CCB Ccb = RfsdAllocateCcb();
1127
1128 if (Ccb == NULL) {
1129 Status = STATUS_INSUFFICIENT_RESOURCES;
1130 goto errorout;
1131 }
1132
1133 IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
1134 IrpSp->FileObject->FsContext = Vcb;
1135 IrpSp->FileObject->FsContext2 = Ccb;
1136
1137 Vcb->ReferenceCount++;
1138 Vcb->OpenHandleCount++;
1139
1140 Irp->IoStatus.Information = FILE_OPENED;
1141 }
1142
1143 errorout:
1144
1145 return Status;
1146 }
1147
1148 __drv_mustHoldCriticalRegion
1149 NTSTATUS
1150 RfsdCreate (IN PRFSD_IRP_CONTEXT IrpContext)
1151 {
1152 PDEVICE_OBJECT DeviceObject;
1153 PIRP Irp;
1154 PIO_STACK_LOCATION IrpSp;
1155 PRFSD_VCB Vcb = 0;
1156 NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
1157 PRFSD_FCBVCB Xcb = NULL;
1158
1159 PAGED_CODE();
1160
1161 DeviceObject = IrpContext->DeviceObject;
1162
1163 Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
1164
1165 ASSERT(IsMounted(Vcb));
1166
1167 Irp = IrpContext->Irp;
1168
1169 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1170
1171 Xcb = (PRFSD_FCBVCB) (IrpSp->FileObject->FsContext);
1172
1173 if (DeviceObject == RfsdGlobal->DeviceObject) {
1174 RfsdPrint((DBG_INFO, "RfsdCreate: Create on main device object.\n"));
1175
1176 Status = STATUS_SUCCESS;
1177
1178 Irp->IoStatus.Information = FILE_OPENED;
1179
1180 RfsdUnpinRepinnedBcbs(IrpContext);
1181
1182 RfsdCompleteIrpContext(IrpContext, Status);
1183
1184 return Status;
1185 }
1186
1187 _SEH2_TRY {
1188
1189 if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
1190 Status = STATUS_ACCESS_DENIED;
1191
1192 if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
1193 Status = STATUS_VOLUME_DISMOUNTED;
1194 }
1195
1196 _SEH2_LEAVE;
1197 }
1198
1199 if ( ((IrpSp->FileObject->FileName.Length == 0) &&
1200 (IrpSp->FileObject->RelatedFileObject == NULL)) ||
1201 (Xcb && Xcb->Identifier.Type == RFSDVCB) ) {
1202 Status = RfsdCreateVolume(IrpContext, Vcb);
1203 } else {
1204 Status = RfsdCreateFile(IrpContext, Vcb);
1205 }
1206
1207 } _SEH2_FINALLY {
1208
1209 if (!IrpContext->ExceptionInProgress) {
1210 RfsdUnpinRepinnedBcbs(IrpContext);
1211
1212 RfsdCompleteIrpContext(IrpContext, Status);
1213 }
1214 } _SEH2_END;
1215
1216 return Status;
1217 }
1218
1219 #if !RFSD_READ_ONLY
1220
1221 NTSTATUS
1222 RfsdCreateInode(
1223 PRFSD_IRP_CONTEXT IrpContext,
1224 PRFSD_VCB Vcb,
1225 PRFSD_FCB ParentFcb,
1226 ULONG Type,
1227 ULONG FileAttr,
1228 PUNICODE_STRING FileName)
1229 {
1230 NTSTATUS Status;
1231 ULONG Inode;
1232 ULONG Group;
1233 RFSD_INODE RfsdIno;
1234
1235 PAGED_CODE();
1236 #if 0
1237 RtlZeroMemory(&RfsdIno, sizeof(RFSD_INODE));
1238
1239 DbgBreak();
1240 #if DISABLED
1241 Group = (ParentFcb->RfsdMcb->Inode - 1) / BLOCKS_PER_GROUP;
1242 #endif
1243
1244 RfsdPrint(( DBG_INFO,
1245 "RfsdCreateInode: %S in %S(Key=%x,%xh)\n",
1246 FileName->Buffer,
1247 ParentFcb->RfsdMcb->ShortName.Buffer,
1248 ParentFcb->RfsdMcb->Key.k_dir_id, ParentFcb->RfsdMcb->Key.k_objectid));
1249
1250 Status = RfsdNewInode(IrpContext, Vcb, Group,Type, &Inode);
1251
1252 if (!NT_SUCCESS(Status)) {
1253 goto errorout;
1254 }
1255
1256 Status = RfsdAddEntry(IrpContext, Vcb, ParentFcb, Type, Inode, FileName);
1257
1258 if (!NT_SUCCESS(Status)) {
1259 DbgBreak();
1260 RfsdFreeInode(IrpContext, Vcb, Inode, Type);
1261
1262 goto errorout;
1263 }
1264
1265 RfsdSaveInode(IrpContext, Vcb, ParentFcb->RfsdMcb->Inode, ParentFcb->Inode);
1266
1267 RfsdIno.i_ctime = ParentFcb->Inode->i_mtime;
1268 RfsdIno.i_mode = ( S_IPERMISSION_MASK &
1269 ParentFcb->Inode->i_mode );
1270 RfsdIno.i_uid = ParentFcb->Inode->i_uid;
1271 RfsdIno.i_gid = ParentFcb->Inode->i_gid;
1272
1273 //~ RfsdIno.i_dir_acl = ParentFcb->Inode->i_dir_acl;
1274 //~ RfsdIno.i_file_acl = ParentFcb->Inode->i_file_acl;
1275 RfsdIno.u.i_generation = ParentFcb->Inode->u.i_generation;
1276
1277 //~ RfsdIno.osd2 = ParentFcb->Inode->osd2;
1278
1279 if (IsFlagOn(FileAttr, FILE_ATTRIBUTE_READONLY)) {
1280 RfsdSetReadOnly(RfsdIno.i_mode);
1281 }
1282
1283 if (Type == RFSD_FT_DIR) {
1284 RfsdIno.i_mode |= S_IFDIR;
1285 RfsdIno.i_links_count = 2;
1286 } else if (Type == RFSD_FT_REG_FILE) {
1287 RfsdIno.i_mode |= S_IFREG;
1288 RfsdIno.i_links_count = 1;
1289 } else {
1290 DbgBreak();
1291 RfsdIno.i_links_count = 1;
1292 }
1293
1294 RfsdSaveInode(IrpContext, Vcb, Inode, &RfsdIno);
1295
1296 RfsdPrint((DBG_INFO, "RfsdCreateInode: New Inode = %xh (Type=%xh)\n", Inode, Type));
1297
1298 errorout:
1299 #endif // 0
1300 return 0;//Status;
1301 }
1302
1303 NTSTATUS
1304 RfsdSupersedeOrOverWriteFile(
1305 PRFSD_IRP_CONTEXT IrpContext,
1306 PRFSD_VCB Vcb,
1307 PRFSD_FCB Fcb,
1308 ULONG Disposition)
1309 {
1310 LARGE_INTEGER CurrentTime;
1311 LARGE_INTEGER AllocationSize;
1312 NTSTATUS Status = STATUS_SUCCESS;
1313
1314 PAGED_CODE();
1315 #if 0
1316 KeQuerySystemTime(&CurrentTime);
1317
1318 AllocationSize.QuadPart = (LONGLONG)0;
1319
1320 if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(AllocationSize))) {
1321 Status = STATUS_USER_MAPPED_FILE;
1322 return Status;
1323 }
1324
1325 DbgBreak();
1326 #if DISABLED
1327 Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
1328 #endif
1329
1330 if (NT_SUCCESS(Status)) {
1331 Fcb->Header.AllocationSize.QuadPart =
1332 Fcb->Header.FileSize.QuadPart = (LONGLONG) 0;
1333
1334 Fcb->Inode->i_size = 0;
1335
1336 if (S_ISREG(Fcb->Inode->i_mode)) {
1337 KdPrint(("Reminder: Fcb->Inode->i_size_high = 0;\n"));
1338 //~Fcb->Inode->i_size_high = 0;
1339 }
1340
1341 if (Disposition == FILE_SUPERSEDE)
1342 Fcb->Inode->i_ctime = RfsdInodeTime(CurrentTime);
1343
1344 Fcb->Inode->i_atime =
1345 Fcb->Inode->i_mtime = RfsdInodeTime(CurrentTime);
1346 } else {
1347 LARGE_INTEGER iSize;
1348
1349 iSize.QuadPart = (LONGLONG) Fcb->Inode->i_size;
1350
1351 if (S_ISREG(Fcb->Inode->i_mode))
1352 KdPrint(("Reminder: Fcb->Inode->i_size_high = 0;\n"));
1353 //~ iSize.HighPart = (LONG)(Fcb->Inode->i_size_high);
1354
1355 if (iSize.QuadPart > Fcb->Header.AllocationSize.QuadPart)
1356 iSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
1357
1358 Fcb->Header.FileSize.QuadPart = iSize.QuadPart;
1359
1360 Fcb->Inode->i_size = iSize.LowPart;
1361 //~ Fcb->Inode->i_size_high = (ULONG) iSize.HighPart;
1362 }
1363
1364 RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
1365 #endif // 0
1366 return Status;
1367 }
1368
1369 #endif // !RFSD_READ_ONLY
1370
1371 /**
1372 Searches to find if the name if is located in the dentry span within the block.
1373
1374 STATUS_SUCCESS if the name was not found, but processing should continue
1375 STATUS_EVENT_DONE if the name was found, and processing should stop
1376 */
1377 NTSTATUS
1378 RfsdScanDirCallback(
1379 ULONG BlockNumber,
1380 PVOID pContext )
1381 {
1382 PRFSD_SCANDIR_CALLBACK_CONTEXT pCallbackContext = (PRFSD_SCANDIR_CALLBACK_CONTEXT) pContext;
1383 RFSD_KEY_IN_MEMORY DirectoryKey;
1384 PUCHAR pBlockBuffer = NULL;
1385 PRFSD_ITEM_HEAD pDirectoryItemHeader = NULL;
1386 PUCHAR pDirectoryItemBuffer = NULL;
1387 NTSTATUS Status;
1388 BOOLEAN bFound = FALSE;
1389 PRFSD_DENTRY_HEAD pPrevDentry = NULL;
1390 ULONG idxDentryInSpan = 0;
1391 UNICODE_STRING InodeFileName;
1392 USHORT InodeFileNameLength;
1393
1394 PAGED_CODE();
1395
1396 InodeFileName.Buffer = NULL;
1397
1398 RfsdPrint((DBG_FUNC, /*__FUNCTION__*/ " invoked on block %i\n", BlockNumber));
1399
1400
1401 _SEH2_TRY {
1402
1403 // Load the block
1404 pBlockBuffer = RfsdAllocateAndLoadBlock(pCallbackContext->Vcb, BlockNumber);
1405 if (!pBlockBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
1406
1407 // Construct the item key to search for
1408 DirectoryKey = *(pCallbackContext->pDirectoryKey);
1409 DirectoryKey.k_type = RFSD_KEY_TYPE_v2_DIRENTRY;
1410
1411 // Get the item header and its information
1412 Status = RfsdFindItemHeaderInBlock(
1413 pCallbackContext->Vcb, &DirectoryKey, pBlockBuffer,
1414 ( &pDirectoryItemHeader ), //<
1415 &CompareKeysWithoutOffset
1416 );
1417
1418 // If this block doesn't happen to contain a directory item, skip it.
1419 if ( (Status == STATUS_NO_SUCH_MEMBER) || !pDirectoryItemHeader )
1420 {
1421 KdPrint(("Block %i did not contain the appropriate diritem header\n", BlockNumber));
1422 Status = STATUS_SUCCESS; _SEH2_LEAVE;
1423 }
1424
1425 // Setup the item buffer
1426 pDirectoryItemBuffer = (PUCHAR) pBlockBuffer + pDirectoryItemHeader->ih_item_location;
1427
1428
1429
1430 // Allocate the unicode filename buffer
1431 InodeFileName.Buffer = ExAllocatePoolWithTag(PagedPool, (RFSD_NAME_LEN + 1) * 2, RFSD_POOL_TAG);
1432 if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
1433
1434
1435 while (!bFound && (idxDentryInSpan < pDirectoryItemHeader->u.ih_entry_count) ) {
1436 OEM_STRING OemName;
1437
1438 //
1439 // reading dir entries from Dcb
1440 //
1441
1442 PRFSD_DENTRY_HEAD pCurrentDentry = (PRFSD_DENTRY_HEAD) (pDirectoryItemBuffer + (idxDentryInSpan * sizeof(RFSD_DENTRY_HEAD)));
1443
1444 // Skip the directory entry for the parent of the root directory (because it should not be shown, and has no stat data)
1445 // (NOTE: Any change made here should also be mirrored in RfsdDirControlCallback)
1446 if (pCurrentDentry->deh_dir_id == 0 /*&& pCurrentDentry->deh_objectid == 1*/)
1447 { goto ProcessNextEntry; }
1448
1449 // Retrieve the filename of the loaded directory entry from the buffer (encoded with the codepage)
1450 // NOTE: The filename is not gauranteed to be null-terminated, and so the end may implicitly be the start of the previous entry.
1451 OemName.Buffer = (PUCHAR) pDirectoryItemBuffer + pCurrentDentry->deh_location;
1452 OemName.MaximumLength = (pPrevDentry ? pPrevDentry->deh_location : // The end of this entry is the start of the previous
1453 pDirectoryItemHeader->ih_item_len // Otherwise this is the first entry, the end of which is the end of the item.
1454 ) - pCurrentDentry->deh_location;
1455 OemName.Length = RfsdStringLength(OemName.Buffer, OemName.MaximumLength);
1456
1457
1458
1459 // Convert that name to unicode
1460 {
1461 InodeFileNameLength = (USHORT) RfsdOEMToUnicodeSize(&OemName) + 2;
1462
1463 // If the unicode InodeFileName.Buffer is not large enough, expand it
1464 if (InodeFileName.MaximumLength < InodeFileNameLength)
1465 {
1466 // Free the existing buffer
1467 if (InodeFileName.Buffer) { ExFreePool(InodeFileName.Buffer); }
1468
1469 // Allocate a new larger buffer
1470 InodeFileName.Buffer = ExAllocatePoolWithTag(PagedPool, InodeFileNameLength, RFSD_POOL_TAG);
1471 if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
1472 InodeFileName.MaximumLength = InodeFileNameLength;
1473 }
1474
1475 InodeFileName.Length = 0;
1476
1477 RtlZeroMemory( InodeFileName.Buffer, InodeFileNameLength);
1478
1479 Status = RfsdOEMToUnicode(
1480 &InodeFileName,
1481 &OemName );
1482
1483 if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
1484 }
1485
1486
1487 // Compare it to the name we are searching for
1488 if (!RtlCompareUnicodeString(
1489 pCallbackContext->pTargetFilename,
1490 &InodeFileName,
1491 TRUE )) {
1492 // This entry MATCHED! Copy the matching dentry into the output field on the context
1493 bFound = TRUE;
1494
1495 *(pCallbackContext->pMatchingIndex) = (pCallbackContext->idxCurrentDentry * sizeof(RFSD_DENTRY_HEAD));
1496 RtlCopyMemory(pCallbackContext->pMatchingDentry, pCurrentDentry, sizeof(RFSD_DENTRY_HEAD));
1497
1498 RfsdPrint(( DBG_INFO, /*__FUNCTION__*/ ": Found: Name=%S Key=%xh,%xh\n",
1499 InodeFileName.Buffer, pCurrentDentry->deh_dir_id, pCurrentDentry->deh_objectid ));
1500
1501 Status = STATUS_EVENT_DONE;
1502 break;
1503 }
1504
1505 ProcessNextEntry:
1506 // Advance to the next directory entry
1507 pPrevDentry = pCurrentDentry;
1508 ++idxDentryInSpan;
1509 ++(pCallbackContext->idxCurrentDentry);
1510 }
1511
1512 if (!bFound) {
1513 // Indicate success, so that parsing will continue with subsequent blocks.
1514 Status = STATUS_SUCCESS;
1515 }
1516 } _SEH2_FINALLY {
1517 if (pBlockBuffer) ExFreePool(pBlockBuffer);
1518 if (InodeFileName.Buffer) ExFreePool(InodeFileName.Buffer);
1519 } _SEH2_END;
1520
1521
1522 return Status;
1523
1524 }