* Sync up to trunk HEAD (r62975).
[reactos.git] / drivers / filesystems / cdfs / finfo.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: services/fs/cdfs/finfo.c
23 * PURPOSE: CDROM (ISO 9660) filesystem driver
24 * PROGRAMMER: Art Yerkes
25 * Eric Kohl
26 * UPDATE HISTORY:
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include "cdfs.h"
32
33 #define NDEBUG
34 #include <debug.h>
35
36 /* FUNCTIONS ****************************************************************/
37
38 /*
39 * FUNCTION: Retrieve the standard file information
40 */
41 static NTSTATUS
42 CdfsGetStandardInformation(PFCB Fcb,
43 PDEVICE_OBJECT DeviceObject,
44 PFILE_STANDARD_INFORMATION StandardInfo,
45 PULONG BufferLength)
46 {
47 DPRINT("CdfsGetStandardInformation() called\n");
48
49 UNREFERENCED_PARAMETER(DeviceObject);
50
51 if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
52 return STATUS_BUFFER_OVERFLOW;
53
54 /* PRECONDITION */
55 ASSERT(StandardInfo != NULL);
56 ASSERT(Fcb != NULL);
57
58 RtlZeroMemory(StandardInfo,
59 sizeof(FILE_STANDARD_INFORMATION));
60
61 if (CdfsFCBIsDirectory(Fcb))
62 {
63 StandardInfo->AllocationSize.QuadPart = 0LL;
64 StandardInfo->EndOfFile.QuadPart = 0LL;
65 StandardInfo->Directory = TRUE;
66 }
67 else
68 {
69 StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize;
70 StandardInfo->EndOfFile = Fcb->RFCB.FileSize;
71 StandardInfo->Directory = FALSE;
72 }
73 StandardInfo->NumberOfLinks = 0;
74 StandardInfo->DeletePending = FALSE;
75
76 *BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
77 return(STATUS_SUCCESS);
78 }
79
80
81 /*
82 * FUNCTION: Retrieve the file position information
83 */
84 static NTSTATUS
85 CdfsGetPositionInformation(PFILE_OBJECT FileObject,
86 PFILE_POSITION_INFORMATION PositionInfo,
87 PULONG BufferLength)
88 {
89 DPRINT("CdfsGetPositionInformation() called\n");
90
91 if (*BufferLength < sizeof(FILE_POSITION_INFORMATION))
92 return STATUS_BUFFER_OVERFLOW;
93
94 PositionInfo->CurrentByteOffset.QuadPart =
95 FileObject->CurrentByteOffset.QuadPart;
96
97 DPRINT("Getting position %I64x\n",
98 PositionInfo->CurrentByteOffset.QuadPart);
99
100 *BufferLength -= sizeof(FILE_POSITION_INFORMATION);
101 return(STATUS_SUCCESS);
102 }
103
104
105 /*
106 * FUNCTION: Retrieve the basic file information
107 */
108 static NTSTATUS
109 CdfsGetBasicInformation(PFILE_OBJECT FileObject,
110 PFCB Fcb,
111 PDEVICE_OBJECT DeviceObject,
112 PFILE_BASIC_INFORMATION BasicInfo,
113 PULONG BufferLength)
114 {
115 DPRINT("CdfsGetBasicInformation() called\n");
116
117 UNREFERENCED_PARAMETER(FileObject);
118 UNREFERENCED_PARAMETER(DeviceObject);
119
120 if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
121 return STATUS_BUFFER_OVERFLOW;
122
123 CdfsDateTimeToSystemTime(Fcb,
124 &BasicInfo->CreationTime);
125 CdfsDateTimeToSystemTime(Fcb,
126 &BasicInfo->LastAccessTime);
127 CdfsDateTimeToSystemTime(Fcb,
128 &BasicInfo->LastWriteTime);
129 CdfsDateTimeToSystemTime(Fcb,
130 &BasicInfo->ChangeTime);
131
132 CdfsFileFlagsToAttributes(Fcb,
133 &BasicInfo->FileAttributes);
134
135 *BufferLength -= sizeof(FILE_BASIC_INFORMATION);
136
137 return(STATUS_SUCCESS);
138 }
139
140
141 /*
142 * FUNCTION: Retrieve the file name information
143 */
144 static NTSTATUS
145 CdfsGetNameInformation(PFILE_OBJECT FileObject,
146 PFCB Fcb,
147 PDEVICE_OBJECT DeviceObject,
148 PFILE_NAME_INFORMATION NameInfo,
149 PULONG BufferLength)
150 {
151 ULONG NameLength;
152 ULONG BytesToCopy;
153
154 DPRINT("CdfsGetNameInformation() called\n");
155
156 ASSERT(NameInfo != NULL);
157 ASSERT(Fcb != NULL);
158
159 UNREFERENCED_PARAMETER(FileObject);
160 UNREFERENCED_PARAMETER(DeviceObject);
161
162 /* If buffer can't hold at least the file name length, bail out */
163 if (*BufferLength < (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
164 return STATUS_BUFFER_OVERFLOW;
165
166 /* Calculate file name length in bytes */
167 NameLength = Fcb->PathName.Length;
168 NameInfo->FileNameLength = NameLength;
169
170 /* Calculate amount of bytes to copy not to overflow the buffer */
171 BytesToCopy = min(NameLength,
172 *BufferLength - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]));
173
174 /* Fill in the bytes */
175 RtlCopyMemory(NameInfo->FileName, Fcb->PathName.Buffer, BytesToCopy);
176
177 /* Check if we could write more but are not able to */
178 if (*BufferLength < NameLength + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
179 {
180 /* Return number of bytes written */
181 *BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + BytesToCopy;
182 return STATUS_BUFFER_OVERFLOW;
183 }
184
185 /* We filled up as many bytes, as needed */
186 *BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + NameLength);
187
188 return STATUS_SUCCESS;
189 }
190
191
192 /*
193 * FUNCTION: Retrieve the internal file information
194 */
195 static NTSTATUS
196 CdfsGetInternalInformation(PFCB Fcb,
197 PFILE_INTERNAL_INFORMATION InternalInfo,
198 PULONG BufferLength)
199 {
200 DPRINT("CdfsGetInternalInformation() called\n");
201
202 ASSERT(InternalInfo);
203 ASSERT(Fcb);
204
205 if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
206 return(STATUS_BUFFER_OVERFLOW);
207
208 InternalInfo->IndexNumber.QuadPart = Fcb->IndexNumber.QuadPart;
209
210 *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
211
212 return(STATUS_SUCCESS);
213 }
214
215
216 /*
217 * FUNCTION: Retrieve the file network open information
218 */
219 static NTSTATUS
220 CdfsGetNetworkOpenInformation(PFCB Fcb,
221 PFILE_NETWORK_OPEN_INFORMATION NetworkInfo,
222 PULONG BufferLength)
223 {
224 ASSERT(NetworkInfo);
225 ASSERT(Fcb);
226
227 if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION))
228 return(STATUS_BUFFER_OVERFLOW);
229
230 CdfsDateTimeToSystemTime(Fcb,
231 &NetworkInfo->CreationTime);
232 CdfsDateTimeToSystemTime(Fcb,
233 &NetworkInfo->LastAccessTime);
234 CdfsDateTimeToSystemTime(Fcb,
235 &NetworkInfo->LastWriteTime);
236 CdfsDateTimeToSystemTime(Fcb,
237 &NetworkInfo->ChangeTime);
238 if (CdfsFCBIsDirectory(Fcb))
239 {
240 NetworkInfo->AllocationSize.QuadPart = 0LL;
241 NetworkInfo->EndOfFile.QuadPart = 0LL;
242 }
243 else
244 {
245 NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize;
246 NetworkInfo->EndOfFile = Fcb->RFCB.FileSize;
247 }
248 CdfsFileFlagsToAttributes(Fcb,
249 &NetworkInfo->FileAttributes);
250
251 *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION);
252
253 return(STATUS_SUCCESS);
254 }
255
256
257 /*
258 * FUNCTION: Retrieve all file information
259 */
260 static NTSTATUS
261 CdfsGetAllInformation(PFILE_OBJECT FileObject,
262 PFCB Fcb,
263 PFILE_ALL_INFORMATION Info,
264 PULONG BufferLength)
265 {
266 ULONG NameLength;
267
268 ASSERT(Info);
269 ASSERT(Fcb);
270
271 NameLength = Fcb->PathName.Length;
272 if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength)
273 return(STATUS_BUFFER_OVERFLOW);
274
275 /* Basic Information */
276 CdfsDateTimeToSystemTime(Fcb,
277 &Info->BasicInformation.CreationTime);
278 CdfsDateTimeToSystemTime(Fcb,
279 &Info->BasicInformation.LastAccessTime);
280 CdfsDateTimeToSystemTime(Fcb,
281 &Info->BasicInformation.LastWriteTime);
282 CdfsDateTimeToSystemTime(Fcb,
283 &Info->BasicInformation.ChangeTime);
284 CdfsFileFlagsToAttributes(Fcb,
285 &Info->BasicInformation.FileAttributes);
286
287 /* Standard Information */
288 if (CdfsFCBIsDirectory(Fcb))
289 {
290 Info->StandardInformation.AllocationSize.QuadPart = 0LL;
291 Info->StandardInformation.EndOfFile.QuadPart = 0LL;
292 Info->StandardInformation.Directory = TRUE;
293 }
294 else
295 {
296 Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize;
297 Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize;
298 Info->StandardInformation.Directory = FALSE;
299 }
300 Info->StandardInformation.NumberOfLinks = 0;
301 Info->StandardInformation.DeletePending = FALSE;
302
303 /* Internal Information */
304 Info->InternalInformation.IndexNumber.QuadPart = Fcb->IndexNumber.QuadPart;
305
306 /* EA Information */
307 Info->EaInformation.EaSize = 0;
308
309 /* Access Information */
310 /* The IO-Manager adds this information */
311
312 /* Position Information */
313 Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart;
314
315 /* Mode Information */
316 /* The IO-Manager adds this information */
317
318 /* Alignment Information */
319 /* The IO-Manager adds this information */
320
321 /* Name Information */
322 Info->NameInformation.FileNameLength = NameLength;
323 RtlCopyMemory(Info->NameInformation.FileName,
324 Fcb->PathName.Buffer,
325 NameLength + sizeof(WCHAR));
326
327 *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR));
328
329 return STATUS_SUCCESS;
330 }
331
332
333 /*
334 * FUNCTION: Retrieve the specified file information
335 */
336 NTSTATUS NTAPI
337 CdfsQueryInformation(PDEVICE_OBJECT DeviceObject,
338 PIRP Irp)
339 {
340 FILE_INFORMATION_CLASS FileInformationClass;
341 PIO_STACK_LOCATION Stack;
342 PFILE_OBJECT FileObject;
343 PFCB Fcb;
344 PVOID SystemBuffer;
345 ULONG BufferLength;
346
347 NTSTATUS Status = STATUS_SUCCESS;
348
349 DPRINT("CdfsQueryInformation() called\n");
350
351 Stack = IoGetCurrentIrpStackLocation(Irp);
352 FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
353 FileObject = Stack->FileObject;
354 Fcb = FileObject->FsContext;
355
356 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
357 BufferLength = Stack->Parameters.QueryFile.Length;
358
359 switch (FileInformationClass)
360 {
361 case FileStandardInformation:
362 Status = CdfsGetStandardInformation(Fcb,
363 DeviceObject,
364 SystemBuffer,
365 &BufferLength);
366 break;
367
368 case FilePositionInformation:
369 Status = CdfsGetPositionInformation(FileObject,
370 SystemBuffer,
371 &BufferLength);
372 break;
373
374 case FileBasicInformation:
375 Status = CdfsGetBasicInformation(FileObject,
376 Fcb,
377 DeviceObject,
378 SystemBuffer,
379 &BufferLength);
380 break;
381
382 case FileNameInformation:
383 Status = CdfsGetNameInformation(FileObject,
384 Fcb,
385 DeviceObject,
386 SystemBuffer,
387 &BufferLength);
388 break;
389
390 case FileInternalInformation:
391 Status = CdfsGetInternalInformation(Fcb,
392 SystemBuffer,
393 &BufferLength);
394 break;
395
396 case FileNetworkOpenInformation:
397 Status = CdfsGetNetworkOpenInformation(Fcb,
398 SystemBuffer,
399 &BufferLength);
400 break;
401
402 case FileAllInformation:
403 Status = CdfsGetAllInformation(FileObject,
404 Fcb,
405 SystemBuffer,
406 &BufferLength);
407 break;
408
409 case FileAlternateNameInformation:
410 Status = STATUS_NOT_IMPLEMENTED;
411 break;
412
413 default:
414 DPRINT("Unimplemented information class %x\n", FileInformationClass);
415 Status = STATUS_INVALID_PARAMETER;
416 break;
417 }
418
419 Irp->IoStatus.Status = Status;
420 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
421 Irp->IoStatus.Information =
422 Stack->Parameters.QueryFile.Length - BufferLength;
423 else
424 Irp->IoStatus.Information = 0;
425
426 IoCompleteRequest(Irp, IO_NO_INCREMENT);
427
428 return(Status);
429 }
430
431
432 /*
433 * FUNCTION: Set the file position information
434 */
435 static NTSTATUS
436 CdfsSetPositionInformation(PFILE_OBJECT FileObject,
437 PFILE_POSITION_INFORMATION PositionInfo)
438 {
439 DPRINT ("CdfsSetPositionInformation()\n");
440
441 DPRINT ("PositionInfo %p\n", PositionInfo);
442 DPRINT ("Setting position %I64d\n", PositionInfo->CurrentByteOffset.QuadPart);
443
444 FileObject->CurrentByteOffset.QuadPart =
445 PositionInfo->CurrentByteOffset.QuadPart;
446
447 return STATUS_SUCCESS;
448 }
449
450
451 /*
452 * FUNCTION: Set the specified file information
453 */
454 NTSTATUS NTAPI
455 CdfsSetInformation(PDEVICE_OBJECT DeviceObject,
456 PIRP Irp)
457 {
458 FILE_INFORMATION_CLASS FileInformationClass;
459 PIO_STACK_LOCATION Stack;
460 PFILE_OBJECT FileObject;
461 PVOID SystemBuffer;
462
463 NTSTATUS Status = STATUS_SUCCESS;
464
465 UNREFERENCED_PARAMETER(DeviceObject);
466
467 DPRINT("CdfsSetInformation() called\n");
468
469 Stack = IoGetCurrentIrpStackLocation(Irp);
470 FileInformationClass = Stack->Parameters.SetFile.FileInformationClass;
471 FileObject = Stack->FileObject;
472
473 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
474
475 switch (FileInformationClass)
476 {
477 case FilePositionInformation:
478 Status = CdfsSetPositionInformation(FileObject,
479 SystemBuffer);
480 break;
481
482 case FileBasicInformation:
483 case FileRenameInformation:
484 Status = STATUS_NOT_IMPLEMENTED;
485 break;
486
487 default:
488 Status = STATUS_NOT_SUPPORTED;
489 break;
490 }
491
492 Irp->IoStatus.Status = Status;
493 Irp->IoStatus.Information = 0;
494
495 IoCompleteRequest(Irp, IO_NO_INCREMENT);
496
497 return Status;
498 }
499
500 /* EOF */