Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfinfo.cGo 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
1.6.3
|