/* * FUNCTION: Retrieve the standard file information */ static NTSTATUS NtfsGetStandardInformation(PNTFS_FCB Fcb, PDEVICE_OBJECT DeviceObject, PFILE_STANDARD_INFORMATION StandardInfo, PULONG BufferLength) { UNREFERENCED_PARAMETER(DeviceObject); DPRINT1("NtfsGetStandardInformation(%p, %p, %p, %p)\n", Fcb, DeviceObject, StandardInfo, BufferLength); if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION)) return STATUS_BUFFER_OVERFLOW; /* PRECONDITION */ ASSERT(StandardInfo != NULL); ASSERT(Fcb != NULL); RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION)); StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize; StandardInfo->EndOfFile = Fcb->RFCB.FileSize; StandardInfo->NumberOfLinks = Fcb->LinkCount; StandardInfo->DeletePending = FALSE; StandardInfo->Directory = NtfsFCBIsDirectory(Fcb); *BufferLength -= sizeof(FILE_STANDARD_INFORMATION); return STATUS_SUCCESS; }
VOID NtfsReleaseFCB(PNTFS_VCB Vcb, PNTFS_FCB Fcb) { KIRQL oldIrql; DPRINT("releasing FCB at %p: %S, refCount:%d\n", Fcb, Fcb->PathName, Fcb->RefCount); KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); Fcb->RefCount--; if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb)) { RemoveEntryList(&Fcb->FcbListEntry); KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); CcUninitializeCacheMap(Fcb->FileObject, NULL, NULL); NtfsDestroyFCB(Fcb); } else { KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); } }
NTSTATUS NtfsGetFCBForFile(PNTFS_VCB Vcb, PNTFS_FCB *pParentFCB, PNTFS_FCB *pFCB, const PWSTR pFileName) { NTSTATUS Status; WCHAR pathName [MAX_PATH]; WCHAR elementName [MAX_PATH]; PWCHAR currentElement; PNTFS_FCB FCB; PNTFS_FCB parentFCB; DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S')\n", Vcb, pParentFCB, pFCB, pFileName); /* Dummy code */ // FCB = NtfsOpenRootFCB(Vcb); // *pFCB = FCB; // *pParentFCB = NULL; #if 1 /* Trivial case, open of the root directory on volume */ if (pFileName [0] == L'\0' || wcscmp(pFileName, L"\\") == 0) { DPRINT("returning root FCB\n"); FCB = NtfsOpenRootFCB(Vcb); *pFCB = FCB; *pParentFCB = NULL; return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND; } else { currentElement = pFileName + 1; wcscpy (pathName, L"\\"); FCB = NtfsOpenRootFCB (Vcb); } parentFCB = NULL; /* Parse filename and check each path element for existance and access */ while (NtfsGetNextPathElement(currentElement) != 0) { /* Skip blank directory levels */ if ((NtfsGetNextPathElement(currentElement) - currentElement) == 0) { currentElement++; continue; } DPRINT("Parsing, currentElement:%S\n", currentElement); DPRINT(" parentFCB:%p FCB:%p\n", parentFCB, FCB); /* Descend to next directory level */ if (parentFCB) { NtfsReleaseFCB(Vcb, parentFCB); parentFCB = NULL; } /* fail if element in FCB is not a directory */ if (!NtfsFCBIsDirectory(FCB)) { DPRINT("Element in requested path is not a directory\n"); NtfsReleaseFCB(Vcb, FCB); FCB = 0; *pParentFCB = NULL; *pFCB = NULL; return STATUS_OBJECT_PATH_NOT_FOUND; } parentFCB = FCB; /* Extract next directory level into dirName */ NtfsWSubString(pathName, pFileName, NtfsGetNextPathElement(currentElement) - pFileName); DPRINT(" pathName:%S\n", pathName); FCB = NtfsGrabFCBFromTable(Vcb, pathName); if (FCB == NULL) { NtfsWSubString(elementName, currentElement, NtfsGetNextPathElement(currentElement) - currentElement); DPRINT(" elementName:%S\n", elementName); Status = NtfsDirFindFile(Vcb, parentFCB, elementName, &FCB); if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { *pParentFCB = parentFCB; *pFCB = NULL; currentElement = NtfsGetNextPathElement(currentElement); if (*currentElement == L'\0' || NtfsGetNextPathElement(currentElement + 1) == 0) { return STATUS_OBJECT_NAME_NOT_FOUND; } else { return STATUS_OBJECT_PATH_NOT_FOUND; } } else if (!NT_SUCCESS(Status)) { NtfsReleaseFCB(Vcb, parentFCB); *pParentFCB = NULL; *pFCB = NULL; return Status; } } currentElement = NtfsGetNextPathElement(currentElement); } *pParentFCB = parentFCB; *pFCB = FCB; #endif return STATUS_SUCCESS; }