创建一个虚拟分区 我试图用C++来在USB驱动器上创建一个隐藏的虚拟分区。
我可以在windows中使用虚拟磁盘API来执行此操作吗?是的,虚拟磁盘API支持在不为卷分配驱动器号的情况下创建和装载卷。这是通过传递给 困难的部分是在没有驱动器号的情况下访问卷。虚拟磁盘API不提供获取虚拟驱动器上的卷列表的直接方法。这一点很重要,因为驱动器号不可用,因此必须通过UNC路径访问卷。要获取UNC路径,您需要枚举所有已装入的卷,以查找位于虚拟硬盘驱动器上的卷。这是通过打开每个装入的卷并使用来检索与文件句柄关联的设备信息来完成的 包含的示例执行以下步骤来创建、装载和访问虚拟驱动器上的隐藏卷创建一个虚拟分区 我试图用C++来在USB驱动器上创建一个隐藏的虚拟分区。,c++,windows,C++,Windows,我可以在windows中使用虚拟磁盘API来执行此操作吗?是的,虚拟磁盘API支持在不为卷分配驱动器号的情况下创建和装载卷。这是通过传递给 困难的部分是在没有驱动器号的情况下访问卷。虚拟磁盘API不提供获取虚拟驱动器上的卷列表的直接方法。这一点很重要,因为驱动器号不可用,因此必须通过UNC路径访问卷。要获取UNC路径,您需要枚举所有已装入的卷,以查找位于虚拟硬盘驱动器上的卷。这是通过打开每个装入的卷并使用来检索与文件句柄关联的设备信息来完成的 包含的示例执行以下步骤来创建、装载和访问虚拟驱动器上
[步骤3和4需要从磁盘管理控制面板手动完成。这当然可以通过编程完成,但会为示例添加更多代码。]
#包括
#包括
#包括
#包括
#pragma注释(lib,“virtdisk.lib”)
//修复未解决的链接错误
静态常量GUID虚拟存储类型供应商MICROSOFT={0xEC984AEC、0xA0F9、0x47e9、0x90、0x1F、0x71、0x41、0x5A、0x66、0x34、0x5B};
#定义数组大小(a)\
((sizeof(a)/sizeof(*(a)))/\
静态施法(!(sizeof(a)%sizeof(*(a)щщ))
DWORD CreateDisk(PCWSTR virtualDiskFilePath,句柄*句柄)
{
虚拟存储类型存储类型=
{
虚拟存储类型设备VHD,
虚拟存储类型供应商微软
};
创建虚拟磁盘参数参数={};
parameters.Version=创建虚拟磁盘版本1;
parameters.Version1.MaximumSize=1024*1024*1024;
parameters.Version1.BlockSizeInBytes=创建\虚拟\磁盘\参数\默认\块\大小;
parameters.Version1.SectorSizeInBytes=创建\虚拟\磁盘\参数\默认\扇区\大小;
parameters.Version1.SourcePath=NULL;
int结果=::CreateVirtualDisk(
&存储类型,
virtualDiskFilePath,
虚拟磁盘访问所有,
无效的
创建虚拟磁盘标志无,
0,
&参数,
无效的
手柄);
返回结果;
}
DWORD OpenDisk(PCWSTR virtualDiskFilePath,句柄*句柄)
{
虚拟存储类型存储类型=
{
虚拟存储类型设备VHD,
虚拟存储类型供应商微软
};
打开虚拟磁盘参数=
{
打开虚拟磁盘版本1
};
parameters.Version1.RWDepth=1024;
return::OpenVirtualDisk(
&存储类型,
virtualDiskFilePath,
虚拟磁盘访问所有,
打开虚拟磁盘标志无,
&参数,
手柄);
}
int main(int argc,char*argv[])
{
LPTSTR virtualDiskFilePath=\u T(“c:\\source\\drive.vhd”);
把手;
德沃德结果;
乌龙比特兹;
bool=false;
//创建或打开虚拟磁盘文件
结果=CreateDisk(virtualDiskFilePath和句柄);
如果(结果==错误文件存在)
{
结果=OpenDisk(virtualDiskFilePath和句柄);
如果(结果!=错误\u成功)
{
std::wcout@HarryJohnston实际上Windows确实支持它们。@CaptainObvlious:您的答案是关于虚拟磁盘上的分区,这似乎是对OP实际含义的合理猜测,但AFAIK通常不被称为“虚拟分区”。“步骤3和4需要从磁盘管理控制面板手动完成。这当然可以通过编程完成,但会为示例添加更多的代码。”----请提供更多详细信息,说明如何通过编程完成这些步骤。
// This call requires elevated privileges to succeed.
::AttachVirtualDisk(
handle, // Handle returned by CreateVirtualDisk or OpenVirtualDisk
NULL,
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER,
0, // no provider-specific flags
0, // no parameters
NULL);
#include <iostream>
#include <fstream>
#include <string>
#include <virtdisk.h>
#pragma comment(lib, "virtdisk.lib")
// Fix unresolved link error
static const GUID VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = { 0xEC984AEC, 0xA0F9, 0x47e9, 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B };
#define ARRAY_SIZE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
DWORD CreateDisk(PCWSTR virtualDiskFilePath, HANDLE *handle)
{
VIRTUAL_STORAGE_TYPE storageType =
{
VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT
};
CREATE_VIRTUAL_DISK_PARAMETERS parameters = {};
parameters.Version = CREATE_VIRTUAL_DISK_VERSION_1;
parameters.Version1.MaximumSize = 1024 * 1024 * 1024;
parameters.Version1.BlockSizeInBytes = CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_BLOCK_SIZE;
parameters.Version1.SectorSizeInBytes = CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_SECTOR_SIZE;
parameters.Version1.SourcePath = NULL;
int result = ::CreateVirtualDisk(
&storageType,
virtualDiskFilePath,
VIRTUAL_DISK_ACCESS_ALL,
NULL,
CREATE_VIRTUAL_DISK_FLAG_NONE,
0,
¶meters,
NULL,
handle);
return result;
}
DWORD OpenDisk(PCWSTR virtualDiskFilePath, HANDLE *handle)
{
VIRTUAL_STORAGE_TYPE storageType =
{
VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT
};
OPEN_VIRTUAL_DISK_PARAMETERS parameters =
{
OPEN_VIRTUAL_DISK_VERSION_1
};
parameters.Version1.RWDepth = 1024;
return ::OpenVirtualDisk(
&storageType,
virtualDiskFilePath,
VIRTUAL_DISK_ACCESS_ALL,
OPEN_VIRTUAL_DISK_FLAG_NONE,
¶meters,
handle);
}
int main(int argc, char *argv[])
{
LPTSTR virtualDiskFilePath = _T("c:\\source\\drive.vhd");
HANDLE handle;
DWORD result;
ULONG bytesUsed;
bool vhdCreated = false;
// Create or open a virtual disk file
result = CreateDisk(virtualDiskFilePath, &handle);
if(result == ERROR_FILE_EXISTS)
{
result = OpenDisk(virtualDiskFilePath, &handle);
if(result != ERROR_SUCCESS)
{
std::wcout << "Unable to open virtual disk" << std::endl;
return 1;
}
}
else if(result != ERROR_SUCCESS)
{
std::wcout << "Unable to create virtual disk" << std::endl;
return 1;
}
else
{
vhdCreated = true;
}
// Now that the virtual disk is open we need to mount it.
//
// FROM MSDN:
// To attach and detach a virtual disk, you must also have the
// SE_MANAGE_VOLUME_NAME privilege present in your token. This privilege
// is stripped from an administrator's token when User Account Control is
// in use, so you may need to elevate your application to gain access to
// the unrestricted token that includes this privilege.
result = ::AttachVirtualDisk(
handle,
NULL,
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER,
0, // no provider-specific flags
0, // no parameters
NULL);
if(result != ERROR_SUCCESS)
{
std::wcout << "Unable to attach virtual disk" << std::endl;
return 1;
}
if(result == ERROR_SUCCESS && vhdCreated == true)
{
std::wcout
<< "Virtual disk image created. Go into the Computer Management admin panel" << std::endl
<< "and add a volume and format it.\n" << std::endl;
system("pause");
}
// Now we need to grab the device name \\.\PhysicalDrive#
TCHAR physicalDriveName[MAX_PATH];
DWORD physicalDriveNameSize = ARRAY_SIZE(physicalDriveName);
result = ::GetVirtualDiskPhysicalPath(handle, &physicalDriveNameSize, physicalDriveName);
if(result != ERROR_SUCCESS)
{
std::wcout << "Unable to retrieve virtual disk path" << std::endl;
return 1;
}
const std::wstring deviceName = physicalDriveName;
// HACK!!! Wait for windows to complete the mount.
Sleep(2500);
// In order to get the UNC path of the volumes located on the virtual disk we
// need to enumerate all mounted volumes and check which device they are located
// on.
std::wstring volumeName;
TCHAR volumeNameBuffer[MAX_PATH];
HANDLE hVol = ::FindFirstVolume(volumeNameBuffer, ARRAY_SIZE(volumeNameBuffer));
if(hVol == INVALID_HANDLE_VALUE)
{
std::wcout << "Unable to find first volume" << std::endl;
return 1;
}
do
{
// Get rid of trailing backslash so we can open the volume
size_t len = wcslen(volumeNameBuffer);
if (volumeNameBuffer[len-1] == '\\')
{
volumeNameBuffer[len-1] = 0;
}
HANDLE volumeHandle = ::CreateFile(
volumeNameBuffer,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if(volumeHandle == INVALID_HANDLE_VALUE)
{
std::wcout << "Unable to open volume " << volumeNameBuffer << std::endl;
}
else
{
// We can grab the id of the device and use it to create a
// proper device name.
STORAGE_DEVICE_NUMBER deviceInfo = {0};
if (::DeviceIoControl(
volumeHandle,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL,
0,
&deviceInfo,
sizeof(deviceInfo),
&bytesUsed,
NULL))
{
std::wstring tmpName(
std::wstring(L"\\\\.\\PhysicalDrive")
+ std::to_wstring((long long)deviceInfo.DeviceNumber));
if(_wcsicmp(tmpName.c_str(), deviceName.c_str()) == 0)
{
volumeName = std::wstring(volumeNameBuffer) + L"\\\\";
CloseHandle(volumeHandle);
break;
}
}
CloseHandle(volumeHandle);
}
}
while(::FindNextVolume(hVol, volumeNameBuffer, ARRAY_SIZE(volumeNameBuffer)) != FALSE);
::FindVolumeClose(hVol);
if(volumeName.size() == 0)
{
std::wcout << "Unable to locate a volume on this device" << std::endl;
return 1;
}
std::wcout << "Device: " << physicalDriveName << std::endl;
std::wcout << "Volume: " << volumeName << std::endl;
std::wcout << "\n\nSuccess! Now create the file!" << std::endl;
// Now let's create a file for fits and giggles
std::ofstream output;
output.open(volumeName + L"hello.txt");
if(output.fail())
{
std::wcout << "Unable to open output file." << std::endl;
return 1;
}
output.close();
// Volume will be unmounted when the application closes
system("pause");
return 0;
}