none
How list recursively a directory after send of IRP? RRS feed

  • Question

  • I need list recursively all files and folders (and also subfolders) of root directory after send a IRP, and delete each file and folder founds using a code that also will send IRP to do this. Until now i'm able only list the content of a root directory through the following code.

    Some idea about how do this?

    #include <ntddk.h>
    #include <WinDef.h>
    
    NTSTATUS EventCompletion(
        IN PDEVICE_OBJECT DeviceObject,
        IN PIRP Irp,
        IN PVOID Context
    )
    {
        PIO_STATUS_BLOCK lpiosb;
        lpiosb = Irp->UserIosb;
        lpiosb->Status = Irp->IoStatus.Status;
        lpiosb->Information = Irp->IoStatus.Information;
        KeSetEvent(Irp->UserEvent, 0, FALSE);
        IoFreeIrp(Irp);
        return STATUS_MORE_PROCESSING_REQUIRED;
    }
    
    typedef struct _FILE_DIRECTORY_INFORMATION {
        ULONG         NextEntryOffset;
        ULONG         FileIndex;
        LARGE_INTEGER CreationTime;
        LARGE_INTEGER LastAccessTime;
        LARGE_INTEGER LastWriteTime;
        LARGE_INTEGER ChangeTime;
        LARGE_INTEGER EndOfFile;
        LARGE_INTEGER AllocationSize;
        ULONG         FileAttributes;
        ULONG         FileNameLength;
        WCHAR         FileName[1];
    } FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
    
    typedef struct _DIRECTORY_INFO {
        char           FileName[50];
        LARGE_INTEGER  AllocationSize;
        TIME_FIELDS    CreationTime;
        TIME_FIELDS    LastAccessTime;
        TIME_FIELDS    LastWriteTime;
        TIME_FIELDS    ChangeTime;
        ULONG          FileAttributes;
    }DIRECTORY_INFO, *PDIRECTORY_INFO;
    
    PVOID GetDirectory(char *lpDirName, PULONG dwRetSize)
    {
        NTSTATUS status;
        ULONG dwBytesReturned;
        OBJECT_ATTRIBUTES oa;
        PDEVICE_OBJECT lpDeviceObject;
        KEVENT event;
        IO_STACK_LOCATION iost;
        PIO_STACK_LOCATION lpsp;
        IO_STATUS_BLOCK ios;
        PIRP lpirp = NULL;
        HANDLE hFile;
        PVOID lpSystemBuffer;
        PFILE_DIRECTORY_INFORMATION lpInformation;
        PFILE_DIRECTORY_INFORMATION lpRealInformation;
        PDIRECTORY_INFO lpDirInfo;
        PFILE_OBJECT lpFileObject;
        UNICODE_STRING unFileName;
        UNICODE_STRING UN;
        ANSI_STRING anFileName;
        CHAR buffer[1024];
        PUCHAR lpNext;
        dwBytesReturned = 0;
        status = STATUS_UNSUCCESSFUL;
    
        RtlZeroMemory(buffer, 1024);
        strcpy(buffer, "\\DosDevices\\");
        strcat(buffer, lpDirName);
        RtlInitAnsiString(&anFileName, buffer);
        RtlAnsiStringToUnicodeString(&unFileName, &anFileName, TRUE);
    
        InitializeObjectAttributes(&oa, &unFileName, OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, NULL, NULL);
        status = ZwOpenFile(&hFile, FILE_LIST_DIRECTORY + SYNCHRONIZE + FILE_ANY_ACCESS, &oa, &ios, FILE_SHARE_READ + FILE_SHARE_WRITE + FILE_SHARE_DELETE, FILE_DIRECTORY_FILE + FILE_SYNCHRONOUS_IO_NONALERT);
    
        if (NT_SUCCESS(status))
        {
            DbgPrint("ZwOpenFile Success\n");
        }
        else
            goto endcddir;
    
        status = ObReferenceObjectByHandle(hFile, FILE_LIST_DIRECTORY + SYNCHRONIZE, 0, KernelMode, &lpFileObject, NULL);
    
        if (!NT_SUCCESS(status))
        {
            ZwClose(hFile);
            goto endcddir;
        }
    
        DbgPrint("open file object success\n");
        lpDeviceObject = IoGetRelatedDeviceObject(lpFileObject);
        lpirp = IoAllocateIrp(lpDeviceObject->StackSize, FALSE);
    
        if (!lpirp)
        {
            DbgPrint("allocate irp failed\n");
            ObDereferenceObject(lpFileObject);
            ZwClose(hFile);
            goto endcddir;
        }
    
        DbgPrint("allocate irp success\n");
        KeInitializeEvent(&event, SynchronizationEvent, FALSE);
        lpInformation = ExAllocatePool(PagedPool, 655350);
        lpSystemBuffer = ExAllocatePool(PagedPool, 655350);
        RtlZeroMemory(lpSystemBuffer, 655350);
        RtlZeroMemory(lpInformation, 655350);
    
        lpirp->UserEvent = &event;
        lpirp->UserBuffer = lpInformation;
        lpirp->AssociatedIrp.SystemBuffer = lpInformation;
        lpirp->MdlAddress = NULL;
        lpirp->Flags = 0;
        lpirp->UserIosb = &ios;
        lpirp->Tail.Overlay.OriginalFileObject = lpFileObject;
        lpirp->Tail.Overlay.Thread = PsGetCurrentThread();
        lpirp->RequestorMode = KernelMode;
    
        lpsp = IoGetNextIrpStackLocation(lpirp);
        lpsp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
        lpsp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
        lpsp->FileObject = lpFileObject;
        lpsp->DeviceObject = lpDeviceObject;
        lpsp->Flags = SL_RESTART_SCAN;
        lpsp->Control = 0;
        lpsp->Parameters.QueryDirectory.FileIndex = 0;
        lpsp->Parameters.QueryDirectory.FileInformationClass = FileDirectoryInformation;
        lpsp->Parameters.QueryDirectory.FileName = NULL;
        lpsp->Parameters.QueryDirectory.Length = 655350;
    
        IoSetCompletionRoutine(lpirp, EventCompletion, 0, TRUE, TRUE, TRUE);
    
        status = IoCallDriver(lpDeviceObject, lpirp);
        KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
        lpDirInfo = (PDIRECTORY_INFO)lpSystemBuffer;
        lpRealInformation = lpInformation;
    
        while (1)
        {
            UN.Length = (USHORT)lpInformation->FileNameLength;
            UN.MaximumLength = (USHORT)lpInformation->FileNameLength;
            UN.Buffer = &(lpInformation->FileName[0]);
            RtlUnicodeStringToAnsiString(&anFileName, &UN, TRUE);
            strcpy(lpDirInfo->FileName, anFileName.Buffer);
            KdPrint(("%s\n", anFileName.Buffer));
            RtlFreeAnsiString(&anFileName);
            lpDirInfo->AllocationSize = lpInformation->AllocationSize;
            lpDirInfo->FileAttributes = lpInformation->FileAttributes;
            RtlTimeToTimeFields(&(lpInformation->CreationTime), &(lpDirInfo->CreationTime));
            RtlTimeToTimeFields(&(lpInformation->LastAccessTime), &(lpDirInfo->LastAccessTime));
            RtlTimeToTimeFields(&(lpInformation->LastWriteTime), &(lpDirInfo->LastWriteTime));
            RtlTimeToTimeFields(&(lpInformation->ChangeTime), &(lpDirInfo->ChangeTime));
            lpDirInfo->FileAttributes = lpInformation->FileAttributes;
            dwBytesReturned += sizeof(DIRECTORY_INFO);
    
            if (lpInformation->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                DbgPrint("Directory found!\n");
            }
    
            if (!lpInformation->NextEntryOffset) goto exit;
    
            lpNext = (PUCHAR)lpInformation;
            lpNext += lpInformation->NextEntryOffset;
            lpInformation = (PFILE_DIRECTORY_INFORMATION)(lpNext);
            lpDirInfo++;
        }
    
    endcddir:
        RtlFreeUnicodeString(&unFileName);
        return NULL;
    
    exit:
        ExFreePool(lpRealInformation);
        ObDereferenceObject(lpFileObject);
        ZwClose(hFile);
        RtlFreeUnicodeString(&unFileName);
        *dwRetSize = dwBytesReturned;
        return lpSystemBuffer;
    }
    
    ////////////// DriverEntry //////////////////
    
    ULONG  dwRetSize;
    GetDirectory("C:\\MyDirectory", &dwRetSize);



    • Edited by FLASHCODR Sunday, June 10, 2018 1:59 AM
    Sunday, June 10, 2018 1:56 AM

Answers

  • There's no shortcut.  With the names you get back, you have to go through each one to find out if it is a file or a folder, and if it is a folder you go read it recursively.

    By the way, it would be a lot easier to use ZwQueryDirectoryFile instead of creating the IRPs yourself.


    Tim Roberts, Driver MVP Providenza & Boekelheide, Inc.

    • Marked as answer by FLASHCODR Sunday, June 10, 2018 5:10 AM
    Sunday, June 10, 2018 4:53 AM