Sync with trunk (aka 'I want my virtualbox mouse integration too')
[reactos.git] / drivers / filesystems / fastfat_new / finfo.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/finfo.c
5 * PURPOSE: File Information support routines
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #define NDEBUG
12 #include "fastfat.h"
13
14 /* FUNCTIONS ****************************************************************/
15
16 VOID
17 NTAPI
18 FatiQueryBasicInformation(IN PFAT_IRP_CONTEXT IrpContext,
19 IN PFCB Fcb,
20 IN PFILE_OBJECT FileObject,
21 IN OUT PFILE_BASIC_INFORMATION Buffer,
22 IN OUT PLONG Length)
23 {
24 /* Zero the buffer */
25 RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION));
26
27 /* Deduct the written length */
28 *Length -= sizeof(FILE_BASIC_INFORMATION);
29
30 /* Check if it's a dir or a file */
31 if (FatNodeType(Fcb) == FAT_NTC_FCB)
32 {
33 // FIXME: Read dirent and get times from there
34 Buffer->LastAccessTime.QuadPart = 0;
35 Buffer->CreationTime.QuadPart = 0;
36 Buffer->LastWriteTime.QuadPart = 0;
37 }
38 else
39 {
40 // FIXME: May not be really correct
41 Buffer->FileAttributes = 0;
42 DPRINT1("Basic info of a directory '%wZ' is requested!\n", &Fcb->FullFileName);
43 }
44
45
46 /* If attribute is 0, set normal */
47 if (Buffer->FileAttributes == 0)
48 Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
49 }
50
51 VOID
52 NTAPI
53 FatiQueryStandardInformation(IN PFAT_IRP_CONTEXT IrpContext,
54 IN PFCB Fcb,
55 IN PFILE_OBJECT FileObject,
56 IN OUT PFILE_STANDARD_INFORMATION Buffer,
57 IN OUT PLONG Length)
58 {
59 /* Zero the buffer */
60 RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION));
61
62 /* Deduct the written length */
63 *Length -= sizeof(FILE_STANDARD_INFORMATION);
64
65 Buffer->NumberOfLinks = 1;
66 Buffer->DeletePending = FALSE; // FIXME
67
68 /* Check if it's a dir or a file */
69 if (FatNodeType(Fcb) == FAT_NTC_FCB)
70 {
71 Buffer->Directory = FALSE;
72
73 Buffer->EndOfFile.LowPart = Fcb->FatHandle->Filesize;
74 Buffer->AllocationSize = Buffer->EndOfFile;
75 DPRINT("Filesize %d, chain length %d\n", Fcb->FatHandle->Filesize, Fcb->FatHandle->iChainLength);
76 }
77 else
78 {
79 Buffer->Directory = TRUE;
80 }
81 }
82
83 VOID
84 NTAPI
85 FatiQueryInternalInformation(IN PFAT_IRP_CONTEXT IrpContext,
86 IN PFCB Fcb,
87 IN PFILE_OBJECT FileObject,
88 IN OUT PFILE_INTERNAL_INFORMATION Buffer,
89 IN OUT PLONG Length)
90 {
91 UNIMPLEMENTED;
92 }
93
94 VOID
95 NTAPI
96 FatiQueryNameInformation(IN PFAT_IRP_CONTEXT IrpContext,
97 IN PFCB Fcb,
98 IN PFILE_OBJECT FileObject,
99 IN OUT PFILE_NAME_INFORMATION Buffer,
100 IN OUT PLONG Length)
101 {
102 ULONG ByteSize;
103 ULONG Trim = 0;
104 BOOLEAN Overflow = FALSE;
105
106 /* Deduct the minimum written length */
107 *Length -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
108
109 /* Build full name if needed */
110 if (!Fcb->FullFileName.Buffer)
111 {
112 FatSetFullFileNameInFcb(IrpContext, Fcb);
113 }
114
115 DPRINT("FullFileName %wZ\n", &Fcb->FullFileName);
116
117 if (*Length < Fcb->FullFileName.Length - Trim)
118 {
119 /* Buffer can't fit all data */
120 ByteSize = *Length;
121 Overflow = TRUE;
122 }
123 else
124 {
125 /* Deduct the amount of bytes we are going to write */
126 ByteSize = Fcb->FullFileName.Length - Trim;
127 *Length -= ByteSize;
128 }
129
130 /* Copy the name */
131 RtlCopyMemory(Buffer->FileName,
132 Fcb->FullFileName.Buffer,
133 ByteSize);
134
135 /* Set the length */
136 Buffer->FileNameLength = Fcb->FullFileName.Length - Trim;
137
138 /* Is this a shortname query? */
139 if (Trim)
140 {
141 /* Yes, not supported atm */
142 ASSERT(FALSE);
143 }
144
145 /* Indicate overflow by passing -1 as the length */
146 if (Overflow) *Length = -1;
147 }
148
149 NTSTATUS
150 NTAPI
151 FatiQueryInformation(IN PFAT_IRP_CONTEXT IrpContext,
152 IN PIRP Irp)
153 {
154 PFILE_OBJECT FileObject;
155 PIO_STACK_LOCATION IrpSp;
156 FILE_INFORMATION_CLASS InfoClass;
157 TYPE_OF_OPEN FileType;
158 PVCB Vcb;
159 PFCB Fcb;
160 PCCB Ccb;
161 LONG Length;
162 PVOID Buffer;
163 BOOLEAN VcbLocked = FALSE, FcbLocked = FALSE;
164 NTSTATUS Status = STATUS_SUCCESS;
165
166 /* Get IRP stack location */
167 IrpSp = IoGetCurrentIrpStackLocation(Irp);
168
169 /* Get the file object */
170 FileObject = IrpSp->FileObject;
171
172 /* Copy variables to something with shorter names */
173 InfoClass = IrpSp->Parameters.QueryFile.FileInformationClass;
174 Length = IrpSp->Parameters.QueryFile.Length;
175 Buffer = Irp->AssociatedIrp.SystemBuffer;
176
177 DPRINT("FatiQueryInformation\n", 0);
178 DPRINT("\tIrp = %08lx\n", Irp);
179 DPRINT("\tLength = %08lx\n", Length);
180 DPRINT("\tFileInformationClass = %08lx\n", InfoClass);
181 DPRINT("\tBuffer = %08lx\n", Buffer);
182
183 FileType = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
184
185 DPRINT("Vcb %p, Fcb %p, Ccb %p, open type %d\n", Vcb, Fcb, Ccb, FileType);
186
187 /* Acquire VCB lock */
188 if (InfoClass == FileNameInformation ||
189 InfoClass == FileAllInformation)
190 {
191 if (!FatAcquireExclusiveVcb(IrpContext, Vcb))
192 {
193 ASSERT(FALSE);
194 }
195
196 /* Remember we locked the VCB */
197 VcbLocked = TRUE;
198 }
199
200 /* Acquire FCB lock */
201 // FIXME: If not paging file
202 if (!FatAcquireSharedFcb(IrpContext, Fcb))
203 {
204 ASSERT(FALSE);
205 }
206 FcbLocked = TRUE;
207
208 switch (InfoClass)
209 {
210 case FileBasicInformation:
211 FatiQueryBasicInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
212 break;
213 case FileStandardInformation:
214 FatiQueryStandardInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
215 break;
216 case FileInternalInformation:
217 FatiQueryInternalInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
218 break;
219 case FileNameInformation:
220 FatiQueryNameInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
221 break;
222 default:
223 DPRINT1("Unimplemented information class %d requested\n", InfoClass);
224 Status = STATUS_INVALID_PARAMETER;
225 }
226
227 /* Check for buffer overflow */
228 if (Length < 0)
229 {
230 Status = STATUS_BUFFER_OVERFLOW;
231 Length = 0;
232 }
233
234 /* Set IoStatus.Information to amount of filled bytes */
235 Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
236
237 /* Release FCB locks */
238 if (FcbLocked) FatReleaseFcb(IrpContext, Fcb);
239 if (VcbLocked) FatReleaseVcb(IrpContext, Vcb);
240
241 /* Complete request and return status */
242 FatCompleteRequest(IrpContext, Irp, Status);
243 return Status;
244 }
245
246 NTSTATUS
247 NTAPI
248 FatQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
249 {
250 NTSTATUS Status;
251 BOOLEAN TopLevel, CanWait;
252 PFAT_IRP_CONTEXT IrpContext;
253
254 CanWait = TRUE;
255 TopLevel = FALSE;
256 Status = STATUS_INVALID_DEVICE_REQUEST;
257
258 /* Get CanWait flag */
259 if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
260 CanWait = IoIsOperationSynchronous(Irp);
261
262 /* Enter FsRtl critical region */
263 FsRtlEnterFileSystem();
264
265 /* Set Top Level IRP if not set */
266 if (IoGetTopLevelIrp() == NULL)
267 {
268 IoSetTopLevelIrp(Irp);
269 TopLevel = TRUE;
270 }
271
272 /* Build an irp context */
273 IrpContext = FatBuildIrpContext(Irp, CanWait);
274
275 /* Perform the actual read */
276 Status = FatiQueryInformation(IrpContext, Irp);
277
278 /* Restore top level Irp */
279 if (TopLevel) IoSetTopLevelIrp(NULL);
280
281 /* Leave FsRtl critical region */
282 FsRtlExitFileSystem();
283
284 return Status;
285 }
286
287 NTSTATUS
288 NTAPI
289 FatSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
290 {
291 DPRINT1("FatSetInformation()\n");
292 return STATUS_NOT_IMPLEMENTED;
293 }
294
295 /* EOF */