I am trying out VirtualDisk APIs,
So far I am able to Open a VHDX file, get some of the properties by using GetVirtualDiskInformation.
But I am not able to get RCT information and ChangedAreas.
The first call to GetVirtualDiskInformation is successful.
The second call to GetVirtualDiskInformation fails with insufficient buffer ERROR_INSUFFICIENT_BUFFER(122).
Call to QueryChangesVirtualDisk fails with ERROR_INVALID_HANDLE(6).
The RCT ID hardcoded in the code is proper, I am able to get the ChangedAreas using WMI Explorer.
Attached screenshot of the same.
If it is invalid handle, then GetVirtualDiskInformation should also throw the same error?
#include "pch.h"
#include <iostream>
#include <string>
#include <cstdlib>
#define WINVER _WIN32_WINNT_WIN10
#include <windows.h>
#include <winioctl.h>
#include <virtdisk.h>
#include <initguid.h>
#pragma comment(lib, "virtdisk.lib")
DEFINE_GUID(VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT, 0xec984aec, 0xa0f9, 0x47e9, 0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b);
DEFINE_GUID(VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN, 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
int main()
{
HANDLE vhdHandle;
_VIRTUAL_STORAGE_TYPE storageType;
storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;
wchar_t path[] = L"C:\\Hyper-V\\Virtual Hard Disks\\Lacazette\\Windows2016.vhdx";
VIRTUAL_DISK_ACCESS_MASK mask = VIRTUAL_DISK_ACCESS_GET_INFO;
PGET_VIRTUAL_DISK_INFO diskInfo;
ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);
std::wcout << "size of diskinfo structure " << diskInfoSize << std::endl;
diskInfo = (PGET_VIRTUAL_DISK_INFO)malloc(diskInfoSize);
if (diskInfo == NULL)
{
std::cout << "Failed to malloc disk info, ret=" << std::endl;
return 0;
}
std::wcout << "Opening Virtual disk " << path << std::endl;
DWORD res = OpenVirtualDisk(&storageType, path,
VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS,
NULL,
&vhdHandle);
if (res != ERROR_SUCCESS)
{
std::cout << "Failed to open disk, ret=" << res << std::endl;
return 0;
}
diskInfo->Version = GET_VIRTUAL_DISK_INFO_SIZE;
res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
if (res != ERROR_SUCCESS)
{
std::cout << "Failed to GET_VIRTUAL_DISK_INFO_SIZE, ret=" << res << std::endl;
}
long physicalSize = diskInfo->Size.PhysicalSize;
long virtualSize = diskInfo->Size.VirtualSize;
long sectorSize = diskInfo->Size.SectorSize;
long blockSize = diskInfo->Size.BlockSize;
std::wcout << "physicalSize :" << physicalSize << std::endl;
std::wcout << "virtualSize :" << virtualSize << std::endl;
std::wcout << "sectorSize :" << sectorSize << std::endl;
std::wcout << "blockSize :" << blockSize << std::endl;
diskInfo->Version = GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
if (res != ERROR_SUCCESS)
{
std::cout << "Failed to GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE, ret=" << res << std::endl;
}
std::cout << "\nrct id:" << diskInfo->ChangeTrackingState.MostRecentId << std::endl;
std::cout << "\nQuerying for changed disk areas...\n" << std::endl;
wchar_t rctId[] = L"rctX:c2eb01d9:ccb1:405d:acb6:f0e76d055906:00000001";
ULONG64 byteOffset = 0L;
ULONG64 byteLength = 19327352832;
QUERY_CHANGES_VIRTUAL_DISK_RANGE* changedAreas = NULL;
ULONG rangeCount = 0L;
ULONG64 processedLength = 0L;
res = QueryChangesVirtualDisk(&vhdHandle, rctId, byteOffset, byteLength,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
changedAreas, &rangeCount, &processedLength);
if (res != ERROR_SUCCESS)
{
std::cout << "Failed to get chanegd areas, ret=" << res << std::endl;
if (vhdHandle != NULL)
{
CloseHandle(vhdHandle);
std::cout << "closing handle!" <<std::endl;
}
return 0;
}
std::cout << "Total changed areas:" << rangeCount << std::endl;
std::cout << "Total processed length:" << processedLength << std::endl;
if (vhdHandle != NULL)
{
CloseHandle(vhdHandle);
}
return 0;
}
Output of the program:
Screenshot of wmi explorer output.
Here's something that more or less works.. the issue was with the format of the rctid which I was passing to the QueryChangesVirtualDisk API. Should be as in the below sample. I was enclosing it inside the braces {} which was not correct. The below code returns RCT changed blocks successfully
Another observation is that it seems the ChangeTrackingState.MostRecentId which we get from GetVirtualDiskInformation for a offline vhdx is one more than what we initially created while the VM was up.. For example, I created a reference point with rctid: rctX:4abdf273:7e45:4748:85af:78ec4af82ebf:00000000 Now when the vhdx is offline and if I query the ChangeTrackingState.MostRecentId it is giving me this : rctX:4abdf273:7e45:4748:85af:78ec4af82ebf:00000001 which fails the QueryChangesVirtualDisk with invalid rctid error. The below function expects the user to pass the correct rctid externally. Apparently, the Get-VmReferencePoints still lists only the earlier 00000 reference point.. This one (00001) seems to be returned only by the GetVirtualDiskInformation API
Finally, for the other issue of getting access denied with a live VM, it seems we have to set the VIRTUAL_DISK_ACCESS_MASK in OpenVirtualDisk to 0 along with version 3 of OPEN_VIRTUAL_DISK_PARAMETERS as shown below. With this we we are able to query RCT CBT from a live checkpointed VM's base disk. Got clarified from https://github.com/cloudbase/rct-service/issues/1
#include <windows.h>
#include <virtdisk.h>
#include <iostream>
bool QueryRCTData(const std::wstring& file, const std::wstring& rctid)
{
DWORD fRet;
HANDLE hVHD;
VIRTUAL_STORAGE_TYPE vst =
{
VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN,
{0xEC984AEC, 0xA0F9, 0x47e9, { 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B }}
};
OPEN_VIRTUAL_DISK_PARAMETERS params = { 0 };
params.Version = OPEN_VIRTUAL_DISK_VERSION_3;
DWORD fRet = OpenVirtualDisk(
&vst,
file.c_str(),
(VIRTUAL_DISK_ACCESS_MASK) 0, //VIRTUAL_DISK_ACCESS_ALL, //VIRTUAL_DISK_ACCESS_GET_INFO,
OPEN_VIRTUAL_DISK_FLAG_NONE,
¶ms,
&hvhd);
if (fRet != ERROR_SUCCESS)
{
std::cout << "OpenVirtualDisk failed " << fRet << "\n";
return false;
}
//query rctid
WCHAR vdinfo[2048];
ZeroMemory(vdinfo, sizeof(vdinfo));
((GET_VIRTUAL_DISK_INFO *)vdinfo)->Version = GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
ULONG vdinfoSize = sizeof(vdinfo);
fRet = GetVirtualDiskInformation(
hVHD,
&vdinfoSize,
(PGET_VIRTUAL_DISK_INFO)vdinfo,
NULL);
if (fRet != ERROR_SUCCESS)
{
std::cout << "GetVirtualDiskInformation GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE failed " << fRet << "\n";
return false;
}
std::wcout << "RCT ID : " << std::wstring(((GET_VIRTUAL_DISK_INFO *)vdinfo)->ChangeTrackingState.MostRecentId) << "\n";
//query disk length
ZeroMemory(vdinfo, sizeof(vdinfo));
((GET_VIRTUAL_DISK_INFO *)vdinfo)->Version = GET_VIRTUAL_DISK_INFO_SIZE;
vdinfoSize = sizeof(vdinfo);
fRet = GetVirtualDiskInformation(
hVHD,
&vdinfoSize,
(PGET_VIRTUAL_DISK_INFO)vdinfo,
NULL);
if (fRet != ERROR_SUCCESS)
{
std::cout << "GetVirtualDiskInformation GET_VIRTUAL_DISK_INFO_SIZE failed " << fRet << "\n";
return false;
}
std::cout << "Disk length : " << ((GET_VIRTUAL_DISK_INFO *)vdinfo)->Size.VirtualSize << "\n";
ULONG RangeCount = 1024;
ULONG64 ProcessedLength = 0;
QUERY_CHANGES_VIRTUAL_DISK_RANGE Ranges[1024] = { 0 };
fRet = QueryChangesVirtualDisk(
hVHD,
rctid.c_str(), //((GET_VIRTUAL_DISK_INFO *)vdinfo)->ChangeTrackingState.MostRecentId,
0,
((GET_VIRTUAL_DISK_INFO *)vdinfo)->Size.VirtualSize,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
Ranges,
&RangeCount,
&ProcessedLength);
if (fRet != ERROR_SUCCESS)
{
std::cout << "QueryChangesVirtualDisk failed " << fRet << "\n";
return false;
}
std::cout << "RangeCount : " << RangeCount << "\n";
std::cout << "ProcessedLength : " << ProcessedLength << "\n";
for (int i = 0; i < RangeCount; i++)
{
std::cout << "Range offset : " << Ranges[i].ByteOffset << "\n";
std::cout << "Range length : " << Ranges[i].ByteLength << "\n";
}
CloseHandle(hVHD);
return true;
}
int main(void)
{
QueryRCTData(L"D:\\BACKUP\\INCR\\Virtual Hard Disks\\2019.vhdx", L"rctX:4abdf273:7e45:4748:85af:78ec4af82ebf:00000000");
return 0;
}
#pragma comment(lib, "virtdisk.lib")
Here is my working code for getting changed blocks from offline VHDX.
(most credit goes to Neelabh Mam who posted above)
Hope it might help someone struggling to make RCT work with C++.
BOOLEAN VHDWRAP_CONVENTION CloseVhd(HANDLE hDisk)
{
return CloseHandle(hDisk) == TRUE;
}
HANDLE VHDWRAP_CONVENTION OpenVhdx(PCWSTR path, unsigned mask)
{
DWORD fRet;
HANDLE hVHD;
VIRTUAL_STORAGE_TYPE vst =
{
VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN,
{0xEC984AEC, 0xA0F9, 0x47e9, { 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B }}
};
OPEN_VIRTUAL_DISK_PARAMETERS params = { 0 };
params.Version = OPEN_VIRTUAL_DISK_VERSION_3;
fRet = OpenVirtualDisk(
&vst,
path, (VIRTUAL_DISK_ACCESS_MASK)mask,
OPEN_VIRTUAL_DISK_FLAG_NONE,
¶ms,
&hVHD);
g_dwLastError = fRet;
return hVHD;
}
VHDWRAP_API BOOLEAN VHDWRAP_CONVENTION EnableVhdRct(HANDLE hVHD)
{
SET_VIRTUAL_DISK_INFO vdinfo;
vdinfo.Version = SET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
vdinfo.ChangeTrackingEnabled = TRUE;
DWORD fRet = SetVirtualDiskInformation(hVHD, &vdinfo);
g_dwLastError = fRet;
return fRet == 0;
}
VHDWRAP_API BOOLEAN VHDWRAP_CONVENTION DisableVhdRct(HANDLE hVHD)
{
SET_VIRTUAL_DISK_INFO vdinfo;
vdinfo.Version = SET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
vdinfo.ChangeTrackingEnabled = FALSE;
DWORD fRet = SetVirtualDiskInformation(hVHD, &vdinfo);
g_dwLastError = fRet;
return fRet == 0;
}
VHDWRAP_API BOOLEAN VHDWRAP_CONVENTION QueryVhdRct(HANDLE hVHD, LPCWSTR szRctId)
{
//query rctid
WCHAR vdinfo[1024];
ZeroMemory(vdinfo, sizeof(vdinfo));
((GET_VIRTUAL_DISK_INFO*)vdinfo)->Version = GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE;
ULONG vdinfoSize = sizeof(vdinfo);
DWORD fRet = GetVirtualDiskInformation(
hVHD,
&vdinfoSize,
(PGET_VIRTUAL_DISK_INFO)vdinfo,
NULL);
g_dwLastError = fRet;
if (fRet != ERROR_SUCCESS)
{
std::cout << "GetVirtualDiskInformation GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE failed " << fRet << "\n";
return false;
}
std::wcout << L"RCT status : " << ((((GET_VIRTUAL_DISK_INFO*)vdinfo)->ChangeTrackingState.Enabled) ? L"enabled" : L"disabled") << L"\n";
std::wcout << L"RCT ID : " << std::wstring(((GET_VIRTUAL_DISK_INFO*)vdinfo)->ChangeTrackingState.MostRecentId) << "\n";
std::wcout << L"RCT changes : " << ((((GET_VIRTUAL_DISK_INFO*)vdinfo)->ChangeTrackingState.NewerChanges) ? L"yes": L"no") << "\n";
//query disk length
_GET_VIRTUAL_DISK_INFO sizeInfo;
sizeInfo.Version = GET_VIRTUAL_DISK_INFO_SIZE;
vdinfoSize = sizeof(sizeInfo);
fRet = GetVirtualDiskInformation(
hVHD,
&vdinfoSize,
(PGET_VIRTUAL_DISK_INFO)&sizeInfo,
NULL);
g_dwLastError = fRet;
if (fRet != ERROR_SUCCESS)
{
std::cout << "GetVirtualDiskInformation GET_VIRTUAL_DISK_INFO_SIZE failed " << fRet << "\n";
return FALSE;
}
std::cout << "Disk length : " << sizeInfo.Size.VirtualSize << "\n";
const ULONG MaxRangeCount = 4096*1024;
ULONG RangeCount = MaxRangeCount;
ULONG64 ProcessedLength = 0;
QUERY_CHANGES_VIRTUAL_DISK_RANGE* Ranges = new QUERY_CHANGES_VIRTUAL_DISK_RANGE[MaxRangeCount];
fRet = QueryChangesVirtualDisk(
hVHD,
szRctId?szRctId : ((GET_VIRTUAL_DISK_INFO *)vdinfo)->ChangeTrackingState.MostRecentId,
0,
sizeInfo.Size.VirtualSize,
QUERY_CHANGES_VIRTUAL_DISK_FLAG_NONE,
Ranges,
&RangeCount,
&ProcessedLength);
g_dwLastError = fRet;
if (fRet != ERROR_SUCCESS)
{
delete[] Ranges;
std::cout << "QueryChangesVirtualDisk failed " << fRet << " ranges:" << RangeCount << " len " << ProcessedLength << "\n";
return FALSE;
}
if (MaxRangeCount <= RangeCount || ProcessedLength < sizeInfo.Size.VirtualSize)
{
delete[] Ranges;
std::cout << "Not enough resources to capture all the changes \n";
return FALSE;
}
std::cout << "RangeCount : " << RangeCount << "\n";
std::cout << "ProcessedLength : " << ProcessedLength << "\n";
for (int i = 0; i < RangeCount; i++)
{
std::cout << "Range offset : " << Ranges[i].ByteOffset << "\n";
std::cout << "Range length : " << Ranges[i].ByteLength << "\n";
}
delete[] Ranges;
return TRUE;
}
i'm trying to retrive the difference between CurrentTime and LastInputTime and comparing it to another value. CurrentTime is updating correctly but LastInputTime is always a constant value, i dont know why sometimes is 0 , sometimes is other constant value . Any help ?
void localSessions()
{
while (TRUE)
{
cout << "Risky local logon sessions :" << endl;
DWORD pCount;
PWTS_SESSION_INFO pSessionsInfo=new WTS_SESSION_INFO[MAX_SESSIONS];
WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionsInfo, &pCount);
DWORD bytes;
for (auto it = 0; it < pCount; it++)
{
WTSINFOEX* ptr;
if (pSessionsInfo[it].State == WTSActive)
{
INT ret = WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, pSessionsInfo[it].SessionId, WTSSessionInfoEx, (LPSTR*)&ptr, &bytes);
if (ret != 0)
{
INT ret = Gambit::OS::Environment::GetOSVersion();
INT unlocked = 0, unknown = 0;
LONGLONG last_input = ptr->Data.WTSInfoExLevel1.CurrentTime.QuadPart - ptr->Data.WTSInfoExLevel1.LastInputTime.QuadPart;
cout << last_input << endl;
HANDLE token;
WTSQueryUserToken(pSessionsInfo[it].SessionId, &token);
ImpersonateLoggedOnUser(token);
BOOL active;
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &active, 0);
RevertToSelf();
if (!(ret >= 16 && ret <= 19))
{
if ((ptr->Data.WTSInfoExLevel1.SessionFlags & WTS_SESSIONSTATE_UNLOCK) != 0)
{
unlocked = 1;
}
}
else if (ret >= 16 && ret <= 19)
{
if ((ptr->Data.WTSInfoExLevel1.SessionFlags & WTS_SESSIONSTATE_LOCK) != 0)
{
unlocked = 1;
}
}
if (unlocked == 1 && active == FALSE && last_input > 500000000000)
{
cout << "Winstation name : " << ptr->Data.WTSInfoExLevel1.WinStationName << endl;
cout << "UserName name : " << ptr->Data.WTSInfoExLevel1.UserName << endl;
cout << "Domain name : " << ptr->Data.WTSInfoExLevel1.DomainName << endl;
}
cout << endl;
}
}
}
cout << endl << endl;
Sleep(1000);
}
}
LastInputTime is zero for a local session.
For a remote session, when there is no user input after last query of LastInputTime, it will keep unchanged. If there is a user input (like mouse move etc), LastInputTime will update to new time.
If you want to monitor local session user input time you can use GetLastInputInfo instead.
This is all the source code for a program i'm trying to make, and I can't get WriteProcessMemory to work at all. It returns the correct messages, saying that everything went successfully, but nothing actually changes in the game. Does anyone know of a fix?
#include <iostream>
#include <Windows.h>
using namespace std;
// variables
int plcHold = 1;
string hlthLoop = "OFF";
string ammoLoop = "OFF";
DWORD pid;
DWORD playerAddr;
DWORD hlthOffs = 0xF8;
// main function
int main()
{
// finding pid, opening proc, finding player address
HWND hwnd = FindWindowA(NULL, "AssaultCube");
if(hwnd == NULL)
{
cout << "Error; Couldn't find window" << endl;
} else{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(pHandle == NULL)
{
cout << "Error; Couldn't open process" << endl;
} else{
ReadProcessMemory(pHandle, (LPCVOID)0x50F4F4, &playerAddr, sizeof(playerAddr), 0);
if(ReadProcessMemory != FALSE)
{
cout << "Health successfully read!" << endl;
} else{
cout << "Error code " << GetLastError << endl;
}
}
while(plcHold == 1){
cout << "========== *****'s Assault Cube Trainer ==========\n" << endl;
cout << "=============== Health Loop - " << hlthLoop << " ================" << endl;
Sleep(1500);
system("cls");
if(GetAsyncKeyState(0x5A))
{
cout << "Health successfully edited!" << endl;
WriteProcessMemory(pHandle, LPVOID(playerAddr + hlthOffs), 0, sizeof(999), 0);
CloseHandle(pHandle);
}
}
}
return 0;
}
You're passing a null pointer to WriteProcessMemory for the third (lpBuffer) parameter. You have to pass the address of the actual value, not the value itself. If you want to write an integer value, try this:
DWORD val = 0; // or 999?
WriteProcessMemory(
pHandle, static_cast<LPVOID>(playerAddr + hlthOffs),
&val, sizeof(val), 0);
I'm using a file that has MBR code at an offset of 54 bytes.
In the main() function, I'm calling OpenMBbrFile(), then ReadMbrData().
However, I'm not able to read MBR in my Buffer Properly. Please Help Me with the Issue..................................................................................................................................................................................................................................................................................................................................................................................................................
BOOL OpenMbrFile(LPWSTR sPath)
{
cout << "OpenMBR: Create Handle" << endl;
m_hMbrFile = CreateFile(sPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL);
if (m_hMbrFile == INVALID_HANDLE_VALUE) return FALSE;
return TRUE;
}
BOOL CloseMbrFile()
{
cout << "CloseMBR: Closing Handle" << endl;
BOOL bReturn = TRUE;
if (m_hMbrFile != INVALID_HANDLE_VALUE)
bReturn = CloseHandle(m_hMbrFile);
m_hMbrFile = NULL;
cout << "Returning from CloseMBR" << endl;
return bReturn;
}
BOOL ReadMbrData()
{
cout << "ReadMBR: Initialization" << endl;
BOOL bReturn = FALSE;
DWORD dwByteRead = 0;
LARGE_INTEGER filepointer;
filepointer.QuadPart = 54; //MBR data in File at offset 54
BYTE* pBuff = NULL;
pBuff = new BYTE[512];
if (!pBuff)
{
cout << "ReadMBR: Cleaning Stuff up" << endl;
if (pBuff) delete[] pBuff;
CloseMbrFile();
ClosePhysicalDrive();
return bReturn;
}
if (m_hMbrFile == INVALID_HANDLE_VALUE) return FALSE;
cout << "ReadMBR: Setting fp" << endl;
if(!SetFilePointerEx(m_hMbrFile, filepointer, NULL, FILE_BEGIN))
{
cout << "Failed to SetFilePointer ( " << m_hMbrFile << ", " << filepointer.QuadPart << ", 0, FILE_BEGIN)" << endl;
cout << "ReadMBR: Cleaning Stuff up" << endl;
if (pBuff) delete[] pBuff;
CloseMbrFile();
ClosePhysicalDrive();
return bReturn;
}
cout << "ReadMBR: Starting to read File" << endl;
bReturn = ReadFile(m_hMbrFile, pBuff, sizeof(*pBuff), &dwByteRead, 0);
if (bReturn)
bReturn = (sizeof(*pBuff) == dwByteRead); //Need to check this condition? shd it be 512 or size of wud do??
cout << "ReadMBR: Cleaning Stuff up" << endl;
if (pBuff) delete[] pBuff;
CloseMbrFile();
ClosePhysicalDrive();
return bReturn;
}
I get an example of c++ code from msdn, where I try to get info about my partitions, but in this code my DeviceIoControl methom returns 0, end error code 3. How can I fix this error?
Code here:
#define WINVER 0x0500
#include <windows.h>
#include <winioctl.h>
#include <iostream>
#include <stdio.h>
void DisplayVolumeInfo(CHAR *volume)
{
HANDLE hDevice = CreateFileA(
volume,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM,
NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
PARTITION_INFORMATION partInfo;
DWORD retcount = 0;
BOOL res = DeviceIoControl(
hDevice,
IOCTL_DISK_GET_PARTITION_INFO,
(LPVOID)NULL,
(DWORD)0,
(LPVOID)&partInfo,
sizeof(partInfo),
&retcount,
(LPOVERLAPPED)NULL);
if (res)
std::cout << "Volume size = " << partInfo.PartitionLength.QuadPart << " bytes (" << (unsigned long long)(partInfo.PartitionLength.QuadPart / 1024 / 1024) << "Mb)" << std::endl;
else
std::cout << "Can't do IOCTL_DISK_GET_PARTITION_INFO (error code=" << GetLastError() << ")" << std::endl;
DISK_GEOMETRY diskGeometry;
retcount = 0;
res = DeviceIoControl(
hDevice,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL, 0,
&diskGeometry, sizeof(diskGeometry),
&retcount,
(LPOVERLAPPED)NULL);
if (res)
{
std::cout << "Cylinders = " << diskGeometry.Cylinders.QuadPart << std::endl;
std::cout << "Tracks/cylinder = " << diskGeometry.TracksPerCylinder << std::endl;
std::cout << "Sectors/track = " << diskGeometry.SectorsPerTrack << std::endl;
std::cout << "Bytes/sector = " << diskGeometry.BytesPerSector << std::endl;
}
else
std::cout << "Can't do IOCTL_DISK_GET_DRIVE_GEOMETRY (error code=" << GetLastError() << ")" << std::endl;
CloseHandle(hDevice);
}
else
std::cout << "Error opening volume " << volume << " (error code=" << GetLastError() << ")" << std::endl;
}
int main()
{
DWORD CharCount = 0;
char DeviceName[MAX_PATH] = "";
DWORD Error = ERROR_SUCCESS;
HANDLE FindHandle = INVALID_HANDLE_VALUE;
BOOL Found = FALSE;
size_t Index = 0;
BOOL Success = FALSE;
char VolumeName[MAX_PATH] = "";
//
// Enumerate all volumes in the system.
FindHandle = FindFirstVolumeA(VolumeName, MAX_PATH);
if (FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
printf("FindFirstVolume failed with error code %d\n", Error);
return 0;
}
for (;;)
{
//
// Skip the \\?\ prefix and remove the trailing backslash.
Index = strlen(VolumeName) - 1;
if (VolumeName[0] != '\\' ||
VolumeName[1] != '\\' ||
VolumeName[2] != '?' ||
VolumeName[3] != '\\' ||
VolumeName[Index] != '\\')
{
Error = ERROR_BAD_PATHNAME;
printf("FindFirstVolume/FindNextVolume returned a bad path: %s\n", VolumeName);
break;
}
//
// QueryDosDeviceW does not allow a trailing backslash,
// so temporarily remove it.
VolumeName[Index] = '\0';
CharCount = QueryDosDeviceA(&VolumeName[4], DeviceName, MAX_PATH);
VolumeName[Index] = '\\';
if ( CharCount == 0 )
{
Error = GetLastError();
printf("QueryDosDevice failed with error code %d\n", Error);
break;
}
printf("\nFound a device:\n %s", DeviceName);
printf("\nVolume name: %s", VolumeName);
printf("\n");
DisplayVolumeInfo(VolumeName);
//
// Move on to the next volume.
Success = FindNextVolumeA(FindHandle, VolumeName, MAX_PATH);
if ( !Success )
{
Error = GetLastError();
if (Error != ERROR_NO_MORE_FILES)
{
printf("FindNextVolumeW failed with error code %d\n", Error);
break;
}
//
// Finished iterating
// through all the volumes.
Error = ERROR_SUCCESS;
break;
}
}
FindVolumeClose(FindHandle);
FindHandle = INVALID_HANDLE_VALUE;
return 0;
}
Has anybody met this problem?
P.S. I work on Windows 7 x32