Пример MSDN SafeHandle - PullRequest
       20

Пример MSDN SafeHandle

0 голосов
/ 04 сентября 2018

Возможно, глупый вопрос ... Я новичок в C # и .Net.

В примере для класса SafeHandle (C #) на 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);

Мой вопрос: Как Win32 HANDLE из функции C CreateFile попадает в MySafeFileHandle объекты, защищенные IntPtr переменную «handle»? Конструктор MySafeFileHandle является приватным и даже не принимает IntPtr в качестве аргумента!

Комментарий к выражению CreateFile что-то говорит о

… слой маршаллинга платформы CLR будет хранить дескриптор в объекте SafeHandle атомарным способом.

Я не уверен, что точно знаю, что это значит, кто-нибудь может объяснить, пожалуйста?

1 Ответ

0 голосов
/ 05 сентября 2018

Краткий ответ: это волшебство. Среда выполнения знает, как правильно преобразовать неуправляемые дескрипторы (которые являются просто значениями размера указателя) в SafeHandle и обратно.

Длинный ответ: это достаточно продвинутая технология. В частности, ILSafeHandleMarshaler является (неуправляемым!) Классом, который заботится о маршалинге SafeHandle s туда-сюда. Исходный код кратко описывает процесс:

// 1) create local for new safehandle
// 2) prealloc a safehandle
// 3) create local to hold returned handle
// 4) [byref] add byref IntPtr to native sig
// 5) [byref] pass address of local as last arg
// 6) store return value in safehandle

Код, который он выдает для загрузки неуправляемого дескриптора в безопасный дескриптор, на самом деле является управляемым кодом, хотя и управляемым кодом, который успешно игнорирует доступность. Он получает и вызывает конструктор по умолчанию для создания нового экземпляра:

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 на самом деле недоступны, но этот код не подлежит проверке видимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...