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

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.

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.

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

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:xxxxx@ntfsd…
>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
>
>

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.

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.

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.