可能是一个愚蠢的问题...我是C#和.Net的新手。

In the example for the SafeHandle class (C#) on MSDN,代码使我有点头疼。

[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
internal class MySafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    private MySafeFileHandle()
      : base(true)
    {}
    // other code here
}

[SuppressUnmanagedCodeSecurity()]
internal static class NativeMethods
{
    // other code...

    // Allocate a file object in the kernel, then return a handle to it.
    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
    internal extern static MySafeFileHandle CreateFile(String fileName,
       int dwDesiredAccess, System.IO.FileShare dwShareMode,
       IntPtr securityAttrs_MustBeZero, System.IO.FileMode
       dwCreationDisposition, int dwFlagsAndAttributes,
       IntPtr hTemplateFile_MustBeZero);

    // other code...
}

// Later in the code the handle is created like this:
MySafeFileHandle tmpHandle;
tmpHandle = NativeMethods.CreateFile(fileName, NativeMethods.GENERIC_READ,
            FileShare.Read, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

我的问题是:来自C函数CreateFile的Win32 HANDLE如何进入受MySafeFileHandle保护的IntPtr“handle”变量的MySafeFileHandle对象? IntPtr的构造函数是私有(private)的,甚至不需要CreateFile作为参数!

ojit_code语句上方的注释说明了一些有关



我不确定我确切知道这是什么意思,任何人都可以解释一下吗?

最佳答案

简短的答案:这是魔术。运行时知道如何正确地将非托管句柄(只是指针大小的值)转换为SafeHandle并返回。

长答案:这是足够先进的技术。具体来说,ILSafeHandleMarshaler是(不受管理的!)类,负责来回处理SafeHandle的编码(marshal)处理。 source code有助于总结该过程:



它发出的将非托管句柄加载到安全句柄中的代码实际上是托管代码,尽管托管代码愉快地忽略了可访问性。它获取并调用默认构造函数以创建新实例:

MethodDesc* pMDCtor = pMT->GetDefaultConstructor();
pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
pslIL->EmitSTLOC(dwReturnHandleLocal);

然后直接设置SafeHandle.handle字段:
mdToken tkNativeHandleField =
    pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
...

// 6) store return value in safehandle
pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
pslCleanupIL->EmitSTFLD(tkNativeHandleField);

实际上,构造函数和handle字段均不可访问,但是此代码不受可见性检查。

关于c# - MSDN SafeHandle示例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52171900/

10-17 02:09