Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvolume.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/volume.c 00005 * PURPOSE: VFAT Filesystem 00006 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) 00007 * Herve Poussineau (reactos@poussine.freesurf.fr) 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #define NDEBUG 00013 #include "vfat.h" 00014 00015 /* FUNCTIONS ****************************************************************/ 00016 00017 static NTSTATUS 00018 FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject, 00019 PFILE_FS_VOLUME_INFORMATION FsVolumeInfo, 00020 PULONG BufferLength) 00021 { 00022 DPRINT("FsdGetFsVolumeInformation()\n"); 00023 DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo); 00024 DPRINT("BufferLength %lu\n", *BufferLength); 00025 00026 DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength)); 00027 DPRINT("LabelLength %hu\n", DeviceObject->Vpb->VolumeLabelLength); 00028 DPRINT("Label %*.S\n", DeviceObject->Vpb->VolumeLabelLength / sizeof(WCHAR), DeviceObject->Vpb->VolumeLabel); 00029 00030 if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION)) 00031 return STATUS_INFO_LENGTH_MISMATCH; 00032 00033 if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength)) 00034 return STATUS_BUFFER_OVERFLOW; 00035 00036 /* valid entries */ 00037 FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber; 00038 FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength; 00039 RtlCopyMemory(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel, FsVolumeInfo->VolumeLabelLength); 00040 00041 /* dummy entries */ 00042 FsVolumeInfo->VolumeCreationTime.QuadPart = 0; 00043 FsVolumeInfo->SupportsObjects = FALSE; 00044 00045 DPRINT("Finished FsdGetFsVolumeInformation()\n"); 00046 00047 *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength); 00048 00049 DPRINT("BufferLength %lu\n", *BufferLength); 00050 00051 return(STATUS_SUCCESS); 00052 } 00053 00054 00055 static NTSTATUS 00056 FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt, 00057 PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, 00058 PULONG BufferLength) 00059 { 00060 PCWSTR pName; ULONG Length; 00061 DPRINT("FsdGetFsAttributeInformation()\n"); 00062 DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo); 00063 DPRINT("BufferLength %lu\n", *BufferLength); 00064 00065 if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION)) 00066 return STATUS_INFO_LENGTH_MISMATCH; 00067 00068 if (DeviceExt->FatInfo.FatType == FAT32) 00069 { 00070 Length = 10; 00071 pName = L"FAT32"; 00072 } 00073 else 00074 { 00075 Length = 6; 00076 pName = L"FAT"; 00077 } 00078 00079 DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length)); 00080 00081 if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length)) 00082 return STATUS_BUFFER_OVERFLOW; 00083 00084 FsAttributeInfo->FileSystemAttributes = 00085 FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK; 00086 00087 FsAttributeInfo->MaximumComponentNameLength = 255; 00088 00089 FsAttributeInfo->FileSystemNameLength = Length; 00090 00091 RtlCopyMemory(FsAttributeInfo->FileSystemName, pName, Length ); 00092 00093 DPRINT("Finished FsdGetFsAttributeInformation()\n"); 00094 00095 *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length); 00096 DPRINT("BufferLength %lu\n", *BufferLength); 00097 00098 return(STATUS_SUCCESS); 00099 } 00100 00101 00102 static NTSTATUS 00103 FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject, 00104 PFILE_FS_SIZE_INFORMATION FsSizeInfo, 00105 PULONG BufferLength) 00106 { 00107 PDEVICE_EXTENSION DeviceExt; 00108 NTSTATUS Status; 00109 00110 DPRINT("FsdGetFsSizeInformation()\n"); 00111 DPRINT("FsSizeInfo = %p\n", FsSizeInfo); 00112 00113 if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION)) 00114 return(STATUS_BUFFER_OVERFLOW); 00115 00116 DeviceExt = DeviceObject->DeviceExtension; 00117 Status = CountAvailableClusters(DeviceExt, &FsSizeInfo->AvailableAllocationUnits); 00118 00119 FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->FatInfo.NumberOfClusters; 00120 FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->FatInfo.SectorsPerCluster; 00121 FsSizeInfo->BytesPerSector = DeviceExt->FatInfo.BytesPerSector; 00122 00123 DPRINT("Finished FsdGetFsSizeInformation()\n"); 00124 if (NT_SUCCESS(Status)) 00125 *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION); 00126 00127 return(Status); 00128 } 00129 00130 00131 static NTSTATUS 00132 FsdGetFsDeviceInformation 00133 ( 00134 PDEVICE_OBJECT DeviceObject, 00135 PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, 00136 PULONG BufferLength 00137 ) 00138 { 00139 DPRINT("FsdGetFsDeviceInformation()\n"); 00140 DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo); 00141 DPRINT("BufferLength %lu\n", *BufferLength); 00142 DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION)); 00143 00144 if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION)) 00145 return(STATUS_BUFFER_OVERFLOW); 00146 00147 FsDeviceInfo->DeviceType = FILE_DEVICE_DISK; 00148 FsDeviceInfo->Characteristics = DeviceObject->Characteristics; 00149 00150 DPRINT("FsdGetFsDeviceInformation() finished.\n"); 00151 00152 *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION); 00153 DPRINT("BufferLength %lu\n", *BufferLength); 00154 00155 return(STATUS_SUCCESS); 00156 } 00157 00158 00159 static NTSTATUS 00160 FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject, 00161 PFILE_FS_LABEL_INFORMATION FsLabelInfo) 00162 { 00163 PDEVICE_EXTENSION DeviceExt; 00164 PVOID Context = NULL; 00165 ULONG DirIndex = 0; 00166 PDIR_ENTRY Entry; 00167 PVFATFCB pRootFcb; 00168 LARGE_INTEGER FileOffset; 00169 BOOLEAN LabelFound = FALSE; 00170 DIR_ENTRY VolumeLabelDirEntry; 00171 ULONG VolumeLabelDirIndex; 00172 ULONG LabelLen; 00173 NTSTATUS Status = STATUS_UNSUCCESSFUL; 00174 OEM_STRING StringO; 00175 UNICODE_STRING StringW; 00176 CHAR cString[43]; 00177 ULONG SizeDirEntry; 00178 ULONG EntriesPerPage; 00179 00180 DPRINT("FsdSetFsLabelInformation()\n"); 00181 00182 DeviceExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 00183 00184 if (sizeof(DeviceObject->Vpb->VolumeLabel) < FsLabelInfo->VolumeLabelLength) 00185 { 00186 return STATUS_NAME_TOO_LONG; 00187 } 00188 00189 if (DeviceExt->Flags & VCB_IS_FATX) 00190 { 00191 if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 42) 00192 return STATUS_NAME_TOO_LONG; 00193 SizeDirEntry = sizeof(FATX_DIR_ENTRY); 00194 EntriesPerPage = FATX_ENTRIES_PER_PAGE; 00195 } 00196 else 00197 { 00198 if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 11) 00199 return STATUS_NAME_TOO_LONG; 00200 SizeDirEntry = sizeof(FAT_DIR_ENTRY); 00201 EntriesPerPage = FAT_ENTRIES_PER_PAGE; 00202 } 00203 00204 /* Create Volume label dir entry */ 00205 LabelLen = FsLabelInfo->VolumeLabelLength / sizeof(WCHAR); 00206 RtlZeroMemory(&VolumeLabelDirEntry, SizeDirEntry); 00207 StringW.Buffer = FsLabelInfo->VolumeLabel; 00208 StringW.Length = StringW.MaximumLength = (USHORT)FsLabelInfo->VolumeLabelLength; 00209 StringO.Buffer = cString; 00210 StringO.Length = 0; 00211 StringO.MaximumLength = 42; 00212 Status = RtlUnicodeStringToOemString(&StringO, &StringW, FALSE); 00213 if (!NT_SUCCESS(Status)) 00214 return Status; 00215 if (DeviceExt->Flags & VCB_IS_FATX) 00216 { 00217 RtlCopyMemory(VolumeLabelDirEntry.FatX.Filename, cString, LabelLen); 00218 memset(&VolumeLabelDirEntry.FatX.Filename[LabelLen], ' ', 42 - LabelLen); 00219 VolumeLabelDirEntry.FatX.Attrib = _A_VOLID; 00220 } 00221 else 00222 { 00223 RtlCopyMemory(VolumeLabelDirEntry.Fat.Filename, cString, max(sizeof(VolumeLabelDirEntry.Fat.Filename), LabelLen)); 00224 if (LabelLen > sizeof(VolumeLabelDirEntry.Fat.Filename)) 00225 { 00226 memset(VolumeLabelDirEntry.Fat.Ext, ' ', sizeof(VolumeLabelDirEntry.Fat.Ext)); 00227 RtlCopyMemory(VolumeLabelDirEntry.Fat.Ext, cString + sizeof(VolumeLabelDirEntry.Fat.Filename), LabelLen - sizeof(VolumeLabelDirEntry.Fat.Filename)); 00228 } 00229 else 00230 { 00231 memset(&VolumeLabelDirEntry.Fat.Filename[LabelLen], ' ', sizeof(VolumeLabelDirEntry.Fat.Filename) - LabelLen); 00232 } 00233 VolumeLabelDirEntry.Fat.Attrib = _A_VOLID; 00234 } 00235 00236 pRootFcb = vfatOpenRootFCB(DeviceExt); 00237 00238 /* Search existing volume entry on disk */ 00239 FileOffset.QuadPart = 0; 00240 if (CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry)) 00241 { 00242 while (TRUE) 00243 { 00244 if (ENTRY_VOLUME(DeviceExt, Entry)) 00245 { 00246 /* Update entry */ 00247 LabelFound = TRUE; 00248 RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry); 00249 CcSetDirtyPinnedData(Context, NULL); 00250 Status = STATUS_SUCCESS; 00251 break; 00252 } 00253 if (ENTRY_END(DeviceExt, Entry)) 00254 { 00255 break; 00256 } 00257 DirIndex++; 00258 Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry); 00259 if ((DirIndex % EntriesPerPage) == 0) 00260 { 00261 CcUnpinData(Context); 00262 FileOffset.u.LowPart += PAGE_SIZE; 00263 if (!CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry)) 00264 { 00265 Context = NULL; 00266 break; 00267 } 00268 } 00269 } 00270 if (Context) 00271 { 00272 CcUnpinData(Context); 00273 } 00274 } 00275 if (!LabelFound) 00276 { 00277 /* Add new entry for label */ 00278 if (!vfatFindDirSpace(DeviceExt, pRootFcb, 1, &VolumeLabelDirIndex)) 00279 Status = STATUS_DISK_FULL; 00280 else 00281 { 00282 FileOffset.u.HighPart = 0; 00283 FileOffset.u.LowPart = VolumeLabelDirIndex * SizeDirEntry; 00284 if (!CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry, 00285 TRUE, &Context, (PVOID*)&Entry)) 00286 { 00287 Status = STATUS_UNSUCCESSFUL; 00288 } 00289 else 00290 { 00291 RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry); 00292 CcSetDirtyPinnedData(Context, NULL); 00293 CcUnpinData(Context); 00294 Status = STATUS_SUCCESS; 00295 } 00296 } 00297 } 00298 00299 vfatReleaseFCB(DeviceExt, pRootFcb); 00300 if (!NT_SUCCESS(Status)) 00301 { 00302 return Status; 00303 } 00304 00305 /* Update volume label in memory */ 00306 DeviceObject->Vpb->VolumeLabelLength = (USHORT)FsLabelInfo->VolumeLabelLength; 00307 RtlCopyMemory(DeviceObject->Vpb->VolumeLabel, FsLabelInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabelLength); 00308 00309 return Status; 00310 } 00311 00312 00313 NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext) 00314 /* 00315 * FUNCTION: Retrieve the specified volume information 00316 */ 00317 { 00318 FS_INFORMATION_CLASS FsInformationClass; 00319 NTSTATUS RC = STATUS_SUCCESS; 00320 PVOID SystemBuffer; 00321 ULONG BufferLength; 00322 00323 /* PRECONDITION */ 00324 ASSERT(IrpContext); 00325 00326 DPRINT("VfatQueryVolumeInformation(IrpContext %p)\n", IrpContext); 00327 00328 if (!ExAcquireResourceSharedLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, 00329 (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT))) 00330 { 00331 return VfatQueueRequest (IrpContext); 00332 } 00333 00334 /* INITIALIZATION */ 00335 FsInformationClass = IrpContext->Stack->Parameters.QueryVolume.FsInformationClass; 00336 BufferLength = IrpContext->Stack->Parameters.QueryVolume.Length; 00337 SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer; 00338 00339 00340 DPRINT ("FsInformationClass %d\n", FsInformationClass); 00341 DPRINT ("SystemBuffer %p\n", SystemBuffer); 00342 00343 switch (FsInformationClass) 00344 { 00345 case FileFsVolumeInformation: 00346 RC = FsdGetFsVolumeInformation(IrpContext->DeviceObject, 00347 SystemBuffer, 00348 &BufferLength); 00349 break; 00350 00351 case FileFsAttributeInformation: 00352 RC = FsdGetFsAttributeInformation(IrpContext->DeviceObject->DeviceExtension, 00353 SystemBuffer, 00354 &BufferLength); 00355 break; 00356 00357 case FileFsSizeInformation: 00358 RC = FsdGetFsSizeInformation(IrpContext->DeviceObject, 00359 SystemBuffer, 00360 &BufferLength); 00361 break; 00362 00363 case FileFsDeviceInformation: 00364 RC = FsdGetFsDeviceInformation(IrpContext->DeviceObject, 00365 SystemBuffer, 00366 &BufferLength); 00367 break; 00368 00369 default: 00370 RC = STATUS_NOT_SUPPORTED; 00371 } 00372 00373 ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource); 00374 IrpContext->Irp->IoStatus.Status = RC; 00375 if (NT_SUCCESS(RC)) 00376 IrpContext->Irp->IoStatus.Information = 00377 IrpContext->Stack->Parameters.QueryVolume.Length - BufferLength; 00378 else 00379 IrpContext->Irp->IoStatus.Information = 0; 00380 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); 00381 VfatFreeIrpContext(IrpContext); 00382 00383 return RC; 00384 } 00385 00386 00387 NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext) 00388 /* 00389 * FUNCTION: Set the specified volume information 00390 */ 00391 { 00392 FS_INFORMATION_CLASS FsInformationClass; 00393 NTSTATUS Status = STATUS_SUCCESS; 00394 PVOID SystemBuffer; 00395 ULONG BufferLength; 00396 PIO_STACK_LOCATION Stack = IrpContext->Stack; 00397 00398 /* PRECONDITION */ 00399 ASSERT(IrpContext); 00400 00401 DPRINT ("VfatSetVolumeInformation(IrpContext %p)\n", IrpContext); 00402 00403 if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, 00404 (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT))) 00405 { 00406 return VfatQueueRequest (IrpContext); 00407 } 00408 00409 FsInformationClass = Stack->Parameters.SetVolume.FsInformationClass; 00410 BufferLength = Stack->Parameters.SetVolume.Length; 00411 SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer; 00412 00413 DPRINT ("FsInformationClass %d\n", FsInformationClass); 00414 DPRINT ("BufferLength %d\n", BufferLength); 00415 DPRINT ("SystemBuffer %p\n", SystemBuffer); 00416 00417 switch(FsInformationClass) 00418 { 00419 case FileFsLabelInformation: 00420 Status = FsdSetFsLabelInformation(IrpContext->DeviceObject, 00421 SystemBuffer); 00422 break; 00423 00424 default: 00425 Status = STATUS_NOT_SUPPORTED; 00426 } 00427 00428 ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource); 00429 IrpContext->Irp->IoStatus.Status = Status; 00430 IrpContext->Irp->IoStatus.Information = 0; 00431 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); 00432 VfatFreeIrpContext(IrpContext); 00433 00434 return(Status); 00435 } 00436 00437 /* EOF */ Generated on Mon May 28 2012 04:19:04 for ReactOS by
1.7.6.1
|