c# - 在 C# 中正确地马歇尔 ioctl
问题描述
我正在尝试通过 C# 中的 ioctl 获取有关 DVD 的信息
C 结构看起来像这样,并且在混合的 CLR C++ 库中工作
typedef enum {
DvdChallengeKey = 0x01,
DvdBusKey1,
DvdBusKey2,
DvdTitleKey,
DvdAsf,
DvdSetRpcKey = 0x6,
DvdGetRpcKey = 0x8,
DvdDiskKey = 0x80,
DvdInvalidateAGID = 0x3f
} DVD_KEY_TYPE;
typedef struct DVD_COPY_PROTECT_KEY
{
ULONG KeyLength;
DVD_SESSION_ID SessionId;
DVD_KEY_TYPE KeyType;
ULONG KeyFlags;
union
{
struct
{
ULONG FileHandle;
ULONG Reserved; // used for NT alignment
};
LARGE_INTEGER TitleOffset;
} Parameters;
UCHAR KeyData[0];
} DVD_COPY_PROTECT_KEY, * PDVD_COPY_PROTECT_KEY;
我的 C# 等效外观
public enum DVD_KEY_TYPE
{
DvdChallengeKey = 0x01,
DvdBusKey1,
DvdBusKey2,
DvdTitleKey,
DvdAsf,
DvdSetRpcKey = 0x6,
DvdGetRpcKey = 0x8,
DvdDiskKey = 0x80,
DvdInvalidateAGID = 0x3f
}
[StructLayout(LayoutKind.Sequential)]
public struct DVD_COPY_PROTECT_KEY
{
public uint KeyLength;
public int SessionId;
public DVD_KEY_TYPE KeyType;
public uint KeyFlags;
[MarshalAs(UnmanagedType.Struct)]
public DVD_COPY_PROTECT_KEY_Parameters Parameters;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
private byte[] KeyData;
public DVD_COPY_PROTECT_KEY(DVD_KEY_TYPE keyType, int sessionId)
{
SessionId = sessionId;
KeyType = keyType;
KeyFlags = 0;
KeyData = new byte[10];
KeyLength = 32;//GetKeyLength(this);
Parameters = new DVD_COPY_PROTECT_KEY_Parameters();
var t = Marshal.SizeOf(Parameters);
var t1 = Marshal.SizeOf(Parameters.Inner);
var t2 = Marshal.SizeOf(Parameters.TitleOffset);
var challenge = GetChallenge();
/* Get challenge from host */
for (int i = 0; i < 10; ++i)
{
KeyData[9 - i] = challenge[i];
}
}
public static byte[] GetChallenge()
{
byte[] p_challenge = new byte[10];
/* Setup a challenge, any values should work */
for (int i = 0; i < 10; ++i)
{
p_challenge[i] = (byte)i;
}
return p_challenge;
}
public static uint GetKeyLength(DVD_COPY_PROTECT_KEY dcpk)
{
int size = Marshal.SizeOf(dcpk);
switch (dcpk.KeyType)
{
case DVD_KEY_TYPE.DvdChallengeKey:
return (uint)(12 + size); //36
case DVD_KEY_TYPE.DvdBusKey1:
return (uint)(8 + size); //32
case DVD_KEY_TYPE.DvdBusKey2:
return (uint)(8 + size);
default:
return 0;
}
}
}
[StructLayout(LayoutKind.Explicit)]
public struct DVD_COPY_PROTECT_KEY_Parameters
{
[FieldOffset(0)]
public DVD_COPY_PROTECT_KEY_Parameters_Inner Inner;
[FieldOffset(0)]
public int TitleOffset;
}
[StructLayout(LayoutKind.Sequential)]
public struct DVD_COPY_PROTECT_KEY_Parameters_Inner
{
public IntPtr FileHandle;
public uint Reserved;
}
如果我调用 DeviceIoControl,我会得到一个异常 PInvokeStackImbalance,如果我改用类,我会从 Marshal.GetLastWin32Error(); 得到 ErrorCode 87;
有人有什么想法吗?
更新 我的 DeviceIoControl
[System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
public extern static int DeviceIoControl(IntPtr hDevice, uint IoControlCode, ref DVD_COPY_PROTECT_KEY dcpk, uint InBufferSize, ref DVD_COPY_PROTECT_KEY dcpk2, uint OutBufferSize, ref uint BytesReturned, IntPtr Overlapped);
我现在添加了 ref 关键字,我得到的结构没有异常但 ErrorCode 87
解决方案
推荐阅读
- javascript - 如何在 Javascript 中生成加密安全的伪随机数?
- python - Python 中的 Lambda 表达式
- python - handle_data() 返回什么?
- python - 使用基于列表名称的逻辑将列表转换为 DataFrame
- php - Apple 验证收据数据 21002 错误 - PHP 后端和 React Native
- django - 来自 Django 模型方法的搜索结果,包括先前调用同一方法的结果
- ruby - Ruby - 石头、纸和剪刀游戏的玩家对玩家
- mysql - 有没有办法通过快递将我的 MySQL 数据库 Dockerize 并将该容器托管在数字海洋 .. 等上?
- typescript - TypeScript:当启用严格的函数类型时,键入一个接受新对象的函数
- json - 如何按顺序制作lua表键