gpt4 book ai didi

delphi - CreateVirtualDisk 给出错误 87(参数不正确。)

转载 作者:行者123 更新时间:2023-12-03 14:47:06 31 4
gpt4 key购买 nike

在 Windows 10 上,尝试使用 CreateVirtualDisk API创建虚拟磁盘失败并返回错误代码 87。

完整的最小可重现示例。

program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils,
Winapi.Windows;

type
// Identifiers for virtual storage types and providers
VIRTUAL_STORAGE_TYPE = record
DeviceId: ULONG; // VIRTUAL_STORAGE_TYPE_DEVICE_xxx
VendorId: TGUID; // VIRTUAL_STORAGE_TYPE_VENDOR_xxx
end;
PVIRTUAL_STORAGE_TYPE = ^VIRTUAL_STORAGE_TYPE;

const
VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT: TGUID = '{EC984AEC-A0F9-47e9-901F-71415A66345B}';
VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN: TGUID = '{00000000-0000-0000-0000-000000000000}';

type
// Version definitions
CREATE_VIRTUAL_DISK_VERSION = (
CREATE_VIRTUAL_DISK_VERSION_UNSPECIFIED = 0,
CREATE_VIRTUAL_DISK_VERSION_1 = 1
);

// Versioned CreateVirtualDisk parameter structure
CREATE_VIRTUAL_DISK_PARAMETERS_V1 = record
Version: CREATE_VIRTUAL_DISK_VERSION;
UniqueId: TGUID;
MaximumSize: ULONGLONG;
BlockSizeInBytes: ULONG;
SectorSizeInBytes: ULONG;
ParentPath: LPCWSTR;
SourcePath: LPCWSTR;
end;
PCREATE_VIRTUAL_DISK_PARAMETERS = Pointer;

const
VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN = 0; //Device type is unknown or not valid.
VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1; //CD or DVD image file device type. (.iso file) Windows 7 and Windows Server 2008 R2: This value is not supported before Windows 8 and Windows Server 2012.
VIRTUAL_STORAGE_TYPE_DEVICE_VHD = 2; //Virtual hard disk device type. (.vhd file)
VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 3; //VHDX format virtual hard disk device type. (.vhdx file) Windows 7 and Windows Server 2008 R2: This value is not supported before Windows 8 and Windows Server 2012.

type
VIRTUAL_DISK_ACCESS_MASK = (
VIRTUAL_DISK_ACCESS_NONE = $00000000,
VIRTUAL_DISK_ACCESS_ATTACH_RO = $00010000,
VIRTUAL_DISK_ACCESS_ATTACH_RW = $00020000,
VIRTUAL_DISK_ACCESS_DETACH = $00040000,
VIRTUAL_DISK_ACCESS_GET_INFO = $00080000,
VIRTUAL_DISK_ACCESS_CREATE = $00100000,
VIRTUAL_DISK_ACCESS_METAOPS = $00200000,
VIRTUAL_DISK_ACCESS_READ = $000d0000,
VIRTUAL_DISK_ACCESS_ALL = $003f0000,
VIRTUAL_DISK_ACCESS_WRITABLE = $00320000
);

// Flags for CreateVirtualDisk
CREATE_VIRTUAL_DISK_FLAG = (
CREATE_VIRTUAL_DISK_FLAG_NONE = $00000000, // i.e. dynamically expanding disk
CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION = $00000001 // Pre-allocate all physical space necessary for the virtual size of the disk (e.g. a fixed VHD).
);

function CreateVirtualDisk(
{in} VirtualStorageType: PVIRTUAL_STORAGE_TYPE;
{in} Path: PWideChar;
{in} VirtualDiskAccessMask: VIRTUAL_DISK_ACCESS_MASK;
{in_opt} SecurityDescriptor: PSECURITY_DESCRIPTOR;
{in} Flags: CREATE_VIRTUAL_DISK_FLAG;
{in} ProviderSpecificFlags: ULONG;
{in} Parameters: PCREATE_VIRTUAL_DISK_PARAMETERS;
{in_opt} Overlapped: POverlapped;
out Handle: THandle
): DWORD; stdcall; external 'VirtDisk.dll';

procedure CreateVhd(Path: UnicodeString; FileSizeBytes: Int64);
var
storageType: VIRTUAL_STORAGE_TYPE;
parameters: CREATE_VIRTUAL_DISK_PARAMETERS_V1;
vhdHandle: THandle;
res: DWORD;
begin
// Specify UNKNOWN for both device and vendor so the system will use the file extension to determine the correct VHD format.
storageType.DeviceId := VIRTUAL_STORAGE_TYPE_DEVICE_VHD; //VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
storageType.VendorId := VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT; //VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;

parameters := Default(CREATE_VIRTUAL_DISK_PARAMETERS_V1);
parameters.Version := CREATE_VIRTUAL_DISK_VERSION_1;
parameters.UniqueId := TGuid.NewGuid;
parameters.MaximumSize := FileSizeBytes;
parameters.BlockSizeInBytes := 0; //CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_BLOCK_SIZE;
parameters.SectorSizeInBytes := 512; //CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_SECTOR_SIZE;
parameters.ParentPath := nil;
parameters.SourcePath := nil;


res := CreateVirtualDisk(
@storageType,
PWideChar(Path),
VIRTUAL_DISK_ACCESS_NONE,
nil, // default security descriptor
CREATE_VIRTUAL_DISK_FLAG_NONE, // dynamically expanding disk
0,
@parameters,
nil, //not overlapped
{out}vhdHandle);

if res <> ERROR_SUCCESS then
begin
RaiseLastOSError(res);
Exit;
end;

CloseHandle(vhdHandle);
end;

begin
try
CreateVhd('C:\test.vhd', 15*1024*1024); //15 MB
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;

WriteLn('Press enter to close...');
ReadLn;
end.

显然以管理员身份运行没有什么区别。

奖励阅读

最佳答案

@RbMm 的 first comment到问题点在哪里寻找以及如何解决问题。他指出 C++ 翻译没有重现该问题。那么问题肯定出在头文件(virtdisk.h)的翻译上。该评论甚至指出 Delphi 的翻译可能不准确。

快速浏览代码以查找我们遇到枚举的常见翻译错误。对于显式分配的值(最大的为 3 个字节),第一个值 (VIRTUAL_DISK_ACCESS_MASK) 很好,编译器将在此处使用 4 个字节。

下一个有问题:

CREATE_VIRTUAL_DISK_FLAG = (
CREATE_VIRTUAL_DISK_FLAG_NONE = $00000000, // i.e. dynamically expanding disk
CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION = $00000001 // Pre-allocate all physical space necessary for the virtual size of the disk (e.g. a fixed VHD).

出于对枚举大小的保守考虑,编译器将为此类型使用 1 个字节。这将导致二进制文件与导出函数 (CreateVirtualDisk) 不匹配,因此为 87 (ERROR_INVALID_PARAMETER)。

您可以使用{$Z4}在这部分的声明之前。

测试表明您还需要考虑同一评论中的其他建议,即使用 VIRTUAL_DISK_ACCESS_NONE。这会导致我的测试中出现 5,即 ERROR_ACCESS_DENIED。我可以使用 VIRTUAL_DISK_ACCESS_ALL 创建磁盘,就像评论建议的那样。

更多测试表明,使用虚拟磁盘的根驱动器的根可能不是一个好主意,这在 this comment 中提到过。 。我对“C:\test.vhd”的测试成功,但我找不到该文件。使用另一个可写目录,我可以毫无问题地定位该文件。

关于delphi - CreateVirtualDisk 给出错误 87(参数不正确。),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59546734/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com