739ec308d8f07db2f23ab35265f10ee305e64cb6
[reactos.git] / reactos / drivers / fs / vfat / finfo.c
1 /* $Id: finfo.c,v 1.10 2001/11/01 10:44:11 hbirr Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/vfat/finfo.c
6 * PURPOSE: VFAT Filesystem
7 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
8 *
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <wchar.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 #include "vfat.h"
20
21 /* FUNCTIONS ****************************************************************/
22
23 static NTSTATUS
24 VfatGetStandardInformation(PVFATFCB FCB,
25 PDEVICE_OBJECT DeviceObject,
26 PFILE_STANDARD_INFORMATION StandardInfo,
27 PULONG BufferLength)
28 /*
29 * FUNCTION: Retrieve the standard file information
30 */
31 {
32 PDEVICE_EXTENSION DeviceExtension;
33
34 if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
35 return STATUS_BUFFER_OVERFLOW;
36
37 DeviceExtension = DeviceObject->DeviceExtension;
38 /* PRECONDITION */
39 assert (DeviceExtension != NULL);
40 assert (DeviceExtension->BytesPerCluster != 0);
41 assert (StandardInfo != NULL);
42 assert (FCB != NULL);
43
44 RtlZeroMemory(StandardInfo,
45 sizeof(FILE_STANDARD_INFORMATION));
46
47 StandardInfo->AllocationSize = FCB->RFCB.AllocationSize;
48 StandardInfo->EndOfFile = FCB->RFCB.FileSize;
49 StandardInfo->NumberOfLinks = 0;
50 StandardInfo->DeletePending = FCB->Flags & FCB_DELETE_PENDING ? TRUE : FALSE;
51 StandardInfo->Directory = FCB->entry.Attrib & 0x10 ? TRUE : FALSE;
52
53 *BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
54 return(STATUS_SUCCESS);
55 }
56
57 static NTSTATUS
58 VfatSetPositionInformation(PFILE_OBJECT FileObject,
59 PVFATFCB FCB,
60 PDEVICE_OBJECT DeviceObject,
61 PFILE_POSITION_INFORMATION PositionInfo)
62 {
63 DPRINT ("FsdSetPositionInformation()\n");
64
65 DPRINT ("PositionInfo %x\n", PositionInfo);
66 DPRINT ("Setting position %d\n", PositionInfo->CurrentByteOffset.u.LowPart);
67 memcpy (&FileObject->CurrentByteOffset, &PositionInfo->CurrentByteOffset,
68 sizeof (LARGE_INTEGER));
69
70 return (STATUS_SUCCESS);
71 }
72
73 static NTSTATUS
74 VfatGetPositionInformation(PFILE_OBJECT FileObject,
75 PVFATFCB FCB,
76 PDEVICE_OBJECT DeviceObject,
77 PFILE_POSITION_INFORMATION PositionInfo,
78 PULONG BufferLength)
79 {
80 DPRINT ("VfatGetPositionInformation()\n");
81
82 if (*BufferLength < sizeof(FILE_POSITION_INFORMATION))
83 return STATUS_BUFFER_OVERFLOW;
84
85 PositionInfo->CurrentByteOffset.QuadPart =
86 FileObject->CurrentByteOffset.QuadPart;
87
88 DPRINT("Getting position %I64x\n",
89 PositionInfo->CurrentByteOffset.QuadPart);
90
91 *BufferLength -= sizeof(FILE_POSITION_INFORMATION);
92 return(STATUS_SUCCESS);
93 }
94
95 static NTSTATUS
96 VfatGetBasicInformation(PFILE_OBJECT FileObject,
97 PVFATFCB FCB,
98 PDEVICE_OBJECT DeviceObject,
99 PFILE_BASIC_INFORMATION BasicInfo,
100 PULONG BufferLength)
101 {
102 DPRINT("VfatGetBasicInformation()\n");
103
104 if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
105 return STATUS_BUFFER_OVERFLOW;
106
107 FsdDosDateTimeToFileTime(FCB->entry.CreationDate,
108 FCB->entry.CreationTime,
109 &BasicInfo->CreationTime);
110 FsdDosDateTimeToFileTime(FCB->entry.AccessDate,
111 0,
112 &BasicInfo->LastAccessTime);
113 FsdDosDateTimeToFileTime(FCB->entry.UpdateDate,
114 FCB->entry.UpdateTime,
115 &BasicInfo->LastWriteTime);
116 FsdDosDateTimeToFileTime(FCB->entry.UpdateDate,
117 FCB->entry.UpdateTime,
118 &BasicInfo->ChangeTime);
119
120 BasicInfo->FileAttributes = FCB->entry.Attrib;
121 DPRINT("Getting attributes %x\n", BasicInfo->FileAttributes);
122
123 *BufferLength -= sizeof(FILE_BASIC_INFORMATION);
124 return(STATUS_SUCCESS);
125 }
126
127
128 static NTSTATUS
129 VfatSetDispositionInformation(PFILE_OBJECT FileObject,
130 PVFATFCB FCB,
131 PDEVICE_OBJECT DeviceObject,
132 PFILE_DISPOSITION_INFORMATION DispositionInfo)
133 {
134 KIRQL oldIrql;
135 VFATFCB tmpFcb;
136 WCHAR star[2];
137 ULONG Index;
138 NTSTATUS Status = STATUS_SUCCESS;
139 int count;
140
141 PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
142
143 DPRINT ("FsdSetDispositionInformation()\n");
144
145 assert (DeviceExt != NULL);
146 assert (DeviceExt->BytesPerCluster != 0);
147 assert (FCB != NULL);
148
149 if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..")
150 || !wcscmp(FCB->ObjectName, L"."))
151 {
152 // we cannot delete a '.', '..' or the root directory
153 return STATUS_ACCESS_DENIED;
154 }
155 if (DispositionInfo->DoDeleteFile)
156 {
157 KeAcquireSpinLock (&DeviceExt->FcbListLock, &oldIrql);
158 count = FCB->RefCount;
159 if (FCB->RefCount > 1)
160 Status = STATUS_ACCESS_DENIED;
161 else
162 {
163 FCB->Flags |= FCB_DELETE_PENDING;
164 FileObject->DeletePending = TRUE;
165 }
166 KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
167 DPRINT("RefCount:%d\n", count);
168 if (NT_SUCCESS(Status) && vfatFCBIsDirectory(DeviceExt, FCB))
169 {
170 memset (&tmpFcb, 0, sizeof(VFATFCB));
171 tmpFcb.ObjectName = tmpFcb.PathName;
172 star[0] = L'*';
173 star[1] = 0;
174 // skip '.' and '..', start by 2
175 Index = 2;
176 Status = FindFile (DeviceExt, &tmpFcb, FCB, star, &Index, NULL);
177 if (NT_SUCCESS(Status))
178 {
179 DPRINT1("found: \'%S\'\n", tmpFcb.PathName);
180 Status = STATUS_DIRECTORY_NOT_EMPTY;
181 FCB->Flags &= ~FCB_DELETE_PENDING;
182 FileObject->DeletePending = FALSE;
183 }
184 else
185 {
186 Status = STATUS_SUCCESS;
187 }
188 }
189 }
190 else
191 FileObject->DeletePending = FALSE;
192 return Status;
193 }
194
195 static NTSTATUS
196 VfatGetNameInformation(PFILE_OBJECT FileObject,
197 PVFATFCB FCB,
198 PDEVICE_OBJECT DeviceObject,
199 PFILE_NAME_INFORMATION NameInfo,
200 PULONG BufferLength)
201 /*
202 * FUNCTION: Retrieve the file name information
203 */
204 {
205 ULONG NameLength;
206
207 assert (NameInfo != NULL);
208 assert (FCB != NULL);
209
210 NameLength = wcslen(FCB->PathName) * sizeof(WCHAR);
211 if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength)
212 return STATUS_BUFFER_OVERFLOW;
213
214 NameInfo->FileNameLength = NameLength;
215 memcpy(NameInfo->FileName,
216 FCB->PathName,
217 NameLength + sizeof(WCHAR));
218
219 *BufferLength -=
220 (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR));
221
222 return STATUS_SUCCESS;
223 }
224
225 static NTSTATUS
226 VfatGetInternalInformation(PVFATFCB Fcb,
227 PFILE_INTERNAL_INFORMATION InternalInfo,
228 PULONG BufferLength)
229 {
230 assert (InternalInfo);
231 assert (Fcb);
232
233 if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
234 return STATUS_BUFFER_OVERFLOW;
235 // FIXME: get a real index, that can be used in a create operation
236 InternalInfo->IndexNumber.QuadPart = 0;
237 *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
238 return STATUS_SUCCESS;
239 }
240
241 NTSTATUS STDCALL
242 VfatQueryInformation(PDEVICE_OBJECT DeviceObject,
243 PIRP Irp)
244 /*
245 * FUNCTION: Retrieve the specified file information
246 */
247 {
248 PIO_STACK_LOCATION Stack;
249 FILE_INFORMATION_CLASS FileInformationClass;
250 PFILE_OBJECT FileObject = NULL;
251 PVFATFCB FCB = NULL;
252 // PVFATCCB CCB = NULL;
253
254 NTSTATUS RC = STATUS_SUCCESS;
255 PVOID SystemBuffer;
256 ULONG BufferLength;
257
258 /* PRECONDITION */
259 assert (DeviceObject != NULL);
260 assert (Irp != NULL);
261
262 /* INITIALIZATION */
263 Stack = IoGetCurrentIrpStackLocation (Irp);
264 FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
265 FileObject = Stack->FileObject;
266 // CCB = (PVFATCCB)(FileObject->FsContext2);
267 // FCB = CCB->Buffer; // Should be CCB->FCB???
268 FCB = ((PVFATCCB) (FileObject->FsContext2))->pFcb;
269
270 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
271 BufferLength = Stack->Parameters.QueryFile.Length;
272
273 switch (FileInformationClass)
274 {
275 case FileStandardInformation:
276 RC = VfatGetStandardInformation(FCB,
277 DeviceObject,
278 SystemBuffer,
279 &BufferLength);
280 break;
281 case FilePositionInformation:
282 RC = VfatGetPositionInformation(FileObject,
283 FCB,
284 DeviceObject,
285 SystemBuffer,
286 &BufferLength);
287 break;
288 case FileBasicInformation:
289 RC = VfatGetBasicInformation(FileObject,
290 FCB,
291 DeviceObject,
292 SystemBuffer,
293 &BufferLength);
294 break;
295 case FileNameInformation:
296 RC = VfatGetNameInformation(FileObject,
297 FCB,
298 DeviceObject,
299 SystemBuffer,
300 &BufferLength);
301 break;
302 case FileInternalInformation:
303 RC = VfatGetInternalInformation(FCB,
304 SystemBuffer,
305 &BufferLength);
306 break;
307 case FileAlternateNameInformation:
308 case FileAllInformation:
309 RC = STATUS_NOT_IMPLEMENTED;
310 break;
311 default:
312 RC = STATUS_NOT_SUPPORTED;
313 }
314
315 Irp->IoStatus.Status = RC;
316 if (NT_SUCCESS(RC))
317 Irp->IoStatus.Information =
318 Stack->Parameters.QueryFile.Length - BufferLength;
319 else
320 Irp->IoStatus.Information = 0;
321 IoCompleteRequest(Irp,
322 IO_NO_INCREMENT);
323
324 return RC;
325 }
326
327 NTSTATUS STDCALL
328 VfatSetInformation(PDEVICE_OBJECT DeviceObject,
329 PIRP Irp)
330 /*
331 * FUNCTION: Retrieve the specified file information
332 */
333 {
334 PIO_STACK_LOCATION Stack;
335 FILE_INFORMATION_CLASS FileInformationClass;
336 PFILE_OBJECT FileObject = NULL;
337 PVFATFCB FCB = NULL;
338 // PVFATCCB CCB = NULL;
339 NTSTATUS RC = STATUS_SUCCESS;
340 PVOID SystemBuffer;
341
342 /* PRECONDITION */
343 assert(DeviceObject != NULL);
344 assert(Irp != NULL);
345
346 DPRINT("VfatSetInformation(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
347
348 /* INITIALIZATION */
349 Stack = IoGetCurrentIrpStackLocation (Irp);
350 FileInformationClass = Stack->Parameters.SetFile.FileInformationClass;
351 FileObject = Stack->FileObject;
352 FCB = ((PVFATCCB) (FileObject->FsContext2))->pFcb;
353 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
354
355 DPRINT("FileInformationClass %d\n", FileInformationClass);
356 DPRINT("SystemBuffer %x\n", SystemBuffer);
357
358 switch (FileInformationClass)
359 {
360 case FilePositionInformation:
361 RC = VfatSetPositionInformation(FileObject,
362 FCB,
363 DeviceObject,
364 SystemBuffer);
365 break;
366 case FileDispositionInformation:
367 RC = VfatSetDispositionInformation(FileObject,
368 FCB,
369 DeviceObject,
370 SystemBuffer);
371 break;
372 case FileBasicInformation:
373 case FileAllocationInformation:
374 case FileEndOfFileInformation:
375 case FileRenameInformation:
376 RC = STATUS_NOT_IMPLEMENTED;
377 break;
378 default:
379 RC = STATUS_NOT_SUPPORTED;
380 }
381
382 Irp->IoStatus.Status = RC;
383 Irp->IoStatus.Information = 0;
384 IoCompleteRequest(Irp,
385 IO_NO_INCREMENT);
386
387 return RC;
388 }
389
390 /* EOF */