[fastfat_new]
[reactos.git] / reactos / drivers / filesystems / fastfat_new / volume.c
1 /*
2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GNU GPLv3 as published by the Free Software Foundation
4 * FILE: drivers/filesystems/fastfat/volume.c
5 * PURPOSE: Volume information
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 //#define NDEBUG
12 #include "fastfat.h"
13
14 /* FUNCTIONS ****************************************************************/
15
16 NTSTATUS
17 NTAPI
18 FatiQueryFsVolumeInfo(PVCB Vcb,
19 PFILE_FS_VOLUME_INFORMATION Buffer,
20 PLONG Length)
21 {
22 ULONG ByteSize;
23 NTSTATUS Status = STATUS_SUCCESS;
24
25 /* Deduct the minimum written length */
26 *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
27
28 /* Zero it */
29 RtlZeroMemory(Buffer, sizeof(FILE_FS_VOLUME_INFORMATION));
30
31 DPRINT("Serial number 0x%x, label length %d\n",
32 Vcb->Vpb->SerialNumber, Vcb->Vpb->VolumeLabelLength);
33
34 /* Save serial number */
35 Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
36
37 /* Set max byte size */
38 ByteSize = Vcb->Vpb->VolumeLabelLength;
39
40 /* Check buffer length and reduce byte size if needed */
41 if (*Length < Vcb->Vpb->VolumeLabelLength)
42 {
43 /* Copy only up to what buffer size was provided */
44 ByteSize = *Length;
45 Status = STATUS_BUFFER_OVERFLOW;
46 }
47
48 /* Copy volume label */
49 Buffer->VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
50 RtlCopyMemory(Buffer->VolumeLabel, Vcb->Vpb->VolumeLabel, ByteSize);
51 *Length -= ByteSize;
52
53 return Status;
54 }
55
56 NTSTATUS
57 NTAPI
58 FatiQueryFsSizeInfo(PVCB Vcb,
59 PFILE_FS_SIZE_INFORMATION Buffer,
60 PLONG Length)
61 {
62 FF_PARTITION *Partition;
63 NTSTATUS Status = STATUS_SUCCESS;
64
65 /* Deduct the minimum written length */
66 *Length -= sizeof(FILE_FS_SIZE_INFORMATION);
67
68 /* Zero it */
69 RtlZeroMemory(Buffer, sizeof(FILE_FS_SIZE_INFORMATION));
70
71 /* Reference FullFAT's partition */
72 Partition = Vcb->Ioman->pPartition;
73
74 /* Set values */
75 Buffer->AvailableAllocationUnits.LowPart = Partition->FreeClusterCount;
76 Buffer->TotalAllocationUnits.LowPart = Partition->NumClusters;
77 Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
78 Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
79
80 DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->FreeClusterCount,
81 Partition->NumClusters, Vcb->Bpb.SectorsPerCluster, Vcb->Bpb.BytesPerSector);
82
83 return Status;
84 }
85
86 NTSTATUS
87 NTAPI
88 FatiQueryVolumeInfo(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
89 {
90 PFILE_OBJECT FileObject;
91 PIO_STACK_LOCATION IrpSp;
92 FILE_INFORMATION_CLASS InfoClass;
93 TYPE_OF_OPEN FileType;
94 PVCB Vcb;
95 PFCB Fcb;
96 PCCB Ccb;
97 LONG Length;
98 PVOID Buffer;
99 BOOLEAN VcbLocked = FALSE;
100 NTSTATUS Status = STATUS_SUCCESS;
101
102 /* Get IRP stack location */
103 IrpSp = IoGetCurrentIrpStackLocation(Irp);
104
105 /* Get the file object */
106 FileObject = IrpSp->FileObject;
107
108 /* Copy variables to something with shorter names */
109 InfoClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
110 Length = IrpSp->Parameters.QueryVolume.Length;
111 Buffer = Irp->AssociatedIrp.SystemBuffer;
112
113 DPRINT("FatiQueryVolumeInfo\n", 0);
114 DPRINT("\tIrp = %08lx\n", Irp);
115 DPRINT("\tLength = %08lx\n", Length);
116 DPRINT("\tFsInformationClass = %08lx\n", InfoClass);
117 DPRINT("\tBuffer = %08lx\n", Buffer);
118
119 FileType = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
120
121 DPRINT("Vcb %p, Fcb %p, Ccb %p, open type %d\n", Vcb, Fcb, Ccb, FileType);
122
123 switch (InfoClass)
124 {
125 case FileFsVolumeInformation:
126 /* Acquired the shared VCB lock */
127 if (!FatAcquireSharedVcb(IrpContext, Vcb))
128 {
129 ASSERT(FALSE);
130 }
131
132 /* Remember we locked it */
133 VcbLocked = TRUE;
134
135 /* Call FsVolumeInfo handler */
136 Status = FatiQueryFsVolumeInfo(Vcb, Buffer, &Length);
137 break;
138 case FileFsSizeInformation:
139 /* Call FsVolumeInfo handler */
140 Status = FatiQueryFsSizeInfo(Vcb, Buffer, &Length);
141 break;
142 default:
143 DPRINT1("Volume information class %d is not supported!\n", InfoClass);
144 UNIMPLEMENTED;
145 }
146
147 /* Set IoStatus.Information to amount of filled bytes */
148 Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
149
150 /* Release VCB lock */
151 if (VcbLocked) FatReleaseVcb(IrpContext, Vcb);
152
153 /* Complete request and return status */
154 FatCompleteRequest(IrpContext, Irp, Status);
155 return Status;
156 }
157
158 NTSTATUS
159 NTAPI
160 FatQueryVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
161 {
162 NTSTATUS Status;
163 BOOLEAN TopLevel, CanWait;
164 PFAT_IRP_CONTEXT IrpContext;
165
166 CanWait = TRUE;
167 TopLevel = FALSE;
168 Status = STATUS_INVALID_DEVICE_REQUEST;
169
170 /* Get CanWait flag */
171 if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
172 CanWait = IoIsOperationSynchronous(Irp);
173
174 /* Enter FsRtl critical region */
175 FsRtlEnterFileSystem();
176
177 /* Set Top Level IRP if not set */
178 if (IoGetTopLevelIrp() == NULL)
179 {
180 IoSetTopLevelIrp(Irp);
181 TopLevel = TRUE;
182 }
183
184 /* Build an irp context */
185 IrpContext = FatBuildIrpContext(Irp, CanWait);
186
187 /* Call the request handler */
188 Status = FatiQueryVolumeInfo(IrpContext, Irp);
189
190 /* Restore top level Irp */
191 if (TopLevel)
192 IoSetTopLevelIrp(NULL);
193
194 /* Leave FsRtl critical region */
195 FsRtlExitFileSystem();
196
197 return Status;
198 }
199
200 NTSTATUS
201 NTAPI
202 FatSetVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
203 {
204 DPRINT1("FatSetVolumeInfo()\n");
205 return STATUS_NOT_IMPLEMENTED;
206 }
207
208 VOID
209 NTAPI
210 FatReadStreamFile(PVCB Vcb,
211 ULONGLONG ByteOffset,
212 ULONG ByteSize,
213 PBCB *Bcb,
214 PVOID *Buffer)
215 {
216 LARGE_INTEGER Offset;
217
218 Offset.QuadPart = ByteOffset;
219
220 if (!CcMapData(Vcb->StreamFileObject,
221 &Offset,
222 ByteSize,
223 TRUE, // FIXME: CanWait
224 Bcb,
225 Buffer))
226 {
227 ASSERT(FALSE);
228 }
229 }
230
231 /* EOF */