Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTFSD

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

FltCreateFile/Ex() fails with error 0xc000000d in minifilter.

M_DM_D Member Posts: 34
I'm seeing error when I call FltCreateFile/Ex() function from Minifilter. I'm new to this and adding changes to Passthrough WDK example. What I would like to do is to send DeviceIOCtl(FSCTL_*) to NTFS and get data from it.

Here is the code I'm using.

++++
NTSTATUS GetNTFSVolData(
__in PCFLT_RELATED_OBJECTS FltObjects
)
{
NTSTATUS ntStatus;
ULONG dwOutputSize = 0;
// UCHAR volDataBuffer[sizeof(NTFS_VOLUME_DATA_BUFFER)];
// PNTFS_VOLUME_DATA_BUFFER pNtfsVolData = (PNTFS_VOLUME_DATA_BUFFER)volDataBuffer;
NTFS_VOLUME_DATA_BUFFER NtfsVolData;
ULONG dwInputSize = sizeof(NTFS_VOLUME_DATA_BUFFER);
ULONG dwBytesPerCluster = 0;
PFLT_FILE_NAME_INFORMATION nameInfo;

HANDLE hFile;
PFILE_OBJECT fileObject;
UNICODE_STRING fileName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatus;

DbgPrint("Opening volume: %wZ\n", gVolumeRoot);
// This prints "\DosDevices\E:"
InitializeObjectAttributes( &objectAttributes, &gVolumeRoot, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL );

// ntStatus = FltCreateFileEx(gFilterHandle, FltObjects->Instance, &hFile, &fileObject, FILE_READ_ATTRIBUTES,
ntStatus = FltCreateFile(gFilterHandle, FltObjects->Instance, &hFile, FILE_READ_ATTRIBUTES,
&objectAttributes, &ioStatus, (PLARGE_INTEGER) NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0L, NULL, 0L, 0);
// ntStatus is set to 0xc000000d

// ZwCreateFile() would work.
// ntStatus = ZwCreateFile(&hFile, FILE_READ_ATTRIBUTES, &objectAttributes, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL,
// FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
ntStatus = ObReferenceObjectByHandle(hFile, FILE_READ_ATTRIBUTES, *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL); // This would also work.
ntStatus = FltDeviceIoControlFile(FltObjects->Instance, fileObject, FSCTL_GET_NTFS_VOLUME_DATA,
(PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize, &dwOutputSize);
// This call to FltDeviceIoControlFile() would return ntStatus = 0xc0000002.


// FltOpenVolume() would be successful.
ntStatus = FltOpenVolume(FltObjects->Instance, &hFile, &fileObject);
if( NT_SUCCESS(ntStatus) ) {
DbgPrint("FltOpenVolume() successful.\n");

// But this call to FltDeviceIoControlFile() would return ntStatus = 0xc0000002.
ntStatus = FltDeviceIoControlFile(FltObjects->Instance, fileObject, FSCTL_GET_NTFS_VOLUME_DATA,
(PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize, &dwOutputSize);
if( NT_SUCCESS(ntStatus) )
DbgPrint("FltDeviceIoControlFile::FSCTL_GET_NTFS_VOLUME_DATA successful.\n");
else {
DbgPrint("FltDeviceIoControlFile::FSCTL_GET_NTFS_VOLUME_DATA return status: 0x%x\n", ntStatus);
// Query API would work fine.
ntStatus = FltQueryVolumeInformation(FltObjects->Instance, &ioStatus, (PVOID)&fsVolSize,
sizeof(fsVolSize), FileFsSizeInformation);
if( NT_SUCCESS(ntStatus) ) {
DbgPrint("FltQueryVolumeInformation successful.\n");
DbgPrint("Cluster size: %d\n", fsVolSize.SectorsPerAllocationUnit * fsVolSize.BytesPerSector);
}
else
DbgPrint("FltQueryVolumeInformation return status: 0x%x\n", ntStatus);
}
FltClose(hFile);
}
}
++++++

I'm calling the above function, GetNTFSVolData(), from Pre IRP_MJ_WRITE and PtInstanceTeardownStart() in Passthrough.sys. But same result.

I'm not sure why FltCreateFile() would fail but ZwCreateFile would work. I need to send more FSCTL to NTFS ultimately and would like to avoid sending IRP.

Any idea what I'm doing wrong.

Comments

  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,190
    STATUS_INVALID_PARAMETER.

    I'd guess that FltObjects->Instance isn't an instance associated with "E:\".
    If NULL works as a parameter then that is it confirmed.

    > I'm seeing error when I call FltCreateFile/Ex() function from
    > Minifilter. I'm new to this and adding changes to Passthrough WDK
    > example. What I would like to do is to send DeviceIOCtl(FSCTL_*) to
    > NTFS and get data from it.
    >
    > Here is the code I'm using.
    >
    > ++++
    > NTSTATUS GetNTFSVolData(
    > __in PCFLT_RELATED_OBJECTS FltObjects
    > )
    > {
    > NTSTATUS ntStatus;
    > ULONG dwOutputSize = 0;
    > // UCHAR volDataBuffer[sizeof(NTFS_VOLUME_DATA_BUFFER)];
    > // PNTFS_VOLUME_DATA_BUFFER pNtfsVolData =
    > (PNTFS_VOLUME_DATA_BUFFER)volDa> taBuffer;
    > NTFS_VOLUME_DATA_BUFFER NtfsVolData;
    > ULONG dwInputSize = sizeof(NTFS_VOLUME_DATA_BUFFER);
    > ULONG dwBytesPerCluster = 0;
    > PFLT_FILE_NAME_INFORMATION nameInfo;
    >
    > HANDLE hFile;
    > PFILE_OBJECT fileObject;
    > UNICODE_STRING fileName;
    > OBJECT_ATTRIBUTES objectAttributes;
    > IO_STATUS_BLOCK ioStatus;
    >
    > DbgPrint("Opening volume: %wZ\n", gVolumeRoot);
    > // This prints "\DosDevices\E:"
    > InitializeObjectAttributes( &objectAttributes, &gVolumeRoot,
    > OBJ_KERNEL_HA> NDLE | OBJ_CASE_INSENSITIVE, NULL, NULL );
    >
    > // ntStatus = FltCreateFileEx(gFilterHandle, FltObjects->Instance,
    > &hFile,> &fileObject, FILE_READ_ATTRIBUTES,
    > ntStatus = FltCreateFile(gFilterHandle, FltObjects->Instance, &hFile,
    > FILE> _READ_ATTRIBUTES,
    > &objectAttributes, &ioStatus, (PLARGE_INTEGER) NULL,
    > FILE_ATTRIBUT> E_NORMAL,
    > FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0L, NULL, 0L, 0);
    > // ntStatus is set to 0xc000000d
    >
    > // ZwCreateFile() would work.
    > // ntStatus = ZwCreateFile(&hFile, FILE_READ_ATTRIBUTES,
    > &objectAttributes> , &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL,
    > // FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
    > FILE_NON_DIRECTORY_FILE> , NULL, 0);
    > ntStatus = ObReferenceObjectByHandle(hFile, FILE_READ_ATTRIBUTES,
    > *IoFileO> bjectType, KernelMode, (PVOID*)&fileObject, NULL); // This
    > would also work.
    > ntStatus = FltDeviceIoControlFile(FltObjects->Instance, fileObject,
    > FSCTL> _GET_NTFS_VOLUME_DATA,
    > (PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize,
    > &dwOutputSiz> e);
    > // This call to FltDeviceIoControlFile() would return ntStatus =
    > 0xc00000> 02.
    >
    >
    > // FltOpenVolume() would be successful.
    > ntStatus = FltOpenVolume(FltObjects->Instance, &hFile, &fileObject);
    > if( NT_SUCCESS(ntStatus) ) {
    > DbgPrint("FltOpenVolume() successful.\n");
    >
    > // But this call to FltDeviceIoControlFile() would return ntStatus
    > = 0> xc0000002.
    > ntStatus = FltDeviceIoControlFile(FltObjects->Instance,
    > fileObject, FS> CTL_GET_NTFS_VOLUME_DATA,
    > (PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize,
    > &dwOutputSiz> e);
    > if( NT_SUCCESS(ntStatus) )
    > DbgPrint("FltDeviceIoControlFile::FSCTL_GET_NTFS_VOLUME_DATA
    > succ> essful.\n");
    > else {
    > DbgPrint("FltDeviceIoControlFile::FSCTL_GET_NTFS_VOLUME_DATA
    > retu> rn status: 0x%x\n", ntStatus);
    > // Query API would work fine.
    > ntStatus = FltQueryVolumeInformation(FltObjects->Instance,
    > &ioStat> us, (PVOID)&fsVolSize,
    > sizeof(fsVolSize), FileFsSizeInformation);
    > if( NT_SUCCESS(ntStatus) ) {
    > DbgPrint("FltQueryVolumeInformation successful.\n");
    > DbgPrint("Cluster size: %d\n",
    > fsVolSize.SectorsPerAllocationU> nit * fsVolSize.BytesPerSector);
    > }
    > else
    > DbgPrint("FltQueryVolumeInformation return status:
    > 0x%x\n", nt> Status);
    > }
    > FltClose(hFile);
    > }
    > }
    > ++++++
    >
    > I'm calling the above function, GetNTFSVolData(), from Pre
    > IRP_MJ_WRITE and PtInstanceTeardownStart() in Passthrough.sys. But
    > same result.
    >
    > I'm not sure why FltCreateFile() would fail but ZwCreateFile would
    > work. I need to send more FSCTL to NTFS ultimately and would like to
    > avoid sending IRP.
    >
    > Any idea what I'm doing wrong.
  • M_DM_D Member Posts: 34
    I tried that but it didn't work.

    The following code works fine too.

    ntStatus = FltOpenVolume(FltObjects->Instance, &hFile, &fileObject);
    ntStatus = FltQueryVolumeInformation(FltObjects->Instance, &ioStatus, (PVOID)&fsVolSize,
    sizeof(fsVolSize), FileFsSizeInformation);
    // return success; You can calculate cluster size.
    Using above code I can get cluster size from NTFS. So I thought, may be Insatnce is OK and I don't have to save and retrieve context.

    But following code using FSCTL won't work.
    ntStatus = FltOpenVolume(FltObjects->Instance, &hFile, &fileObject);
    ntStatus = FltDeviceIoControlFile(FltObjects->Instance, fileObject, FSCTL_GET_NTFS_VOLUME_DATA,
    (PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize, &dwOutputSize);
    // This would return ntStatus = 0xc0000002

    Anothre method I tried ...
    InitializeObjectAttributes( &objectAttributes, &gVolumeRoot, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL );
    ntStatus = ZwCreateFile(&hFile, FILE_READ_ATTRIBUTES, &objectAttributes, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL,
    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
    // Successful
    ntStatus = ObReferenceObjectByHandle(hFile, FILE_READ_ATTRIBUTES, *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL);
    // Successful too.
    ntStatus = FltDeviceIoControlFile(FltObjects->Instance, fileObject, FSCTL_GET_NTFS_VOLUME_DATA,
    (PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize, &dwOutputSize);
    // return ntStatus = 0xc0000002

    Another method ....
    InitializeObjectAttributes( &objectAttributes, &gVolumeRoot, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL );
    ntStatus = FltCreateFile(gFilterHandle, NULL, /*FltObjects->Instance,*/ &hFile, FILE_READ_ATTRIBUTES,
    &objectAttributes, &ioStatus, (PLARGE_INTEGER) NULL, FILE_ATTRIBUTE_NORMAL,
    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0L, NULL, 0L, 0);
    // return ntStatus = 0xc000000d
  • Ted_Hess-3Ted_Hess-3 Member Posts: 3
    You are missing a parameter to FltCreateFile. It takes 14 params, you only have 13. Perhaps
    CreateDisposition - try FILE_OPEN.

    /ted

    wrote in message news:[email protected]
    >I tried that but it didn't work.
    >
    > The following code works fine too.
    >
    > ntStatus = FltOpenVolume(FltObjects->Instance, &hFile, &fileObject);
    > ntStatus = FltQueryVolumeInformation(FltObjects->Instance, &ioStatus, (PVOID)&fsVolSize,
    > sizeof(fsVolSize), FileFsSizeInformation);
    > // return success; You can calculate cluster size.
    > Using above code I can get cluster size from NTFS. So I thought, may be Insatnce is OK and I don't
    > have to save and retrieve context.
    >
    > But following code using FSCTL won't work.
    > ntStatus = FltOpenVolume(FltObjects->Instance, &hFile, &fileObject);
    > ntStatus = FltDeviceIoControlFile(FltObjects->Instance, fileObject, FSCTL_GET_NTFS_VOLUME_DATA,
    > (PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize, &dwOutputSize);
    > // This would return ntStatus = 0xc0000002
    >
    > Anothre method I tried ...
    > InitializeObjectAttributes( &objectAttributes, &gVolumeRoot, OBJ_KERNEL_HANDLE |
    > OBJ_CASE_INSENSITIVE, NULL, NULL );
    > ntStatus = ZwCreateFile(&hFile, FILE_READ_ATTRIBUTES, &objectAttributes, &ioStatus, NULL,
    > FILE_ATTRIBUTE_NORMAL,
    > FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0);
    > // Successful
    > ntStatus = ObReferenceObjectByHandle(hFile, FILE_READ_ATTRIBUTES, *IoFileObjectType, KernelMode,
    > (PVOID*)&fileObject, NULL);
    > // Successful too.
    > ntStatus = FltDeviceIoControlFile(FltObjects->Instance, fileObject, FSCTL_GET_NTFS_VOLUME_DATA,
    > (PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize, &dwOutputSize);
    > // return ntStatus = 0xc0000002
    >
    > Another method ....
    > InitializeObjectAttributes( &objectAttributes, &gVolumeRoot, OBJ_KERNEL_HANDLE |
    > OBJ_CASE_INSENSITIVE, NULL, NULL );
    > ntStatus = FltCreateFile(gFilterHandle, NULL, /*FltObjects->Instance,*/ &hFile,
    > FILE_READ_ATTRIBUTES,
    > &objectAttributes, &ioStatus, (PLARGE_INTEGER) NULL, FILE_ATTRIBUTE_NORMAL,
    > FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0L, NULL, 0L, 0);
    > // return ntStatus = 0xc000000d
    >
    >
  • Alex_CarpAlex_Carp Member Posts: 1,016
    Try this instead (using FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES to get
    the volume handle and FltFsControlFile instead of FltDeviceIoControlFile):

    InitializeObjectAttributes( &objectAttributes, &gVolumeRoot,
    OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL );

    // ntStatus = FltCreateFileEx(gFilterHandle, FltObjects->Instance,
    &hFile, &fileObject, FILE_READ_ATTRIBUTES,
    ntStatus = FltCreateFile(gFilterHandle, FltObjects->Instance, &hFile,
    FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
    &objectAttributes, &ioStatus, (PLARGE_INTEGER) NULL,
    FILE_ATTRIBUTE_NORMAL,
    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0L, NULL, 0L, 0);
    // ntStatus is set to 0xc000000d

    // ZwCreateFile() would work.
    // ntStatus = ZwCreateFile(&hFile, FILE_READ_ATTRIBUTES,
    &objectAttributes, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL,
    // FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
    FILE_NON_DIRECTORY_FILE, NULL, 0);
    ntStatus = ObReferenceObjectByHandle(hFile, FILE_READ_ATTRIBUTES,
    *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL); // This would
    also work.
    ntStatus = FltFsControlFile(FltObjects->Instance, fileObject,
    FSCTL_GET_NTFS_VOLUME_DATA,
    (PVOID)NULL, 0, (PVOID)&NtfsVolData, dwInputSize,
    &dwOutputSize);


    Thanks,
    Alex.
  • M_DM_D Member Posts: 34
    Alex,

    I worked on changing code as per your suggestion and found that along with setting ACCESS_MASK to use FILE_WRITE_ATTRIBUTES, I also had to set 11th arg CreateOptions to FILE_NON_DIRECTORY_FILE for FltCreateFile() to work. Then I also has to use FltFsControlFile(FSCTL_GET_NTFS_VOLUME_DATA) to get cluster size. FltDeviceIoControlFile() would fail with 0xc0000002. I got similar result with ZwCreateFile() and FltFsControlFile(). It worked too.
  • M_DM_D Member Posts: 34
    I made more changes to the driver by adding call to FltFsControlFile(FSCTL_GET_RETRIEVAL_POINTERS) in Post callback for IRP_MJ_WRITE. I would get the filename using FltGetFileNameInformation(); FltParseFileNameInformation() in callback and then I would issue call to FltFsControlFile(FSCTL_GET_RETRIEVAL_POINTERS) in the callback fucntion. I'm tracking writes to file E:\foo.txt. What I found that if there is heavy IO to the file (E:\foo.txt), the FltFsControlFile(FSCTL_GET_RETRIEVAL_POINTERS) would fail with 0x80000005 (access denied). I mean if I copy a 1 GB file C:\frr.txt to E:\foo.txt, FltFsControlFile() would fail. But if I'm appending (type C:\ree.txt >> E:\foo.txt), FltFsControlFile(FSCTL_GET_RETRIEVAL_POINTERS) won't fail. When it won't fail, I can see the writes are coming in and file is growing. The size, Extents[0].NextVcn - Extent[0].StartingVcn, would grow every few writes.

    My aim is to get cluster number on the volume for each IRP_MJ_WRITE. I would like to map the write length (Data->Iopb->Parameters.Write.Length) and offset (Data->Iopb->Parameters.Write.ByteOffset) in the file (foo.txt) for each IRP_MJ_WRITE to LCN on the volume. But I'm not sure why I get access_denied error for heavy IO.

    I would also like yours opinion if the method I'm planning to use to get LCN would work or not.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Developing Minifilters 24 May 2021 Live, Online
Writing WDF Drivers 14 June 2021 Live, Online
Internals & Software Drivers 27 September 2021 Live, Online
Kernel Debugging TBD 2021 Live, Online