Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用IOCTL_DVD_*控制代码从C#调用DeviceIoControl_C#_Winapi_Pinvoke_Ioctl - Fatal编程技术网

使用IOCTL_DVD_*控制代码从C#调用DeviceIoControl

使用IOCTL_DVD_*控制代码从C#调用DeviceIoControl,c#,winapi,pinvoke,ioctl,C#,Winapi,Pinvoke,Ioctl,我正试图从C#为IOCTL\u DVD.*控制代码调用DeviceIoControl。在阅读了大量信息并尝试了大量示例后,我没有取得多大进展 我最终要做的是得到一个关于DVD驱动器中当前介质的DVD\u LAYER\u描述符结构。我可以在DVD设备上成功调用CreateFile,但当我尝试使用控制代码IOCTL\u DVD\u START\u SESSION调用DeviceIoControl时,它会返回一个成功代码,但我似乎没有成功返回sessionId值,总是返回0。(然后我尝试使用IOCTL

我正试图从C#为
IOCTL\u DVD.*
控制代码调用DeviceIoControl。在阅读了大量信息并尝试了大量示例后,我没有取得多大进展

我最终要做的是得到一个关于DVD驱动器中当前介质的
DVD\u LAYER\u描述符
结构。我可以在DVD设备上成功调用
CreateFile
,但当我尝试使用控制代码
IOCTL\u DVD\u START\u SESSION
调用
DeviceIoControl
时,它会返回一个成功代码,但我似乎没有成功返回sessionId值,总是返回0。(然后我尝试使用
IOCTL\u DVD\u READ\u结构获取层描述的任何尝试都失败,即函数失败或返回成功,但给出一个空白输出结构。)

<> P>在找到类似调用的C代码后,我可以编译这个代码(使用Visual C++ 2008 Express版),它成功地启动了一个会话,读取了 DVDY-Layer-Suxor描述符< /C>,并且关闭了会话,没有问题,所以我知道这是可行的。 C#问题似乎与外部函数的定义和参数的编组方式有关。以及如何定义传递和返回的各种结构

我查看了www.pinvoke.net,了解了他们是如何定义它的,并使用了一些示例代码和给出的定义,但仍然存在与上面概述的相同的问题。问题的一部分似乎是,对于每个IOCTL控制代码,参数都是不同的,主要是结构,但对于
IOCTL\u DVD\u START\u会话
而言,输出值是32位整数。如何定义C#中的extern方法来处理这些不同的情况?此外,使用大小合适的成员类型定义的各种结构表明,它们在C代码和C代码之间的大小不同,但单个成员的大小相同

如果我使用像
DeviceIOView
这样的程序,观察
IOCTL#u DVD#u START#u会话的C代码和C代码发出的调用
C版本返回一个sessionid为3的sessionid,而DeviceIOView在运行C#code时显示返回的数据,因此返回的数据似乎存在某种编组问题参数,因为我们在C代码中只看到0

关于如何从C#调用DeviceIoControl访问DVD信息,有人有什么想法或工作示例代码吗?(显示应如何定义和使用结构和功能。)如能链接到有用的网站或其他建议,将不胜感激

(在Visual C#2008快速版、.NET 3.5中开发。)

约翰

示例代码(已添加)

第一个版本在两次调用中都失败,错误代码为:

122-错误\u缓冲区不足

87-错误\u无效\u参数

第二个版本似乎成功了,但SessionId的值是-10,即初始化值。(根据MSDN,该值应介于-1和3之间?)结束会话也会成功

[注意:第二个版本的启动会话似乎只在每次其他调用时成功,不确定原因,但这似乎也是我的C代码中的一个问题,因为它的错误处理是再次重试。]

问题在于:

result = DeviceIoControl(_hdev, CTL_CODE(0x00000033, 0x0400, 0, 1),
   IntPtr.Zero, 0, (IntPtr)sessionId, Marshal.SizeOf(sessionId),
   out bytesReturned, IntPtr.Zero);
驱动程序希望指针指向LPBuffer中的缓冲区,但您提供的是sessionId本身(为零)。这当然行不通

以下是您需要做的:

IntPtr buffer = Marshal.AllocHGlobal(sizeof(int));
result = DeviceIoControl(_hdev, CTL_CODE(0x00000033, 0x0400, 0, 1),
    IntPtr.Zero, 0, buffer, sizeof(int), out bytesReturned, IntPtr.Zero);
int sessionId = Marshal.ReadInt32(buffer);
Marshal.FreeHGlobal(buffer);
顺便说一句,这同样适用于以下所有DeviceIoControl调用,当您需要提供指向值的指针时,再次提供值。您还需要检查CTL_代码函数是否生成有效的io代码


同样,DeviceIoControl需要指向输入和输出结构缓冲区的指针。

Post您的p/Invoke代码?将很快发布示例,只是从代码中提取一个示例。这段代码非常混乱,因为它目前只是我自娱自乐的测试代码。
result = DeviceIoControl(_hdev, CTL_CODE(0x00000033, 0x0400, 0, 1),
   IntPtr.Zero, 0, (IntPtr)sessionId, Marshal.SizeOf(sessionId),
   out bytesReturned, IntPtr.Zero);
IntPtr buffer = Marshal.AllocHGlobal(sizeof(int));
result = DeviceIoControl(_hdev, CTL_CODE(0x00000033, 0x0400, 0, 1),
    IntPtr.Zero, 0, buffer, sizeof(int), out bytesReturned, IntPtr.Zero);
int sessionId = Marshal.ReadInt32(buffer);
Marshal.FreeHGlobal(buffer);