static NTSTATUS CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDEVICE_EXTENSION DeviceExtension; LONG BufferLength = 0; PUNICODE_STRING SearchPattern = NULL; FILE_INFORMATION_CLASS FileInformationClass; ULONG FileIndex = 0; PUCHAR Buffer = NULL; PFILE_NAMES_INFORMATION Buffer0 = NULL; PFCB Fcb; PCCB Ccb; FCB TempFcb; BOOLEAN First = FALSE; PIO_STACK_LOCATION Stack; PFILE_OBJECT FileObject; NTSTATUS Status = STATUS_SUCCESS; DPRINT("CdfsQueryDirectory() called\n"); DeviceExtension = DeviceObject->DeviceExtension; Stack = IoGetCurrentIrpStackLocation(Irp); FileObject = Stack->FileObject; RtlInitEmptyUnicodeString(&TempFcb.PathName, TempFcb.PathNameBuffer, sizeof(TempFcb.PathNameBuffer)); Ccb = (PCCB)FileObject->FsContext2; Fcb = (PFCB)FileObject->FsContext; /* Obtain the callers parameters */ BufferLength = Stack->Parameters.QueryDirectory.Length; SearchPattern = Stack->Parameters.QueryDirectory.FileName; FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass; FileIndex = Stack->Parameters.QueryDirectory.FileIndex; /* Determine Buffer for result */ if (Irp->MdlAddress) { Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); } else { Buffer = Irp->UserBuffer; } /* Allocate search pattern in case: * -> We don't have one already in context * -> We have been given an input pattern * -> The pattern length is not null * -> The pattern buffer is not null * Otherwise, we'll fall later and allocate a match all (*) pattern */ if (SearchPattern != NULL && SearchPattern->Length != 0 && SearchPattern->Buffer != NULL) { if (Ccb->DirectorySearchPattern.Buffer == NULL) { First = TRUE; Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, SearchPattern->Length + sizeof(WCHAR), CDFS_SEARCH_PATTERN_TAG); if (Ccb->DirectorySearchPattern.Buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } Ccb->DirectorySearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR); RtlCopyUnicodeString(&Ccb->DirectorySearchPattern, SearchPattern); Ccb->DirectorySearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0; } } else if (Ccb->DirectorySearchPattern.Buffer == NULL) { First = TRUE; Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), CDFS_SEARCH_PATTERN_TAG); if (Ccb->DirectorySearchPattern.Buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } Ccb->DirectorySearchPattern.Length = sizeof(WCHAR); Ccb->DirectorySearchPattern.MaximumLength = 2 * sizeof(WCHAR); Ccb->DirectorySearchPattern.Buffer[0] = L'*'; Ccb->DirectorySearchPattern.Buffer[1] = 0; } DPRINT("Search pattern '%wZ'\n", &Ccb->DirectorySearchPattern); /* Determine directory index */ if (Stack->Flags & SL_INDEX_SPECIFIED) { Ccb->Entry = Stack->Parameters.QueryDirectory.FileIndex; Ccb->Offset = Ccb->CurrentByteOffset.u.LowPart; } else if (First || (Stack->Flags & SL_RESTART_SCAN)) { Ccb->Entry = 0; Ccb->Offset = 0; } DPRINT("Buffer = %p tofind = %wZ\n", Buffer, &Ccb->DirectorySearchPattern); TempFcb.ObjectName = TempFcb.PathName.Buffer; while (Status == STATUS_SUCCESS && BufferLength > 0) { Status = CdfsFindFile(DeviceExtension, &TempFcb, Fcb, &Ccb->DirectorySearchPattern, &Ccb->Entry, &Ccb->Offset); DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry); if (NT_SUCCESS(Status)) { switch (FileInformationClass) { case FileNameInformation: Status = CdfsGetNameInformation(&TempFcb, DeviceExtension, (PFILE_NAMES_INFORMATION)Buffer, BufferLength); break; case FileDirectoryInformation: Status = CdfsGetDirectoryInformation(&TempFcb, DeviceExtension, (PFILE_DIRECTORY_INFORMATION)Buffer, BufferLength); break; case FileFullDirectoryInformation: Status = CdfsGetFullDirectoryInformation(&TempFcb, DeviceExtension, (PFILE_FULL_DIR_INFORMATION)Buffer, BufferLength); break; case FileBothDirectoryInformation: Status = CdfsGetBothDirectoryInformation(&TempFcb, DeviceExtension, (PFILE_BOTH_DIR_INFORMATION)Buffer, BufferLength); break; default: Status = STATUS_INVALID_INFO_CLASS; } if (Status == STATUS_BUFFER_OVERFLOW) { if (Buffer0) { Buffer0->NextEntryOffset = 0; } break; } } else { if (Buffer0) { Buffer0->NextEntryOffset = 0; } if (First) { Status = STATUS_NO_SUCH_FILE; } else { Status = STATUS_NO_MORE_FILES; } break; } Buffer0 = (PFILE_NAMES_INFORMATION)Buffer; Buffer0->FileIndex = FileIndex++; Ccb->Entry++; if (Stack->Flags & SL_RETURN_SINGLE_ENTRY) { break; } BufferLength -= Buffer0->NextEntryOffset; Buffer += Buffer0->NextEntryOffset; } if (Buffer0) { Buffer0->NextEntryOffset = 0; } if (FileIndex > 0) { Status = STATUS_SUCCESS; } return(Status); }
/* * FUNCTION: Retrieve the specified file information */ NTSTATUS NTAPI CdfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp) { FILE_INFORMATION_CLASS FileInformationClass; PIO_STACK_LOCATION Stack; PFILE_OBJECT FileObject; PFCB Fcb; PVOID SystemBuffer; ULONG BufferLength; NTSTATUS Status = STATUS_SUCCESS; DPRINT("CdfsQueryInformation() called\n"); Stack = IoGetCurrentIrpStackLocation(Irp); FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; FileObject = Stack->FileObject; Fcb = FileObject->FsContext; SystemBuffer = Irp->AssociatedIrp.SystemBuffer; BufferLength = Stack->Parameters.QueryFile.Length; switch (FileInformationClass) { case FileStandardInformation: Status = CdfsGetStandardInformation(Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FilePositionInformation: Status = CdfsGetPositionInformation(FileObject, SystemBuffer, &BufferLength); break; case FileBasicInformation: Status = CdfsGetBasicInformation(FileObject, Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FileNameInformation: Status = CdfsGetNameInformation(FileObject, Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FileInternalInformation: Status = CdfsGetInternalInformation(Fcb, SystemBuffer, &BufferLength); break; case FileNetworkOpenInformation: Status = CdfsGetNetworkOpenInformation(Fcb, SystemBuffer, &BufferLength); break; case FileAllInformation: Status = CdfsGetAllInformation(FileObject, Fcb, SystemBuffer, &BufferLength); break; case FileAlternateNameInformation: Status = STATUS_NOT_IMPLEMENTED; break; default: DPRINT("Unimplemented information class %x\n", FileInformationClass); Status = STATUS_INVALID_PARAMETER; break; } Irp->IoStatus.Status = Status; if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) Irp->IoStatus.Information = Stack->Parameters.QueryFile.Length - BufferLength; else Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(Status); }