[REISERFS] Import ReiserFS file system driver for Windows. It will be enabled later...
[reactos.git] / reactos / drivers / filesystems / reiserfs / src / fileinfo.c
1 /*
2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
4 * FILE: fileinfo.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 #ifdef ALLOC_PRAGMA
22 #pragma alloc_text(PAGE, RfsdQueryInformation)
23 #pragma alloc_text(PAGE, RfsdSetInformation)
24 #if !RFSD_READ_ONLY
25 #pragma alloc_text(PAGE, RfsdExpandFile)
26 #pragma alloc_text(PAGE, RfsdTruncateFile)
27 #pragma alloc_text(PAGE, RfsdSetDispositionInfo)
28 #pragma alloc_text(PAGE, RfsdSetRenameInfo)
29 #pragma alloc_text(PAGE, RfsdDeleteFile)
30 #endif // !RFSD_READ_ONLY
31 #endif
32
33 __drv_mustHoldCriticalRegion
34 NTSTATUS
35 RfsdQueryInformation (IN PRFSD_IRP_CONTEXT IrpContext)
36 {
37 PDEVICE_OBJECT DeviceObject;
38 NTSTATUS Status = STATUS_UNSUCCESSFUL;
39 PFILE_OBJECT FileObject;
40 PRFSD_VCB Vcb;
41 PRFSD_FCB Fcb = 0;
42 PRFSD_CCB Ccb;
43 PIRP Irp;
44 PIO_STACK_LOCATION IoStackLocation;
45 FILE_INFORMATION_CLASS FileInformationClass;
46 ULONG Length;
47 PVOID Buffer;
48 BOOLEAN FcbResourceAcquired = FALSE;
49 LONGLONG FileSize;
50 LONGLONG AllocationSize;
51
52 PAGED_CODE();
53
54 _SEH2_TRY {
55
56 ASSERT(IrpContext != NULL);
57
58 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
59 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
60
61 DeviceObject = IrpContext->DeviceObject;
62
63 //
64 // This request is not allowed on the main device object
65 //
66 if (DeviceObject == RfsdGlobal->DeviceObject) {
67 Status = STATUS_INVALID_DEVICE_REQUEST;
68 _SEH2_LEAVE;
69 }
70
71 FileObject = IrpContext->FileObject;
72
73 Fcb = (PRFSD_FCB) FileObject->FsContext;
74
75 ASSERT(Fcb != NULL);
76
77 //
78 // This request is not allowed on volumes
79 //
80 if (Fcb->Identifier.Type == RFSDVCB) {
81 Status = STATUS_INVALID_PARAMETER;
82 _SEH2_LEAVE;
83 }
84
85 ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
86 (Fcb->Identifier.Size == sizeof(RFSD_FCB)));
87
88 Vcb = Fcb->Vcb;
89
90 /*
91 if ( !IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) &&
92 !FlagOn(Fcb->Flags, FCB_PAGE_FILE))
93 */
94 {
95 if (!ExAcquireResourceSharedLite(
96 &Fcb->MainResource,
97 IrpContext->IsSynchronous
98 )) {
99
100 Status = STATUS_PENDING;
101 _SEH2_LEAVE;
102 }
103
104 FcbResourceAcquired = TRUE;
105 }
106
107 Ccb = (PRFSD_CCB) FileObject->FsContext2;
108
109 ASSERT(Ccb != NULL);
110
111 ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
112 (Ccb->Identifier.Size == sizeof(RFSD_CCB)));
113
114 Irp = IrpContext->Irp;
115
116 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
117
118 FileInformationClass =
119 IoStackLocation->Parameters.QueryFile.FileInformationClass;
120
121 Length = IoStackLocation->Parameters.QueryFile.Length;
122
123 Buffer = Irp->AssociatedIrp.SystemBuffer;
124
125 RtlZeroMemory(Buffer, Length);
126
127 FileSize = (LONGLONG) Fcb->Inode->i_size;
128
129 AllocationSize = CEILING_ALIGNED(FileSize, (ULONGLONG)Vcb->BlockSize);
130
131 switch (FileInformationClass) {
132
133 case FileBasicInformation:
134 {
135 PFILE_BASIC_INFORMATION FileBasicInformation;
136
137 if (Length < sizeof(FILE_BASIC_INFORMATION)) {
138 Status = STATUS_INFO_LENGTH_MISMATCH;
139 _SEH2_LEAVE;
140 }
141
142 FileBasicInformation = (PFILE_BASIC_INFORMATION) Buffer;
143
144 FileBasicInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
145
146 FileBasicInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
147
148 FileBasicInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
149
150 FileBasicInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
151
152 FileBasicInformation->FileAttributes = Fcb->RfsdMcb->FileAttr;
153
154 Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
155 Status = STATUS_SUCCESS;
156 _SEH2_LEAVE;
157 }
158
159 #if (_WIN32_WINNT >= 0x0500)
160
161 case FileAttributeTagInformation:
162 {
163 PFILE_ATTRIBUTE_TAG_INFORMATION FATI;
164
165 if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION)) {
166 Status = STATUS_INFO_LENGTH_MISMATCH;
167 _SEH2_LEAVE;
168 }
169
170 FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer;
171
172 FATI->FileAttributes = Fcb->RfsdMcb->FileAttr;
173 FATI->ReparseTag = 0;
174
175 Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
176 Status = STATUS_SUCCESS;
177 _SEH2_LEAVE;
178 }
179 #endif // (_WIN32_WINNT >= 0x0500)
180
181 case FileStandardInformation:
182 {
183 PFILE_STANDARD_INFORMATION FileStandardInformation;
184
185 if (Length < sizeof(FILE_STANDARD_INFORMATION)) {
186 Status = STATUS_INFO_LENGTH_MISMATCH;
187 _SEH2_LEAVE;
188 }
189
190 FileStandardInformation = (PFILE_STANDARD_INFORMATION) Buffer;
191
192 FileStandardInformation->AllocationSize.QuadPart = AllocationSize;
193 FileStandardInformation->EndOfFile.QuadPart = FileSize;
194
195 FileStandardInformation->NumberOfLinks = Fcb->Inode->i_links_count;
196
197 if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
198 FileStandardInformation->DeletePending = FALSE;
199 else
200 FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
201
202 if (Fcb->RfsdMcb->FileAttr & FILE_ATTRIBUTE_DIRECTORY) {
203 FileStandardInformation->Directory = TRUE;
204 } else {
205 FileStandardInformation->Directory = FALSE;
206 }
207
208 Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
209 Status = STATUS_SUCCESS;
210 _SEH2_LEAVE;
211 }
212
213 case FileInternalInformation:
214 {
215 PFILE_INTERNAL_INFORMATION FileInternalInformation;
216
217 if (Length < sizeof(FILE_INTERNAL_INFORMATION)) {
218 Status = STATUS_INFO_LENGTH_MISMATCH;
219 _SEH2_LEAVE;
220 }
221
222 FileInternalInformation = (PFILE_INTERNAL_INFORMATION) Buffer;
223
224 // The "inode number"
225 FileInternalInformation->IndexNumber.LowPart = Fcb->RfsdMcb->Key.k_dir_id;
226 FileInternalInformation->IndexNumber.HighPart = Fcb->RfsdMcb->Key.k_objectid;
227
228 Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION);
229 Status = STATUS_SUCCESS;
230 _SEH2_LEAVE;
231 }
232
233 case FileEaInformation:
234 {
235 PFILE_EA_INFORMATION FileEaInformation;
236
237 if (Length < sizeof(FILE_EA_INFORMATION)) {
238 Status = STATUS_INFO_LENGTH_MISMATCH;
239 _SEH2_LEAVE;
240 }
241
242 FileEaInformation = (PFILE_EA_INFORMATION) Buffer;
243
244 // Romfs doesn't have any extended attributes
245 FileEaInformation->EaSize = 0;
246
247 Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION);
248 Status = STATUS_SUCCESS;
249 _SEH2_LEAVE;
250 }
251
252 case FileNameInformation:
253 {
254 PFILE_NAME_INFORMATION FileNameInformation;
255
256 if (Length < sizeof(FILE_NAME_INFORMATION) +
257 Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR)) {
258 Status = STATUS_INFO_LENGTH_MISMATCH;
259 _SEH2_LEAVE;
260 }
261
262 FileNameInformation = (PFILE_NAME_INFORMATION) Buffer;
263
264 FileNameInformation->FileNameLength = Fcb->RfsdMcb->ShortName.Length;
265
266 RtlCopyMemory(
267 FileNameInformation->FileName,
268 Fcb->RfsdMcb->ShortName.Buffer,
269 Fcb->RfsdMcb->ShortName.Length );
270
271 Irp->IoStatus.Information = sizeof(FILE_NAME_INFORMATION) +
272 Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR);
273 Status = STATUS_SUCCESS;
274 _SEH2_LEAVE;
275 }
276
277 case FilePositionInformation:
278 {
279 PFILE_POSITION_INFORMATION FilePositionInformation;
280
281 if (Length < sizeof(FILE_POSITION_INFORMATION)) {
282 Status = STATUS_INFO_LENGTH_MISMATCH;
283 _SEH2_LEAVE;
284 }
285
286 FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
287
288 FilePositionInformation->CurrentByteOffset =
289 FileObject->CurrentByteOffset;
290
291 Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
292 Status = STATUS_SUCCESS;
293 _SEH2_LEAVE;
294 }
295
296 case FileAllInformation:
297 {
298 PFILE_ALL_INFORMATION FileAllInformation;
299 PFILE_BASIC_INFORMATION FileBasicInformation;
300 PFILE_STANDARD_INFORMATION FileStandardInformation;
301 PFILE_INTERNAL_INFORMATION FileInternalInformation;
302 PFILE_EA_INFORMATION FileEaInformation;
303 PFILE_POSITION_INFORMATION FilePositionInformation;
304 PFILE_NAME_INFORMATION FileNameInformation;
305
306 if (Length < sizeof(FILE_ALL_INFORMATION)) {
307 Status = STATUS_INFO_LENGTH_MISMATCH;
308 _SEH2_LEAVE;
309 }
310
311 FileAllInformation = (PFILE_ALL_INFORMATION) Buffer;
312
313 FileBasicInformation =
314 &FileAllInformation->BasicInformation;
315
316 FileStandardInformation =
317 &FileAllInformation->StandardInformation;
318
319 FileInternalInformation =
320 &FileAllInformation->InternalInformation;
321
322 FileEaInformation =
323 &FileAllInformation->EaInformation;
324
325 FilePositionInformation =
326 &FileAllInformation->PositionInformation;
327
328 FileNameInformation =
329 &FileAllInformation->NameInformation;
330
331 FileBasicInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
332
333 FileBasicInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
334
335 FileBasicInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
336
337 FileBasicInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
338
339 FileBasicInformation->FileAttributes = Fcb->RfsdMcb->FileAttr;
340
341 FileStandardInformation->AllocationSize.QuadPart = AllocationSize;
342
343 FileStandardInformation->EndOfFile.QuadPart = FileSize;
344
345 FileStandardInformation->NumberOfLinks = Fcb->Inode->i_links_count;
346
347 if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
348 FileStandardInformation->DeletePending = FALSE;
349 else
350 FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
351
352 if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
353 FileStandardInformation->Directory = TRUE;
354 } else {
355 FileStandardInformation->Directory = FALSE;
356 }
357
358 // The "inode number"
359 FileInternalInformation->IndexNumber.LowPart = Fcb->RfsdMcb->Key.k_dir_id;
360 FileInternalInformation->IndexNumber.HighPart = Fcb->RfsdMcb->Key.k_objectid;
361
362 // Romfs doesn't have any extended attributes
363 FileEaInformation->EaSize = 0;
364
365 FilePositionInformation->CurrentByteOffset =
366 FileObject->CurrentByteOffset;
367
368 if (Length < sizeof(FILE_ALL_INFORMATION) +
369 Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR)) {
370 Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION);
371 Status = STATUS_BUFFER_OVERFLOW;
372 _SEH2_LEAVE;
373 }
374
375 FileNameInformation->FileNameLength = Fcb->RfsdMcb->ShortName.Length;
376
377 RtlCopyMemory(
378 FileNameInformation->FileName,
379 Fcb->RfsdMcb->ShortName.Buffer,
380 Fcb->RfsdMcb->ShortName.Length
381 );
382
383 Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) +
384 Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR);
385 Status = STATUS_SUCCESS;
386 _SEH2_LEAVE;
387 }
388
389 /*
390 case FileAlternateNameInformation:
391 {
392 // TODO: [ext2fsd] Handle FileAlternateNameInformation
393
394 // Here we would like to use RtlGenerate8dot3Name but I don't
395 // know how to use the argument PGENERATE_NAME_CONTEXT
396 }
397 */
398
399 case FileNetworkOpenInformation:
400 {
401 PFILE_NETWORK_OPEN_INFORMATION FileNetworkOpenInformation;
402
403 if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION)) {
404 Status = STATUS_INFO_LENGTH_MISMATCH;
405 _SEH2_LEAVE;
406 }
407
408 FileNetworkOpenInformation =
409 (PFILE_NETWORK_OPEN_INFORMATION) Buffer;
410
411 FileNetworkOpenInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
412
413 FileNetworkOpenInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
414
415 FileNetworkOpenInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
416
417 FileNetworkOpenInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
418
419 FileNetworkOpenInformation->AllocationSize.QuadPart = AllocationSize;
420
421 FileNetworkOpenInformation->EndOfFile.QuadPart = FileSize;
422
423 FileNetworkOpenInformation->FileAttributes = Fcb->RfsdMcb->FileAttr;
424
425 Irp->IoStatus.Information =
426 sizeof(FILE_NETWORK_OPEN_INFORMATION);
427 Status = STATUS_SUCCESS;
428 _SEH2_LEAVE;
429 }
430
431 default:
432 Status = STATUS_INVALID_INFO_CLASS;
433 }
434
435 } _SEH2_FINALLY {
436
437 if (FcbResourceAcquired) {
438 ExReleaseResourceForThreadLite(
439 &Fcb->MainResource,
440 ExGetCurrentResourceThread());
441 }
442
443 if (!IrpContext->ExceptionInProgress) {
444 if (Status == STATUS_PENDING) {
445 RfsdQueueRequest(IrpContext);
446 } else {
447 RfsdCompleteIrpContext(IrpContext, Status);
448 }
449 }
450 } _SEH2_END;
451
452 return Status;
453 }
454
455 __drv_mustHoldCriticalRegion
456 NTSTATUS
457 RfsdSetInformation (IN PRFSD_IRP_CONTEXT IrpContext)
458 {
459 PDEVICE_OBJECT DeviceObject;
460 NTSTATUS Status = STATUS_UNSUCCESSFUL;
461 PRFSD_VCB Vcb = 0;
462 PFILE_OBJECT FileObject;
463 PRFSD_FCB Fcb = 0;
464 PRFSD_CCB Ccb;
465 PIRP Irp;
466 PIO_STACK_LOCATION IoStackLocation;
467 FILE_INFORMATION_CLASS FileInformationClass;
468
469 ULONG NotifyFilter = 0;
470
471 ULONG Length;
472 PVOID Buffer;
473 BOOLEAN FcbMainResourceAcquired = FALSE;
474
475 BOOLEAN VcbResourceAcquired = FALSE;
476 BOOLEAN FcbPagingIoResourceAcquired = FALSE;
477
478 PAGED_CODE();
479
480 _SEH2_TRY {
481
482 ASSERT(IrpContext != NULL);
483
484 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
485 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
486
487 DeviceObject = IrpContext->DeviceObject;
488
489 //
490 // This request is not allowed on the main device object
491 //
492 if (DeviceObject == RfsdGlobal->DeviceObject) {
493 Status = STATUS_INVALID_DEVICE_REQUEST;
494 _SEH2_LEAVE;
495 }
496
497 Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
498
499 ASSERT(Vcb != NULL);
500
501 ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
502 (Vcb->Identifier.Size == sizeof(RFSD_VCB)));
503
504 ASSERT(IsMounted(Vcb));
505
506 FileObject = IrpContext->FileObject;
507
508 Fcb = (PRFSD_FCB) FileObject->FsContext;
509
510 ASSERT(Fcb != NULL);
511
512 //
513 // This request is not allowed on volumes
514 //
515 if (Fcb->Identifier.Type == RFSDVCB) {
516 DbgBreak();
517
518 Status = STATUS_INVALID_PARAMETER;
519 _SEH2_LEAVE;
520 }
521
522 ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
523 (Fcb->Identifier.Size == sizeof(RFSD_FCB)));
524
525 if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
526 Status = STATUS_FILE_DELETED;
527 _SEH2_LEAVE;
528 }
529
530 Ccb = (PRFSD_CCB) FileObject->FsContext2;
531
532 ASSERT(Ccb != NULL);
533
534 ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
535 (Ccb->Identifier.Size == sizeof(RFSD_CCB)));
536
537 Irp = IrpContext->Irp;
538
539 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
540
541 FileInformationClass =
542 IoStackLocation->Parameters.SetFile.FileInformationClass;
543
544 Length = IoStackLocation->Parameters.SetFile.Length;
545
546 Buffer = Irp->AssociatedIrp.SystemBuffer;
547
548 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
549
550 if (FileInformationClass == FileDispositionInformation ||
551 FileInformationClass == FileRenameInformation ||
552 FileInformationClass == FileLinkInformation) {
553
554 #ifdef _MSC_VER
555 #pragma prefast( suppress: 28137, "by design" )
556 #endif
557 if (!ExAcquireResourceExclusiveLite(
558 &Vcb->MainResource,
559 IrpContext->IsSynchronous )) {
560
561 Status = STATUS_PENDING;
562 _SEH2_LEAVE;
563 }
564
565 VcbResourceAcquired = TRUE;
566 }
567
568 } else if (!FlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
569
570 #ifdef _MSC_VER
571 #pragma prefast( suppress: 28137, "by design" )
572 #endif
573 if (!ExAcquireResourceExclusiveLite(
574 &Fcb->MainResource,
575 IrpContext->IsSynchronous )) {
576 Status = STATUS_PENDING;
577 _SEH2_LEAVE;
578 }
579
580 FcbMainResourceAcquired = TRUE;
581 }
582
583 if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
584
585 if (FileInformationClass != FilePositionInformation) {
586 Status = STATUS_MEDIA_WRITE_PROTECTED;
587 _SEH2_LEAVE;
588 }
589 }
590
591 if (FileInformationClass == FileDispositionInformation ||
592 FileInformationClass == FileRenameInformation ||
593 FileInformationClass == FileLinkInformation ||
594 FileInformationClass == FileAllocationInformation ||
595 FileInformationClass == FileEndOfFileInformation) {
596
597 #ifdef _MSC_VER
598 #pragma prefast( suppress: 28137, "by design" )
599 #endif
600 if (!ExAcquireResourceExclusiveLite(
601 &Fcb->PagingIoResource,
602 IrpContext->IsSynchronous )) {
603 Status = STATUS_PENDING;
604 _SEH2_LEAVE;
605 }
606
607 FcbPagingIoResourceAcquired = TRUE;
608 }
609
610 /*
611 if (FileInformationClass != FileDispositionInformation
612 && FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
613 {
614 Status = STATUS_DELETE_PENDING;
615 _SEH2_LEAVE;
616 }
617 */
618 switch (FileInformationClass) {
619
620 #if !RFSD_READ_ONLY
621 #if 0
622 case FileBasicInformation:
623 {
624 PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION) Buffer;
625 PRFSD_INODE RfsdInode = Fcb->Inode;
626
627 if (FBI->CreationTime.QuadPart) {
628 RfsdInode->i_ctime = (ULONG)(RfsdInodeTime(FBI->CreationTime));
629 }
630
631 if (FBI->LastAccessTime.QuadPart) {
632 RfsdInode->i_atime = (ULONG)(RfsdInodeTime(FBI->LastAccessTime));
633 }
634
635 if (FBI->LastWriteTime.QuadPart) {
636 RfsdInode->i_mtime = (ULONG)(RfsdInodeTime(FBI->LastWriteTime));
637 }
638
639 if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) {
640 RfsdSetReadOnly(Fcb->Inode->i_mode);
641 SetFlag(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
642 } else {
643 RfsdSetWritable(Fcb->Inode->i_mode);
644 ClearFlag(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
645 }
646
647 if(RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RfsdInode)) {
648 Status = STATUS_SUCCESS;
649 }
650
651 if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
652 SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
653 } else {
654 ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
655 }
656
657 NotifyFilter = FILE_NOTIFY_CHANGE_ATTRIBUTES |
658 FILE_NOTIFY_CHANGE_CREATION |
659 FILE_NOTIFY_CHANGE_LAST_ACCESS |
660 FILE_NOTIFY_CHANGE_LAST_WRITE ;
661
662 Status = STATUS_SUCCESS;
663 }
664
665 break;
666
667 case FileAllocationInformation:
668 {
669 PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer;
670
671 if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
672 Status = STATUS_INVALID_DEVICE_REQUEST;
673 _SEH2_LEAVE;
674 }
675
676 if ( FAI->AllocationSize.QuadPart ==
677 Fcb->Header.AllocationSize.QuadPart) {
678
679 Status = STATUS_SUCCESS;
680
681 } else if ( FAI->AllocationSize.QuadPart >
682 Fcb->Header.AllocationSize.QuadPart ) {
683
684 Status = RfsdExpandFile(
685 IrpContext,
686 Vcb, Fcb,
687 &(FAI->AllocationSize));
688
689 if (NT_SUCCESS(Status)) {
690
691 RfsdSaveInode( IrpContext,
692 Vcb,
693 Fcb->RfsdMcb->Inode,
694 Fcb->Inode );
695 }
696
697 } else {
698
699 if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FAI->AllocationSize))) {
700
701 LARGE_INTEGER EndOfFile;
702
703 EndOfFile.QuadPart = FAI->AllocationSize.QuadPart +
704 (LONGLONG)(Vcb->BlockSize - 1);
705
706 Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile));
707
708 if (NT_SUCCESS(Status)) {
709
710 if ( FAI->AllocationSize.QuadPart <
711 Fcb->Header.FileSize.QuadPart) {
712 Fcb->Header.FileSize.QuadPart =
713 FAI->AllocationSize.QuadPart;
714 }
715
716 RfsdSaveInode( IrpContext,
717 Vcb,
718 Fcb->RfsdMcb->Inode,
719 Fcb->Inode);
720 }
721
722 } else {
723
724 Status = STATUS_USER_MAPPED_FILE;
725 _SEH2_LEAVE;
726 }
727 }
728
729 if (NT_SUCCESS(Status)) {
730
731 CcSetFileSizes(FileObject,
732 (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
733 SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
734
735 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
736 FILE_NOTIFY_CHANGE_LAST_WRITE ;
737
738 }
739
740 }
741
742 break;
743
744 case FileEndOfFileInformation:
745 {
746 PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer;
747
748 BOOLEAN CacheInitialized = FALSE;
749
750 if (IsDirectory(Fcb)) {
751 Status = STATUS_INVALID_DEVICE_REQUEST;
752 _SEH2_LEAVE;
753 }
754
755 if (FEOFI->EndOfFile.HighPart != 0) {
756 Status = STATUS_INVALID_PARAMETER;
757 _SEH2_LEAVE;
758 }
759
760
761 if (IoStackLocation->Parameters.SetFile.AdvanceOnly) {
762 Status = STATUS_SUCCESS;
763 _SEH2_LEAVE;
764 }
765
766 if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) &&
767 (FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
768 !FlagOn(Irp->Flags, IRP_PAGING_IO)) {
769
770 ASSERT( !FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ) );
771
772 CcInitializeCacheMap(
773 FileObject,
774 (PCC_FILE_SIZES)&(Fcb->Header.AllocationSize),
775 FALSE,
776 &(RfsdGlobal->CacheManagerNoOpCallbacks),
777 Fcb );
778
779 CacheInitialized = TRUE;
780 }
781
782 if ( FEOFI->EndOfFile.QuadPart ==
783 Fcb->Header.AllocationSize.QuadPart) {
784
785 Status = STATUS_SUCCESS;
786
787 } else if ( FEOFI->EndOfFile.QuadPart >
788 Fcb->Header.AllocationSize.QuadPart) {
789
790 LARGE_INTEGER FileSize = Fcb->Header.FileSize;
791
792 Status = RfsdExpandFile(IrpContext, Vcb, Fcb, &(FEOFI->EndOfFile));
793
794 if (NT_SUCCESS(Status)) {
795
796 Fcb->Header.FileSize.QuadPart = FEOFI->EndOfFile.QuadPart;
797
798 Fcb->Inode->i_size = FEOFI->EndOfFile.QuadPart;
799
800 Fcb->Header.ValidDataLength.QuadPart =
801 (LONGLONG)(0x7fffffffffffffff);
802
803 RfsdSaveInode( IrpContext,
804 Vcb,
805 Fcb->RfsdMcb->Inode,
806 Fcb->Inode);
807
808
809 CcSetFileSizes(FileObject,
810 (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
811
812 SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
813
814 RfsdZeroHoles( IrpContext,
815 Vcb, FileObject,
816 FileSize.QuadPart,
817 Fcb->Header.AllocationSize.QuadPart -
818 FileSize.QuadPart );
819
820 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
821 FILE_NOTIFY_CHANGE_LAST_WRITE ;
822
823 }
824 } else {
825
826 if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FEOFI->EndOfFile))) {
827
828 LARGE_INTEGER EndOfFile = FEOFI->EndOfFile;
829
830 EndOfFile.QuadPart = EndOfFile.QuadPart +
831 (LONGLONG)(Vcb->BlockSize - 1);
832
833 Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile));
834
835 if (NT_SUCCESS(Status)) {
836
837 Fcb->Header.FileSize.QuadPart = FEOFI->EndOfFile.QuadPart;
838 Fcb->Inode->i_size = FEOFI->EndOfFile.QuadPart;
839
840 RfsdSaveInode( IrpContext,
841 Vcb,
842 Fcb->RfsdMcb->Inode,
843 Fcb->Inode);
844
845 CcSetFileSizes(FileObject,
846 (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
847
848 SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
849
850 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
851 FILE_NOTIFY_CHANGE_LAST_WRITE ;
852 }
853
854 } else {
855
856 Status = STATUS_USER_MAPPED_FILE;
857 _SEH2_LEAVE;
858 }
859 }
860 }
861
862 break;
863
864 case FileDispositionInformation:
865 {
866 PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
867
868 Status = RfsdSetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile);
869 }
870
871 break;
872
873 case FileRenameInformation:
874 {
875 Status = RfsdSetRenameInfo(IrpContext, Vcb, Fcb);
876 }
877
878 break;
879 #endif // 0
880 #endif // !RFSD_READ_ONLY
881
882 //
883 // This is the only set file information request supported on read
884 // only file systems
885 //
886 case FilePositionInformation:
887 {
888 PFILE_POSITION_INFORMATION FilePositionInformation;
889
890 if (Length < sizeof(FILE_POSITION_INFORMATION)) {
891 Status = STATUS_INVALID_PARAMETER;
892 _SEH2_LEAVE;
893 }
894
895 FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
896
897 if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
898 (FilePositionInformation->CurrentByteOffset.LowPart &
899 DeviceObject->AlignmentRequirement) ) {
900 Status = STATUS_INVALID_PARAMETER;
901 _SEH2_LEAVE;
902 }
903
904 FileObject->CurrentByteOffset =
905 FilePositionInformation->CurrentByteOffset;
906
907 Status = STATUS_SUCCESS;
908 _SEH2_LEAVE;
909 }
910
911 break;
912
913 default:
914 Status = STATUS_INVALID_INFO_CLASS;
915 }
916
917 } _SEH2_FINALLY {
918
919 if (FcbPagingIoResourceAcquired) {
920 ExReleaseResourceForThreadLite(
921 &Fcb->PagingIoResource,
922 ExGetCurrentResourceThread() );
923 }
924
925 if (NT_SUCCESS(Status) && (NotifyFilter != 0)) {
926 RfsdNotifyReportChange(
927 IrpContext,
928 Vcb,
929 Fcb,
930 NotifyFilter,
931 FILE_ACTION_MODIFIED );
932
933 }
934
935 if (FcbMainResourceAcquired) {
936 ExReleaseResourceForThreadLite(
937 &Fcb->MainResource,
938 ExGetCurrentResourceThread() );
939 }
940
941 if (VcbResourceAcquired) {
942 ExReleaseResourceForThreadLite(
943 &Vcb->MainResource,
944 ExGetCurrentResourceThread() );
945 }
946
947 if (!IrpContext->ExceptionInProgress) {
948 if (Status == STATUS_PENDING) {
949 RfsdQueueRequest(IrpContext);
950 } else {
951 RfsdCompleteIrpContext(IrpContext, Status);
952 }
953 }
954 } _SEH2_END;
955
956 return Status;
957 }
958
959 #if !RFSD_READ_ONLY
960
961 NTSTATUS
962 RfsdExpandFile( PRFSD_IRP_CONTEXT IrpContext,
963 PRFSD_VCB Vcb, PRFSD_FCB Fcb,
964 PLARGE_INTEGER AllocationSize)
965 {
966 ULONG dwRet = 0;
967 NTSTATUS Status = STATUS_SUCCESS;
968
969 PAGED_CODE();
970
971 if (AllocationSize->QuadPart <= Fcb->Header.AllocationSize.QuadPart) {
972 return Status;
973 }
974
975 if (((LONGLONG)SUPER_BLOCK->s_free_blocks_count) * Vcb->BlockSize <=
976 (AllocationSize->QuadPart - Fcb->Header.AllocationSize.QuadPart) ) {
977 RfsdPrint((DBG_ERROR, "RfsdExpandFile: There is no enough disk space available.\n"));
978 return STATUS_DISK_FULL;
979 }
980
981 while (NT_SUCCESS(Status) && (AllocationSize->QuadPart > Fcb->Header.AllocationSize.QuadPart)) {
982 Status = RfsdExpandInode(IrpContext, Vcb, Fcb, &dwRet);
983 }
984
985 return Status;
986 }
987
988 NTSTATUS
989 RfsdTruncateFile( PRFSD_IRP_CONTEXT IrpContext,
990 PRFSD_VCB Vcb, PRFSD_FCB Fcb,
991 PLARGE_INTEGER AllocationSize)
992 {
993 NTSTATUS Status = STATUS_SUCCESS;
994
995 PAGED_CODE();
996
997 while (NT_SUCCESS(Status) && (AllocationSize->QuadPart <
998 Fcb->Header.AllocationSize.QuadPart)) {
999 Status= RfsdTruncateInode(IrpContext, Vcb, Fcb);
1000 }
1001
1002 return Status;
1003 }
1004
1005 NTSTATUS
1006 RfsdSetDispositionInfo(
1007 PRFSD_IRP_CONTEXT IrpContext,
1008 PRFSD_VCB Vcb,
1009 PRFSD_FCB Fcb,
1010 BOOLEAN bDelete)
1011 {
1012 PIRP Irp = IrpContext->Irp;
1013 PIO_STACK_LOCATION IrpSp;
1014
1015 PAGED_CODE();
1016
1017 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1018
1019 RfsdPrint((DBG_INFO, "RfsdSetDispositionInfo: bDelete=%x\n", bDelete));
1020
1021 if (bDelete) {
1022
1023 RfsdPrint((DBG_INFO, "RfsdSetDispositionInformation: MmFlushImageSection on %s.\n",
1024 Fcb->AnsiFileName.Buffer));
1025
1026 if (!MmFlushImageSection( &Fcb->SectionObject,
1027 MmFlushForDelete )) {
1028 return STATUS_CANNOT_DELETE;
1029 }
1030
1031 if (RFSD_IS_ROOT_KEY(Fcb->RfsdMcb->Key)) {
1032 return STATUS_CANNOT_DELETE;
1033 }
1034
1035 if (IsDirectory(Fcb)) {
1036 if (!RfsdIsDirectoryEmpty(Vcb, Fcb)) {
1037 return STATUS_DIRECTORY_NOT_EMPTY;
1038 }
1039 }
1040
1041 SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
1042 IrpSp->FileObject->DeletePending = TRUE;
1043
1044 if (IsDirectory(Fcb)) {
1045 FsRtlNotifyFullChangeDirectory( Vcb->NotifySync,
1046 &Vcb->NotifyList,
1047 Fcb,
1048 NULL,
1049 FALSE,
1050 FALSE,
1051 0,
1052 NULL,
1053 NULL,
1054 NULL );
1055 }
1056
1057 } else {
1058
1059 ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
1060 IrpSp->FileObject->DeletePending = FALSE;
1061 }
1062
1063 return STATUS_SUCCESS;
1064 }
1065
1066 NTSTATUS
1067 RfsdSetRenameInfo(
1068 PRFSD_IRP_CONTEXT IrpContext,
1069 PRFSD_VCB Vcb,
1070 PRFSD_FCB Fcb )
1071 {
1072 PRFSD_FCB TargetDcb;
1073 PRFSD_MCB TargetMcb;
1074
1075 PRFSD_MCB Mcb;
1076 RFSD_INODE Inode;
1077
1078 UNICODE_STRING FileName;
1079
1080 NTSTATUS Status;
1081
1082 PIRP Irp;
1083 PIO_STACK_LOCATION IrpSp;
1084
1085 PFILE_OBJECT FileObject;
1086 PFILE_OBJECT TargetObject;
1087 BOOLEAN ReplaceIfExists;
1088
1089 BOOLEAN bMove = FALSE;
1090
1091 PFILE_RENAME_INFORMATION FRI;
1092
1093 PAGED_CODE();
1094 #if 0
1095 if (Fcb->RfsdMcb->Inode == RFSD_ROOT_INO) {
1096 Status = STATUS_INVALID_PARAMETER;
1097 goto errorout;
1098 }
1099
1100 Irp = IrpContext->Irp;
1101 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1102
1103 FileObject = IrpSp->FileObject;
1104 TargetObject = IrpSp->Parameters.SetFile.FileObject;
1105 ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
1106
1107 FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
1108
1109 if (TargetObject == NULL) {
1110
1111 UNICODE_STRING NewName;
1112
1113 NewName.Buffer = FRI->FileName;
1114 NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength;
1115
1116 while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] == L'\\') {
1117 NewName.Buffer[NewName.Length/2 - 1] = 0;
1118 NewName.Length -= 2;
1119 }
1120
1121 while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] != L'\\') {
1122 NewName.Length -= 2;
1123 }
1124
1125 NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length);
1126 NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length);
1127
1128 FileName = NewName;
1129
1130 TargetDcb = NULL;
1131 TargetMcb = Fcb->RfsdMcb->Parent;
1132
1133 if (FileName.Length >= RFSD_NAME_LEN*sizeof(USHORT)) {
1134 Status = STATUS_OBJECT_NAME_INVALID;
1135 goto errorout;
1136 }
1137
1138 } else {
1139
1140 TargetDcb = (PRFSD_FCB)(TargetObject->FsContext);
1141
1142 if (!TargetDcb || TargetDcb->Vcb != Vcb) {
1143
1144 DbgBreak();
1145
1146 Status = STATUS_INVALID_PARAMETER;
1147 goto errorout;
1148 }
1149
1150 TargetMcb = TargetDcb->RfsdMcb;
1151
1152 FileName = TargetObject->FileName;
1153 }
1154
1155 if (FsRtlDoesNameContainWildCards(&FileName)) {
1156 Status = STATUS_OBJECT_NAME_INVALID;
1157 goto errorout;
1158 }
1159
1160 if (TargetMcb->Inode == Fcb->RfsdMcb->Parent->Inode) {
1161 if (FsRtlAreNamesEqual( &FileName,
1162 &(Fcb->RfsdMcb->ShortName),
1163 FALSE,
1164 NULL )) {
1165 Status = STATUS_SUCCESS;
1166 goto errorout;
1167 }
1168 } else {
1169 bMove = TRUE;
1170 }
1171
1172 TargetDcb = TargetMcb->RfsdFcb;
1173
1174 if (!TargetDcb)
1175 TargetDcb = RfsdCreateFcbFromMcb(Vcb, TargetMcb);
1176
1177 if ((TargetMcb->Inode != Fcb->RfsdMcb->Parent->Inode) &&
1178 (Fcb->RfsdMcb->Parent->RfsdFcb == NULL) ) {
1179 RfsdCreateFcbFromMcb(Vcb, Fcb->RfsdMcb->Parent);
1180 }
1181
1182 if (!TargetDcb || !(Fcb->RfsdMcb->Parent->RfsdFcb)) {
1183 Status = STATUS_UNSUCCESSFUL;
1184
1185 goto errorout;
1186 }
1187
1188 Mcb = NULL;
1189 Status = RfsdLookupFileName(
1190 Vcb,
1191 &FileName,
1192 TargetMcb,
1193 &Mcb,
1194 &Inode );
1195
1196 if (NT_SUCCESS(Status)) {
1197
1198 if ( (!ReplaceIfExists) ||
1199 (IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) ||
1200 (IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY))) {
1201 Status = STATUS_OBJECT_NAME_COLLISION;
1202 goto errorout;
1203 }
1204
1205 if (ReplaceIfExists) {
1206 Status = STATUS_NOT_IMPLEMENTED;
1207 goto errorout;
1208 }
1209 }
1210
1211 if (IsDirectory(Fcb)) {
1212
1213 Status = RfsdRemoveEntry( IrpContext, Vcb,
1214 Fcb->RfsdMcb->Parent->RfsdFcb,
1215 RFSD_FT_DIR,
1216 Fcb->RfsdMcb->Inode );
1217
1218 if (!NT_SUCCESS(Status)) {
1219 DbgBreak();
1220
1221 goto errorout;
1222 }
1223
1224 Status = RfsdAddEntry( IrpContext, Vcb,
1225 TargetDcb,
1226 RFSD_FT_DIR,
1227 Fcb->RfsdMcb->Inode,
1228 &FileName );
1229
1230 if (!NT_SUCCESS(Status)) {
1231
1232 DbgBreak();
1233
1234 RfsdAddEntry( IrpContext, Vcb,
1235 Fcb->RfsdMcb->Parent->RfsdFcb,
1236 RFSD_FT_DIR,
1237 Fcb->RfsdMcb->Inode,
1238 &Fcb->RfsdMcb->ShortName );
1239
1240 goto errorout;
1241 }
1242
1243 if( !RfsdSaveInode( IrpContext,
1244 Vcb,
1245 TargetMcb->Inode,
1246 TargetDcb->Inode)) {
1247 Status = STATUS_UNSUCCESSFUL;
1248
1249 DbgBreak();
1250
1251 goto errorout;
1252 }
1253
1254 if( !RfsdSaveInode( IrpContext,
1255 Vcb,
1256 Fcb->RfsdMcb->Parent->Inode,
1257 Fcb->RfsdMcb->Parent->RfsdFcb->Inode)) {
1258
1259 Status = STATUS_UNSUCCESSFUL;
1260
1261 DbgBreak();
1262
1263 goto errorout;
1264 }
1265
1266 Status = RfsdSetParentEntry( IrpContext, Vcb, Fcb,
1267 Fcb->RfsdMcb->Parent->Inode,
1268 TargetDcb->RfsdMcb->Inode );
1269
1270
1271 if (!NT_SUCCESS(Status)) {
1272 DbgBreak();
1273 goto errorout;
1274 }
1275
1276 } else {
1277
1278 Status = RfsdRemoveEntry( IrpContext, Vcb,
1279 Fcb->RfsdMcb->Parent->RfsdFcb,
1280 RFSD_FT_REG_FILE,
1281 Fcb->RfsdMcb->Inode );
1282 if (!NT_SUCCESS(Status)) {
1283 DbgBreak();
1284 goto errorout;
1285 }
1286
1287 Status = RfsdAddEntry( IrpContext,
1288 Vcb, TargetDcb,
1289 RFSD_FT_REG_FILE,
1290 Fcb->RfsdMcb->Inode,
1291 &FileName );
1292
1293 if (!NT_SUCCESS(Status)) {
1294
1295 DbgBreak();
1296
1297 RfsdAddEntry( IrpContext, Vcb,
1298 Fcb->RfsdMcb->Parent->RfsdFcb,
1299 RFSD_FT_REG_FILE,
1300 Fcb->RfsdMcb->Inode,
1301 &Fcb->RfsdMcb->ShortName );
1302
1303 goto errorout;
1304 }
1305 }
1306
1307 if (NT_SUCCESS(Status)) {
1308
1309 if (Fcb->RfsdMcb->ShortName.MaximumLength < (FileName.Length + 2)) {
1310
1311 ExFreePool(Fcb->RfsdMcb->ShortName.Buffer);
1312 Fcb->RfsdMcb->ShortName.Buffer =
1313 ExAllocatePoolWithTag(PagedPool, FileName.Length + 2, RFSD_POOL_TAG);
1314
1315 if (!Fcb->RfsdMcb->ShortName.Buffer) {
1316 Status = STATUS_INSUFFICIENT_RESOURCES;
1317 goto errorout;
1318 }
1319
1320 Fcb->RfsdMcb->ShortName.MaximumLength = FileName.Length + 2;
1321 }
1322
1323 {
1324 RtlZeroMemory( Fcb->RfsdMcb->ShortName.Buffer,
1325 Fcb->RfsdMcb->ShortName.MaximumLength);
1326
1327 RtlCopyMemory( Fcb->RfsdMcb->ShortName.Buffer,
1328 FileName.Buffer, FileName.Length);
1329
1330 Fcb->RfsdMcb->ShortName.Length = FileName.Length;
1331 }
1332
1333 #if DBG
1334
1335 Fcb->AnsiFileName.Length = (USHORT)
1336 RfsdUnicodeToOEMSize(&FileName) + 1;
1337
1338 if (Fcb->AnsiFileName.MaximumLength < FileName.Length) {
1339 ExFreePool(Fcb->AnsiFileName.Buffer);
1340
1341 Fcb->AnsiFileName.Buffer =
1342 ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.Length + 1, RFSD_POOL_TAG);
1343
1344 if (!Fcb->AnsiFileName.Buffer) {
1345 Status = STATUS_INSUFFICIENT_RESOURCES;
1346 goto errorout;
1347 }
1348
1349 RtlZeroMemory( Fcb->AnsiFileName.Buffer,
1350 Fcb->AnsiFileName.Length + 1);
1351 Fcb->AnsiFileName.MaximumLength =
1352 Fcb->AnsiFileName.Length + 1;
1353 }
1354
1355 RfsdUnicodeToOEM( &(Fcb->AnsiFileName),
1356 &FileName );
1357
1358 #endif
1359
1360 if (bMove) {
1361
1362 RfsdNotifyReportChange(
1363 IrpContext,
1364 Vcb,
1365 Fcb,
1366 (IsDirectory(Fcb) ?
1367 FILE_NOTIFY_CHANGE_DIR_NAME :
1368 FILE_NOTIFY_CHANGE_FILE_NAME ),
1369 FILE_ACTION_REMOVED);
1370
1371 } else {
1372
1373 RfsdNotifyReportChange(
1374 IrpContext,
1375 Vcb,
1376 Fcb,
1377 (IsDirectory(Fcb) ?
1378 FILE_NOTIFY_CHANGE_DIR_NAME :
1379 FILE_NOTIFY_CHANGE_FILE_NAME ),
1380 FILE_ACTION_RENAMED_OLD_NAME);
1381
1382 }
1383
1384 RfsdDeleteMcbNode(Vcb, Fcb->RfsdMcb->Parent, Fcb->RfsdMcb);
1385 RfsdAddMcbNode(Vcb, TargetMcb, Fcb->RfsdMcb);
1386
1387 if (bMove) {
1388
1389 RfsdNotifyReportChange(
1390 IrpContext,
1391 Vcb,
1392 Fcb,
1393 (IsDirectory(Fcb) ?
1394 FILE_NOTIFY_CHANGE_DIR_NAME :
1395 FILE_NOTIFY_CHANGE_FILE_NAME ),
1396 FILE_ACTION_ADDED);
1397 } else {
1398
1399 RfsdNotifyReportChange(
1400 IrpContext,
1401 Vcb,
1402 Fcb,
1403 (IsDirectory(Fcb) ?
1404 FILE_NOTIFY_CHANGE_DIR_NAME :
1405 FILE_NOTIFY_CHANGE_FILE_NAME ),
1406 FILE_ACTION_RENAMED_NEW_NAME );
1407
1408 }
1409 }
1410
1411 errorout:
1412 #endif // 0
1413 return 0;//Status;
1414 }
1415
1416 NTSTATUS
1417 RfsdDeleteFile(
1418 PRFSD_IRP_CONTEXT IrpContext,
1419 PRFSD_VCB Vcb,
1420 PRFSD_FCB Fcb )
1421 {
1422 BOOLEAN bRet = FALSE;
1423 LARGE_INTEGER AllocationSize;
1424 PRFSD_FCB Dcb = NULL;
1425 NTSTATUS Status = STATUS_SUCCESS;
1426
1427 PAGED_CODE();
1428 #if 0
1429 RfsdPrint((DBG_INFO, "RfsdDeleteFile: File %S (%xh) will be deleted!\n",
1430 Fcb->RfsdMcb->ShortName.Buffer, Fcb->RfsdMcb->Inode));
1431
1432 if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
1433 return Status;
1434 }
1435
1436 if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
1437 if (!RfsdIsDirectoryEmpty(Vcb, Fcb)) {
1438 ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
1439
1440 return STATUS_DIRECTORY_NOT_EMPTY;
1441 }
1442 }
1443
1444 RfsdPrint((DBG_INFO, "RfsdDeleteFile: RFSDSB->S_FREE_BLOCKS = %xh .\n",
1445 Vcb->SuperBlock->s_free_blocks_count));
1446
1447 if (IsDirectory(Fcb)) {
1448 if (Fcb->Inode->i_links_count <= 2) {
1449 } else {
1450 Status = STATUS_CANNOT_DELETE;
1451 }
1452 } else {
1453 if (Fcb->Inode->i_links_count <= 1) {
1454 } else {
1455 Status = STATUS_CANNOT_DELETE;
1456 }
1457 }
1458
1459 if (!NT_SUCCESS(Status)) {
1460 DbgBreak();
1461 return Status;
1462 }
1463
1464 if (Fcb->RfsdMcb->Parent->RfsdFcb) {
1465
1466 Status = RfsdRemoveEntry(
1467 IrpContext, Vcb,
1468 Fcb->RfsdMcb->Parent->RfsdFcb,
1469 (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
1470 RFSD_FT_DIR : RFSD_FT_REG_FILE),
1471 Fcb->RfsdMcb->Inode);
1472 } else {
1473
1474 Dcb = RfsdCreateFcbFromMcb(Vcb, Fcb->RfsdMcb->Parent);
1475 if (Dcb) {
1476 Status = RfsdRemoveEntry(
1477 IrpContext, Vcb, Dcb,
1478 (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
1479 RFSD_FT_DIR : RFSD_FT_REG_FILE),
1480 Fcb->RfsdMcb->Inode);
1481 }
1482 }
1483
1484 if (NT_SUCCESS(Status)) {
1485
1486 LARGE_INTEGER SysTime;
1487 KeQuerySystemTime(&SysTime);
1488
1489 AllocationSize.QuadPart = (LONGLONG)0;
1490
1491 Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
1492
1493 //
1494 // Update the inode's data length . It should be ZERO if succeeds.
1495 //
1496
1497 if (Fcb->Header.FileSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) {
1498
1499 Fcb->Header.FileSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
1500 Fcb->Inode->i_size = Fcb->Header.AllocationSize.QuadPart;
1501 }
1502
1503 Fcb->Inode->i_links_count = 0;
1504
1505 RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
1506
1507 if (IsDirectory(Fcb)) {
1508 bRet = RfsdFreeInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RFSD_FT_DIR);
1509 } else {
1510 bRet = RfsdFreeInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RFSD_FT_REG_FILE);
1511 }
1512
1513 SetFlag(Fcb->Flags, FCB_FILE_DELETED);
1514 RfsdDeleteMcbNode(Vcb, Fcb->RfsdMcb->Parent, Fcb->RfsdMcb);
1515
1516 } else {
1517 DbgBreak();
1518 RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
1519 }
1520
1521 RfsdPrint((DBG_INFO, "RfsdDeleteFile: Succeed... RFSDSB->S_FREE_BLOCKS = %xh .\n",
1522 Vcb->SuperBlock->s_free_blocks_count));
1523 #endif // 0
1524 return Status;
1525 }
1526
1527 #endif // !RFSD_READ_ONLY