ReactOS Fundraising Campaign 2012
 
€ 3,303 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

finfo.c

Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:        See COPYING in the top level directory
00003  * PROJECT:          ReactOS kernel
00004  * FILE:             drivers/fs/vfat/finfo.c
00005  * PURPOSE:          VFAT Filesystem
00006  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
00007  *                   Herve Poussineau (reactos@poussine.freesurf.fr)
00008  *
00009  */
00010 
00011 /* INCLUDES *****************************************************************/
00012 
00013 #define NDEBUG
00014 #include "vfat.h"
00015 
00016 /* GLOBALS ******************************************************************/
00017 
00018 const char* FileInformationClassNames[] =
00019 {
00020   "??????",
00021   "FileDirectoryInformation",
00022   "FileFullDirectoryInformation",
00023   "FileBothDirectoryInformation",
00024   "FileBasicInformation",
00025   "FileStandardInformation",
00026   "FileInternalInformation",
00027   "FileEaInformation",
00028   "FileAccessInformation",
00029   "FileNameInformation",
00030   "FileRenameInformation",
00031   "FileLinkInformation",
00032   "FileNamesInformation",
00033   "FileDispositionInformation",
00034   "FilePositionInformation",
00035   "FileFullEaInformation",
00036   "FileModeInformation",
00037   "FileAlignmentInformation",
00038   "FileAllInformation",
00039   "FileAllocationInformation",
00040   "FileEndOfFileInformation",
00041   "FileAlternateNameInformation",
00042   "FileStreamInformation",
00043   "FilePipeInformation",
00044   "FilePipeLocalInformation",
00045   "FilePipeRemoteInformation",
00046   "FileMailslotQueryInformation",
00047   "FileMailslotSetInformation",
00048   "FileCompressionInformation",
00049   "FileObjectIdInformation",
00050   "FileCompletionInformation",
00051   "FileMoveClusterInformation",
00052   "FileQuotaInformation",
00053   "FileReparsePointInformation",
00054   "FileNetworkOpenInformation",
00055   "FileAttributeTagInformation",
00056   "FileTrackingInformation",
00057   "FileIdBothDirectoryInformation",
00058   "FileIdFullDirectoryInformation",
00059   "FileValidDataLengthInformation",
00060   "FileShortNameInformation",
00061   "FileMaximumInformation"
00062 };
00063 
00064 /* FUNCTIONS ****************************************************************/
00065 
00066 static NTSTATUS
00067 VfatGetStandardInformation(PVFATFCB FCB,
00068                PFILE_STANDARD_INFORMATION StandardInfo,
00069                PULONG BufferLength)
00070 /*
00071  * FUNCTION: Retrieve the standard file information
00072  */
00073 {
00074 
00075   if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
00076     return STATUS_BUFFER_OVERFLOW;
00077 
00078   /* PRECONDITION */
00079   ASSERT(StandardInfo != NULL);
00080   ASSERT(FCB != NULL);
00081 
00082   if (vfatFCBIsDirectory(FCB))
00083     {
00084       StandardInfo->AllocationSize.QuadPart = 0;
00085       StandardInfo->EndOfFile.QuadPart = 0;
00086       StandardInfo->Directory = TRUE;
00087     }
00088   else
00089     {
00090       StandardInfo->AllocationSize = FCB->RFCB.AllocationSize;
00091       StandardInfo->EndOfFile = FCB->RFCB.FileSize;
00092       StandardInfo->Directory = FALSE;
00093     }
00094   StandardInfo->NumberOfLinks = 1;
00095   StandardInfo->DeletePending = FCB->Flags & FCB_DELETE_PENDING ? TRUE : FALSE;
00096 
00097   *BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
00098   return(STATUS_SUCCESS);
00099 }
00100 
00101 static NTSTATUS
00102 VfatSetPositionInformation(PFILE_OBJECT FileObject,
00103                PFILE_POSITION_INFORMATION PositionInfo)
00104 {
00105   DPRINT ("FsdSetPositionInformation()\n");
00106 
00107   DPRINT ("PositionInfo %p\n", PositionInfo);
00108   DPRINT ("Setting position %d\n", PositionInfo->CurrentByteOffset.u.LowPart);
00109 
00110   FileObject->CurrentByteOffset.QuadPart =
00111     PositionInfo->CurrentByteOffset.QuadPart;
00112 
00113   return (STATUS_SUCCESS);
00114 }
00115 
00116 static NTSTATUS
00117 VfatGetPositionInformation(PFILE_OBJECT FileObject,
00118                PVFATFCB FCB,
00119                PDEVICE_OBJECT DeviceObject,
00120                PFILE_POSITION_INFORMATION PositionInfo,
00121                PULONG BufferLength)
00122 {
00123   UNREFERENCED_PARAMETER(FileObject);
00124   UNREFERENCED_PARAMETER(FCB);
00125   UNREFERENCED_PARAMETER(DeviceObject);
00126 
00127   DPRINT ("VfatGetPositionInformation()\n");
00128 
00129   if (*BufferLength < sizeof(FILE_POSITION_INFORMATION))
00130     return STATUS_BUFFER_OVERFLOW;
00131 
00132   PositionInfo->CurrentByteOffset.QuadPart =
00133     FileObject->CurrentByteOffset.QuadPart;
00134 
00135   DPRINT("Getting position %I64x\n",
00136      PositionInfo->CurrentByteOffset.QuadPart);
00137 
00138   *BufferLength -= sizeof(FILE_POSITION_INFORMATION);
00139   return(STATUS_SUCCESS);
00140 }
00141 
00142 static NTSTATUS
00143 VfatSetBasicInformation(PFILE_OBJECT FileObject,
00144             PVFATFCB FCB,
00145             PDEVICE_EXTENSION DeviceExt,
00146             PFILE_BASIC_INFORMATION BasicInfo)
00147 {
00148   DPRINT("VfatSetBasicInformation()\n");
00149 
00150   ASSERT(NULL != FileObject);
00151   ASSERT(NULL != FCB);
00152   ASSERT(NULL != DeviceExt);
00153   ASSERT(NULL != BasicInfo);
00154   /* Check volume label bit */
00155   ASSERT(0 == (*FCB->Attributes & _A_VOLID));
00156 
00157   if (FCB->Flags & FCB_IS_FATX_ENTRY)
00158   {
00159     if (BasicInfo->CreationTime.QuadPart != 0 && BasicInfo->CreationTime.QuadPart != -1)
00160     {
00161       FsdSystemTimeToDosDateTime(DeviceExt,
00162                                  &BasicInfo->CreationTime,
00163                                  &FCB->entry.FatX.CreationDate,
00164                                  &FCB->entry.FatX.CreationTime);
00165     }
00166 
00167     if (BasicInfo->LastAccessTime.QuadPart != 0 && BasicInfo->LastAccessTime.QuadPart != -1)
00168     {
00169       FsdSystemTimeToDosDateTime(DeviceExt,
00170                                  &BasicInfo->LastAccessTime,
00171                                  &FCB->entry.FatX.AccessDate,
00172                                  &FCB->entry.FatX.AccessTime);
00173     }
00174 
00175     if (BasicInfo->LastWriteTime.QuadPart != 0 && BasicInfo->LastWriteTime.QuadPart != -1)
00176     {
00177       FsdSystemTimeToDosDateTime(DeviceExt,
00178                                  &BasicInfo->LastWriteTime,
00179                                  &FCB->entry.FatX.UpdateDate,
00180                                  &FCB->entry.FatX.UpdateTime);
00181     }
00182   }
00183   else
00184   {
00185     if (BasicInfo->CreationTime.QuadPart != 0 && BasicInfo->CreationTime.QuadPart != -1)
00186     {
00187       FsdSystemTimeToDosDateTime(DeviceExt,
00188                                  &BasicInfo->CreationTime,
00189                                  &FCB->entry.Fat.CreationDate,
00190                                  &FCB->entry.Fat.CreationTime);
00191     }
00192 
00193     if (BasicInfo->LastAccessTime.QuadPart != 0 && BasicInfo->LastAccessTime.QuadPart != -1)
00194     {
00195       FsdSystemTimeToDosDateTime(DeviceExt,
00196                                  &BasicInfo->LastAccessTime,
00197                                  &FCB->entry.Fat.AccessDate,
00198                                  NULL);
00199     }
00200 
00201     if (BasicInfo->LastWriteTime.QuadPart != 0 && BasicInfo->LastWriteTime.QuadPart != -1)
00202     {
00203       FsdSystemTimeToDosDateTime(DeviceExt,
00204                                  &BasicInfo->LastWriteTime,
00205                                  &FCB->entry.Fat.UpdateDate,
00206                                  &FCB->entry.Fat.UpdateTime);
00207     }
00208   }
00209 
00210   if (BasicInfo->FileAttributes)
00211   {
00212     *FCB->Attributes = (unsigned char)((*FCB->Attributes &
00213                         (FILE_ATTRIBUTE_DIRECTORY | 0x48)) |
00214                         (BasicInfo->FileAttributes &
00215                          (FILE_ATTRIBUTE_ARCHIVE |
00216                           FILE_ATTRIBUTE_SYSTEM |
00217                           FILE_ATTRIBUTE_HIDDEN |
00218                           FILE_ATTRIBUTE_READONLY)));
00219     DPRINT("Setting attributes 0x%02x\n", *FCB->Attributes);
00220   }
00221 
00222   VfatUpdateEntry(FCB);
00223 
00224   return(STATUS_SUCCESS);
00225 }
00226 
00227 static NTSTATUS
00228 VfatGetBasicInformation(PFILE_OBJECT FileObject,
00229             PVFATFCB FCB,
00230             PDEVICE_OBJECT DeviceObject,
00231             PFILE_BASIC_INFORMATION BasicInfo,
00232             PULONG BufferLength)
00233 {
00234   PDEVICE_EXTENSION DeviceExt;
00235   
00236   UNREFERENCED_PARAMETER(FileObject);
00237   
00238   DPRINT("VfatGetBasicInformation()\n");
00239 
00240   DeviceExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00241 
00242   if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
00243     return STATUS_BUFFER_OVERFLOW;
00244 
00245   if (FCB->Flags & FCB_IS_FATX_ENTRY)
00246   {
00247     FsdDosDateTimeToSystemTime(DeviceExt,
00248                  FCB->entry.FatX.CreationDate,
00249                  FCB->entry.FatX.CreationTime,
00250                  &BasicInfo->CreationTime);
00251     FsdDosDateTimeToSystemTime(DeviceExt,
00252                  FCB->entry.FatX.AccessDate,
00253                  FCB->entry.FatX.AccessTime,
00254                  &BasicInfo->LastAccessTime);
00255     FsdDosDateTimeToSystemTime(DeviceExt,
00256                  FCB->entry.FatX.UpdateDate,
00257                  FCB->entry.FatX.UpdateTime,
00258                  &BasicInfo->LastWriteTime);
00259     BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
00260   }
00261   else
00262   {
00263     FsdDosDateTimeToSystemTime(DeviceExt,
00264                  FCB->entry.Fat.CreationDate,
00265                  FCB->entry.Fat.CreationTime,
00266                  &BasicInfo->CreationTime);
00267     FsdDosDateTimeToSystemTime(DeviceExt,
00268                  FCB->entry.Fat.AccessDate,
00269                  0,
00270                  &BasicInfo->LastAccessTime);
00271     FsdDosDateTimeToSystemTime(DeviceExt,
00272                  FCB->entry.Fat.UpdateDate,
00273                  FCB->entry.Fat.UpdateTime,
00274                  &BasicInfo->LastWriteTime);
00275     BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
00276   }
00277 
00278   BasicInfo->FileAttributes = *FCB->Attributes & 0x3f;
00279   /* Synthesize FILE_ATTRIBUTE_NORMAL */
00280   if (0 == (BasicInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
00281                                          FILE_ATTRIBUTE_ARCHIVE |
00282                                          FILE_ATTRIBUTE_SYSTEM |
00283                                          FILE_ATTRIBUTE_HIDDEN |
00284                                          FILE_ATTRIBUTE_READONLY)))
00285   {
00286     DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
00287     BasicInfo->FileAttributes |= FILE_ATTRIBUTE_NORMAL;
00288   }
00289   DPRINT("Getting attributes 0x%02x\n", BasicInfo->FileAttributes);
00290 
00291   *BufferLength -= sizeof(FILE_BASIC_INFORMATION);
00292   return(STATUS_SUCCESS);
00293 }
00294 
00295 
00296 static NTSTATUS
00297 VfatSetDispositionInformation(PFILE_OBJECT FileObject,
00298                   PVFATFCB FCB,
00299                   PDEVICE_OBJECT DeviceObject,
00300                   PFILE_DISPOSITION_INFORMATION DispositionInfo)
00301 {
00302 #if DBG
00303    PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
00304 #endif
00305 
00306    DPRINT ("FsdSetDispositionInformation(<%wZ>, Delete %d)\n", &FCB->PathNameU, DispositionInfo->DeleteFile);
00307 
00308    ASSERT(DeviceExt != NULL);
00309    ASSERT(DeviceExt->FatInfo.BytesPerCluster != 0);
00310    ASSERT(FCB != NULL);
00311 
00312    if (!DispositionInfo->DeleteFile)
00313    {
00314       /* undelete the file */
00315       FCB->Flags &= ~FCB_DELETE_PENDING;
00316       FileObject->DeletePending = FALSE;
00317       return STATUS_SUCCESS;
00318    }
00319 
00320    if (FCB->Flags & FCB_DELETE_PENDING)
00321    {
00322       /* stream already marked for deletion. just update the file object */
00323       FileObject->DeletePending = TRUE;
00324       return STATUS_SUCCESS;
00325    }
00326 
00327    if (*FCB->Attributes & FILE_ATTRIBUTE_READONLY)
00328    {
00329       return STATUS_CANNOT_DELETE;
00330    }
00331 
00332    if (vfatFCBIsRoot(FCB) ||
00333      (FCB->LongNameU.Length == sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.') ||
00334      (FCB->LongNameU.Length == 2 * sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.' && FCB->LongNameU.Buffer[1] == L'.'))
00335    {
00336       // we cannot delete a '.', '..' or the root directory
00337       return STATUS_ACCESS_DENIED;
00338    }
00339 
00340 
00341    if (!MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
00342    {
00343       /* can't delete a file if its mapped into a process */
00344 
00345       DPRINT("MmFlushImageSection returned FALSE\n");
00346       return STATUS_CANNOT_DELETE;
00347    }
00348 
00349    if (vfatFCBIsDirectory(FCB) && !VfatIsDirectoryEmpty(FCB))
00350    {
00351       /* can't delete a non-empty directory */
00352 
00353       return STATUS_DIRECTORY_NOT_EMPTY;
00354    }
00355 
00356    /* all good */
00357    FCB->Flags |= FCB_DELETE_PENDING;
00358    FileObject->DeletePending = TRUE;
00359 
00360    return STATUS_SUCCESS;
00361 }
00362 
00363 static NTSTATUS
00364 VfatGetNameInformation(PFILE_OBJECT FileObject,
00365                PVFATFCB FCB,
00366                PDEVICE_OBJECT DeviceObject,
00367                PFILE_NAME_INFORMATION NameInfo,
00368                PULONG BufferLength)
00369 /*
00370  * FUNCTION: Retrieve the file name information
00371  */
00372 {
00373   ULONG BytesToCopy;
00374 
00375   UNREFERENCED_PARAMETER(FileObject);
00376   UNREFERENCED_PARAMETER(DeviceObject);
00377 
00378   ASSERT(NameInfo != NULL);
00379   ASSERT(FCB != NULL);
00380 
00381   /* If buffer can't hold at least the file name length, bail out */
00382   if (*BufferLength < (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
00383     return STATUS_BUFFER_OVERFLOW;
00384 
00385   /* Save file name length, and as much file len, as buffer length allows */
00386   NameInfo->FileNameLength = FCB->PathNameU.Length;
00387 
00388   /* Calculate amount of bytes to copy not to overflow the buffer */
00389   BytesToCopy = min(FCB->PathNameU.Length,
00390                     *BufferLength - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]));
00391 
00392   /* Fill in the bytes */
00393   RtlCopyMemory(NameInfo->FileName, FCB->PathNameU.Buffer, BytesToCopy);
00394 
00395   /* Check if we could write more but are not able to */
00396   if (*BufferLength < FCB->PathNameU.Length + (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
00397   {
00398     /* Return number of bytes written */
00399     *BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + BytesToCopy;
00400     return STATUS_BUFFER_OVERFLOW;
00401   }
00402 
00403   /* We filled up as many bytes, as needed */
00404   *BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + FCB->PathNameU.Length);
00405 
00406   return STATUS_SUCCESS;
00407 }
00408 
00409 static NTSTATUS
00410 VfatGetInternalInformation(PVFATFCB Fcb,
00411                PFILE_INTERNAL_INFORMATION InternalInfo,
00412                PULONG BufferLength)
00413 {
00414   ASSERT(InternalInfo);
00415   ASSERT(Fcb);
00416 
00417   if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
00418     return STATUS_BUFFER_OVERFLOW;
00419   // FIXME: get a real index, that can be used in a create operation
00420   InternalInfo->IndexNumber.QuadPart = 0;
00421   *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
00422   return STATUS_SUCCESS;
00423 }
00424 
00425 
00426 static NTSTATUS
00427 VfatGetNetworkOpenInformation(PVFATFCB Fcb,
00428                   PDEVICE_EXTENSION DeviceExt,
00429                   PFILE_NETWORK_OPEN_INFORMATION NetworkInfo,
00430                   PULONG BufferLength)
00431 /*
00432  * FUNCTION: Retrieve the file network open information
00433  */
00434 {
00435   ASSERT(NetworkInfo);
00436   ASSERT(Fcb);
00437 
00438   if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION))
00439     return(STATUS_BUFFER_OVERFLOW);
00440 
00441   if (Fcb->Flags & FCB_IS_FATX_ENTRY)
00442   {
00443     FsdDosDateTimeToSystemTime(DeviceExt,
00444                  Fcb->entry.FatX.CreationDate,
00445                  Fcb->entry.FatX.CreationTime,
00446                  &NetworkInfo->CreationTime);
00447     FsdDosDateTimeToSystemTime(DeviceExt,
00448                  Fcb->entry.FatX.AccessDate,
00449                  Fcb->entry.FatX.AccessTime,
00450                  &NetworkInfo->LastAccessTime);
00451     FsdDosDateTimeToSystemTime(DeviceExt,
00452                  Fcb->entry.FatX.UpdateDate,
00453                  Fcb->entry.FatX.UpdateTime,
00454                  &NetworkInfo->LastWriteTime);
00455     NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
00456   }
00457   else
00458   {
00459     FsdDosDateTimeToSystemTime(DeviceExt,
00460                  Fcb->entry.Fat.CreationDate,
00461                  Fcb->entry.Fat.CreationTime,
00462                  &NetworkInfo->CreationTime);
00463     FsdDosDateTimeToSystemTime(DeviceExt,
00464                  Fcb->entry.Fat.AccessDate,
00465                  0,
00466                  &NetworkInfo->LastAccessTime);
00467     FsdDosDateTimeToSystemTime(DeviceExt,
00468                  Fcb->entry.Fat.UpdateDate,
00469                  Fcb->entry.Fat.UpdateTime,
00470                  &NetworkInfo->LastWriteTime);
00471     NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
00472   }
00473   if (vfatFCBIsDirectory(Fcb))
00474     {
00475       NetworkInfo->EndOfFile.QuadPart = 0L;
00476       NetworkInfo->AllocationSize.QuadPart = 0L;
00477     }
00478   else
00479     {
00480       NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize;
00481       NetworkInfo->EndOfFile = Fcb->RFCB.FileSize;
00482     }
00483   NetworkInfo->FileAttributes = *Fcb->Attributes & 0x3f;
00484   /* Synthesize FILE_ATTRIBUTE_NORMAL */
00485   if (0 == (NetworkInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
00486                                            FILE_ATTRIBUTE_ARCHIVE |
00487                                            FILE_ATTRIBUTE_SYSTEM |
00488                                            FILE_ATTRIBUTE_HIDDEN |
00489                                            FILE_ATTRIBUTE_READONLY)))
00490   {
00491     DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
00492     NetworkInfo->FileAttributes |= FILE_ATTRIBUTE_NORMAL;
00493   }
00494 
00495   *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION);
00496   return STATUS_SUCCESS;
00497 }
00498 
00499 
00500 static NTSTATUS
00501 VfatGetEaInformation(PFILE_OBJECT FileObject,
00502              PVFATFCB Fcb,
00503              PDEVICE_OBJECT DeviceObject,
00504              PFILE_EA_INFORMATION Info,
00505              PULONG BufferLength)
00506 {
00507     PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
00508 
00509     UNREFERENCED_PARAMETER(FileObject);
00510     UNREFERENCED_PARAMETER(Fcb);
00511 
00512     /* FIXME - use SEH to access the buffer! */
00513     Info->EaSize = 0;
00514     *BufferLength -= sizeof(*Info);
00515     if (DeviceExt->FatInfo.FatType == FAT12 ||
00516         DeviceExt->FatInfo.FatType == FAT16)
00517     {
00518         /* FIXME */
00519         DPRINT1("VFAT: FileEaInformation not implemented!\n");
00520     }
00521     return STATUS_SUCCESS;
00522 }
00523 
00524 
00525 static NTSTATUS
00526 VfatGetAllInformation(PFILE_OBJECT FileObject,
00527               PVFATFCB Fcb,
00528               PDEVICE_OBJECT DeviceObject,
00529               PFILE_ALL_INFORMATION Info,
00530               PULONG BufferLength)
00531 /*
00532  * FUNCTION: Retrieve the all file information
00533  */
00534 {
00535   NTSTATUS Status;
00536   ULONG InitialBufferLength = *BufferLength;
00537 
00538   ASSERT(Info);
00539   ASSERT(Fcb);
00540 
00541   if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR))
00542     return(STATUS_BUFFER_OVERFLOW);
00543 
00544   /* Basic Information */
00545   Status = VfatGetBasicInformation(FileObject, Fcb, DeviceObject, &Info->BasicInformation, BufferLength);
00546   if (!NT_SUCCESS(Status)) return Status;
00547   /* Standard Information */
00548   Status = VfatGetStandardInformation(Fcb, &Info->StandardInformation, BufferLength);
00549   if (!NT_SUCCESS(Status)) return Status;
00550   /* Internal Information */
00551   Status = VfatGetInternalInformation(Fcb, &Info->InternalInformation, BufferLength);
00552   if (!NT_SUCCESS(Status)) return Status;
00553   /* EA Information */
00554   Info->EaInformation.EaSize = 0;
00555   /* Access Information: The IO-Manager adds this information */
00556   /* Position Information */
00557   Status = VfatGetPositionInformation(FileObject, Fcb, DeviceObject, &Info->PositionInformation, BufferLength);
00558   if (!NT_SUCCESS(Status)) return Status;
00559   /* Mode Information: The IO-Manager adds this information */
00560   /* Alignment Information: The IO-Manager adds this information */
00561   /* Name Information */
00562   Status = VfatGetNameInformation(FileObject, Fcb, DeviceObject, &Info->NameInformation, BufferLength);
00563   if (!NT_SUCCESS(Status)) return Status;
00564 
00565   *BufferLength = InitialBufferLength - (sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR));
00566 
00567   return STATUS_SUCCESS;
00568 }
00569 
00570 static VOID UpdateFileSize(PFILE_OBJECT FileObject, PVFATFCB Fcb, ULONG Size, ULONG ClusterSize)
00571 {
00572    if (Size > 0)
00573    {
00574       Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, ClusterSize);
00575    }
00576    else
00577    {
00578       Fcb->RFCB.AllocationSize.QuadPart = (LONGLONG)0;
00579    }
00580    if (!vfatFCBIsDirectory(Fcb))
00581    {
00582       if (Fcb->Flags & FCB_IS_FATX_ENTRY)
00583          Fcb->entry.FatX.FileSize = Size;
00584       else
00585          Fcb->entry.Fat.FileSize = Size;
00586    }
00587    Fcb->RFCB.FileSize.QuadPart = Size;
00588    Fcb->RFCB.ValidDataLength.QuadPart = Size;
00589 
00590    CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
00591 }
00592 
00593 NTSTATUS
00594 VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
00595                  PVFATFCB Fcb,
00596                  PDEVICE_EXTENSION DeviceExt,
00597                  PLARGE_INTEGER AllocationSize)
00598 {
00599   ULONG OldSize;
00600   ULONG Cluster, FirstCluster;
00601   NTSTATUS Status;
00602 
00603   ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;
00604   ULONG NewSize = AllocationSize->u.LowPart;
00605   ULONG NCluster;
00606   BOOLEAN AllocSizeChanged = FALSE;
00607 
00608   DPRINT("VfatSetAllocationSizeInformation(File <%wZ>, AllocationSize %d %d)\n", &Fcb->PathNameU,
00609       AllocationSize->HighPart, AllocationSize->LowPart);
00610 
00611   if (Fcb->Flags & FCB_IS_FATX_ENTRY)
00612     OldSize = Fcb->entry.FatX.FileSize;
00613   else
00614     OldSize = Fcb->entry.Fat.FileSize;
00615   if (AllocationSize->u.HighPart > 0)
00616   {
00617     return STATUS_INVALID_PARAMETER;
00618   }
00619   if (OldSize == NewSize)
00620     {
00621       return(STATUS_SUCCESS);
00622     }
00623 
00624   FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
00625 
00626   if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)
00627   {
00628     AllocSizeChanged = TRUE;
00629     if (FirstCluster == 0)
00630     {
00631       Fcb->LastCluster = Fcb->LastOffset = 0;
00632       Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE);
00633       if (!NT_SUCCESS(Status))
00634       {
00635     DPRINT1("NextCluster failed. Status = %x\n", Status);
00636     return Status;
00637       }
00638       if (FirstCluster == 0xffffffff)
00639       {
00640          return STATUS_DISK_FULL;
00641       }
00642       Status = OffsetToCluster(DeviceExt, FirstCluster,
00643                                ROUND_DOWN(NewSize - 1, ClusterSize),
00644                                &NCluster, TRUE);
00645       if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
00646       {
00647          /* disk is full */
00648          NCluster = Cluster = FirstCluster;
00649          Status = STATUS_SUCCESS;
00650          while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
00651          {
00652             Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
00653             WriteCluster (DeviceExt, Cluster, 0);
00654             Cluster = NCluster;
00655          }
00656          return STATUS_DISK_FULL;
00657       }
00658       if (Fcb->Flags & FCB_IS_FATX_ENTRY)
00659       {
00660          Fcb->entry.FatX.FirstCluster = FirstCluster;
00661       }
00662       else
00663       {
00664         if (DeviceExt->FatInfo.FatType == FAT32)
00665         {
00666           Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
00667           Fcb->entry.Fat.FirstClusterHigh = FirstCluster >> 16;
00668         }
00669         else
00670         {
00671             ASSERT((FirstCluster >> 16) == 0);
00672             Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
00673         }
00674       }
00675     }
00676     else
00677     {
00678        if (Fcb->LastCluster > 0)
00679        {
00680           if (Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize == Fcb->LastOffset)
00681           {
00682              Cluster = Fcb->LastCluster;
00683              Status = STATUS_SUCCESS;
00684           }
00685           else
00686           {
00687              Status = OffsetToCluster(DeviceExt, Fcb->LastCluster,
00688                                       Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize - Fcb->LastOffset,
00689                                       &Cluster, FALSE);
00690           }
00691        }
00692        else
00693        {
00694           Status = OffsetToCluster(DeviceExt, FirstCluster,
00695                                    Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize,
00696                                    &Cluster, FALSE);
00697        }
00698        if (!NT_SUCCESS(Status))
00699        {
00700           return Status;
00701        }
00702 
00703        Fcb->LastCluster = Cluster;
00704        Fcb->LastOffset = Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize;
00705 
00706        /* FIXME: Check status */
00707        /* Cluster points now to the last cluster within the chain */
00708        Status = OffsetToCluster(DeviceExt, Cluster,
00709                             ROUND_DOWN(NewSize - 1, ClusterSize) - Fcb->LastOffset,
00710                                 &NCluster, TRUE);
00711        if (NCluster == 0xffffffff || !NT_SUCCESS(Status))
00712        {
00713       /* disk is full */
00714       NCluster = Cluster;
00715           Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
00716       WriteCluster(DeviceExt, Cluster, 0xffffffff);
00717       Cluster = NCluster;
00718           while (NT_SUCCESS(Status) && Cluster != 0xffffffff && Cluster > 1)
00719       {
00720         Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
00721             WriteCluster (DeviceExt, Cluster, 0);
00722         Cluster = NCluster;
00723       }
00724       return STATUS_DISK_FULL;
00725        }
00726     }
00727     UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
00728   }
00729   else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
00730   {
00731 
00732     DPRINT("Check for the ability to set file size\n");
00733     if (!MmCanFileBeTruncated
00734       (FileObject->SectionObjectPointer,
00735       (PLARGE_INTEGER)AllocationSize))
00736     {
00737       DPRINT("Couldn't set file size!\n");
00738       return STATUS_USER_MAPPED_FILE;
00739     }
00740     DPRINT("Can set file size\n");
00741 
00742     AllocSizeChanged = TRUE;
00743     /* FIXME: Use the cached cluster/offset better way. */
00744     Fcb->LastCluster = Fcb->LastOffset = 0;
00745     UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
00746     if (NewSize > 0)
00747     {
00748       Status = OffsetToCluster(DeviceExt, FirstCluster,
00749               ROUND_DOWN(NewSize - 1, ClusterSize),
00750           &Cluster, FALSE);
00751 
00752       NCluster = Cluster;
00753       Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
00754       WriteCluster(DeviceExt, Cluster, 0xffffffff);
00755       Cluster = NCluster;
00756     }
00757     else
00758     {
00759       if (Fcb->Flags & FCB_IS_FATX_ENTRY)
00760       {
00761          Fcb->entry.FatX.FirstCluster = 0;
00762       }
00763       else
00764       {
00765         if (DeviceExt->FatInfo.FatType == FAT32)
00766         {
00767           Fcb->entry.Fat.FirstCluster = 0;
00768           Fcb->entry.Fat.FirstClusterHigh = 0;
00769         }
00770         else
00771         {
00772             Fcb->entry.Fat.FirstCluster = 0;
00773         }
00774       }
00775 
00776       NCluster = Cluster = FirstCluster;
00777       Status = STATUS_SUCCESS;
00778     }
00779     while (NT_SUCCESS(Status) && 0xffffffff != Cluster && Cluster > 1)
00780     {
00781        Status = NextCluster (DeviceExt, FirstCluster, &NCluster, FALSE);
00782        WriteCluster (DeviceExt, Cluster, 0);
00783        Cluster = NCluster;
00784     }
00785   }
00786   else
00787   {
00788      UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
00789   }
00790   /* Update the on-disk directory entry */
00791   Fcb->Flags |= FCB_IS_DIRTY;
00792   if (AllocSizeChanged)
00793     {
00794       VfatUpdateEntry(Fcb);
00795     }
00796   return STATUS_SUCCESS;
00797 }
00798 
00799 NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
00800 /*
00801  * FUNCTION: Retrieve the specified file information
00802  */
00803 {
00804   FILE_INFORMATION_CLASS FileInformationClass;
00805   PVFATFCB FCB = NULL;
00806 
00807   NTSTATUS Status = STATUS_SUCCESS;
00808   PVOID SystemBuffer;
00809   ULONG BufferLength;
00810 
00811   /* PRECONDITION */
00812   ASSERT(IrpContext);
00813 
00814   /* INITIALIZATION */
00815   FileInformationClass = IrpContext->Stack->Parameters.QueryFile.FileInformationClass;
00816   FCB = (PVFATFCB) IrpContext->FileObject->FsContext;
00817 
00818   DPRINT("VfatQueryInformation is called for '%s'\n",
00819          FileInformationClass >= FileMaximumInformation - 1 ? "????" : FileInformationClassNames[FileInformationClass]);
00820 
00821 
00822   SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
00823   BufferLength = IrpContext->Stack->Parameters.QueryFile.Length;
00824 
00825   if (!(FCB->Flags & FCB_IS_PAGE_FILE))
00826   {
00827      if (!ExAcquireResourceSharedLite(&FCB->MainResource,
00828                                       (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
00829      {
00830         return VfatQueueRequest (IrpContext);
00831      }
00832   }
00833 
00834 
00835   switch (FileInformationClass)
00836     {
00837     case FileStandardInformation:
00838       Status = VfatGetStandardInformation(FCB,
00839                       SystemBuffer,
00840                       &BufferLength);
00841       break;
00842     case FilePositionInformation:
00843       Status = VfatGetPositionInformation(IrpContext->FileObject,
00844                       FCB,
00845                       IrpContext->DeviceObject,
00846                       SystemBuffer,
00847                       &BufferLength);
00848       break;
00849     case FileBasicInformation:
00850       Status = VfatGetBasicInformation(IrpContext->FileObject,
00851                    FCB,
00852                    IrpContext->DeviceObject,
00853                    SystemBuffer,
00854                    &BufferLength);
00855       break;
00856     case FileNameInformation:
00857       Status = VfatGetNameInformation(IrpContext->FileObject,
00858                   FCB,
00859                   IrpContext->DeviceObject,
00860                   SystemBuffer,
00861                   &BufferLength);
00862       break;
00863     case FileInternalInformation:
00864       Status = VfatGetInternalInformation(FCB,
00865                       SystemBuffer,
00866                       &BufferLength);
00867       break;
00868     case FileNetworkOpenInformation:
00869       Status = VfatGetNetworkOpenInformation(FCB,
00870                      IrpContext->DeviceExt,
00871                      SystemBuffer,
00872                      &BufferLength);
00873       break;
00874     case FileAllInformation:
00875       Status = VfatGetAllInformation(IrpContext->FileObject,
00876                  FCB,
00877                  IrpContext->DeviceObject,
00878                  SystemBuffer,
00879                  &BufferLength);
00880       break;
00881 
00882     case FileEaInformation:
00883       Status = VfatGetEaInformation(IrpContext->FileObject,
00884                 FCB,
00885                 IrpContext->DeviceObject,
00886                 SystemBuffer,
00887                 &BufferLength);
00888       break;
00889 
00890     case FileAlternateNameInformation:
00891       Status = STATUS_NOT_IMPLEMENTED;
00892       break;
00893     default:
00894       Status = STATUS_INVALID_PARAMETER;
00895     }
00896 
00897   if (!(FCB->Flags & FCB_IS_PAGE_FILE))
00898   {
00899      ExReleaseResourceLite(&FCB->MainResource);
00900   }
00901   IrpContext->Irp->IoStatus.Status = Status;
00902   if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
00903     IrpContext->Irp->IoStatus.Information =
00904       IrpContext->Stack->Parameters.QueryFile.Length - BufferLength;
00905   else
00906     IrpContext->Irp->IoStatus.Information = 0;
00907   IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
00908   VfatFreeIrpContext(IrpContext);
00909 
00910   return Status;
00911 }
00912 
00913 NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
00914 /*
00915  * FUNCTION: Retrieve the specified file information
00916  */
00917 {
00918   FILE_INFORMATION_CLASS FileInformationClass;
00919   PVFATFCB FCB = NULL;
00920   NTSTATUS RC = STATUS_SUCCESS;
00921   PVOID SystemBuffer;
00922   BOOLEAN CanWait = (IrpContext->Flags & IRPCONTEXT_CANWAIT) != 0;
00923 
00924   /* PRECONDITION */
00925   ASSERT(IrpContext);
00926 
00927   DPRINT("VfatSetInformation(IrpContext %p)\n", IrpContext);
00928 
00929   /* INITIALIZATION */
00930   FileInformationClass =
00931     IrpContext->Stack->Parameters.SetFile.FileInformationClass;
00932   FCB = (PVFATFCB) IrpContext->FileObject->FsContext;
00933   SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
00934 
00935   DPRINT("VfatSetInformation is called for '%s'\n",
00936          FileInformationClass >= FileMaximumInformation - 1 ? "????" : FileInformationClassNames[ FileInformationClass]);
00937 
00938   DPRINT("FileInformationClass %d\n", FileInformationClass);
00939   DPRINT("SystemBuffer %p\n", SystemBuffer);
00940 
00941   /* Special: We should call MmCanFileBeTruncated here to determine if changing
00942      the file size would be allowed.  If not, we bail with the right error.
00943      We must do this before acquiring the lock. */
00944   if (FileInformationClass == FileEndOfFileInformation)
00945   {
00946       DPRINT("Check for the ability to set file size\n");
00947       if (!MmCanFileBeTruncated
00948          (IrpContext->FileObject->SectionObjectPointer,
00949           (PLARGE_INTEGER)SystemBuffer))
00950       {
00951          DPRINT("Couldn't set file size!\n");
00952          IrpContext->Irp->IoStatus.Status = STATUS_USER_MAPPED_FILE;
00953          IrpContext->Irp->IoStatus.Information = 0;
00954          IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
00955          VfatFreeIrpContext(IrpContext);
00956          return STATUS_USER_MAPPED_FILE;
00957       }
00958       DPRINT("Can set file size\n");
00959   }
00960 
00961   if (!(FCB->Flags & FCB_IS_PAGE_FILE))
00962     {
00963       if (!ExAcquireResourceExclusiveLite(&FCB->MainResource,
00964                                           (BOOLEAN)CanWait))
00965     {
00966       return(VfatQueueRequest (IrpContext));
00967     }
00968     }
00969 
00970   switch (FileInformationClass)
00971     {
00972     case FilePositionInformation:
00973       RC = VfatSetPositionInformation(IrpContext->FileObject,
00974                       SystemBuffer);
00975       break;
00976     case FileDispositionInformation:
00977       RC = VfatSetDispositionInformation(IrpContext->FileObject,
00978                      FCB,
00979                      IrpContext->DeviceObject,
00980                      SystemBuffer);
00981       break;
00982     case FileAllocationInformation:
00983     case FileEndOfFileInformation:
00984       RC = VfatSetAllocationSizeInformation(IrpContext->FileObject,
00985                         FCB,
00986                         IrpContext->DeviceExt,
00987                         (PLARGE_INTEGER)SystemBuffer);
00988       break;
00989     case FileBasicInformation:
00990       RC = VfatSetBasicInformation(IrpContext->FileObject,
00991                    FCB,
00992                    IrpContext->DeviceExt,
00993                    SystemBuffer);
00994       break;
00995     case FileRenameInformation:
00996       RC = STATUS_NOT_IMPLEMENTED;
00997       break;
00998     default:
00999       RC = STATUS_NOT_SUPPORTED;
01000     }
01001 
01002   if (!(FCB->Flags & FCB_IS_PAGE_FILE))
01003   {
01004      ExReleaseResourceLite(&FCB->MainResource);
01005   }
01006 
01007   IrpContext->Irp->IoStatus.Status = RC;
01008   IrpContext->Irp->IoStatus.Information = 0;
01009   IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
01010   VfatFreeIrpContext(IrpContext);
01011 
01012   return RC;
01013 }
01014 
01015 /* EOF */

Generated on Tue May 15 04:50:47 2012 for ReactOS by doxygen 1.6.3

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.