[USBOHCI_NEW][USBUHCI_NEW] Avoid unnecessary/incorrect status defines.
[reactos.git] / drivers / filesystems / ffs / src / fileinfo.c
1 /*
2 * FFS File System Driver for Windows
3 *
4 * fileinfo.c
5 *
6 * 2004.5.6 ~
7 *
8 * Lee Jae-Hong, http://www.pyrasis.com
9 *
10 * See License.txt
11 *
12 */
13
14 #include "ntifs.h"
15 #include "ffsdrv.h"
16
17 /* Globals */
18
19 extern PFFS_GLOBAL FFSGlobal;
20
21
22 /* Definitions */
23
24 #ifdef ALLOC_PRAGMA
25 #pragma alloc_text(PAGE, FFSQueryInformation)
26 #pragma alloc_text(PAGE, FFSSetInformation)
27 #pragma alloc_text(PAGE, FFSExpandFile)
28 #pragma alloc_text(PAGE, FFSTruncateFile)
29 #pragma alloc_text(PAGE, FFSSetDispositionInfo)
30 #pragma alloc_text(PAGE, FFSSetRenameInfo)
31 #pragma alloc_text(PAGE, FFSDeleteFile)
32 #endif
33
34
35 __drv_mustHoldCriticalRegion
36 NTSTATUS
37 FFSQueryInformation(
38 IN PFFS_IRP_CONTEXT IrpContext)
39 {
40 PDEVICE_OBJECT DeviceObject;
41 NTSTATUS Status = STATUS_UNSUCCESSFUL;
42 PFILE_OBJECT FileObject;
43 PFFS_VCB Vcb;
44 PFFS_FCB Fcb = 0;
45 PFFS_CCB Ccb;
46 PIRP Irp;
47 PIO_STACK_LOCATION IoStackLocation;
48 FILE_INFORMATION_CLASS FileInformationClass;
49 ULONG Length;
50 PVOID Buffer;
51 BOOLEAN FcbResourceAcquired = FALSE;
52
53 PAGED_CODE();
54
55 _SEH2_TRY
56 {
57 ASSERT(IrpContext != NULL);
58
59 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
60 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
61
62 DeviceObject = IrpContext->DeviceObject;
63
64 //
65 // This request is not allowed on the main device object
66 //
67 if (DeviceObject == FFSGlobal->DeviceObject)
68 {
69 Status = STATUS_INVALID_DEVICE_REQUEST;
70 _SEH2_LEAVE;
71 }
72
73 FileObject = IrpContext->FileObject;
74
75 Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
76
77 ASSERT(Vcb != NULL);
78
79 Fcb = (PFFS_FCB)FileObject->FsContext;
80
81 ASSERT(Fcb != NULL);
82
83 //
84 // This request is not allowed on volumes
85 //
86 if (Fcb->Identifier.Type == FFSVCB)
87 {
88 Status = STATUS_INVALID_PARAMETER;
89 _SEH2_LEAVE;
90 }
91
92 ASSERT((Fcb->Identifier.Type == FFSFCB) &&
93 (Fcb->Identifier.Size == sizeof(FFS_FCB)));
94 /*
95 if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) &&
96 !FlagOn(Fcb->Flags, FCB_PAGE_FILE))
97 */
98 {
99 if (!ExAcquireResourceSharedLite(
100 &Fcb->MainResource,
101 IrpContext->IsSynchronous))
102 {
103 Status = STATUS_PENDING;
104 _SEH2_LEAVE;
105 }
106
107 FcbResourceAcquired = TRUE;
108 }
109
110 Ccb = (PFFS_CCB)FileObject->FsContext2;
111
112 ASSERT(Ccb != NULL);
113
114 ASSERT((Ccb->Identifier.Type == FFSCCB) &&
115 (Ccb->Identifier.Size == sizeof(FFS_CCB)));
116
117 Irp = IrpContext->Irp;
118
119 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
120
121 FileInformationClass =
122 IoStackLocation->Parameters.QueryFile.FileInformationClass;
123
124 Length = IoStackLocation->Parameters.QueryFile.Length;
125
126 Buffer = Irp->AssociatedIrp.SystemBuffer;
127
128 RtlZeroMemory(Buffer, Length);
129
130 switch (FileInformationClass)
131 {
132 case FileBasicInformation:
133 {
134 PFILE_BASIC_INFORMATION FileBasicInformation;
135
136 if (Length < sizeof(FILE_BASIC_INFORMATION))
137 {
138 Status = STATUS_INFO_LENGTH_MISMATCH;
139 _SEH2_LEAVE;
140 }
141
142 FileBasicInformation = (PFILE_BASIC_INFORMATION)Buffer;
143
144 if (FS_VERSION == 1)
145 {
146 FileBasicInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
147
148 FileBasicInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
149
150 FileBasicInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
151
152 FileBasicInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
153 }
154 else
155 {
156 FileBasicInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
157
158 FileBasicInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
159
160 FileBasicInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
161
162 FileBasicInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
163 }
164
165 FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
166
167 Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
168 Status = STATUS_SUCCESS;
169 _SEH2_LEAVE;
170 }
171
172 #if (_WIN32_WINNT >= 0x0500)
173
174 case FileAttributeTagInformation:
175 {
176 PFILE_ATTRIBUTE_TAG_INFORMATION FATI;
177
178 if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION))
179 {
180 Status = STATUS_INFO_LENGTH_MISMATCH;
181 _SEH2_LEAVE;
182 }
183
184 FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer;
185
186 FATI->FileAttributes = Fcb->FFSMcb->FileAttr;
187 FATI->ReparseTag = 0;
188
189 Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
190 Status = STATUS_SUCCESS;
191 _SEH2_LEAVE;
192 }
193 #endif // (_WIN32_WINNT >= 0x0500)
194
195 case FileStandardInformation:
196 {
197 PFILE_STANDARD_INFORMATION FileStandardInformation;
198
199 if (Length < sizeof(FILE_STANDARD_INFORMATION))
200 {
201 Status = STATUS_INFO_LENGTH_MISMATCH;
202 _SEH2_LEAVE;
203 }
204
205 FileStandardInformation = (PFILE_STANDARD_INFORMATION)Buffer;
206
207 if (FS_VERSION == 1)
208 {
209 FileStandardInformation->AllocationSize.QuadPart =
210 (LONGLONG)(Fcb->dinode1->di_size);
211
212 FileStandardInformation->EndOfFile.QuadPart =
213 (LONGLONG)(Fcb->dinode1->di_size);
214
215 FileStandardInformation->NumberOfLinks = Fcb->dinode1->di_nlink;
216 }
217 else
218 {
219 FileStandardInformation->AllocationSize.QuadPart =
220 (LONGLONG)(Fcb->dinode2->di_size);
221
222 FileStandardInformation->EndOfFile.QuadPart =
223 (LONGLONG)(Fcb->dinode2->di_size);
224
225 FileStandardInformation->NumberOfLinks = Fcb->dinode2->di_nlink;
226 }
227
228 if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
229 FileStandardInformation->DeletePending = FALSE;
230 else
231 FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
232
233 if (Fcb->FFSMcb->FileAttr & FILE_ATTRIBUTE_DIRECTORY)
234 {
235 FileStandardInformation->Directory = TRUE;
236 }
237 else
238 {
239 FileStandardInformation->Directory = FALSE;
240 }
241
242 Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
243 Status = STATUS_SUCCESS;
244 _SEH2_LEAVE;
245 }
246
247 case FileInternalInformation:
248 {
249 PFILE_INTERNAL_INFORMATION FileInternalInformation;
250
251 if (Length < sizeof(FILE_INTERNAL_INFORMATION))
252 {
253 Status = STATUS_INFO_LENGTH_MISMATCH;
254 _SEH2_LEAVE;
255 }
256
257 FileInternalInformation = (PFILE_INTERNAL_INFORMATION)Buffer;
258
259 // The "inode number"
260 FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Fcb->FFSMcb->Inode;
261
262 Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION);
263 Status = STATUS_SUCCESS;
264 _SEH2_LEAVE;
265 }
266
267 case FileEaInformation:
268 {
269 PFILE_EA_INFORMATION FileEaInformation;
270
271 if (Length < sizeof(FILE_EA_INFORMATION))
272 {
273 Status = STATUS_INFO_LENGTH_MISMATCH;
274 _SEH2_LEAVE;
275 }
276
277 FileEaInformation = (PFILE_EA_INFORMATION)Buffer;
278
279 // Romfs doesn't have any extended attributes
280 FileEaInformation->EaSize = 0;
281
282 Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION);
283 Status = STATUS_SUCCESS;
284 _SEH2_LEAVE;
285 }
286
287 case FileNameInformation:
288 {
289 PFILE_NAME_INFORMATION FileNameInformation;
290
291 if (Length < sizeof(FILE_NAME_INFORMATION) +
292 Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR))
293 {
294 Status = STATUS_INFO_LENGTH_MISMATCH;
295 _SEH2_LEAVE;
296 }
297
298 FileNameInformation = (PFILE_NAME_INFORMATION)Buffer;
299
300 FileNameInformation->FileNameLength = Fcb->FFSMcb->ShortName.Length;
301
302 RtlCopyMemory(
303 FileNameInformation->FileName,
304 Fcb->FFSMcb->ShortName.Buffer,
305 Fcb->FFSMcb->ShortName.Length);
306
307 Irp->IoStatus.Information = sizeof(FILE_NAME_INFORMATION) +
308 Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR);
309 Status = STATUS_SUCCESS;
310 _SEH2_LEAVE;
311 }
312
313 case FilePositionInformation:
314 {
315 PFILE_POSITION_INFORMATION FilePositionInformation;
316
317 if (Length < sizeof(FILE_POSITION_INFORMATION))
318 {
319 Status = STATUS_INFO_LENGTH_MISMATCH;
320 _SEH2_LEAVE;
321 }
322
323 FilePositionInformation = (PFILE_POSITION_INFORMATION)Buffer;
324
325 FilePositionInformation->CurrentByteOffset =
326 FileObject->CurrentByteOffset;
327
328 Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
329 Status = STATUS_SUCCESS;
330 _SEH2_LEAVE;
331 }
332
333 case FileAllInformation:
334 {
335 PFILE_ALL_INFORMATION FileAllInformation;
336 PFILE_BASIC_INFORMATION FileBasicInformation;
337 PFILE_STANDARD_INFORMATION FileStandardInformation;
338 PFILE_INTERNAL_INFORMATION FileInternalInformation;
339 PFILE_EA_INFORMATION FileEaInformation;
340 PFILE_POSITION_INFORMATION FilePositionInformation;
341 PFILE_NAME_INFORMATION FileNameInformation;
342
343 if (Length < sizeof(FILE_ALL_INFORMATION))
344 {
345 Status = STATUS_INFO_LENGTH_MISMATCH;
346 _SEH2_LEAVE;
347 }
348
349 FileAllInformation = (PFILE_ALL_INFORMATION)Buffer;
350
351 FileBasicInformation =
352 &FileAllInformation->BasicInformation;
353
354 FileStandardInformation =
355 &FileAllInformation->StandardInformation;
356
357 FileInternalInformation =
358 &FileAllInformation->InternalInformation;
359
360 FileEaInformation =
361 &FileAllInformation->EaInformation;
362
363 FilePositionInformation =
364 &FileAllInformation->PositionInformation;
365
366 FileNameInformation =
367 &FileAllInformation->NameInformation;
368
369 if (FS_VERSION == 1)
370 {
371 FileBasicInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
372
373 FileBasicInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
374
375 FileBasicInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
376
377 FileBasicInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
378
379 FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
380
381 FileStandardInformation->AllocationSize.QuadPart =
382 (LONGLONG)(Fcb->dinode1->di_size);
383
384 FileStandardInformation->EndOfFile.QuadPart =
385 (LONGLONG)(Fcb->dinode1->di_size);
386
387 FileStandardInformation->NumberOfLinks = Fcb->dinode1->di_nlink;
388 }
389 else
390 {
391 FileBasicInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
392
393 FileBasicInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
394
395 FileBasicInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
396
397 FileBasicInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
398
399 FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
400
401 FileStandardInformation->AllocationSize.QuadPart =
402 (LONGLONG)(Fcb->dinode2->di_size);
403
404 FileStandardInformation->EndOfFile.QuadPart =
405 (LONGLONG)(Fcb->dinode2->di_size);
406
407 FileStandardInformation->NumberOfLinks = Fcb->dinode2->di_nlink;
408 }
409
410 if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
411 FileStandardInformation->DeletePending = FALSE;
412 else
413 FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
414
415 if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
416 {
417 FileStandardInformation->Directory = TRUE;
418 }
419 else
420 {
421 FileStandardInformation->Directory = FALSE;
422 }
423
424 // The "inode number"
425 FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Fcb->FFSMcb->Inode;
426
427 // Romfs doesn't have any extended attributes
428 FileEaInformation->EaSize = 0;
429
430 FilePositionInformation->CurrentByteOffset =
431 FileObject->CurrentByteOffset;
432
433 if (Length < sizeof(FILE_ALL_INFORMATION) +
434 Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR))
435 {
436 Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION);
437 Status = STATUS_BUFFER_OVERFLOW;
438 _SEH2_LEAVE;
439 }
440
441 FileNameInformation->FileNameLength = Fcb->FFSMcb->ShortName.Length;
442
443 RtlCopyMemory(
444 FileNameInformation->FileName,
445 Fcb->FFSMcb->ShortName.Buffer,
446 Fcb->FFSMcb->ShortName.Length);
447
448 Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) +
449 Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR);
450 Status = STATUS_SUCCESS;
451 _SEH2_LEAVE;
452 }
453
454 /*
455 case FileAlternateNameInformation:
456 {
457 // TODO: Handle FileAlternateNameInformation
458
459 // Here we would like to use RtlGenerate8dot3Name but I don't
460 // know how to use the argument PGENERATE_NAME_CONTEXT
461 }
462 */
463
464 case FileNetworkOpenInformation:
465 {
466 PFILE_NETWORK_OPEN_INFORMATION FileNetworkOpenInformation;
467
468 if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION))
469 {
470 Status = STATUS_INFO_LENGTH_MISMATCH;
471 _SEH2_LEAVE;
472 }
473
474 FileNetworkOpenInformation =
475 (PFILE_NETWORK_OPEN_INFORMATION)Buffer;
476
477 if (FS_VERSION == 1)
478 {
479 FileNetworkOpenInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
480
481 FileNetworkOpenInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
482
483 FileNetworkOpenInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
484
485 FileNetworkOpenInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
486
487 FileNetworkOpenInformation->AllocationSize.QuadPart =
488 (LONGLONG)(Fcb->dinode1->di_size);
489
490 FileNetworkOpenInformation->EndOfFile.QuadPart =
491 (LONGLONG)(Fcb->dinode1->di_size);
492 }
493 else
494 {
495 FileNetworkOpenInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
496
497 FileNetworkOpenInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
498
499 FileNetworkOpenInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
500
501 FileNetworkOpenInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
502
503 FileNetworkOpenInformation->AllocationSize.QuadPart =
504 (LONGLONG)(Fcb->dinode2->di_size);
505
506 FileNetworkOpenInformation->EndOfFile.QuadPart =
507 (LONGLONG)(Fcb->dinode2->di_size);
508 }
509
510 FileNetworkOpenInformation->FileAttributes =
511 Fcb->FFSMcb->FileAttr;
512
513 Irp->IoStatus.Information =
514 sizeof(FILE_NETWORK_OPEN_INFORMATION);
515 Status = STATUS_SUCCESS;
516 _SEH2_LEAVE;
517 }
518
519 default:
520 Status = STATUS_INVALID_INFO_CLASS;
521 }
522 }
523 _SEH2_FINALLY
524 {
525 if (FcbResourceAcquired)
526 {
527 ExReleaseResourceForThreadLite(
528 &Fcb->MainResource,
529 ExGetCurrentResourceThread());
530 }
531
532 if (!IrpContext->ExceptionInProgress)
533 {
534 if (Status == STATUS_PENDING)
535 {
536 FFSQueueRequest(IrpContext);
537 }
538 else
539 {
540 FFSCompleteIrpContext(IrpContext, Status);
541 }
542 }
543 } _SEH2_END;
544
545 return Status;
546 }
547
548
549 __drv_mustHoldCriticalRegion
550 NTSTATUS
551 FFSSetInformation(
552 IN PFFS_IRP_CONTEXT IrpContext)
553 {
554 PDEVICE_OBJECT DeviceObject;
555 NTSTATUS Status = STATUS_UNSUCCESSFUL;
556 PFFS_VCB Vcb = 0;
557 PFILE_OBJECT FileObject;
558 PFFS_FCB Fcb = 0;
559 PFFS_CCB Ccb;
560 PIRP Irp;
561 PIO_STACK_LOCATION IoStackLocation;
562 FILE_INFORMATION_CLASS FileInformationClass;
563
564 ULONG NotifyFilter = 0;
565
566 ULONG Length;
567 PVOID Buffer;
568 BOOLEAN FcbMainResourceAcquired = FALSE;
569
570 BOOLEAN VcbResourceAcquired = FALSE;
571 BOOLEAN FcbPagingIoResourceAcquired = FALSE;
572
573 PAGED_CODE();
574
575 _SEH2_TRY
576 {
577 ASSERT(IrpContext != NULL);
578
579 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
580 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
581
582 DeviceObject = IrpContext->DeviceObject;
583
584 //
585 // This request is not allowed on the main device object
586 //
587 if (DeviceObject == FFSGlobal->DeviceObject)
588 {
589 Status = STATUS_INVALID_DEVICE_REQUEST;
590 _SEH2_LEAVE;
591 }
592
593 Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
594
595 ASSERT(Vcb != NULL);
596
597 ASSERT((Vcb->Identifier.Type == FFSVCB) &&
598 (Vcb->Identifier.Size == sizeof(FFS_VCB)));
599
600 ASSERT(IsMounted(Vcb));
601
602 FileObject = IrpContext->FileObject;
603
604 Fcb = (PFFS_FCB)FileObject->FsContext;
605
606 ASSERT(Fcb != NULL);
607
608 //
609 // This request is not allowed on volumes
610 //
611 if (Fcb->Identifier.Type == FFSVCB)
612 {
613 FFSBreakPoint();
614
615 Status = STATUS_INVALID_PARAMETER;
616 _SEH2_LEAVE;
617 }
618
619 ASSERT((Fcb->Identifier.Type == FFSFCB) &&
620 (Fcb->Identifier.Size == sizeof(FFS_FCB)));
621
622 if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
623 {
624 Status = STATUS_FILE_DELETED;
625 _SEH2_LEAVE;
626 }
627
628 Ccb = (PFFS_CCB)FileObject->FsContext2;
629
630 ASSERT(Ccb != NULL);
631
632 ASSERT((Ccb->Identifier.Type == FFSCCB) &&
633 (Ccb->Identifier.Size == sizeof(FFS_CCB)));
634
635 Irp = IrpContext->Irp;
636
637 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
638
639 FileInformationClass =
640 IoStackLocation->Parameters.SetFile.FileInformationClass;
641
642 Length = IoStackLocation->Parameters.SetFile.Length;
643
644 Buffer = Irp->AssociatedIrp.SystemBuffer;
645
646 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
647 {
648 if (FileInformationClass == FileDispositionInformation ||
649 FileInformationClass == FileRenameInformation ||
650 FileInformationClass == FileLinkInformation)
651 {
652 #ifdef _MSC_VER
653 #pragma prefast( suppress: 28137, "by design" )
654 #endif
655 if (!ExAcquireResourceExclusiveLite(
656 &Vcb->MainResource,
657 IrpContext->IsSynchronous))
658 {
659 Status = STATUS_PENDING;
660 _SEH2_LEAVE;
661 }
662
663 VcbResourceAcquired = TRUE;
664 }
665 }
666 else if (!FlagOn(Fcb->Flags, FCB_PAGE_FILE))
667 {
668 #ifdef _MSC_VER
669 #pragma prefast( suppress: 28137, "by design" )
670 #endif
671 if (!ExAcquireResourceExclusiveLite(
672 &Fcb->MainResource,
673 IrpContext->IsSynchronous))
674 {
675 Status = STATUS_PENDING;
676 _SEH2_LEAVE;
677 }
678
679 FcbMainResourceAcquired = TRUE;
680 }
681
682 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
683 {
684 if (FileInformationClass != FilePositionInformation)
685 {
686 Status = STATUS_MEDIA_WRITE_PROTECTED;
687 _SEH2_LEAVE;
688 }
689 }
690
691 if (FileInformationClass == FileDispositionInformation ||
692 FileInformationClass == FileRenameInformation ||
693 FileInformationClass == FileLinkInformation ||
694 FileInformationClass == FileAllocationInformation ||
695 FileInformationClass == FileEndOfFileInformation)
696 {
697 #ifdef _MSC_VER
698 #pragma prefast( suppress: 28137, "by design" )
699 #endif
700 if (!ExAcquireResourceExclusiveLite(
701 &Fcb->PagingIoResource,
702 IrpContext->IsSynchronous))
703 {
704 Status = STATUS_PENDING;
705 _SEH2_LEAVE;
706 }
707
708 FcbPagingIoResourceAcquired = TRUE;
709 }
710
711 /*
712 if (FileInformationClass != FileDispositionInformation
713 && FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
714 {
715 Status = STATUS_DELETE_PENDING;
716 _SEH2_LEAVE;
717 }
718 */
719
720 switch (FileInformationClass)
721 {
722
723 #if !FFS_READ_ONLY
724
725 case FileBasicInformation:
726 {
727 PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION)Buffer;
728
729 if (FS_VERSION == 1)
730 {
731 PFFSv1_INODE dinode1 = Fcb->dinode1;
732
733 if(FBI->CreationTime.QuadPart)
734 {
735 dinode1->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime));
736 }
737
738 if(FBI->LastAccessTime.QuadPart)
739 {
740 dinode1->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime));
741 }
742
743 if(FBI->LastWriteTime.QuadPart)
744 {
745 dinode1->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime));
746 }
747
748 if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY))
749 {
750 FFSSetReadOnly(Fcb->dinode1->di_mode);
751 SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
752 }
753 else
754 {
755 FFSSetWritable(Fcb->dinode1->di_mode);
756 ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
757 }
758
759 if(FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1))
760 {
761 Status = STATUS_SUCCESS;
762 }
763
764 if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY)
765 {
766 SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
767 }
768 else
769 {
770 ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
771 }
772 }
773 else
774 {
775 PFFSv2_INODE dinode2 = Fcb->dinode2;
776
777 if(FBI->CreationTime.QuadPart)
778 {
779 dinode2->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime));
780 }
781
782 if(FBI->LastAccessTime.QuadPart)
783 {
784 dinode2->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime));
785 }
786
787 if(FBI->LastWriteTime.QuadPart)
788 {
789 dinode2->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime));
790 }
791
792 if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY))
793 {
794 FFSSetReadOnly(Fcb->dinode2->di_mode);
795 SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
796 }
797 else
798 {
799 FFSSetWritable(Fcb->dinode2->di_mode);
800 ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
801 }
802
803 if(FFSv2SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode2))
804 {
805 Status = STATUS_SUCCESS;
806 }
807
808 if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY)
809 {
810 SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
811 }
812 else
813 {
814 ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
815 }
816 }
817
818 NotifyFilter = FILE_NOTIFY_CHANGE_ATTRIBUTES |
819 FILE_NOTIFY_CHANGE_CREATION |
820 FILE_NOTIFY_CHANGE_LAST_ACCESS |
821 FILE_NOTIFY_CHANGE_LAST_WRITE ;
822
823 Status = STATUS_SUCCESS;
824 }
825 break;
826
827 case FileAllocationInformation:
828 {
829 PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer;
830
831 if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
832 {
833 Status = STATUS_INVALID_DEVICE_REQUEST;
834 _SEH2_LEAVE;
835 }
836
837 if (FAI->AllocationSize.QuadPart ==
838 Fcb->Header.AllocationSize.QuadPart)
839 {
840 Status = STATUS_SUCCESS;
841 }
842 else if (FAI->AllocationSize.QuadPart >
843 Fcb->Header.AllocationSize.QuadPart)
844 {
845 if(FFSExpandFile(IrpContext,
846 Vcb, Fcb,
847 &(FAI->AllocationSize)))
848 {
849 if (FFSv1SaveInode(IrpContext,
850 Vcb,
851 Fcb->FFSMcb->Inode,
852 Fcb->dinode1))
853 {
854 Status = STATUS_SUCCESS;
855 }
856 }
857 else
858 {
859 Status = STATUS_INSUFFICIENT_RESOURCES;
860 }
861 }
862 else
863 {
864 if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FAI->AllocationSize)))
865 {
866 LARGE_INTEGER EndOfFile;
867
868 EndOfFile.QuadPart = FAI->AllocationSize.QuadPart +
869 (LONGLONG)(Vcb->BlockSize - 1);
870
871 if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile)))
872 {
873 if (FAI->AllocationSize.QuadPart <
874 Fcb->Header.FileSize.QuadPart)
875 {
876 Fcb->Header.FileSize.QuadPart =
877 FAI->AllocationSize.QuadPart;
878 }
879
880 FFSv1SaveInode(IrpContext,
881 Vcb,
882 Fcb->FFSMcb->Inode,
883 Fcb->dinode1);
884
885 Status = STATUS_SUCCESS;
886 }
887 }
888 else
889 {
890 Status = STATUS_USER_MAPPED_FILE;
891 _SEH2_LEAVE;
892 }
893 }
894
895 if (NT_SUCCESS(Status))
896 {
897 CcSetFileSizes(FileObject,
898 (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
899 SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
900
901 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
902 FILE_NOTIFY_CHANGE_LAST_WRITE ;
903
904 }
905
906 }
907 break;
908
909 case FileEndOfFileInformation:
910 {
911 PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer;
912
913 BOOLEAN CacheInitialized = FALSE;
914
915 if (IsDirectory(Fcb))
916 {
917 Status = STATUS_INVALID_DEVICE_REQUEST;
918 _SEH2_LEAVE;
919 }
920
921 if (FEOFI->EndOfFile.HighPart != 0)
922 {
923 Status = STATUS_INVALID_PARAMETER;
924 _SEH2_LEAVE;
925 }
926
927
928 if (IoStackLocation->Parameters.SetFile.AdvanceOnly)
929 {
930 Status = STATUS_SUCCESS;
931 _SEH2_LEAVE;
932 }
933
934 if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) &&
935 (FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
936 !FlagOn(Irp->Flags, IRP_PAGING_IO)) {
937
938 ASSERT(!FlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE));
939
940 CcInitializeCacheMap(
941 FileObject,
942 (PCC_FILE_SIZES)&(Fcb->Header.AllocationSize),
943 FALSE,
944 &(FFSGlobal->CacheManagerNoOpCallbacks),
945 Fcb);
946
947 CacheInitialized = TRUE;
948 }
949
950 if (FEOFI->EndOfFile.QuadPart ==
951 Fcb->Header.AllocationSize.QuadPart)
952 {
953 Status = STATUS_SUCCESS;
954 }
955 else if (FEOFI->EndOfFile.QuadPart >
956 Fcb->Header.AllocationSize.QuadPart)
957 {
958 LARGE_INTEGER FileSize = Fcb->Header.FileSize;
959
960 if(FFSExpandFile(IrpContext, Vcb, Fcb, &(FEOFI->EndOfFile)))
961 {
962 {
963 Fcb->Header.FileSize.QuadPart =
964 FEOFI->EndOfFile.QuadPart;
965 Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart;
966 Fcb->Header.ValidDataLength.QuadPart =
967 (LONGLONG)(0x7fffffffffffffff);
968 }
969
970 if (FFSv1SaveInode(IrpContext,
971 Vcb,
972 Fcb->FFSMcb->Inode,
973 Fcb->dinode1))
974 {
975 Status = STATUS_SUCCESS;
976 }
977 }
978 else
979 {
980 Status = STATUS_INSUFFICIENT_RESOURCES;
981 }
982
983
984 if (NT_SUCCESS(Status))
985 {
986 CcSetFileSizes(FileObject,
987 (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
988
989 SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
990
991 FFSZeroHoles(IrpContext,
992 Vcb, FileObject,
993 FileSize.QuadPart,
994 Fcb->Header.AllocationSize.QuadPart -
995 FileSize.QuadPart);
996
997 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
998 FILE_NOTIFY_CHANGE_LAST_WRITE ;
999
1000 }
1001 }
1002 else
1003 {
1004 if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FEOFI->EndOfFile)))
1005 {
1006 LARGE_INTEGER EndOfFile = FEOFI->EndOfFile;
1007
1008 EndOfFile.QuadPart = EndOfFile.QuadPart +
1009 (LONGLONG)(Vcb->BlockSize - 1);
1010
1011 if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile)))
1012 {
1013 Fcb->Header.FileSize.QuadPart =
1014 FEOFI->EndOfFile.QuadPart;
1015 Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart;
1016
1017 FFSv1SaveInode(IrpContext,
1018 Vcb,
1019 Fcb->FFSMcb->Inode,
1020 Fcb->dinode1);
1021
1022 Status = STATUS_SUCCESS;
1023 }
1024 }
1025 else
1026 {
1027 Status = STATUS_USER_MAPPED_FILE;
1028 _SEH2_LEAVE;
1029 }
1030
1031 if (NT_SUCCESS(Status))
1032 {
1033 CcSetFileSizes(FileObject,
1034 (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
1035
1036 SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
1037
1038 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
1039 FILE_NOTIFY_CHANGE_LAST_WRITE ;
1040
1041 }
1042 }
1043 }
1044
1045 break;
1046
1047 case FileDispositionInformation:
1048 {
1049 PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
1050
1051 Status = FFSSetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile);
1052 }
1053
1054 break;
1055
1056 case FileRenameInformation:
1057 {
1058 Status = FFSSetRenameInfo(IrpContext, Vcb, Fcb);
1059 }
1060
1061 break;
1062
1063 #endif // !FFS_READ_ONLY
1064
1065 //
1066 // This is the only set file information request supported on read
1067 // only file systems
1068 //
1069 case FilePositionInformation:
1070 {
1071 PFILE_POSITION_INFORMATION FilePositionInformation;
1072
1073 if (Length < sizeof(FILE_POSITION_INFORMATION))
1074 {
1075 Status = STATUS_INVALID_PARAMETER;
1076 _SEH2_LEAVE;
1077 }
1078
1079 FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
1080
1081 if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
1082 (FilePositionInformation->CurrentByteOffset.LowPart &
1083 DeviceObject->AlignmentRequirement))
1084 {
1085 Status = STATUS_INVALID_PARAMETER;
1086 _SEH2_LEAVE;
1087 }
1088
1089 FileObject->CurrentByteOffset =
1090 FilePositionInformation->CurrentByteOffset;
1091
1092 Status = STATUS_SUCCESS;
1093 _SEH2_LEAVE;
1094 }
1095
1096 break;
1097
1098 default:
1099 Status = STATUS_INVALID_INFO_CLASS;
1100 }
1101 }
1102 _SEH2_FINALLY
1103 {
1104
1105 if (FcbPagingIoResourceAcquired)
1106 {
1107 ExReleaseResourceForThreadLite(
1108 &Fcb->PagingIoResource,
1109 ExGetCurrentResourceThread());
1110 }
1111
1112 if (NT_SUCCESS(Status) && (NotifyFilter != 0))
1113 {
1114 FFSNotifyReportChange(
1115 IrpContext,
1116 Vcb,
1117 Fcb,
1118 NotifyFilter,
1119 FILE_ACTION_MODIFIED);
1120
1121 }
1122
1123 if (FcbMainResourceAcquired)
1124 {
1125 ExReleaseResourceForThreadLite(
1126 &Fcb->MainResource,
1127 ExGetCurrentResourceThread());
1128 }
1129
1130 if (VcbResourceAcquired)
1131 {
1132 ExReleaseResourceForThreadLite(
1133 &Vcb->MainResource,
1134 ExGetCurrentResourceThread());
1135 }
1136
1137 if (!IrpContext->ExceptionInProgress)
1138 {
1139 if (Status == STATUS_PENDING)
1140 {
1141 FFSQueueRequest(IrpContext);
1142 }
1143 else
1144 {
1145 FFSCompleteIrpContext(IrpContext, Status);
1146 }
1147 }
1148 } _SEH2_END;
1149
1150 return Status;
1151 }
1152
1153 #if !FFS_READ_ONLY
1154
1155 BOOLEAN
1156 FFSExpandFile(
1157 PFFS_IRP_CONTEXT IrpContext,
1158 PFFS_VCB Vcb,
1159 PFFS_FCB Fcb,
1160 PLARGE_INTEGER AllocationSize)
1161 {
1162 ULONG dwRet = 0;
1163 BOOLEAN bRet = TRUE;
1164
1165 PAGED_CODE();
1166
1167 if (AllocationSize->QuadPart <= Fcb->Header.AllocationSize.QuadPart)
1168 {
1169 return TRUE;
1170 }
1171
1172 if (((LONGLONG)SUPER_BLOCK->fs_size - (LONGLONG)SUPER_BLOCK->fs_dsize) * Vcb->BlockSize <=
1173 (AllocationSize->QuadPart - Fcb->Header.AllocationSize.QuadPart))
1174 {
1175 FFSPrint((DBG_ERROR, "FFSExpandFile: There is no enough disk space available.\n"));
1176 return FALSE;
1177 }
1178
1179 while (bRet && (AllocationSize->QuadPart > Fcb->Header.AllocationSize.QuadPart))
1180 {
1181 bRet = FFSExpandInode(IrpContext, Vcb, Fcb, &dwRet);
1182 }
1183
1184 return bRet;
1185 }
1186
1187
1188 BOOLEAN
1189 FFSTruncateFile(
1190 PFFS_IRP_CONTEXT IrpContext,
1191 PFFS_VCB Vcb,
1192 PFFS_FCB Fcb,
1193 PLARGE_INTEGER AllocationSize)
1194 {
1195 BOOLEAN bRet = TRUE;
1196
1197 PAGED_CODE();
1198
1199 while (bRet && (AllocationSize->QuadPart <
1200 Fcb->Header.AllocationSize.QuadPart))
1201 {
1202 bRet = FFSTruncateInode(IrpContext, Vcb, Fcb);
1203 }
1204
1205 return bRet;
1206 }
1207
1208
1209 NTSTATUS
1210 FFSSetDispositionInfo(
1211 PFFS_IRP_CONTEXT IrpContext,
1212 PFFS_VCB Vcb,
1213 PFFS_FCB Fcb,
1214 BOOLEAN bDelete)
1215 {
1216 PIRP Irp = IrpContext->Irp;
1217 PIO_STACK_LOCATION IrpSp;
1218
1219 PAGED_CODE();
1220
1221 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1222
1223 FFSPrint((DBG_INFO, "FFSSetDispositionInfo: bDelete=%x\n", bDelete));
1224
1225 if (bDelete)
1226 {
1227 FFSPrint((DBG_INFO, "FFSSetDispositionInformation: MmFlushImageSection on %s.\n",
1228 Fcb->AnsiFileName.Buffer));
1229
1230 if (!MmFlushImageSection(&Fcb->SectionObject,
1231 MmFlushForDelete))
1232 {
1233 return STATUS_CANNOT_DELETE;
1234 }
1235
1236 if (Fcb->FFSMcb->Inode == FFS_ROOT_INO)
1237 {
1238 return STATUS_CANNOT_DELETE;
1239 }
1240
1241 if (IsDirectory(Fcb))
1242 {
1243 if (!FFSIsDirectoryEmpty(Vcb, Fcb))
1244 {
1245 return STATUS_DIRECTORY_NOT_EMPTY;
1246 }
1247 }
1248
1249 SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
1250 IrpSp->FileObject->DeletePending = TRUE;
1251
1252 if (IsDirectory(Fcb))
1253 {
1254 FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
1255 &Vcb->NotifyList,
1256 Fcb,
1257 NULL,
1258 FALSE,
1259 FALSE,
1260 0,
1261 NULL,
1262 NULL,
1263 NULL);
1264 }
1265 }
1266 else
1267 {
1268 ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
1269 IrpSp->FileObject->DeletePending = FALSE;
1270 }
1271
1272 return STATUS_SUCCESS;
1273 }
1274
1275
1276 __drv_mustHoldCriticalRegion
1277 NTSTATUS
1278 FFSSetRenameInfo(
1279 PFFS_IRP_CONTEXT IrpContext,
1280 PFFS_VCB Vcb,
1281 PFFS_FCB Fcb)
1282 {
1283 PFFS_FCB TargetDcb;
1284 PFFS_MCB TargetMcb;
1285
1286 PFFS_MCB Mcb;
1287 FFSv1_INODE dinode1;
1288
1289 UNICODE_STRING FileName;
1290
1291 NTSTATUS Status;
1292
1293 PIRP Irp;
1294 PIO_STACK_LOCATION IrpSp;
1295
1296 PFILE_OBJECT FileObject;
1297 PFILE_OBJECT TargetObject;
1298 BOOLEAN ReplaceIfExists;
1299
1300 BOOLEAN bMove = FALSE;
1301
1302 PFILE_RENAME_INFORMATION FRI;
1303
1304 PAGED_CODE();
1305
1306 if (Fcb->FFSMcb->Inode == FFS_ROOT_INO)
1307 {
1308 Status = STATUS_INVALID_PARAMETER;
1309 goto errorout;
1310 }
1311
1312 Irp = IrpContext->Irp;
1313 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1314
1315 FileObject = IrpSp->FileObject;
1316 TargetObject = IrpSp->Parameters.SetFile.FileObject;
1317 ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
1318
1319 FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1320
1321 if (TargetObject == NULL)
1322 {
1323 UNICODE_STRING NewName;
1324
1325 NewName.Buffer = FRI->FileName;
1326 NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength;
1327
1328 while (NewName.Length > 0 && NewName.Buffer[NewName.Length / 2 - 1] == L'\\')
1329 {
1330 NewName.Buffer[NewName.Length / 2 - 1] = 0;
1331 NewName.Length -= 2;
1332 }
1333
1334 while (NewName.Length > 0 && NewName.Buffer[NewName.Length / 2 - 1] != L'\\')
1335 {
1336 NewName.Length -= 2;
1337 }
1338
1339 NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length);
1340 NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length);
1341
1342 FileName = NewName;
1343
1344 TargetDcb = NULL;
1345 TargetMcb = Fcb->FFSMcb->Parent;
1346
1347 if (FileName.Length >= FFS_NAME_LEN*sizeof(USHORT))
1348 {
1349 Status = STATUS_OBJECT_NAME_INVALID;
1350 goto errorout;
1351 }
1352 }
1353 else
1354 {
1355 TargetDcb = (PFFS_FCB)(TargetObject->FsContext);
1356
1357 if (!TargetDcb || TargetDcb->Vcb != Vcb)
1358 {
1359 FFSBreakPoint();
1360
1361 Status = STATUS_INVALID_PARAMETER;
1362 goto errorout;
1363 }
1364
1365 TargetMcb = TargetDcb->FFSMcb;
1366
1367 FileName = TargetObject->FileName;
1368 }
1369
1370 if (FsRtlDoesNameContainWildCards(&FileName))
1371 {
1372 Status = STATUS_OBJECT_NAME_INVALID;
1373 goto errorout;
1374 }
1375
1376 if (TargetMcb->Inode == Fcb->FFSMcb->Parent->Inode)
1377 {
1378 if (FsRtlAreNamesEqual(&FileName,
1379 &(Fcb->FFSMcb->ShortName),
1380 FALSE,
1381 NULL))
1382 {
1383 Status = STATUS_SUCCESS;
1384 goto errorout;
1385 }
1386 }
1387 else
1388 {
1389 bMove = TRUE;
1390 }
1391
1392 TargetDcb = TargetMcb->FFSFcb;
1393
1394 if (!TargetDcb)
1395 TargetDcb = FFSCreateFcbFromMcb(Vcb, TargetMcb);
1396
1397 if ((TargetMcb->Inode != Fcb->FFSMcb->Parent->Inode) &&
1398 (Fcb->FFSMcb->Parent->FFSFcb == NULL))
1399 {
1400 FFSCreateFcbFromMcb(Vcb, Fcb->FFSMcb->Parent);
1401 }
1402
1403 if (!TargetDcb || !(Fcb->FFSMcb->Parent->FFSFcb))
1404 {
1405 Status = STATUS_UNSUCCESSFUL;
1406
1407 goto errorout;
1408 }
1409
1410 Mcb = NULL;
1411 Status = FFSv1LookupFileName(
1412 Vcb,
1413 &FileName,
1414 TargetMcb,
1415 &Mcb,
1416 &dinode1);
1417
1418 if (NT_SUCCESS(Status))
1419 {
1420 if ((!ReplaceIfExists) ||
1421 (IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) ||
1422 (IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY)))
1423 {
1424 Status = STATUS_OBJECT_NAME_COLLISION;
1425 goto errorout;
1426 }
1427
1428 if (ReplaceIfExists)
1429 {
1430 Status = STATUS_NOT_IMPLEMENTED;
1431 goto errorout;
1432 }
1433 }
1434
1435 if (IsDirectory(Fcb))
1436 {
1437
1438 Status = FFSRemoveEntry(IrpContext, Vcb,
1439 Fcb->FFSMcb->Parent->FFSFcb,
1440 DT_DIR,
1441 Fcb->FFSMcb->Inode);
1442
1443 if (!NT_SUCCESS(Status))
1444 {
1445 FFSBreakPoint();
1446
1447 goto errorout;
1448 }
1449
1450 Status = FFSAddEntry(IrpContext, Vcb,
1451 TargetDcb,
1452 DT_DIR,
1453 Fcb->FFSMcb->Inode,
1454 &FileName);
1455
1456 if (!NT_SUCCESS(Status))
1457 {
1458 FFSBreakPoint();
1459
1460 FFSAddEntry(IrpContext, Vcb,
1461 Fcb->FFSMcb->Parent->FFSFcb,
1462 DT_DIR,
1463 Fcb->FFSMcb->Inode,
1464 &Fcb->FFSMcb->ShortName);
1465
1466 goto errorout;
1467 }
1468
1469 if(!FFSv1SaveInode(IrpContext,
1470 Vcb,
1471 TargetMcb->Inode,
1472 TargetDcb->dinode1))
1473 {
1474 Status = STATUS_UNSUCCESSFUL;
1475
1476 FFSBreakPoint();
1477
1478 goto errorout;
1479 }
1480
1481 if(!FFSv1SaveInode(IrpContext,
1482 Vcb,
1483 Fcb->FFSMcb->Parent->Inode,
1484 Fcb->FFSMcb->Parent->FFSFcb->dinode1))
1485 {
1486 Status = STATUS_UNSUCCESSFUL;
1487
1488 FFSBreakPoint();
1489
1490 goto errorout;
1491 }
1492
1493 Status = FFSSetParentEntry(IrpContext, Vcb, Fcb,
1494 Fcb->FFSMcb->Parent->Inode,
1495 TargetDcb->FFSMcb->Inode);
1496
1497
1498 if (!NT_SUCCESS(Status))
1499 {
1500 FFSBreakPoint();
1501 goto errorout;
1502 }
1503 }
1504 else
1505 {
1506 Status = FFSRemoveEntry(IrpContext, Vcb,
1507 Fcb->FFSMcb->Parent->FFSFcb,
1508 DT_REG,
1509 Fcb->FFSMcb->Inode);
1510 if (!NT_SUCCESS(Status))
1511 {
1512 FFSBreakPoint();
1513 goto errorout;
1514 }
1515
1516 Status = FFSAddEntry(IrpContext,
1517 Vcb, TargetDcb,
1518 DT_REG,
1519 Fcb->FFSMcb->Inode,
1520 &FileName);
1521
1522 if (!NT_SUCCESS(Status))
1523 {
1524 FFSBreakPoint();
1525
1526 FFSAddEntry(IrpContext, Vcb,
1527 Fcb->FFSMcb->Parent->FFSFcb,
1528 DT_REG,
1529 Fcb->FFSMcb->Inode,
1530 &Fcb->FFSMcb->ShortName);
1531
1532 goto errorout;
1533 }
1534 }
1535
1536 if (NT_SUCCESS(Status))
1537 {
1538 if (Fcb->FFSMcb->ShortName.MaximumLength < (FileName.Length + 2))
1539 {
1540 ExFreePool(Fcb->FFSMcb->ShortName.Buffer);
1541 Fcb->FFSMcb->ShortName.Buffer =
1542 ExAllocatePoolWithTag(PagedPool, FileName.Length + 2, FFS_POOL_TAG);
1543
1544 if (!Fcb->FFSMcb->ShortName.Buffer)
1545 {
1546 Status = STATUS_INSUFFICIENT_RESOURCES;
1547 goto errorout;
1548 }
1549
1550 Fcb->FFSMcb->ShortName.MaximumLength = FileName.Length + 2;
1551 }
1552
1553 {
1554 RtlZeroMemory(Fcb->FFSMcb->ShortName.Buffer,
1555 Fcb->FFSMcb->ShortName.MaximumLength);
1556
1557 RtlCopyMemory(Fcb->FFSMcb->ShortName.Buffer,
1558 FileName.Buffer, FileName.Length);
1559
1560 Fcb->FFSMcb->ShortName.Length = FileName.Length;
1561 }
1562
1563 #if DBG
1564
1565 Fcb->AnsiFileName.Length = (USHORT)
1566 RtlxUnicodeStringToOemSize(&FileName);
1567
1568 if (Fcb->AnsiFileName.MaximumLength < FileName.Length)
1569 {
1570 ExFreePool(Fcb->AnsiFileName.Buffer);
1571
1572 Fcb->AnsiFileName.Buffer =
1573 ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.Length + 1, FFS_POOL_TAG);
1574
1575 if (!Fcb->AnsiFileName.Buffer)
1576 {
1577 Status = STATUS_INSUFFICIENT_RESOURCES;
1578 goto errorout;
1579 }
1580
1581 RtlZeroMemory(Fcb->AnsiFileName.Buffer,
1582 Fcb->AnsiFileName.Length + 1);
1583 Fcb->AnsiFileName.MaximumLength =
1584 Fcb->AnsiFileName.Length + 1;
1585 }
1586
1587 FFSUnicodeToOEM(&(Fcb->AnsiFileName),
1588 &FileName);
1589
1590 #endif
1591
1592 if (bMove)
1593 {
1594 FFSNotifyReportChange(
1595 IrpContext,
1596 Vcb,
1597 Fcb,
1598 (IsDirectory(Fcb) ?
1599 FILE_NOTIFY_CHANGE_DIR_NAME :
1600 FILE_NOTIFY_CHANGE_FILE_NAME),
1601 FILE_ACTION_REMOVED);
1602
1603 }
1604 else
1605 {
1606 FFSNotifyReportChange(
1607 IrpContext,
1608 Vcb,
1609 Fcb,
1610 (IsDirectory(Fcb) ?
1611 FILE_NOTIFY_CHANGE_DIR_NAME :
1612 FILE_NOTIFY_CHANGE_FILE_NAME),
1613 FILE_ACTION_RENAMED_OLD_NAME);
1614
1615 }
1616
1617 FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
1618 FFSAddMcbNode(Vcb, TargetMcb, Fcb->FFSMcb);
1619
1620 if (bMove)
1621 {
1622 FFSNotifyReportChange(
1623 IrpContext,
1624 Vcb,
1625 Fcb,
1626 (IsDirectory(Fcb) ?
1627 FILE_NOTIFY_CHANGE_DIR_NAME :
1628 FILE_NOTIFY_CHANGE_FILE_NAME),
1629 FILE_ACTION_ADDED);
1630 }
1631 else
1632 {
1633 FFSNotifyReportChange(
1634 IrpContext,
1635 Vcb,
1636 Fcb,
1637 (IsDirectory(Fcb) ?
1638 FILE_NOTIFY_CHANGE_DIR_NAME :
1639 FILE_NOTIFY_CHANGE_FILE_NAME),
1640 FILE_ACTION_RENAMED_NEW_NAME);
1641
1642 }
1643 }
1644
1645 errorout:
1646
1647 return Status;
1648 }
1649
1650
1651 __drv_mustHoldCriticalRegion
1652 BOOLEAN
1653 FFSDeleteFile(
1654 PFFS_IRP_CONTEXT IrpContext,
1655 PFFS_VCB Vcb,
1656 PFFS_FCB Fcb)
1657 {
1658 BOOLEAN bRet = FALSE;
1659 LARGE_INTEGER AllocationSize;
1660 PFFS_FCB Dcb = NULL;
1661
1662 NTSTATUS Status;
1663
1664 PAGED_CODE();
1665
1666 FFSPrint((DBG_INFO, "FFSDeleteFile: File %S (%xh) will be deleted!\n",
1667 Fcb->FFSMcb->ShortName.Buffer, Fcb->FFSMcb->Inode));
1668
1669 if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
1670 {
1671 return TRUE;
1672 }
1673
1674 if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
1675 {
1676 if (!FFSIsDirectoryEmpty(Vcb, Fcb))
1677 {
1678 ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
1679
1680 return FALSE;
1681 }
1682 }
1683
1684 FFSPrint((DBG_INFO, "FFSDeleteFile: FFSSB->S_FREE_BLOCKS = %xh .\n",
1685 Vcb->ffs_super_block->fs_size - Vcb->ffs_super_block->fs_dsize));
1686
1687 Status = STATUS_UNSUCCESSFUL;
1688
1689 {
1690 if (Fcb->FFSMcb->Parent->FFSFcb)
1691 {
1692 Status = FFSRemoveEntry(
1693 IrpContext, Vcb,
1694 Fcb->FFSMcb->Parent->FFSFcb,
1695 (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
1696 DT_DIR : DT_REG),
1697 Fcb->FFSMcb->Inode);
1698 }
1699 else
1700 {
1701 Dcb = FFSCreateFcbFromMcb(Vcb, Fcb->FFSMcb->Parent);
1702 if (Dcb)
1703 {
1704 Status = FFSRemoveEntry(
1705 IrpContext, Vcb, Dcb,
1706 (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
1707 DT_DIR : DT_REG),
1708 Fcb->FFSMcb->Inode);
1709 }
1710 }
1711 }
1712
1713 if (NT_SUCCESS(Status))
1714 {
1715 Fcb->dinode1->di_nlink--;
1716
1717 if (IsDirectory(Fcb))
1718 {
1719 if (Fcb->dinode1->di_nlink < 2)
1720 {
1721 bRet = TRUE;
1722 }
1723 }
1724 else
1725 {
1726 if (Fcb->dinode1->di_nlink == 0)
1727 {
1728 bRet = TRUE;
1729 }
1730 }
1731 }
1732
1733
1734 if (bRet)
1735 {
1736 AllocationSize.QuadPart = (LONGLONG)0;
1737 bRet = FFSTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
1738
1739 //
1740 // Update the inode's data length . It should be ZERO if succeeds.
1741 //
1742
1743 if (Fcb->dinode1->di_size > Fcb->Header.AllocationSize.LowPart)
1744 {
1745 Fcb->dinode1->di_size = Fcb->Header.AllocationSize.LowPart;
1746 }
1747
1748 Fcb->Header.FileSize.QuadPart = (LONGLONG) Fcb->dinode1->di_size;
1749
1750 if (bRet)
1751 {
1752 {
1753 LARGE_INTEGER SysTime;
1754 KeQuerySystemTime(&SysTime);
1755
1756 /*Fcb->dinode->di_dtime = FFSInodeTime(SysTime); XXX */
1757
1758 FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
1759 }
1760
1761 if (IsDirectory(Fcb))
1762 {
1763 bRet = FFSFreeInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, DT_DIR);
1764 }
1765 else
1766 {
1767 bRet = FFSFreeInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, DT_REG);
1768 }
1769
1770 SetFlag(Fcb->Flags, FCB_FILE_DELETED);
1771 FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
1772 }
1773 else
1774 {
1775 FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
1776 }
1777 }
1778 else
1779 {
1780 FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
1781 }
1782
1783 FFSPrint((DBG_INFO, "FFSDeleteFile: Succeed... FFSSB->S_FREE_BLOCKS = %xh .\n",
1784 Vcb->ffs_super_block->fs_size - Vcb->ffs_super_block->fs_dsize));
1785
1786 return bRet;
1787 }
1788
1789 #endif // !FFS_READ_ONLY