I am working on file virtualization and versioning project. For that, I need to access the logical blocks of file contents directly without copying into memory. Anyone could you help me with code snippets that works on my 64 bit windows?
I tried the following code to access the MFT file. But it responds like 'Access denied' even though I ran with administrator privileges.
#include<windows.h>
#include<stdio.h>
#include<winioctl.h>
// Format the Win32 system error code to string
void ErrorMessage(DWORD dwCode);
int wmain(int argc, WCHAR **argv){
HANDLE hVolume;
WCHAR lpDrive[] = L"\\\\.\\C:";
PNTFS_VOLUME_DATA_BUFFER ntfsVolData = {0};
BOOL bDioControl = FALSE;
DWORD dwWritten = 0;
hVolume = CreateFile(lpDrive, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if(hVolume == INVALID_HANDLE_VALUE){
wprintf(L"CreateFile() failed!\n");
ErrorMessage(GetLastError());
if(CloseHandle(hVolume) != 0)
wprintf(L"hVolume handle was closed successfully!\n");
else{
wprintf(L"Failed to close hVolume handle!\n");
ErrorMessage(GetLastError());
}
}
else
wprintf(L"CreateFile() is pretty fine!\n");
ntfsVolData = (PNTFS_VOLUME_DATA_BUFFER)malloc(sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA));
bDioControl = DeviceIoControl(hVolume, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, ntfsVolData,sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA), &dwWritten, NULL);
if(bDioControl == 0){
wprintf(L"DeviceIoControl() failed!\n");
ErrorMessage(GetLastError());
if(CloseHandle(hVolume) != 0)
wprintf(L"hVolume handle was closed successfully!\n");
else{
wprintf(L"Failed to close hVolume handle!\n");
ErrorMessage(GetLastError());
}
}
getchar();
}
void ErrorMessage(DWORD dwCode){
DWORD dwErrCode = dwCode;
DWORD dwNumChar;
LPWSTR szErrString = NULL; // will be allocated and filled by FormatMessage
dwNumChar = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM, 0, dwErrCode, 0, (LPWSTR)&szErrString, 0,0 ); // since getting message from system tables
if(dwNumChar == 0)wprintf(L"FormatMessage() failed, error %u\n", GetLastError());//else//wprintf(L"FormatMessage() should be fine!\n");
wprintf(L"Error code %u:\n %s\n", dwErrCode, szErrString) ;// This buffer used by FormatMessage()
if(LocalFree(szErrString) != NULL)
wprintf(L"Failed to free up the buffer, error %u\n", GetLastError());//else//wprintf(L"Buffer has been freed\n");
}
CreateFile() failed!
Error code 5:
Access is denied.
hVolume handle was closed successfully!
DeviceIoControl() failed!
Error code 6:
The handle is invalid.
hVolume handle was closed successfully!
Thank you
Admin privileges aren't enough. What you need to do is request backup and restore privileges for your process. MSDN has sample code. Keep in mind that you probably need both
SE_BACKUP_NAMEandSE_RESTORE_NAME.The process is a bit cumbersome:
OpenProcessTokenon your process withTOKEN_ADJUST_PRIVILEGESLookupPrivilegeValueto get the privilege based on the string constants (one forSE_BACKUP_NAME, one forSE_RESTORE_NAME)AdjustTokenPrivilegesto acquire the backup and restore privilegesIf you do this properly, the rest of your code should work. To actually enumerate the MFT, you'll want to use the
FSCTL_ENUM_USN_DATAvariant ofDeviceIOControl.