Esempio n. 1
0
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);
}
Esempio n. 2
0
/*
* 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);
}