- Implement file sharing checks.
[reactos.git] / reactos / drivers / fs / vfat / finfo.c
1 /* $Id: finfo.c,v 1.37 2004/08/28 22:19:12 navaraf Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: drivers/fs/vfat/finfo.c
6 * PURPOSE: VFAT Filesystem
7 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
8 * Hartmut Birr
9 *
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <wchar.h>
16
17 #define NDEBUG
18 #include <debug.h>
19
20 #include "vfat.h"
21
22 /* FUNCTIONS ****************************************************************/
23
24 static NTSTATUS
25 VfatGetStandardInformation(PVFATFCB FCB,
26 PFILE_STANDARD_INFORMATION StandardInfo,
27 PULONG BufferLength)
28 /*
29 * FUNCTION: Retrieve the standard file information
30 */
31 {
32
33 if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
34 return STATUS_BUFFER_OVERFLOW;
35
36 /* PRECONDITION */
37 assert (StandardInfo != NULL);
38 assert (FCB != NULL);
39
40 if (vfatFCBIsDirectory(FCB))
41 {
42 StandardInfo->AllocationSize.QuadPart = 0LL;
43 StandardInfo->EndOfFile.QuadPart = 0LL;
44 StandardInfo->Directory = TRUE;
45 }
46 else
47 {
48 StandardInfo->AllocationSize = FCB->RFCB.AllocationSize;
49 StandardInfo->EndOfFile = FCB->RFCB.FileSize;
50 StandardInfo->Directory = FALSE;
51 }
52 StandardInfo->NumberOfLinks = 0;
53 StandardInfo->DeletePending = FCB->Flags & FCB_DELETE_PENDING ? TRUE : FALSE;
54
55 *BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
56 return(STATUS_SUCCESS);
57 }
58
59 static NTSTATUS
60 VfatSetPositionInformation(PFILE_OBJECT FileObject,
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 VfatSetBasicInformation(PFILE_OBJECT FileObject,
97 PVFATFCB FCB,
98 PDEVICE_EXTENSION DeviceExt,
99 PFILE_BASIC_INFORMATION BasicInfo)
100 {
101 DPRINT("VfatSetBasicInformation()\n");
102
103 assert (NULL != FileObject);
104 assert (NULL != FCB);
105 assert (NULL != DeviceExt);
106 assert (NULL != BasicInfo);
107 /* Check volume label bit */
108 assert(0 == (FCB->entry.Attrib & 0x08));
109
110 FsdFileTimeToDosDateTime((TIME *)&(BasicInfo->CreationTime),
111 &(FCB->entry.CreationDate),
112 &(FCB->entry.CreationTime));
113 FsdFileTimeToDosDateTime((TIME *)&(BasicInfo->LastAccessTime),
114 &(FCB->entry.AccessDate),
115 NULL);
116 FsdFileTimeToDosDateTime((TIME *)&(BasicInfo->LastWriteTime),
117 &(FCB->entry.UpdateDate),
118 &(FCB->entry.UpdateTime));
119
120 FCB->entry.Attrib = (unsigned char)((FCB->entry.Attrib &
121 (FILE_ATTRIBUTE_DIRECTORY | 0x48)) |
122 (BasicInfo->FileAttributes &
123 (FILE_ATTRIBUTE_ARCHIVE |
124 FILE_ATTRIBUTE_SYSTEM |
125 FILE_ATTRIBUTE_HIDDEN |
126 FILE_ATTRIBUTE_READONLY)));
127 DPRINT("Setting attributes 0x%02x\n", FCB->entry.Attrib);
128
129 VfatUpdateEntry(FCB);
130
131 return(STATUS_SUCCESS);
132 }
133
134 static NTSTATUS
135 VfatGetBasicInformation(PFILE_OBJECT FileObject,
136 PVFATFCB FCB,
137 PDEVICE_OBJECT DeviceObject,
138 PFILE_BASIC_INFORMATION BasicInfo,
139 PULONG BufferLength)
140 {
141 DPRINT("VfatGetBasicInformation()\n");
142
143 if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
144 return STATUS_BUFFER_OVERFLOW;
145
146 FsdDosDateTimeToFileTime(FCB->entry.CreationDate,
147 FCB->entry.CreationTime,
148 (TIME *)&BasicInfo->CreationTime);
149 FsdDosDateTimeToFileTime(FCB->entry.AccessDate,
150 0,
151 (TIME *)&BasicInfo->LastAccessTime);
152 FsdDosDateTimeToFileTime(FCB->entry.UpdateDate,
153 FCB->entry.UpdateTime,
154 (TIME *)&BasicInfo->LastWriteTime);
155 BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
156
157 BasicInfo->FileAttributes = FCB->entry.Attrib & 0x3f;
158 /* Synthesize FILE_ATTRIBUTE_NORMAL */
159 if (0 == (BasicInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
160 FILE_ATTRIBUTE_ARCHIVE |
161 FILE_ATTRIBUTE_SYSTEM |
162 FILE_ATTRIBUTE_HIDDEN |
163 FILE_ATTRIBUTE_READONLY)))
164 {
165 BasicInfo->FileAttributes |= FILE_ATTRIBUTE_NORMAL;
166 }
167 DPRINT("Getting attributes 0x%02x\n", BasicInfo->FileAttributes);
168
169 *BufferLength -= sizeof(FILE_BASIC_INFORMATION);
170 return(STATUS_SUCCESS);
171 }
172
173
174 static NTSTATUS
175 VfatSetDispositionInformation(PFILE_OBJECT FileObject,
176 PVFATFCB FCB,
177 PDEVICE_OBJECT DeviceObject,
178 PFILE_DISPOSITION_INFORMATION DispositionInfo)
179 {
180 NTSTATUS Status = STATUS_SUCCESS;
181
182 PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
183
184 DPRINT ("FsdSetDispositionInformation()\n");
185
186 assert (DeviceExt != NULL);
187 assert (DeviceExt->FatInfo.BytesPerCluster != 0);
188 assert (FCB != NULL);
189
190 if (FCB->entry.Attrib & FILE_ATTRIBUTE_READONLY)
191 {
192 return STATUS_CANNOT_DELETE;
193 }
194
195 if (vfatFCBIsRoot(FCB) ||
196 (FCB->LongNameU.Length == sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.') ||
197 (FCB->LongNameU.Length == 2 * sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.' && FCB->LongNameU.Buffer[1] == L'.'))
198 {
199 // we cannot delete a '.', '..' or the root directory
200 return STATUS_ACCESS_DENIED;
201 }
202
203 if (DispositionInfo->DoDeleteFile)
204 {
205 if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
206 {
207 if (FCB->RefCount > 1)
208 {
209 DPRINT1("%d %x\n", FCB->RefCount, CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointer));
210 Status = STATUS_ACCESS_DENIED;
211 }
212 else
213 {
214 FCB->Flags |= FCB_DELETE_PENDING;
215 FileObject->DeletePending = TRUE;
216 }
217 }
218 else
219 {
220 DPRINT("MmFlushImageSection returned FALSE\n");
221 Status = STATUS_CANNOT_DELETE;
222 }
223 if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
224 {
225 if (!VfatIsDirectoryEmpty(FCB))
226 {
227 Status = STATUS_DIRECTORY_NOT_EMPTY;
228 FCB->Flags &= ~FCB_DELETE_PENDING;
229 FileObject->DeletePending = FALSE;
230 }
231 else
232 {
233 Status = STATUS_SUCCESS;
234 }
235 }
236 }
237 else
238 {
239 FileObject->DeletePending = FALSE;
240 }
241 return Status;
242 }
243
244 static NTSTATUS
245 VfatGetNameInformation(PFILE_OBJECT FileObject,
246 PVFATFCB FCB,
247 PDEVICE_OBJECT DeviceObject,
248 PFILE_NAME_INFORMATION NameInfo,
249 PULONG BufferLength)
250 /*
251 * FUNCTION: Retrieve the file name information
252 */
253 {
254
255 assert (NameInfo != NULL);
256 assert (FCB != NULL);
257
258 if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR))
259 return STATUS_BUFFER_OVERFLOW;
260
261 NameInfo->FileNameLength = FCB->PathNameU.Length;
262 memcpy(NameInfo->FileName, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
263 NameInfo->FileName[FCB->PathNameU.Length / sizeof(WCHAR)] = 0;
264
265 *BufferLength -= (sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR));
266
267 return STATUS_SUCCESS;
268 }
269
270 static NTSTATUS
271 VfatGetInternalInformation(PVFATFCB Fcb,
272 PFILE_INTERNAL_INFORMATION InternalInfo,
273 PULONG BufferLength)
274 {
275 assert (InternalInfo);
276 assert (Fcb);
277
278 if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
279 return STATUS_BUFFER_OVERFLOW;
280 // FIXME: get a real index, that can be used in a create operation
281 InternalInfo->IndexNumber.QuadPart = 0;
282 *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
283 return STATUS_SUCCESS;
284 }
285
286
287 static NTSTATUS
288 VfatGetNetworkOpenInformation(PVFATFCB Fcb,
289 PFILE_NETWORK_OPEN_INFORMATION NetworkInfo,
290 PULONG BufferLength)
291 /*
292 * FUNCTION: Retrieve the file network open information
293 */
294 {
295 assert (NetworkInfo);
296 assert (Fcb);
297
298 if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION))
299 return(STATUS_BUFFER_OVERFLOW);
300
301 FsdDosDateTimeToFileTime(Fcb->entry.CreationDate,
302 Fcb->entry.CreationTime,
303 &NetworkInfo->CreationTime);
304 FsdDosDateTimeToFileTime(Fcb->entry.AccessDate,
305 0,
306 &NetworkInfo->LastAccessTime);
307 FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate,
308 Fcb->entry.UpdateTime,
309 &NetworkInfo->LastWriteTime);
310 NetworkInfo->ChangeTime = NetworkInfo->LastWriteTime;
311 if (vfatFCBIsDirectory(Fcb))
312 {
313 NetworkInfo->EndOfFile.QuadPart = 0L;
314 NetworkInfo->AllocationSize.QuadPart = 0L;
315 }
316 else
317 {
318 NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize;
319 NetworkInfo->EndOfFile = Fcb->RFCB.FileSize;
320 }
321 NetworkInfo->FileAttributes = Fcb->entry.Attrib & 0x3f;
322
323 *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION);
324 return STATUS_SUCCESS;
325 }
326
327
328 static NTSTATUS
329 VfatGetAllInformation(PFILE_OBJECT FileObject,
330 PVFATFCB Fcb,
331 PFILE_ALL_INFORMATION Info,
332 PULONG BufferLength)
333 /*
334 * FUNCTION: Retrieve the all file information
335 */
336 {
337
338 assert (Info);
339 assert (Fcb);
340
341 if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR))
342 return(STATUS_BUFFER_OVERFLOW);
343
344 /* Basic Information */
345 FsdDosDateTimeToFileTime(Fcb->entry.CreationDate,
346 Fcb->entry.CreationTime,
347 (TIME *)&Info->BasicInformation.CreationTime);
348 FsdDosDateTimeToFileTime(Fcb->entry.AccessDate,
349 0,
350 (TIME *)&Info->BasicInformation.LastAccessTime);
351 FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate,
352 Fcb->entry.UpdateTime,
353 (TIME *)&Info->BasicInformation.LastWriteTime);
354 Info->BasicInformation.ChangeTime = Info->BasicInformation.LastWriteTime;
355 Info->BasicInformation.FileAttributes = Fcb->entry.Attrib & 0x3f;
356
357 /* Standard Information */
358 if (vfatFCBIsDirectory(Fcb))
359 {
360 Info->StandardInformation.AllocationSize.QuadPart = 0LL;
361 Info->StandardInformation.EndOfFile.QuadPart = 0LL;
362 Info->StandardInformation.Directory = TRUE;
363 }
364 else
365 {
366 Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize;
367 Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize;
368 Info->StandardInformation.Directory = FALSE;
369 }
370 Info->StandardInformation.NumberOfLinks = 0;
371 Info->StandardInformation.DeletePending = Fcb->Flags & FCB_DELETE_PENDING ? TRUE : FALSE;
372
373 /* Internal Information */
374 /* FIXME: get a real index, that can be used in a create operation */
375 Info->InternalInformation.IndexNumber.QuadPart = 0;
376
377 /* EA Information */
378 Info->EaInformation.EaSize = 0;
379
380 /* Access Information */
381 /* The IO-Manager adds this information */
382
383 /* Position Information */
384 Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart;
385
386 /* Mode Information */
387 /* The IO-Manager adds this information */
388
389 /* Alignment Information */
390 /* The IO-Manager adds this information */
391
392 /* Name Information */
393 Info->NameInformation.FileNameLength = Fcb->PathNameU.Length;
394 RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathNameU.Buffer, Fcb->PathNameU.Length);
395 Info->NameInformation.FileName[Fcb->PathNameU.Length / sizeof(WCHAR)] = 0;
396
397 *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR));
398
399 return STATUS_SUCCESS;
400 }
401
402 VOID UpdateFileSize(PFILE_OBJECT FileObject, PVFATFCB Fcb, ULONG Size, ULONG ClusterSize)
403 {
404 if (Size > 0)
405 {
406 Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, ClusterSize);
407 }
408 else
409 {
410 Fcb->RFCB.AllocationSize.QuadPart = (LONGLONG)0;
411 }
412 if (!vfatFCBIsDirectory(Fcb))
413 {
414 Fcb->entry.FileSize = Size;
415 }
416 Fcb->RFCB.FileSize.QuadPart = Size;
417 Fcb->RFCB.ValidDataLength.QuadPart = Size;
418
419 if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
420 {
421 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
422 }
423 }
424
425 NTSTATUS
426 VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
427 PVFATFCB Fcb,
428 PDEVICE_EXTENSION DeviceExt,
429 PLARGE_INTEGER AllocationSize)
430 {
431 ULONG OldSize;
432 ULONG Cluster, FirstCluster;
433 NTSTATUS Status;
434
435 ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;
436 ULONG NewSize = AllocationSize->u.LowPart;
437 ULONG NCluster;
438 BOOL AllocSizeChanged = FALSE;
439
440 DPRINT("VfatSetAllocationSizeInformation()\n");
441
442 OldSize = Fcb->entry.FileSize;
443 if (AllocationSize->u.HighPart > 0)
444 {
445 return STATUS_INVALID_PARAMETER;
446 }
447 if (OldSize == NewSize)
448 {
449 return(STATUS_SUCCESS);
450 }
451
452 FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
453
454 if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)
455 {
456 AllocSizeChanged = TRUE;
457 if (FirstCluster == 0)
458 {
459 Fcb->LastCluster = Fcb->LastOffset = 0;
460 Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE);
461 if (!NT_SUCCESS(Status))
462 {
463 DPRINT1("NextCluster failed. Status = %x\n", Status);
464 return Status;
465 }
466 if (FirstCluster == 0xffffffff)
467 {
468 return STATUS_DISK_FULL;
469 }
470 Status = OffsetToCluster(DeviceExt, FirstCluster,
471 ROUND_DOWN(NewSize - 1, ClusterSize),
472 &NCluster, TRUE);
473 if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
474 {
475 /* disk is full */
476 NCluster = Cluster = FirstCluster;
477 Status = STATUS_SUCCESS;
478 while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
479 {
480 Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
481 WriteCluster (DeviceExt, Cluster, 0);
482 Cluster = NCluster;
483 }
484 return STATUS_DISK_FULL;
485 }
486 Fcb->entry.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
487 Fcb->entry.FirstClusterHigh = (unsigned short)((FirstCluster & 0xFFFF0000) >> 16);
488 }
489 else
490 {
491 if (Fcb->LastCluster > 0 &&
492 (Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize) > Fcb->LastOffset)
493 {
494 Status = OffsetToCluster(DeviceExt, Fcb->LastCluster,
495 Fcb->RFCB.AllocationSize.u.LowPart -
496 ClusterSize - Fcb->LastOffset,
497 &Cluster, FALSE);
498 }
499 else
500 {
501 Status = OffsetToCluster(DeviceExt, FirstCluster,
502 Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,
503 &Cluster, FALSE);
504 }
505
506 Fcb->LastCluster = Cluster;
507 Fcb->LastOffset = Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize;
508
509 /* FIXME: Check status */
510 /* Cluster points now to the last cluster within the chain */
511 Status = OffsetToCluster(DeviceExt, FirstCluster,
512 ROUND_DOWN(NewSize - 1, ClusterSize),
513 &NCluster, TRUE);
514 if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
515 {
516 /* disk is full */
517 NCluster = Cluster;
518 Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
519 WriteCluster(DeviceExt, Cluster, 0xffffffff);
520 Cluster = NCluster;
521 while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
522 {
523 Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
524 WriteCluster (DeviceExt, Cluster, 0);
525 Cluster = NCluster;
526 }
527 return STATUS_DISK_FULL;
528 }
529 }
530 UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
531 }
532 else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
533 {
534 AllocSizeChanged = TRUE;
535 /* FIXME: Use the cached cluster/offset better way. */
536 Fcb->LastCluster = Fcb->LastCluster = 0;
537 UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
538 if (NewSize > 0)
539 {
540 Status = OffsetToCluster(DeviceExt, FirstCluster,
541 ROUND_DOWN(NewSize - 1, ClusterSize),
542 &Cluster, FALSE);
543
544 NCluster = Cluster;
545 Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
546 WriteCluster(DeviceExt, Cluster, 0xffffffff);
547 Cluster = NCluster;
548 }
549 else
550 {
551 Fcb->entry.FirstCluster = 0;
552 Fcb->entry.FirstClusterHigh = 0;
553
554 NCluster = Cluster = FirstCluster;
555 Status = STATUS_SUCCESS;
556 }
557 while (NT_SUCCESS(Status) && 0xffffffff != Cluster && Cluster > 1)
558 {
559 Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
560 WriteCluster (DeviceExt, Cluster, 0);
561 Cluster = NCluster;
562 }
563 }
564 else
565 {
566 UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
567 }
568 /* Update the on-disk directory entry */
569 Fcb->Flags |= FCB_IS_DIRTY;
570 if (AllocSizeChanged)
571 {
572 VfatUpdateEntry(Fcb);
573 }
574 return STATUS_SUCCESS;
575 }
576
577 NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
578 /*
579 * FUNCTION: Retrieve the specified file information
580 */
581 {
582 FILE_INFORMATION_CLASS FileInformationClass;
583 PVFATFCB FCB = NULL;
584
585 NTSTATUS RC = STATUS_SUCCESS;
586 PVOID SystemBuffer;
587 ULONG BufferLength;
588
589 /* PRECONDITION */
590 assert (IrpContext);
591
592 /* INITIALIZATION */
593 FileInformationClass = IrpContext->Stack->Parameters.QueryFile.FileInformationClass;
594 FCB = (PVFATFCB) IrpContext->FileObject->FsContext;
595
596 SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
597 BufferLength = IrpContext->Stack->Parameters.QueryFile.Length;
598
599 if (!(FCB->Flags & FCB_IS_PAGE_FILE))
600 {
601 if (!ExAcquireResourceSharedLite(&FCB->MainResource,
602 (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
603 {
604 return VfatQueueRequest (IrpContext);
605 }
606 }
607
608
609 switch (FileInformationClass)
610 {
611 case FileStandardInformation:
612 RC = VfatGetStandardInformation(FCB,
613 SystemBuffer,
614 &BufferLength);
615 break;
616 case FilePositionInformation:
617 RC = VfatGetPositionInformation(IrpContext->FileObject,
618 FCB,
619 IrpContext->DeviceObject,
620 SystemBuffer,
621 &BufferLength);
622 break;
623 case FileBasicInformation:
624 RC = VfatGetBasicInformation(IrpContext->FileObject,
625 FCB,
626 IrpContext->DeviceObject,
627 SystemBuffer,
628 &BufferLength);
629 break;
630 case FileNameInformation:
631 RC = VfatGetNameInformation(IrpContext->FileObject,
632 FCB,
633 IrpContext->DeviceObject,
634 SystemBuffer,
635 &BufferLength);
636 break;
637 case FileInternalInformation:
638 RC = VfatGetInternalInformation(FCB,
639 SystemBuffer,
640 &BufferLength);
641 break;
642 case FileNetworkOpenInformation:
643 RC = VfatGetNetworkOpenInformation(FCB,
644 SystemBuffer,
645 &BufferLength);
646 break;
647 case FileAllInformation:
648 RC = VfatGetAllInformation(IrpContext->FileObject,
649 FCB,
650 SystemBuffer,
651 &BufferLength);
652 break;
653
654 case FileAlternateNameInformation:
655 RC = STATUS_NOT_IMPLEMENTED;
656 break;
657 default:
658 RC = STATUS_NOT_SUPPORTED;
659 }
660
661 if (!(FCB->Flags & FCB_IS_PAGE_FILE))
662 {
663 ExReleaseResourceLite(&FCB->MainResource);
664 }
665 IrpContext->Irp->IoStatus.Status = RC;
666 if (NT_SUCCESS(RC))
667 IrpContext->Irp->IoStatus.Information =
668 IrpContext->Stack->Parameters.QueryFile.Length - BufferLength;
669 else
670 IrpContext->Irp->IoStatus.Information = 0;
671 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
672 VfatFreeIrpContext(IrpContext);
673
674 return RC;
675 }
676
677 NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
678 /*
679 * FUNCTION: Retrieve the specified file information
680 */
681 {
682 FILE_INFORMATION_CLASS FileInformationClass;
683 PVFATFCB FCB = NULL;
684 NTSTATUS RC = STATUS_SUCCESS;
685 PVOID SystemBuffer;
686 BOOL CanWait = IrpContext->Flags & IRPCONTEXT_CANWAIT;
687
688 /* PRECONDITION */
689 assert(IrpContext);
690
691 DPRINT("VfatSetInformation(IrpContext %x)\n", IrpContext);
692
693 /* INITIALIZATION */
694 FileInformationClass =
695 IrpContext->Stack->Parameters.SetFile.FileInformationClass;
696 FCB = (PVFATFCB) IrpContext->FileObject->FsContext;
697 SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
698
699 DPRINT("FileInformationClass %d\n", FileInformationClass);
700 DPRINT("SystemBuffer %x\n", SystemBuffer);
701
702 if (!(FCB->Flags & FCB_IS_PAGE_FILE))
703 {
704 if (!ExAcquireResourceExclusiveLite(&FCB->MainResource,
705 (BOOLEAN)CanWait))
706 {
707 return(VfatQueueRequest (IrpContext));
708 }
709 }
710
711 switch (FileInformationClass)
712 {
713 case FilePositionInformation:
714 RC = VfatSetPositionInformation(IrpContext->FileObject,
715 SystemBuffer);
716 break;
717 case FileDispositionInformation:
718 RC = VfatSetDispositionInformation(IrpContext->FileObject,
719 FCB,
720 IrpContext->DeviceObject,
721 SystemBuffer);
722 break;
723 case FileAllocationInformation:
724 case FileEndOfFileInformation:
725 RC = VfatSetAllocationSizeInformation(IrpContext->FileObject,
726 FCB,
727 IrpContext->DeviceExt,
728 (PLARGE_INTEGER)SystemBuffer);
729 break;
730 case FileBasicInformation:
731 RC = VfatSetBasicInformation(IrpContext->FileObject,
732 FCB,
733 IrpContext->DeviceExt,
734 SystemBuffer);
735 break;
736 case FileRenameInformation:
737 RC = STATUS_NOT_IMPLEMENTED;
738 break;
739 default:
740 RC = STATUS_NOT_SUPPORTED;
741 }
742
743 if (!(FCB->Flags & FCB_IS_PAGE_FILE))
744 {
745 ExReleaseResourceLite(&FCB->MainResource);
746 }
747
748 IrpContext->Irp->IoStatus.Status = RC;
749 IrpContext->Irp->IoStatus.Information = 0;
750 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
751 VfatFreeIrpContext(IrpContext);
752
753 return RC;
754 }
755
756 /* EOF */