Почему я не могу использовать дескриптор, возвращенный `WTSVirtualChannelQuery`? - PullRequest
0 голосов
/ 30 апреля 2018

В попытке использовать динамические виртуальные каналы RDP. Я передаю результат WTSVirtualChannelQuery с WTSVirtualFileHandle в FileStream, но он вызывает различные исключения. Почему?

Звоните:

public static FileStream Open(string channelName, WTS_CHANNEL_OPTION option = WTS_CHANNEL_OPTION.DYNAMIC)
{
    // Open
    SafeFileHandle pFile = null;
    using (var sfh = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, channelName, option))
    {
        WtsAllocSafeHandle pBuffer = null;
        try
        {
            int cbReturned;
            if (!WTSVirtualChannelQuery(sfh, WTS_VIRTUAL_CLASS.FileHandle, out pBuffer, out cbReturned)
                || cbReturned < IntPtr.Size)
            {
                throw new Win32Exception();
            }
            pFile = new SafeFileHandle(Marshal.ReadIntPtr(pBuffer.DangerousGetHandle()), false);
        }
        finally
        {
            pBuffer?.Dispose();
        }
    }

    // create
    return new FileStream(pFile, FileAccess.ReadWrite, bufferSize: 32 * 1024 * 1024, isAsync: true);
}

Исключения:

System.ArgumentException: Handle does not support asynchronous operations.  The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened synchronously (that is, it was not opened for overlapped I/O).
    at System.IO.FileStream..ctor(SafeFileHandle handle, FileAccess access, Int32 bufferSize, Boolean isAsync)

и

System.IO.IOException: The handle is invalid.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.VerifyHandleIsSync()
   at System.IO.FileStream..ctor(SafeFileHandle handle, FileAccess access, Int32 bufferSize, Boolean isAsync)

1 Ответ

0 голосов
/ 30 апреля 2018

Дескриптор, возвращаемый WTSVirtualChannelQuery, становится недействительным, как только вызывается WTSFreeMemory. Позвоните DuplicateHandle перед вызовом WTSFreeMemory и используйте дублированный дескриптор.

public static FileStream Open(string channelName, WTS_CHANNEL_OPTION option = WTS_CHANNEL_OPTION.DYNAMIC)
{
    // Open
    SafeFileHandle pFile = null;
    using (var sfh = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, channelName, option))
    {
        WtsAllocSafeHandle pBuffer = null;
        try
        {
            int cbReturned;
            if (!WTSVirtualChannelQuery(sfh, WTS_VIRTUAL_CLASS.FileHandle, out pBuffer, out cbReturned)
                || cbReturned < IntPtr.Size)
            {
                throw new Win32Exception();
            }
            var pWtsFile = Marshal.ReadIntPtr(pBuffer.DangerousGetHandle());
            if (!DuplicateHandle(
                GetCurrentProcess(), pWtsFile,
                GetCurrentProcess(), out pFile, 
                0, false, DUPLICATE_SAME_ACCESS))
            {
                throw new Win32Exception();
            }
        }
        finally
        {
            pBuffer?.Dispose();
        }
    }

    // create
    return new FileStream(pFile, FileAccess.ReadWrite, bufferSize: 32 * 1024 * 1024, isAsync: true);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...