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.
0 ·
Comments
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.
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
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
>
>
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.
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.
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.