【问题标题】:Why can I not pass a SafeHandle implementation to specific pinvoke functions为什么我不能将 SafeHandle 实现传递给特定的 pinvoke 函数
【发布时间】:2019-05-31 16:19:06
【问题描述】:

我正在尝试将我在 pinvoke 代码中使用的所有句柄替换为 SafeHandles 的实现

特别是我为这样的 SafeThreadHandle 创建了一个实现

internal class SafeThreadHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    internal SafeThreadHandle() : base(true) {}

    protected override bool ReleaseHandle()
    {
        return CloseHandle(handle);
    }
}

例如,这对大多数情况都很有效

[DllImport("kernel32.dll")]
internal static extern int ResumeThread(SafeThreadHandle threadHandle);

当我尝试使用 aSafeThreadHandle 作为以下两个 pinvoke 函数的参数时,该函数失败并设置 windows 错误 998,msdn 状态如下

ERROR_NOACCESS 998 (0x3E6) 对内存位置的访问无效。

[DllImport("kernel32.dll")]
internal static extern bool GetThreadContext(SafeThreadHandle threadHandle, ref Context64 context);


[DllImport("kernel32.dll")]
internal static extern bool SetThreadContext(SafeThreadHandle threadHandle, ref Context64 context);

奇怪的是,如果我将 SafeThreadHandle 替换为通过 threadHandle.GetDangerousHandle() 获得的线程句柄的 IntPtr(参数和参数),函数就会成功并按预期工作。

所以我想我的问题是为什么我不能将SafeHandleSafeThreadHandle 实现用作上述两个函数的参数,但我可以将它用于其他函数,例如ResumeThread

【问题讨论】:

  • 我正在使用 OpenThread 获取句柄(它返回一个 SafeThreadHandle),我读到 Marshal 处理它,因此是无参数构造函数
  • 我没有重现该问题。这可能是由于 Context64 参数定义和/或调用造成的。另外,如果您没有在 GetThreadContext 上定义 SetLastError,您如何判断错误。请在某处分享完整的 .zip 副本。
  • 对不起,我从提供的示例中排除了 SetLastError,因为我在开始调试之前输入了它们,但我在我的真实代码中使用它。提供这个项目有点困难,因为它相当大。您可以分享您使用的代码吗?在比较两个来源后,我会发布回复,如果我有任何差异,请告诉您。

标签: c# winapi pinvoke


【解决方案1】:

因此,经过 Simon 的大量测试和帮助,我设法将问题归结为在 pinvoke 函数中引用 Context 结构。

由于某种原因,如果我使用 ref,我无法使用 SafeThreadHandle 作为参数。

所以解决方案是进行以下更改

[DllImport("kernel32.dll")]
internal static extern bool GetThreadContext(SafeThreadHandle threadHandle, IntPtr context);

然后从指针中编组结构体。

【讨论】:

    【解决方案2】:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 2018-09-12
    • 2023-03-16
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    相关资源
    最近更新 更多