static NTSTATUS CdfsGetBothDirectoryInformation(PFCB Fcb, PDEVICE_EXTENSION DeviceExt, PFILE_BOTH_DIR_INFORMATION Info, ULONG BufferLength) { ULONG Length; DPRINT("CdfsGetBothDirectoryInformation() called\n"); UNREFERENCED_PARAMETER(DeviceExt); Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); if ((sizeof (FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength) return(STATUS_BUFFER_OVERFLOW); Info->FileNameLength = Length; Info->NextEntryOffset = ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG)); RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length); /* Convert file times */ CdfsDateTimeToSystemTime(Fcb, &Info->CreationTime); Info->LastWriteTime = Info->CreationTime; Info->ChangeTime = Info->CreationTime; /* Convert file flags */ CdfsFileFlagsToAttributes(Fcb, &Info->FileAttributes); if (CdfsFCBIsDirectory(Fcb)) { Info->EndOfFile.QuadPart = 0; Info->AllocationSize.QuadPart = 0; } else { Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; /* Make AllocSize a rounded up multiple of the sector size */ Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); } // Info->FileIndex=; Info->EaSize = 0; /* Copy short name */ ASSERT(Fcb->ShortNameU.Length / sizeof(WCHAR) <= 12); Info->ShortNameLength = (CCHAR)Fcb->ShortNameU.Length; RtlCopyMemory(Info->ShortName, Fcb->ShortNameU.Buffer, Fcb->ShortNameU.Length); return(STATUS_SUCCESS); }
VOID CdfsReleaseFCB(PDEVICE_EXTENSION Vcb, PFCB Fcb) { KIRQL oldIrql; DPRINT("releasing FCB at %x: %S, refCount:%d\n", Fcb, Fcb->PathName, Fcb->RefCount); KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); Fcb->RefCount--; if (Fcb->RefCount <= 0 && !CdfsFCBIsDirectory(Fcb)) { RemoveEntryList(&Fcb->FcbListEntry); CdfsDestroyFCB(Fcb); } KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); }
/* * FUNCTION: Retrieve the standard file information */ static NTSTATUS CdfsGetStandardInformation(PFCB Fcb, PDEVICE_OBJECT DeviceObject, PFILE_STANDARD_INFORMATION StandardInfo, PULONG BufferLength) { DPRINT("CdfsGetStandardInformation() called\n"); UNREFERENCED_PARAMETER(DeviceObject); if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION)) return STATUS_BUFFER_OVERFLOW; /* PRECONDITION */ ASSERT(StandardInfo != NULL); ASSERT(Fcb != NULL); RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION)); if (CdfsFCBIsDirectory(Fcb)) { StandardInfo->AllocationSize.QuadPart = 0LL; StandardInfo->EndOfFile.QuadPart = 0LL; StandardInfo->Directory = TRUE; } else { StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize; StandardInfo->EndOfFile = Fcb->RFCB.FileSize; StandardInfo->Directory = FALSE; } StandardInfo->NumberOfLinks = 0; StandardInfo->DeletePending = FALSE; *BufferLength -= sizeof(FILE_STANDARD_INFORMATION); return(STATUS_SUCCESS); }
NTSTATUS CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, PFCB Fcb, PFILE_OBJECT FileObject) { PCCB newCCB; newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB); if (newCCB == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); } memset(newCCB, 0, sizeof(CCB)); FileObject->ReadAccess = TRUE; FileObject->WriteAccess = FALSE; FileObject->DeleteAccess = FALSE; FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; FileObject->FsContext = Fcb; FileObject->FsContext2 = newCCB; newCCB->PtrFileObject = FileObject; Fcb->DevExt = Vcb; if (CdfsFCBIsDirectory(Fcb)) { CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), FALSE, &(CdfsGlobalData->CacheMgrCallbacks), Fcb); Fcb->Flags |= FCB_CACHE_INITIALIZED; } DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL); return(STATUS_SUCCESS); }
/* * FUNCTION: Retrieve the file network open information */ static NTSTATUS CdfsGetNetworkOpenInformation(PFCB Fcb, PFILE_NETWORK_OPEN_INFORMATION NetworkInfo, PULONG BufferLength) { ASSERT(NetworkInfo); ASSERT(Fcb); if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION)) return(STATUS_BUFFER_OVERFLOW); CdfsDateTimeToSystemTime(Fcb, &NetworkInfo->CreationTime); CdfsDateTimeToSystemTime(Fcb, &NetworkInfo->LastAccessTime); CdfsDateTimeToSystemTime(Fcb, &NetworkInfo->LastWriteTime); CdfsDateTimeToSystemTime(Fcb, &NetworkInfo->ChangeTime); if (CdfsFCBIsDirectory(Fcb)) { NetworkInfo->AllocationSize.QuadPart = 0LL; NetworkInfo->EndOfFile.QuadPart = 0LL; } else { NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize; NetworkInfo->EndOfFile = Fcb->RFCB.FileSize; } CdfsFileFlagsToAttributes(Fcb, &NetworkInfo->FileAttributes); *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION); return(STATUS_SUCCESS); }
NTSTATUS CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb, PFCB *pParentFCB, PFCB *pFCB, PUNICODE_STRING FileName) { UNICODE_STRING PathName; UNICODE_STRING ElementName; NTSTATUS Status; WCHAR pathName [MAX_PATH]; WCHAR elementName [MAX_PATH]; PWCHAR currentElement; PFCB FCB; PFCB parentFCB; DPRINT("CdfsGetFCBForFile(%x, %x, %x, '%wZ')\n", Vcb, pParentFCB, pFCB, FileName); /* Trivial case, open of the root directory on volume */ if (FileName->Buffer[0] == L'\0' || wcscmp(FileName->Buffer, L"\\") == 0) { DPRINT("returning root FCB\n"); FCB = CdfsOpenRootFCB(Vcb); *pFCB = FCB; *pParentFCB = NULL; return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND); } else { currentElement = &FileName->Buffer[1]; wcscpy (pathName, L"\\"); FCB = CdfsOpenRootFCB (Vcb); } parentFCB = NULL; /* Parse filename and check each path element for existance and access */ while (CdfsGetNextPathElement(currentElement) != 0) { /* Skip blank directory levels */ if ((CdfsGetNextPathElement(currentElement) - currentElement) == 0) { currentElement++; continue; } DPRINT("Parsing, currentElement:%S\n", currentElement); DPRINT(" parentFCB:%x FCB:%x\n", parentFCB, FCB); /* Descend to next directory level */ if (parentFCB) { CdfsReleaseFCB(Vcb, parentFCB); parentFCB = NULL; } /* fail if element in FCB is not a directory */ if (!CdfsFCBIsDirectory(FCB)) { DPRINT("Element in requested path is not a directory\n"); CdfsReleaseFCB(Vcb, FCB); FCB = 0; *pParentFCB = NULL; *pFCB = NULL; return(STATUS_OBJECT_PATH_NOT_FOUND); } parentFCB = FCB; /* Extract next directory level into dirName */ CdfsWSubString(pathName, FileName->Buffer, CdfsGetNextPathElement(currentElement) - FileName->Buffer); DPRINT(" pathName:%S\n", pathName); RtlInitUnicodeString(&PathName, pathName); FCB = CdfsGrabFCBFromTable(Vcb, &PathName); if (FCB == NULL) { CdfsWSubString(elementName, currentElement, CdfsGetNextPathElement(currentElement) - currentElement); DPRINT(" elementName:%S\n", elementName); RtlInitUnicodeString(&ElementName, elementName); Status = CdfsDirFindFile(Vcb, parentFCB, &ElementName, &FCB); if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { *pParentFCB = parentFCB; *pFCB = NULL; currentElement = CdfsGetNextPathElement(currentElement); if (*currentElement == L'\0' || CdfsGetNextPathElement(currentElement + 1) == 0) { return(STATUS_OBJECT_NAME_NOT_FOUND); } else { return(STATUS_OBJECT_PATH_NOT_FOUND); } } else if (!NT_SUCCESS(Status)) { CdfsReleaseFCB(Vcb, parentFCB); *pParentFCB = NULL; *pFCB = NULL; return(Status); } } currentElement = CdfsGetNextPathElement(currentElement); } *pParentFCB = parentFCB; *pFCB = FCB; return STATUS_SUCCESS; }
NTSTATUS CdfsMakeFCBFromDirEntry(PVCB Vcb, PFCB DirectoryFCB, PWSTR LongName, PWSTR ShortName, PDIR_RECORD Record, ULONG DirectorySector, ULONG DirectoryOffset, PFCB * fileFCB) { WCHAR pathName[MAX_PATH]; PFCB rcFCB; ULONG Size; if (LongName [0] != 0 && wcslen (DirectoryFCB->PathName) + sizeof(WCHAR) + wcslen (LongName) > MAX_PATH) { return(STATUS_OBJECT_NAME_INVALID); } wcscpy(pathName, DirectoryFCB->PathName); if (!CdfsFCBIsRoot(DirectoryFCB)) { wcscat(pathName, L"\\"); } if (LongName[0] != 0) { wcscat(pathName, LongName); } else { WCHAR entryName[MAX_PATH]; CdfsGetDirEntryName(Vcb, Record, entryName); wcscat(pathName, entryName); } rcFCB = CdfsCreateFCB(pathName); memcpy(&rcFCB->Entry, Record, sizeof(DIR_RECORD)); /* Copy short name into FCB */ rcFCB->ShortNameU.Length = wcslen(ShortName) * sizeof(WCHAR); rcFCB->ShortNameU.MaximumLength = rcFCB->ShortNameU.Length; rcFCB->ShortNameU.Buffer = rcFCB->ShortNameBuffer; wcscpy(rcFCB->ShortNameBuffer, ShortName); Size = rcFCB->Entry.DataLengthL; rcFCB->RFCB.FileSize.QuadPart = Size; rcFCB->RFCB.ValidDataLength.QuadPart = Size; rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, BLOCKSIZE); if (CdfsFCBIsDirectory(rcFCB)) { CdfsFCBInitializeCache(Vcb, rcFCB); } rcFCB->IndexNumber.u.HighPart = DirectorySector; rcFCB->IndexNumber.u.LowPart = DirectoryOffset; rcFCB->RefCount++; CdfsAddFCBToTable(Vcb, rcFCB); *fileFCB = rcFCB; DPRINT("%S %d %I64d\n", LongName, Size, rcFCB->RFCB.AllocationSize.QuadPart); return(STATUS_SUCCESS); }
/* * FUNCTION: Retrieve all file information */ static NTSTATUS CdfsGetAllInformation(PFILE_OBJECT FileObject, PFCB Fcb, PFILE_ALL_INFORMATION Info, PULONG BufferLength) { ULONG NameLength; ASSERT(Info); ASSERT(Fcb); NameLength = Fcb->PathName.Length; if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength) return(STATUS_BUFFER_OVERFLOW); /* Basic Information */ CdfsDateTimeToSystemTime(Fcb, &Info->BasicInformation.CreationTime); CdfsDateTimeToSystemTime(Fcb, &Info->BasicInformation.LastAccessTime); CdfsDateTimeToSystemTime(Fcb, &Info->BasicInformation.LastWriteTime); CdfsDateTimeToSystemTime(Fcb, &Info->BasicInformation.ChangeTime); CdfsFileFlagsToAttributes(Fcb, &Info->BasicInformation.FileAttributes); /* Standard Information */ if (CdfsFCBIsDirectory(Fcb)) { Info->StandardInformation.AllocationSize.QuadPart = 0LL; Info->StandardInformation.EndOfFile.QuadPart = 0LL; Info->StandardInformation.Directory = TRUE; } else { Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize; Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize; Info->StandardInformation.Directory = FALSE; } Info->StandardInformation.NumberOfLinks = 0; Info->StandardInformation.DeletePending = FALSE; /* Internal Information */ Info->InternalInformation.IndexNumber.QuadPart = Fcb->IndexNumber.QuadPart; /* EA Information */ Info->EaInformation.EaSize = 0; /* Access Information */ /* The IO-Manager adds this information */ /* Position Information */ Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart; /* Mode Information */ /* The IO-Manager adds this information */ /* Alignment Information */ /* The IO-Manager adds this information */ /* Name Information */ Info->NameInformation.FileNameLength = NameLength; RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathName.Buffer, NameLength + sizeof(WCHAR)); *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR)); return STATUS_SUCCESS; }