Not perfect, but works...
Code: Select allNTSTATUS GetFileVolumeHandle(
IN UNICODE_STRING *NativePath,
OUT HANDLE *VolumeHandle)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
WCHAR VolumeLetter[8];
UNICODE_STRING VolumeName;
OBJECT_ATTRIBUTES ObjectAttributes = {0};
IO_STATUS_BLOCK IoStatusBlock;
__try
{
if(NativePath == NULL)
return STATUS_INVALID_PARAMETER_1;
if(NativePath->Buffer == NULL ||
NativePath->Length == 0)
{
return STATUS_INVALID_PARAMETER_1;
}
if(VolumeHandle == NULL)
return STATUS_INVALID_PARAMETER_2;
if(NativePath->Buffer[0] != L'\\' ||
NativePath->Buffer[1] != L'?' ||
NativePath->Buffer[2] != L'?' ||
NativePath->Buffer[3] != L'\\' ||
NativePath->Buffer[5] != L':')
{
return STATUS_OBJECT_PATH_SYNTAX_BAD;
}
*VolumeHandle = NULL;
RtlZeroMemory(
VolumeLetter,
sizeof(VolumeLetter));
NtStatus = StringCchPrintfW(
VolumeLetter,
sizeof(VolumeLetter),
L"\\??\\%c:",
NativePath->Buffer[4]);
if(SUCCEEDED(NtStatus))
{
RtlInitUnicodeString(
&VolumeName,
VolumeLetter);
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.ObjectName = &VolumeName;
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
NtStatus = NtCreateFile(
VolumeHandle, // FileHandle
GENERIC_READ |
GENERIC_WRITE, // DesiredAccess
&ObjectAttributes, // ObjectAttributes
&IoStatusBlock, // IoStatusBlock
NULL, // AllocationSize OPTIONAL
0, // FileAttributes
FILE_SHARE_READ |
FILE_SHARE_WRITE, // ShareAccess
FILE_OPEN, // CreateDisposition
0, // CreateOptions
NULL, // EaBuffer OPTIONAL
0); // EaLength
if(NtStatus)
{
DbgPrint((
">> GetFileVolumeHandle - NtCreateFile - %.8X\n",
NtStatus));
}
}
}
__except(GetExceptionCode() ==
EXCEPTION_BREAKPOINT ?
EXCEPTION_CONTINUE_SEARCH :
EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint((
">> GetFileVolumeHandle - %.8X\n",
GetExceptionCode()));
return GetExceptionCode();
}
return NtStatus;
}
NTSTATUS GetFilePhysicalOffset(
IN UNICODE_STRING *NativePath,
OUT LONGLONG *PhysicalOffset)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
HANDLE FileHandle;
HANDLE VolumeHandle;
ULONG RetrievalPointersLength = PAGE_SIZE;
OBJECT_ATTRIBUTES ObjectAttributes = {0};
IO_STATUS_BLOCK IoStatusBlock;
STARTING_VCN_INPUT_BUFFER StartingVcn = {0};
RETRIEVAL_POINTERS_BUFFER *RetrievalPointers = NULL;
NTFS_VOLUME_DATA_BUFFER VolumeData;
VOLUME_LOGICAL_OFFSET VolumeLogicalOffset;
VOLUME_PHYSICAL_OFFSETS VolumePhysicalOffsets;
__try
{
if(NativePath == NULL)
return STATUS_INVALID_PARAMETER_1;
if(NativePath->Buffer == NULL ||
NativePath->Length == 0)
{
return STATUS_INVALID_PARAMETER_1;
}
if(PhysicalOffset == NULL)
return STATUS_INVALID_PARAMETER_2;
if(NativePath->Buffer[0] != L'\\' ||
NativePath->Buffer[1] != L'?' ||
NativePath->Buffer[2] != L'?' ||
NativePath->Buffer[3] != L'\\' ||
NativePath->Buffer[5] != L':')
{
return STATUS_OBJECT_PATH_SYNTAX_BAD;
}
*PhysicalOffset = 0;
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.ObjectName = NativePath;
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
NtStatus = NtCreateFile(
&FileHandle, // FileHandle
GENERIC_READ |
GENERIC_WRITE, // DesiredAccess
&ObjectAttributes, // ObjectAttributes
&IoStatusBlock, // IoStatusBlock
NULL, // AllocationSize OPTIONAL
0, // FileAttributes
FILE_SHARE_READ |
FILE_SHARE_WRITE, // ShareAccess
FILE_OPEN, // CreateDisposition
0, // CreateOptions
NULL, // EaBuffer OPTIONAL
0); // EaLength
if(NtStatus)
{
DbgPrint((
">> GetFilePhysicalOffset - NtCreateFile - %.8X\n",
NtStatus));
}
if(NT_SUCCESS(NtStatus))
{
do
{
RetrievalPointers = RtlAllocateMemory(RetrievalPointersLength);
if(RetrievalPointers)
{
NtStatus = NtFsControlFile(
FileHandle, // FileHandle
NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&IoStatusBlock, // IoStatusBlock
FSCTL_GET_RETRIEVAL_POINTERS, // FsControlCode
&StartingVcn, // InputBuffer
sizeof(STARTING_VCN_INPUT_BUFFER), // InputBufferLength
RetrievalPointers, // OutputBuffer
RetrievalPointersLength); // OutputBufferLength
if(NtStatus == STATUS_INFO_LENGTH_MISMATCH)
{
RtlFreeMemory(RetrievalPointers);
RetrievalPointersLength *= 2;
}
else if(NT_ERROR(NtStatus))
{
DbgPrint((
">> GetFilePhysicalOffset - FSCTL_GET_RETRIEVAL_POINTERS - %.8X\n",
NtStatus));
RtlFreeMemory(RetrievalPointers);
NtClose(FileHandle);
return NtStatus;
}
}
else
{
NtClose(FileHandle);
return STATUS_INSUFFICIENT_RESOURCES;
}
} while(NtStatus == STATUS_INFO_LENGTH_MISMATCH);
NtStatus = GetFileVolumeHandle(
NativePath, // NativePath
&VolumeHandle); // VolumeHandle
if(NT_SUCCESS(NtStatus))
{
NtStatus = NtFsControlFile(
VolumeHandle, // FileHandle
NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&IoStatusBlock, // IoStatusBlock
FSCTL_GET_NTFS_VOLUME_DATA, // FsControlCode
NULL, // InputBuffer
0, // InputBufferLength
&VolumeData, // OutputBuffer
sizeof(NTFS_VOLUME_DATA_BUFFER)); // OutputBufferLength
if(NtStatus)
{
DbgPrint((
">> GetFilePhysicalOffset - FSCTL_GET_NTFS_VOLUME_DATA - %.8X\n",
NtStatus));
}
if(NT_SUCCESS(NtStatus))
{
VolumeLogicalOffset.LogicalOffset = RetrievalPointers->Extents[0].Lcn.QuadPart *
VolumeData.BytesPerCluster;
NtStatus = NtDeviceIoControlFile(
VolumeHandle, // FileHandle
NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&IoStatusBlock, // IoStatusBlock
IOCTL_VOLUME_LOGICAL_TO_PHYSICAL, // IoControlCode
&VolumeLogicalOffset, // InputBuffer
sizeof(VOLUME_LOGICAL_OFFSET), // InputBufferLength
&VolumePhysicalOffsets, // OutputBuffer
sizeof(VOLUME_PHYSICAL_OFFSETS)); // OutputBufferLength
if(NtStatus)
{
DbgPrint((
">> GetFilePhysicalOffset - IOCTL_VOLUME_LOGICAL_TO_PHYSICAL - %.8X\n",
NtStatus));
}
if(NT_SUCCESS(NtStatus))
{
*PhysicalOffset = (LONGLONG)(VolumePhysicalOffsets.PhysicalOffset[0].Offset /
VolumeData.BytesPerSector);
}
}
NtClose(VolumeHandle);
}
NtClose(FileHandle);
RtlFreeMemory(RetrievalPointers);
}
}
__except(GetExceptionCode() ==
EXCEPTION_BREAKPOINT ?
EXCEPTION_CONTINUE_SEARCH :
EXCEPTION_EXECUTE_HANDLER)
{
if(FileHandle)
NtClose(FileHandle);
if(VolumeHandle)
NtClose(VolumeHandle);
if(RetrievalPointers)
RtlFreeMemory(RetrievalPointers);
DbgPrint((
">> GetFilePhysicalOffset - %.8X\n",
GetExceptionCode()));
return GetExceptionCode();
}
return NtStatus;
}