diff --git a/PInvoke/WTSApi32/Vanara.PInvoke.WTSApi32.csproj b/PInvoke/WTSApi32/Vanara.PInvoke.WTSApi32.csproj
new file mode 100644
index 00000000..7f4d2c00
--- /dev/null
+++ b/PInvoke/WTSApi32/Vanara.PInvoke.WTSApi32.csproj
@@ -0,0 +1,19 @@
+
+
+
+ WTSApi32.dll
+
+
+ PInvoke API (methods, structures and constants) imported from Windows WTSApi32.dll.
+ $(AssemblyName)
+ net20;net35;net40;net45;net5.0-windows;netstandard2.0;netcoreapp2.0;netcoreapp2.1;netcoreapp3.0;netcoreapp3.1
+ Vanara.PInvoke.WTSApi32
+ $(AssemblyName)
+ pinvoke;vanara;net-extensions;interop;WTSApi32;Remote Desktop Services;windows;api
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PInvoke/WTSApi32/WTSApi32.cs b/PInvoke/WTSApi32/WTSApi32.cs
new file mode 100644
index 00000000..ba0fcc7c
--- /dev/null
+++ b/PInvoke/WTSApi32/WTSApi32.cs
@@ -0,0 +1,3717 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using Vanara.Extensions;
+using Vanara.InteropServices;
+using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
+
+namespace Vanara.PInvoke
+{
+ /// Items from the WTSApi32.dll
+ public static partial class WTSApi32
+ {
+ /// A session value the indicates all WTS sessions.
+ public const uint WTS_ANY_SESSION = unchecked((uint)-2);
+
+ private const int CLIENTADDRESS_LENGTH = 30;
+ private const int CLIENTNAME_LENGTH = 20;
+ private const int DOMAIN_LENGTH = 17;
+ private const string Lib_WTSApi32 = "WTSApi32.dll";
+ private const int MAX_PATH = 260;
+ private const int USERNAME_LENGTH = 20;
+ private const int WINSTATIONNAME_LENGTH = 32;
+ private const int WTS_COMMENT_LENGTH = 60;
+ private const int WTS_DRIVE_LENGTH = 3;
+
+ /// The virtual modifier that represents the key to press to stop remote control of the session.
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSStartRemoteControlSessionA")]
+ [Flags]
+ public enum REMOTECONTROL_HOTKEY
+ {
+ /// The SHIFT key.
+ REMOTECONTROL_KBDSHIFT_HOTKEY = 0x1,
+
+ /// The CTRL key.
+ REMOTECONTROL_KBDCTRL_HOTKEY = 0x2,
+
+ /// The ALT key.
+ REMOTECONTROL_KBDALT_HOTKEY = 0x4,
+ }
+
+ /// Options for WTSVirtualChannelOpenEx.
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelOpenEx")]
+ [Flags]
+ public enum WTS_CHANNEL_OPTION
+ {
+ /// Open the channel as a DVC.
+ WTS_CHANNEL_OPTION_DYNAMIC = 0x00000001,
+
+ ///
+ /// Low priority. The data will be sent on both sides with low priority. Use this priority level for block transfers of all
+ /// sizes, where the transfer speed is not important. In almost all (95%) cases, the channel should be opened with this flag.
+ ///
+ WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW = 0x00000000,
+
+ ///
+ /// Medium priority. Use this priority level to send short control messages that must have priority over the data in the low
+ /// priority channels.
+ ///
+ WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED = 0x00000002,
+
+ ///
+ /// High priority. Use this priority level for data that is critical and directly affects the user experience. The transfer size
+ /// may vary. Display data falls into this category.
+ ///
+ WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH = 0x00000004,
+
+ ///
+ /// Real-time priority. Use this priority level only in cases where the data transfer is absolutely critical. The data transfer
+ /// size should be limited to a few hundred bytes per message.
+ ///
+ WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL = 0x00000006,
+
+ ///
+ /// Disables compression for this DVC. You must specify this value in combination with the WTS_CHANNEL_OPTION_DYNAMIC value.
+ ///
+ WTS_CHANNEL_OPTION_DYNAMIC_NO_COMPRESS = 0x00000008
+ }
+
+ ///
+ /// Contains values that indicate the type of user configuration information to set or retrieve in a call to the WTSQueryUserConfig
+ /// and WTSSetUserConfig functions.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_config_class typedef enum _WTS_CONFIG_CLASS {
+ // WTSUserConfigInitialProgram, WTSUserConfigWorkingDirectory, WTSUserConfigfInheritInitialProgram,
+ // WTSUserConfigfAllowLogonTerminalServer, WTSUserConfigTimeoutSettingsConnections, WTSUserConfigTimeoutSettingsDisconnections,
+ // WTSUserConfigTimeoutSettingsIdle, WTSUserConfigfDeviceClientDrives, WTSUserConfigfDeviceClientPrinters,
+ // WTSUserConfigfDeviceClientDefaultPrinter, WTSUserConfigBrokenTimeoutSettings, WTSUserConfigReconnectSettings,
+ // WTSUserConfigModemCallbackSettings, WTSUserConfigModemCallbackPhoneNumber, WTSUserConfigShadowingSettings,
+ // WTSUserConfigTerminalServerProfilePath, WTSUserConfigTerminalServerHomeDir, WTSUserConfigTerminalServerHomeDirDrive,
+ // WTSUserConfigfTerminalServerRemoteHomeDir, WTSUserConfigUser } WTS_CONFIG_CLASS;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NE:wtsapi32._WTS_CONFIG_CLASS")]
+ public enum WTS_CONFIG_CLASS
+ {
+ ///
+ /// A null-terminated string that contains the path of the initial program that Remote Desktop Services runs when the user logs
+ /// on.If the WTSUserConfigfInheritInitialProgram value is 1, the initial program can be any program specified by the client.
+ ///
+ WTSUserConfigInitialProgram,
+
+ /// A null-terminated string that contains the path of the working directory for the initial program.
+ WTSUserConfigWorkingDirectory,
+
+ /// A value that indicates whether the client can specify the initial program.
+ WTSUserConfigfInheritInitialProgram,
+
+ /// A value that indicates whether the user account is permitted to log on to an RD Session Host server.
+ WTSUserConfigfAllowLogonTerminalServer,
+
+ ///
+ /// A DWORD value that specifies the maximum connection duration, in milliseconds. One minute before the connection time-out
+ /// interval expires, the user is notified of the pending disconnection. The user's session is disconnected or terminated
+ /// depending on the WTSUserConfigBrokenTimeoutSettings value. Every time the user logs on, the timer is reset. A value of zero
+ /// indicates that the connection timer is disabled.
+ ///
+ WTSUserConfigTimeoutSettingsConnections,
+
+ ///
+ /// A DWORD value that specifies the maximum duration, in milliseconds, that an RD Session Host server retains a disconnected
+ /// session before the logon is terminated. A value of zero indicates that the disconnection timer is disabled.
+ ///
+ WTSUserConfigTimeoutSettingsDisconnections,
+
+ ///
+ /// A DWORD value that specifies the maximum idle time, in milliseconds. If there is no keyboard or mouse activity for the
+ /// specified interval, the user's session is disconnected or terminated depending on the WTSUserConfigBrokenTimeoutSettings
+ /// value. A value of zero indicates that the idle timer is disabled.
+ ///
+ WTSUserConfigTimeoutSettingsIdle,
+
+ ///
+ /// This constant currently is not used by Remote Desktop Services.A value that indicates whether the RD Session Host server
+ /// automatically reestablishes client drive mappings at logon.
+ ///
+ WTSUserConfigfDeviceClientDrives,
+
+ ///
+ /// RDP 5.0 and later clients: A value that indicates whether the RD Session Host server automatically reestablishes client
+ /// printer mappings at logon.
+ ///
+ WTSUserConfigfDeviceClientPrinters,
+
+ /// RDP 5.0 and later clients: A value that indicates whether the client printer is the default printer.
+ WTSUserConfigfDeviceClientDefaultPrinter,
+
+ ///
+ /// A value that indicates what happens when the connection or idle timers expire or when a connection is lost due to a
+ /// connection error.
+ ///
+ WTSUserConfigBrokenTimeoutSettings,
+
+ /// A value that indicates how a disconnected session for this user can be reconnected.
+ WTSUserConfigReconnectSettings,
+
+ ///
+ /// This constant currently is not used by Remote Desktop Services.A value that indicates the configuration for dial-up
+ /// connections in which the RD Session Host server stops responding and then calls back the client to establish the connection.
+ ///
+ WTSUserConfigModemCallbackSettings,
+
+ ///
+ /// This constant currently is not used by Remote Desktop Services.A null-terminated string that contains the phone number to
+ /// use for callback connections.
+ ///
+ WTSUserConfigModemCallbackPhoneNumber,
+
+ ///
+ /// RDP 5.0 and later clients: A value that indicates whether the user session can be shadowed. Shadowing allows a user to
+ /// remotely monitor the on-screen operations of another user.
+ ///
+ WTSUserConfigShadowingSettings,
+
+ ///
+ /// A null-terminated string that contains the path of the user's profile for RD Session Host server logon. The directory the
+ /// path identifies must be created manually, and must exist prior to the logon. WTSSetUserConfig will not create the directory
+ /// if it does not already exist.
+ ///
+ WTSUserConfigTerminalServerProfilePath,
+
+ ///
+ /// A null-terminated string that contains the path of the user's root directory for RD Session Host server logon. This string
+ /// can specify a local path or a UNC path (\ComputerName\Share\Path). For more information, see WTSUserConfigfTerminalServerRemoteHomeDir.
+ ///
+ WTSUserConfigTerminalServerHomeDir,
+
+ ///
+ /// A null-terminated string that contains a drive name (a drive letter followed by a colon) to which the UNC path specified in
+ /// the WTSUserConfigTerminalServerHomeDir string is mapped. For more information, see WTSUserConfigfTerminalServerRemoteHomeDir.
+ ///
+ WTSUserConfigTerminalServerHomeDirDrive,
+
+ ///
+ /// A value that indicates whether the user's root directory for RD Session Host server logon is a local path or a mapped drive
+ /// letter. Note that this value cannot be used with WTSSetUserConfig.
+ ///
+ WTSUserConfigfTerminalServerRemoteHomeDir,
+
+ ///
+ /// A WTSUSERCONFIG structure that contains configuration data for the session. Windows Server 2008 and Windows Vista: This
+ /// value is not supported.
+ ///
+ WTSUserConfigUser,
+ }
+
+ ///
+ /// Specifies the source of configuration information returned by the WTSQueryUserConfig function. This enumeration type is used in
+ /// the WTSUSERCONFIG structure.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_config_source typedef enum _WTS_CONFIG_SOURCE {
+ // WTSUserConfigSourceSAM } WTS_CONFIG_SOURCE;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NE:wtsapi32._WTS_CONFIG_SOURCE")]
+ public enum WTS_CONFIG_SOURCE
+ {
+ /// The configuration information came from the Security Accounts Manager (SAM) database.
+ WTSUserConfigSourceSAM,
+ }
+
+ /// Specifies the connection state of a Remote Desktop Services session.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_connectstate_class typedef enum
+ // _WTS_CONNECTSTATE_CLASS { WTSActive, WTSConnected, WTSConnectQuery, WTSShadow, WTSDisconnected, WTSIdle, WTSListen, WTSReset,
+ // WTSDown, WTSInit } WTS_CONNECTSTATE_CLASS;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NE:wtsapi32._WTS_CONNECTSTATE_CLASS")]
+ public enum WTS_CONNECTSTATE_CLASS
+ {
+ ///
+ /// A user is logged on to the WinStation. This state occurs when a user is signed in and actively connected to the device.
+ ///
+ WTSActive,
+
+ /// The WinStation is connected to the client.
+ WTSConnected,
+
+ /// The WinStation is in the process of connecting to the client.
+ WTSConnectQuery,
+
+ /// The WinStation is shadowing another WinStation.
+ WTSShadow,
+
+ ///
+ /// The WinStation is active but the client is disconnected. This state occurs when a user is signed in but not actively
+ /// connected to the device, such as when the user has chosen to exit to the lock screen.
+ ///
+ WTSDisconnected,
+
+ /// The WinStation is waiting for a client to connect.
+ WTSIdle,
+
+ ///
+ /// The WinStation is listening for a connection. A listener session waits for requests for new client connections. No user is
+ /// logged on a listener session. A listener session cannot be reset, shadowed, or changed to a regular client session.
+ ///
+ WTSListen,
+
+ /// The WinStation is being reset.
+ WTSReset,
+
+ /// The WinStation is down due to an error.
+ WTSDown,
+
+ /// The WinStation is initializing.
+ WTSInit,
+ }
+
+ /// Bitmask that specifies the set of events to wait for.
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSWaitSystemEvent")]
+ [Flags]
+ public enum WTS_EVENT : uint
+ {
+ /// The wait terminated because of a WTSWaitSystemEvent call with WTS_EVENT_FLUSH.
+ WTS_EVENT_NONE = 0x00000000,
+
+ /// A new WinStation was created.
+ WTS_EVENT_CREATE = 0x00000001,
+
+ /// An existing WinStation was deleted.
+ WTS_EVENT_DELETE = 0x00000002,
+
+ /// An existing WinStation was renamed.
+ WTS_EVENT_RENAME = 0x00000004,
+
+ /// A client connected to a WinStation.
+ WTS_EVENT_CONNECT = 0x00000008,
+
+ /// A client disconnected from a WinStation.
+ WTS_EVENT_DISCONNECT = 0x00000010,
+
+ /// A user logged on to the system from either the Remote Desktop Services console or from a client WinStation.
+ WTS_EVENT_LOGON = 0x00000020,
+
+ /// A user logged off from either the Remote Desktop Services console or from a client WinStation.
+ WTS_EVENT_LOGOFF = 0x00000040,
+
+ ///
+ /// A WinStation connection state changed. For a list of connection states, see the WTS_CONNECTSTATE_CLASS enumeration type.
+ ///
+ WTS_EVENT_STATECHANGE = 0x00000080,
+
+ ///
+ /// The Remote Desktop Services' license state changed. This occurs when a license is added or deleted using License Manager.
+ ///
+ WTS_EVENT_LICENSE = 0x00000100,
+
+ /// Wait for any event type.
+ WTS_EVENT_ALL = 0x7fffffff,
+
+ /// Cause all pending WTSWaitSystemEvent calls on the specified RD Session Host server handle to return.
+ WTS_EVENT_FLUSH = 0x80000000,
+ }
+
+ ///
+ /// Contains values that indicate the type of session information to retrieve in a call to the WTSQuerySessionInformation function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_info_class typedef enum _WTS_INFO_CLASS {
+ // WTSInitialProgram, WTSApplicationName, WTSWorkingDirectory, WTSOEMId, WTSSessionId, WTSUserName, WTSWinStationName,
+ // WTSDomainName, WTSConnectState, WTSClientBuildNumber, WTSClientName, WTSClientDirectory, WTSClientProductId, WTSClientHardwareId,
+ // WTSClientAddress, WTSClientDisplay, WTSClientProtocolType, WTSIdleTime, WTSLogonTime, WTSIncomingBytes, WTSOutgoingBytes,
+ // WTSIncomingFrames, WTSOutgoingFrames, WTSClientInfo, WTSSessionInfo, WTSSessionInfoEx, WTSConfigInfo, WTSValidationInfo,
+ // WTSSessionAddressV4, WTSIsRemoteSession } WTS_INFO_CLASS;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NE:wtsapi32._WTS_INFO_CLASS")]
+ public enum WTS_INFO_CLASS
+ {
+ ///
+ /// A null-terminated string that contains the name of the initial program that Remote Desktop Services runs when the user logs on.
+ ///
+ [CorrespondingType(typeof(string))]
+ WTSInitialProgram,
+
+ ///
+ /// A null-terminated string that contains the published name of the application that the session is running.Windows Server 2008
+ /// R2, Windows 7, Windows Server 2008 and Windows Vista: This value is not supported
+ ///
+ [CorrespondingType(typeof(string))]
+ WTSApplicationName,
+
+ /// A null-terminated string that contains the default directory used when launching the initial program.
+ [CorrespondingType(typeof(string))]
+ WTSWorkingDirectory,
+
+ /// This value is not used.
+ WTSOEMId,
+
+ /// A ULONG value that contains the session identifier.
+ [CorrespondingType(typeof(uint))]
+ WTSSessionId,
+
+ /// A null-terminated string that contains the name of the user associated with the session.
+ [CorrespondingType(typeof(string))]
+ WTSUserName,
+
+ /// A null-terminated string that contains the name of the Remote Desktop Services session.
+ [CorrespondingType(typeof(string))]
+ WTSWinStationName,
+
+ /// A null-terminated string that contains the name of the domain to which the logged-on user belongs.
+ [CorrespondingType(typeof(string))]
+ WTSDomainName,
+
+ /// The session's current connection state. For more information, see WTS_CONNECTSTATE_CLASS.
+ [CorrespondingType(typeof(WTS_CONNECTSTATE_CLASS))]
+ WTSConnectState,
+
+ /// A ULONG value that contains the build number of the client.
+ [CorrespondingType(typeof(uint))]
+ WTSClientBuildNumber,
+
+ /// A null-terminated string that contains the name of the client.
+ [CorrespondingType(typeof(string))]
+ WTSClientName,
+
+ /// A null-terminated string that contains the directory in which the client is installed.
+ [CorrespondingType(typeof(string))]
+ WTSClientDirectory,
+
+ /// A USHORT client-specific product identifier.
+ [CorrespondingType(typeof(ushort))]
+ WTSClientProductId,
+
+ ///
+ /// A ULONG value that contains a client-specific hardware identifier. This option is reserved for future use.
+ /// WTSQuerySessionInformation will always return a value of 0.
+ ///
+ [CorrespondingType(typeof(uint))]
+ WTSClientHardwareId,
+
+ ///
+ /// The network type and network address of the client. For more information, see WTS_CLIENT_ADDRESS. The IP address is offset
+ /// by two bytes from the start of the Address member of the WTS_CLIENT_ADDRESS structure.
+ ///
+ [CorrespondingType(typeof(WTS_CLIENT_ADDRESS))]
+ WTSClientAddress,
+
+ /// Information about the display resolution of the client. For more information, see WTS_CLIENT_DISPLAY.
+ [CorrespondingType(typeof(WTS_CLIENT_DISPLAY))]
+ WTSClientDisplay,
+
+ ///
+ /// A USHORT value that specifies information about the protocol type for the session. This is one of the following values.
+ ///
+ [CorrespondingType(typeof(ushort))]
+ WTSClientProtocolType,
+
+ ///
+ /// This value returns FALSE. If you call GetLastError to get extended error information, GetLastError returns
+ /// ERROR_NOT_SUPPORTED.Windows Server 2008 and Windows Vista: This value is not used.
+ ///
+ WTSIdleTime,
+
+ ///
+ /// This value returns FALSE. If you call GetLastError to get extended error information, GetLastError returns
+ /// ERROR_NOT_SUPPORTED.Windows Server 2008 and Windows Vista: This value is not used.
+ ///
+ WTSLogonTime,
+
+ ///
+ /// This value returns FALSE. If you call GetLastError to get extended error information, GetLastError returns
+ /// ERROR_NOT_SUPPORTED.Windows Server 2008 and Windows Vista: This value is not used.
+ ///
+ WTSIncomingBytes,
+
+ ///
+ /// This value returns FALSE. If you call GetLastError to get extended error information, GetLastError returns
+ /// ERROR_NOT_SUPPORTED.Windows Server 2008 and Windows Vista: This value is not used.
+ ///
+ WTSOutgoingBytes,
+
+ ///
+ /// This value returns FALSE. If you call GetLastError to get extended error information, GetLastError returns
+ /// ERROR_NOT_SUPPORTED.Windows Server 2008 and Windows Vista: This value is not used.
+ ///
+ WTSIncomingFrames,
+
+ ///
+ /// This value returns FALSE. If you call GetLastError to get extended error information, GetLastError returns
+ /// ERROR_NOT_SUPPORTED.Windows Server 2008 and Windows Vista: This value is not used.
+ ///
+ WTSOutgoingFrames,
+
+ /// Information about a Remote Desktop Connection (RDC) client. For more information, see WTSCLIENT.
+ [CorrespondingType(typeof(WTSCLIENT))]
+ WTSClientInfo,
+
+ /// Information about a client session on a RD Session Host server. For more information, see WTSINFO.
+ [CorrespondingType(typeof(WTSINFO))]
+ WTSSessionInfo,
+
+ ///
+ /// Extended information about a session on a RD Session Host server. For more information, see WTSINFOEX. Windows Server 2008
+ /// and Windows Vista: This value is not supported.
+ ///
+ [CorrespondingType(typeof(WTSINFOEX))]
+ WTSSessionInfoEx,
+
+ ///
+ /// A WTSCONFIGINFO structure that contains information about the configuration of a RD Session Host server. Windows Server 2008
+ /// and Windows Vista: This value is not supported.
+ ///
+ [CorrespondingType(typeof(WTSCONFIGINFO))]
+ WTSConfigInfo,
+
+ /// This value is not supported.
+ WTSValidationInfo,
+
+ ///
+ /// A WTS_SESSION_ADDRESS structure that contains the IPv4 address assigned to the session. If the session does not have a
+ /// virtual IP address, the WTSQuerySessionInformation function returns ERROR_NOT_SUPPORTED.Windows Server 2008 and Windows
+ /// Vista: This value is not supported.
+ ///
+ [CorrespondingType(typeof(WTS_SESSION_ADDRESS))]
+ WTSSessionAddressV4,
+
+ ///
+ /// Determines whether the current session is a remote session. The WTSQuerySessionInformation function returns a value of TRUE
+ /// to indicate that the current session is a remote session, and FALSE to indicate that the current session is a local session.
+ /// This value can only be used for the local machine, so the hServer parameter of the WTSQuerySessionInformation function must
+ /// contain WTS_CURRENT_SERVER_HANDLE. Windows Server 2008 and Windows Vista: This value is not supported.
+ ///
+ WTSIsRemoteSession,
+ }
+
+ /// The purpose of the call.
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSCreateListenerA")]
+ public enum WTS_LISTENER
+ {
+ /// Create a new listener.
+ WTS_LISTENER_CREATE = 0x00000001,
+
+ /// Update the settings of an existing listener.
+ WTS_LISTENER_UPDATE = 0x00000010,
+ }
+
+ /// The state of the session.
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSINFOEX_LEVEL1_A")]
+ [Flags]
+ public enum WTS_SESSIONSTATE : uint
+ {
+ /// The session state is not known.
+ WTS_SESSIONSTATE_UNKNOWN = 0xFFFFFFFF,
+
+ /// The session state is locked.
+ WTS_SESSIONSTATE_LOCK = 0x00000000,
+
+ /// The session state is unlocked.
+ WTS_SESSIONSTATE_UNLOCK = 0x00000001,
+ }
+
+ /// Specifies the type of structure that a Remote Desktop Services function has returned in a buffer.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_type_class typedef enum _WTS_TYPE_CLASS {
+ // WTSTypeProcessInfoLevel0, WTSTypeProcessInfoLevel1, WTSTypeSessionInfoLevel1 } WTS_TYPE_CLASS;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NE:wtsapi32._WTS_TYPE_CLASS")]
+ public enum WTS_TYPE_CLASS
+ {
+ /// The buffer contains one or more WTS_PROCESS_INFO structures.
+ WTSTypeProcessInfoLevel0,
+
+ /// The buffer contains one or more WTS_PROCESS_INFO_EX structures.
+ WTSTypeProcessInfoLevel1,
+
+ /// The buffer contains one or more WTS_SESSION_INFO_1 structures.
+ WTSTypeSessionInfoLevel1,
+ }
+
+ /// Contains values that indicate the type of virtual channel information to retrieve.
+ ///
+ /// For an example that shows the use of the WTSVirtualFileHandle value, see WTSVirtualChannelQuery. This example shows how to gain
+ /// access to a virtual channel file handle that can be used for asynchronous I/O.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ne-wtsapi32-wts_virtual_class typedef enum _WTS_VIRTUAL_CLASS {
+ // WTSVirtualClientData, WTSVirtualFileHandle } WTS_VIRTUAL_CLASS;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NE:wtsapi32._WTS_VIRTUAL_CLASS")]
+ public enum WTS_VIRTUAL_CLASS
+ {
+ /// This value is not currently supported.
+ WTSVirtualClientData,
+
+ /// Indicates a request for the file handle of a virtual channel that can be used for asynchronous I/O.
+ WTSVirtualFileHandle,
+ }
+
+ /// Indicates the type of shutdown.
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSShutdownSystem")]
+ public enum WTS_WSD
+ {
+ ///
+ /// Forces all client sessions to log off (except the session calling WTSShutdownSystem) and disables any subsequent
+ /// remote logons. This can be used as a step before shutting down. Logons will be re-enabled when the Remote Desktop Services
+ /// service is restarted.
+ ///
+ WTS_WSD_LOGOFF = 0x00000001,
+
+ ///
+ /// Shuts down the system on the RD Session Host server. This is equivalent to calling the ExitWindowsEx function with
+ /// EWX_SHUTDOWN. The calling process must have the SE_SHUTDOWN_NAME privilege enabled.
+ ///
+ WTS_WSD_SHUTDOWN = 0x00000002,
+
+ ///
+ /// Shuts down and then restarts the system on the RD Session Host server. This is equivalent to calling ExitWindowsEx
+ /// with EWX_REBOOT. The calling process must have the SE_SHUTDOWN_NAME privilege enabled.
+ ///
+ WTS_WSD_REBOOT = 0x00000004,
+
+ ///
+ /// Shuts down the system on the RD Session Host server and, on computers that support software control of AC power, turns off
+ /// the power. This is equivalent to calling ExitWindowsEx with EWX_SHUTDOWN and EWX_POWEROFF. The calling process
+ /// must have the SE_SHUTDOWN_NAME privilege enabled.
+ ///
+ WTS_WSD_POWEROFF = 0x00000008,
+
+ /// This value is not supported currently.
+ WTS_WSD_FASTREBOOT = 0x00000010,
+ }
+
+ /// Closes an open handle to a Remote Desktop Session Host (RD Session Host) server.
+ ///
+ /// A handle to an RD Session Host server opened by a call to the WTSOpenServer or WTSOpenServerEx function.
+ /// Do not pass WTS_CURRENT_SERVER_HANDLE for this parameter.
+ ///
+ /// None
+ ///
+ ///
+ /// Call the WTSCloseServer function as part of your program's clean-up routine to close all the server handles opened by
+ /// calls to the WTSOpenServer or WTSOpenServerEx function.
+ ///
+ /// After the handle has been closed, it cannot be used with any other WTS APIs.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtscloseserver void WTSCloseServer( HANDLE hServer );
+ [DllImport(Lib_WTSApi32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSCloseServer")]
+ public static extern void WTSCloseServer(HWTSSERVER hServer);
+
+ /// Connects a Remote Desktop Services session to an existing session on the local computer.
+ ///
+ ///
+ /// The logon ID of the session to connect to. The user of that session must have permissions to connect to an existing session. The
+ /// output of this session will be routed to the session identified by the TargetLogonId parameter.
+ ///
+ /// This can be LOGONID_CURRENT to use the current session.
+ ///
+ ///
+ ///
+ /// The logon ID of the session to receive the output of the session represented by the LogonId parameter. The output of the session
+ /// identified by the LogonId parameter will be routed to this session.
+ ///
+ /// This can be LOGONID_CURRENT to use the current session.
+ ///
+ ///
+ /// A pointer to the password for the user account that is specified in the LogonId parameter. The value of pPassword can be an
+ /// empty string if the caller is logged on using the same domain name and user name as the logon ID. The value of pPassword cannot
+ /// be NULL.
+ ///
+ ///
+ /// Indicates whether the operation is synchronous. Specify TRUE to wait for the operation to complete, or FALSE to
+ /// return immediately.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ /// Either the LogonId or TargetLogonId parameter can be LOGONID_CURRENT, but not both.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsconnectsessiona BOOL WTSConnectSessionA( ULONG
+ // LogonId, ULONG TargetLogonId, PSTR pPassword, BOOL bWait );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSConnectSessionA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSConnectSession(uint LogonId, uint TargetLogonId, [MarshalAs(UnmanagedType.LPTStr)] string pPassword,
+ [MarshalAs(UnmanagedType.Bool)] bool bWait);
+
+ /// Creates a new Remote Desktop Services listener or configures an existing listener.
+ /// A handle to an RD Session Host server. Always set this parameter to WTS_CURRENT_SERVER_HANDLE.
+ /// This parameter is reserved. Always set this parameter to NULL.
+ /// This parameter is reserved. Always set this parameter to zero.
+ /// A pointer to a null-terminated string that contains the name of the listener to create or configure.
+ /// A pointer to a WTSLISTENERCONFIG structure that contains configuration information for the listener.
+ ///
+ /// The purpose of the call. This parameter can be one of the following values.
+ /// WTS_LISTENER_CREATE (1 (0x1))
+ /// Create a new listener.
+ /// WTS_LISTENER_UPDATE (16 (0x10))
+ /// Update the settings of an existing listener.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ ///
+ /// This function creates or configures a listener that uses Remote Desktop Protocol (RDP). Always set the version member of
+ /// the WTSLISTENERCONFIG structure that is pointed to by the pBuffer parameter to one.
+ ///
+ ///
+ /// This function does not create or configure the security descriptor of the listener. When you call this function to create a new
+ /// listener, the function assigns the default security descriptor to the new listener. To modify the security descriptor, call the
+ /// WTSSetListenerSecurity function. For more information about security descriptors, see SECURITY_DESCRIPTOR.
+ ///
+ ///
+ /// This function does not validate the settings for the new listener. Be sure that the settings are valid before calling this function.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtscreatelistenera BOOL WTSCreateListenerA( HANDLE
+ // hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSCreateListenerA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSCreateListener(HWTSSERVER hServer, [In, Optional] IntPtr pReserved, [In, Optional] uint Reserved,
+ [MarshalAs(UnmanagedType.LPTStr)] string pListenerName, in WTSLISTENERCONFIG pBuffer, WTS_LISTENER flag);
+
+ ///
+ /// Disconnects the logged-on user from the specified Remote Desktop Services session without closing the session. If the user
+ /// subsequently logs on to the same Remote Desktop Session Host (RD Session Host) server, the user is reconnected to the same session.
+ ///
+ ///
+ /// A handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer or WTSOpenServerEx function, or specify
+ /// WTS_CURRENT_SERVER_HANDLE to indicate the RD Session Host server on which your application is running.
+ ///
+ ///
+ ///
+ /// A Remote Desktop Services session identifier. To indicate the current session, specify WTS_CURRENT_SESSION. To retrieve
+ /// the identifiers of all sessions on a specified RD Session Host server, use the WTSEnumerateSessions function.
+ ///
+ ///
+ /// To be able to disconnect another user's session, you need to have the Disconnect permission. For more information, see Remote
+ /// Desktop Services Permissions. To modify permissions on a session, use the Remote Desktop Services Configuration administrative tool.
+ ///
+ ///
+ /// To disconnect sessions running on a virtual machine hosted on a RD Virtualization Host server, you must be a member of the
+ /// Administrators group on the RD Virtualization Host server.
+ ///
+ ///
+ ///
+ /// Indicates whether the operation is synchronous. Specify TRUE to wait for the operation to complete, or FALSE to
+ /// return immediately.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsdisconnectsession BOOL WTSDisconnectSession( HANDLE
+ // hServer, DWORD SessionId, BOOL bWait );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSDisconnectSession")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSDisconnectSession(HWTSSERVER hServer, uint SessionId, [MarshalAs(UnmanagedType.Bool)] bool bWait);
+
+ /// Enables or disables Child Sessions.
+ ///
+ /// Indicates whether to enable or disable child sessions. Pass TRUE if child sessions are to be enabled or FALSE otherwise.
+ ///
+ /// Returns nonzero if the function succeeds or zero otherwise.
+ /// For more information about child sessions, see Child Sessions.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenablechildsessions BOOL WTSEnableChildSessions( BOOL
+ // bEnable );
+ [DllImport(Lib_WTSApi32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnableChildSessions")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSEnableChildSessions([MarshalAs(UnmanagedType.Bool)] bool bEnable);
+
+ /// Enumerates all the Remote Desktop Services listeners on a Remote Desktop Session Host (RD Session Host) server.
+ /// A handle to an RD Session Host server. Always set this parameter to WTS_CURRENT_SERVER_HANDLE.
+ /// This parameter is reserved. Always set this parameter to NULL.
+ /// This parameter is reserved. Always set this parameter to zero.
+ /// A pointer to an array of WTSLISTENERNAME variables that receive the names of the listeners.
+ ///
+ /// A pointer to a DWORD variable that contains the number of listener names in the array referenced by the pListeners
+ /// parameter. If the number of listener names is unknown, pass pListeners as NULL. The function will return the number of
+ /// WTSLISTENERNAME variables necessary to allocate for the array pointed to by the pListeners parameter.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// This function returns all listeners currently running on the server, including listeners that do not support Remote Desktop
+ /// Protocol (RDP).
+ ///
+ ///
+ /// If the number of listeners is unknown, you can call this function with pListeners set to NULL. The function will then
+ /// return, in the pCount parameter, the number of WTSLISTENERNAME variables necessary to receive all the listeners. Allocate
+ /// the array for pListeners based on this number, and then call the function again, setting pListeners to the newly allocated array
+ /// and pCount to the number returned by the first call.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumeratelistenersa BOOL WTSEnumerateListenersA(
+ // HANDLE hServer, PVOID pReserved, DWORD Reserved, PWTSLISTENERNAMEA pListeners, DWORD *pCount );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateListenersA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSEnumerateListeners(HWTSSERVER hServer, [In, Optional] IntPtr pReserved, [In, Optional] uint Reserved,
+ [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] WTSLISTENERNAME[] pListeners, ref uint pCount);
+
+ /// Retrieves information about the active processes on a specified Remote Desktop Session Host (RD Session Host) server.
+ ///
+ /// Handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer function, or specify
+ /// WTS_CURRENT_SERVER_HANDLE to indicate the RD Session Host server on which your application is running.
+ ///
+ /// Reserved; must be zero.
+ /// Specifies the version of the enumeration request. Must be 1.
+ ///
+ /// Pointer to a variable that receives a pointer to an array of WTS_PROCESS_INFO structures. Each structure in the array contains
+ /// information about an active process on the specified RD Session Host server. To free the returned buffer, call the WTSFreeMemory function.
+ ///
+ ///
+ /// Pointer to a variable that receives the number of WTS_PROCESS_INFO structures returned in the ppProcessInfo buffer.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// The caller must be a member of the Administrators group to enumerate processes that are running under a different user's context.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumerateprocessesa BOOL WTSEnumerateProcessesA(
+ // HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA *ppProcessInfo, DWORD *pCount );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateProcessesA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSEnumerateProcesses(HWTSSERVER hServer, [In, Optional] uint Reserved, uint Version,
+ out SafeWTSMemoryHandle ppProcessInfo, out uint pCount);
+
+ ///
+ /// Retrieves information about the active processes on the specified Remote Desktop Session Host (RD Session Host) server or Remote
+ /// Desktop Virtualization Host (RD Virtualization Host) server.
+ ///
+ ///
+ /// A handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer function, or specify
+ /// WTS_CURRENT_SERVER_HANDLE to indicate the server on which your application is running.
+ ///
+ ///
+ ///
+ /// A pointer to a DWORD variable that, on input, specifies the type of information to return. To return an array of
+ /// WTS_PROCESS_INFO structures, specify zero. To return an array of WTS_PROCESS_INFO_EX structures, specify one.
+ ///
+ ///
+ /// If you do not specify a valid value for this parameter, on output, WTSEnumerateProcessesEx sets this parameter to one and
+ /// returns an error. Otherwise, on output, WTSEnumerateProcessesEx does not change the value of this parameter.
+ ///
+ ///
+ ///
+ /// The session for which to enumerate processes. To enumerate processes for all sessions on the server, specify WTS_ANY_SESSION.
+ ///
+ ///
+ /// A pointer to a variable that receives a pointer to an array of WTS_PROCESS_INFO or WTS_PROCESS_INFO_EX structures. The type of
+ /// structure is determined by the value passed to the pLevel parameter. Each structure in the array contains information about an
+ /// active process. When you have finished using the array, free it by calling the WTSFreeMemoryEx function. You should also set the
+ /// pointer to NULL.
+ ///
+ ///
+ /// A pointer to a variable that receives the number of structures returned in the buffer referenced by the ppProcessInfo parameter.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ /// The caller must be a member of the Administrators group to enumerate processes that are running under another user session.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumerateprocessesexa BOOL WTSEnumerateProcessesExA(
+ // HANDLE hServer, DWORD *pLevel, DWORD SessionId, LPSTR *ppProcessInfo, DWORD *pCount );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateProcessesExA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSEnumerateProcessesEx(HWTSSERVER hServer, ref uint pLevel, uint SessionId, out IntPtr ppProcessInfo, out uint pCount);
+
+ ///
+ /// Retrieves information about the active processes on the specified Remote Desktop Session Host (RD Session Host) server or Remote
+ /// Desktop Virtualization Host (RD Virtualization Host) server.
+ ///
+ ///
+ /// A handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer function, or specify
+ /// WTS_CURRENT_SERVER_HANDLE to indicate the server on which your application is running.
+ ///
+ ///
+ /// The session for which to enumerate processes. To enumerate processes for all sessions on the server, specify WTS_ANY_SESSION.
+ ///
+ /// An array of WTS_PROCESS_INFO_EX structures.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ /// The caller must be a member of the Administrators group to enumerate processes that are running under another user session.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumerateprocessesexa BOOL WTSEnumerateProcessesExA(
+ // HANDLE hServer, DWORD *pLevel, DWORD SessionId, LPSTR *ppProcessInfo, DWORD *pCount );
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateProcessesExA")]
+ public static bool WTSEnumerateProcessesEx(HWTSSERVER hServer, uint SessionId, out WTS_PROCESS_INFO_EX[] ppProcessInfo)
+ {
+ uint lvl = 1;
+ if (WTSEnumerateProcessesEx(hServer, ref lvl, SessionId, out var ptr, out var cnt) && lvl == 1)
+ {
+ try
+ {
+ ppProcessInfo = ptr.ToArray((int)cnt);
+ }
+ finally
+ {
+ WTSFreeMemoryEx(WTS_TYPE_CLASS.WTSTypeProcessInfoLevel1, ptr, cnt);
+ }
+ return true;
+ }
+ ppProcessInfo = null;
+ return false;
+ }
+
+ /// Returns a list of all Remote Desktop Session Host (RD Session Host) servers within the specified domain.
+ ///
+ /// Pointer to the name of the domain to be queried. If the value of this parameter is NULL, the specified domain is the
+ /// current domain.
+ ///
+ /// Reserved. The value of this parameter must be 0.
+ /// Version of the enumeration request. The value of the parameter must be 1.
+ ///
+ /// Points to an array of WTS_SERVER_INFO structures, which contains the returned results of the enumeration. After use, the memory
+ /// used by this buffer should be freed by calling WTSFreeMemory.
+ ///
+ ///
+ /// Pointer to a variable that receives the number of WTS_SERVER_INFO structures returned in the ppServerInfo buffer.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ /// This function will not work if NetBT is disabled.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumerateserversa BOOL WTSEnumerateServersA( LPSTR
+ // pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA *ppServerInfo, DWORD *pCount );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateServersA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSEnumerateServers([Optional, MarshalAs(UnmanagedType.LPTStr)] string pDomainName, [Optional] uint Reserved, uint Version,
+ out SafeWTSMemoryHandle ppServerInfo, out uint pCount);
+
+ /// Returns a list of all Remote Desktop Session Host (RD Session Host) servers within the specified domain.
+ ///
+ /// Pointer to the name of the domain to be queried. If the value of this parameter is NULL, the specified domain is the
+ /// current domain.
+ ///
+ /// An array of WTS_SERVER_INFO structures, which contains the returned results of the enumeration.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ /// This function will not work if NetBT is disabled.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumerateserversa BOOL WTSEnumerateServersA( LPSTR
+ // pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA *ppServerInfo, DWORD *pCount );
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateServersA")]
+ public static bool WTSEnumerateServers([Optional] string pDomainName, out WTS_SERVER_INFO[] ppServerInfo)
+ {
+ if (WTSEnumerateServers(pDomainName, 0, 1, out var ptr, out var cnt))
+ {
+ using (ptr)
+ ppServerInfo = ptr.ToArray((int)cnt);
+ return true;
+ }
+ ppServerInfo = null;
+ return false;
+ }
+
+ /// Retrieves a list of sessions on a Remote Desktop Session Host (RD Session Host) server.
+ ///
+ /// A handle to the RD Session Host server.
+ ///
+ /// Note You can use the WTSOpenServer or WTSOpenServerEx functions to retrieve a handle to a specific server, or
+ /// WTS_CURRENT_SERVER_HANDLE to use the RD Session Host server that hosts your application.
+ ///
+ ///
+ /// This parameter is reserved. It must be zero.
+ /// The version of the enumeration request. This parameter must be 1.
+ ///
+ ///
+ /// A pointer to an array of WTS_SESSION_INFO structures that represent the retrieved sessions. To free the returned buffer, call
+ /// the WTSFreeMemory function.
+ ///
+ /// Session permissions:
+ ///
+ /// -
+ ///
+ /// To enumerate a session, you must enable the query information permission. For more information, see Remote Desktop Services Permissions.
+ ///
+ ///
+ /// -
+ /// To change permissions on a session, use the Remote Desktop Services Configuration administrative tool.
+ ///
+ /// -
+ ///
+ /// To enumerate sessions running on a virtual machine hosted on a RD Virtualization Host server, you must be a member of the
+ /// Administrators group on the RD Virtualization Host server.
+ ///
+ ///
+ ///
+ ///
+ /// A pointer to the number of WTS_SESSION_INFO structures returned in the ppSessionInfo parameter.
+ ///
+ /// Returns zero if this function fails. If this function succeeds, a nonzero value is returned.
+ /// To get extended error information, call GetLastError.
+ ///
+ /// For more information, and an extended example on how to use this function, see the following kb article.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumeratesessionsa BOOL WTSEnumerateSessionsA( HANDLE
+ // hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA *ppSessionInfo, DWORD *pCount );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateSessionsA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSEnumerateSessions(HWTSSERVER hServer, [Optional] uint Reserved, uint Version, out SafeWTSMemoryHandle ppSessionInfo, out uint pCount);
+
+ ///
+ /// Retrieves a list of sessions on a specified Remote Desktop Session Host (RD Session Host) server or Remote Desktop
+ /// Virtualization Host (RD Virtualization Host) server.
+ ///
+ ///
+ /// A handle to the target server. Specify a handle returned by the WTSOpenServer or WTSOpenServerEx function. To enumerate sessions
+ /// on the RD Session Host server on which the application is running, specify WTS_CURRENT_SERVER_HANDLE.
+ ///
+ ///
+ /// This parameter is reserved. Always set this parameter to one. On output, WTSEnumerateSessionsEx does not change the value
+ /// of this parameter.
+ ///
+ /// This parameter is reserved. Always set this parameter to zero.
+ ///
+ /// A pointer to a PWTS_SESSION_INFO_1 variable that receives a pointer to an array of WTS_SESSION_INFO_1 structures. Each
+ /// structure in the array contains information about a session on the specified RD Session Host server. If you obtained a handle to
+ /// an RD Virtualization Host server by calling the WTSOpenServerEx function, the array contains information about sessions on
+ /// virtual machines on the server. When you have finished using the array, free it by calling the WTSFreeMemoryEx function. You
+ /// should also set the pointer to NULL.
+ ///
+ ///
+ /// A pointer to a DWORD variable that receives the number of WTS_SESSION_INFO_1 structures returned in the ppSessionInfo buffer.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ ///
+ /// To obtain information about sessions running on virtual machines on an RD Virtualization Host server, you must obtain the handle
+ /// by calling the WTSOpenServerEx function. To free the returned buffer, call the WTSFreeMemoryEx function and set the WTSClassType
+ /// parameter to WTSTypeSessionInfoLevel1.
+ ///
+ ///
+ /// To enumerate a session, you need to have the Query Information permission for that session. For more information, see Remote
+ /// Desktop Services Permissions. To modify permissions on a session, use the Remote Desktop Services Configuration administrative tool.
+ ///
+ ///
+ /// To enumerate sessions running on a virtual machine hosted on an RD Virtualization Host server, you must be a member of the
+ /// Administrators group on the RD Virtualization Host server.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumeratesessionsexa BOOL WTSEnumerateSessionsExA(
+ // HANDLE hServer, DWORD *pLevel, DWORD Filter, PWTS_SESSION_INFO_1A *ppSessionInfo, DWORD *pCount );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateSessionsExA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSEnumerateSessionsEx(HWTSSERVER hServer, in uint pLevel, [Optional] uint Filter, out IntPtr ppSessionInfo, out uint pCount);
+
+ ///
+ /// Retrieves a list of sessions on a specified Remote Desktop Session Host (RD Session Host) server or Remote Desktop
+ /// Virtualization Host (RD Virtualization Host) server.
+ ///
+ ///
+ /// A handle to the target server. Specify a handle returned by the WTSOpenServer or WTSOpenServerEx function. To enumerate sessions
+ /// on the RD Session Host server on which the application is running, specify WTS_CURRENT_SERVER_HANDLE.
+ ///
+ ///
+ /// Receives an array of WTS_SESSION_INFO_1 structures. Each
+ /// structure in the array contains information about a session on the specified RD Session Host server. If you obtained a handle to
+ /// an RD Virtualization Host server by calling the WTSOpenServerEx function, the array contains information about sessions on
+ /// virtual machines on the server.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ ///
+ /// To obtain information about sessions running on virtual machines on an RD Virtualization Host server, you must obtain the handle
+ /// by calling the WTSOpenServerEx function. To free the returned buffer, call the WTSFreeMemoryEx function and set the WTSClassType
+ /// parameter to WTSTypeSessionInfoLevel1.
+ ///
+ ///
+ /// To enumerate a session, you need to have the Query Information permission for that session. For more information, see Remote
+ /// Desktop Services Permissions. To modify permissions on a session, use the Remote Desktop Services Configuration administrative tool.
+ ///
+ ///
+ /// To enumerate sessions running on a virtual machine hosted on an RD Virtualization Host server, you must be a member of the
+ /// Administrators group on the RD Virtualization Host server.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumeratesessionsexa BOOL WTSEnumerateSessionsExA(
+ // HANDLE hServer, DWORD *pLevel, DWORD Filter, PWTS_SESSION_INFO_1A *ppSessionInfo, DWORD *pCount );
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSEnumerateSessionsExA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static bool WTSEnumerateSessionsEx(HWTSSERVER hServer, out WTS_SESSION_INFO_1[] ppSessionInfo)
+ {
+ if (WTSEnumerateSessionsEx(hServer, 1, 0, out var ptr, out var cnt))
+ {
+ try
+ {
+ ppSessionInfo = ptr.ToArray((int)cnt);
+ }
+ finally
+ {
+ WTSFreeMemoryEx(WTS_TYPE_CLASS.WTSTypeSessionInfoLevel1, ptr, cnt);
+ }
+ return true;
+ }
+ ppSessionInfo = null;
+ return false;
+ }
+
+ /// Frees memory allocated by a Remote Desktop Services function.
+ /// Pointer to the memory to free.
+ /// None
+ ///
+ /// Several Remote Desktop Services functions allocate buffers to return information. Use the WTSFreeMemory function to free
+ /// these buffers.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsfreememory void WTSFreeMemory( PVOID pMemory );
+ [DllImport(Lib_WTSApi32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSFreeMemory")]
+ public static extern void WTSFreeMemory(IntPtr pMemory);
+
+ ///
+ /// Frees memory that contains WTS_PROCESS_INFO_EX or WTS_SESSION_INFO_1 structures allocated by a Remote Desktop Services function.
+ ///
+ ///
+ /// A value of the WTS_TYPE_CLASS enumeration type that specifies the type of structures contained in the buffer referenced by the
+ /// pMemory parameter.
+ ///
+ /// A pointer to the buffer to free.
+ /// The number of elements in the buffer referenced by the pMemory parameter.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ /// Several Remote Desktop Services functions allocate buffers to return information. To free buffers that contain
+ /// WTS_PROCESS_INFO_EX or WTS_SESSION_INFO_1 structures, you must call the WTSFreeMemoryEx function. To free other buffers,
+ /// you can call either the WTSFreeMemory function or the WTSFreeMemoryEx function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsfreememoryexa BOOL WTSFreeMemoryExA( WTS_TYPE_CLASS
+ // WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSFreeMemoryExA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSFreeMemoryEx(WTS_TYPE_CLASS WTSTypeClass, IntPtr pMemory, uint NumberOfEntries);
+
+ /// Retrieves the child session identifier, if present.
+ ///
+ /// The address of a ULONG variable that receives the child session identifier. This will be ( ULONG)–1 if there is no
+ /// child session for the current session.
+ ///
+ /// Returns nonzero if the function succeeds or zero otherwise.
+ /// For more information about child sessions, see Child Sessions.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsgetchildsessionid BOOL WTSGetChildSessionId( PULONG
+ // pSessionId );
+ [DllImport(Lib_WTSApi32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSGetChildSessionId")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSGetChildSessionId(out uint pSessionId);
+
+ /// Retrieves the security descriptor of a Remote Desktop Services listener.
+ /// A handle to an RD Session Host server. Always set this parameter to WTS_CURRENT_SERVER_HANDLE.
+ /// This parameter is reserved. Always set this parameter to NULL.
+ /// This parameter is reserved. Always set this parameter to zero.
+ /// A pointer to a null-terminated string that contains the name of the listener.
+ ///
+ ///
+ /// A SECURITY_INFORMATION value that specifies the security information to retrieve. Always enable the
+ /// DACL_SECURITY_INFORMATION and SACL_SECURITY_INFORMATION flags.
+ ///
+ /// For more information about possible values, see SECURITY_INFORMATION.
+ ///
+ ///
+ ///
+ /// A pointer to a SECURITY_DESCRIPTOR structure that receives the security information associated with the listener referenced by
+ /// the pListenerName parameter. The SECURITY_DESCRIPTOR structure is returned in self-relative format. For more information
+ /// about possible values, see SECURITY_DESCRIPTOR.
+ ///
+ /// The discretionary access control list (DACL) of the security descriptor can contain one or more of the following values.
+ /// WTS_SECURITY_ALL_ACCESS
+ /// Combines these values:
+ ///
+ /// -
+ /// STANDARD_RIGHTS_REQUIRED
+ ///
+ /// -
+ /// WTS_SECURITY_CONNECT
+ ///
+ /// -
+ /// WTS_SECURITY_DISCONNECT
+ ///
+ /// -
+ /// WTS_SECURITY_LOGON
+ ///
+ /// -
+ /// WTS_SECURITY_MESSAGE
+ ///
+ /// -
+ /// WTS_SECURITY_QUERY_INFORMATION
+ ///
+ /// -
+ /// WTS_SECURITY_REMOTE_CONTROL
+ ///
+ /// -
+ /// WTS_SECURITY_RESET
+ ///
+ /// -
+ /// WTS_SECURITY_SET_INFORMATION
+ ///
+ /// -
+ /// WTS_SECURITY_VIRTUAL_CHANNELS
+ ///
+ ///
+ /// WTS_SECURITY_CONNECT (256 (0x100))
+ /// The right to connect.
+ /// WTS_SECURITY_CURRENT_GUEST_ACCESS
+ /// Combines these values:
+ ///
+ /// -
+ /// WTS_SECURITY_LOGOFF
+ ///
+ /// -
+ /// WTS_SECURITY_VIRTUAL_CHANNELS
+ ///
+ ///
+ /// WTS_SECURITY_CURRENT_USER_ACCESS
+ /// Combines these values:
+ ///
+ /// -
+ /// WTS_SECURITY_DISCONNECT
+ ///
+ /// -
+ /// WTS_SECURITY_LOGOFF
+ ///
+ /// -
+ /// WTS_SECURITY_RESET
+ ///
+ /// -
+ /// WTS_SECURITY_SET_INFORMATION
+ ///
+ /// -
+ /// WTS_SECURITY_VIRTUAL_CHANNELS
+ ///
+ ///
+ /// WTS_SECURITY_DISCONNECT (512 (0x200))
+ /// The right to disconnect.
+ /// WTS_SECURITY_GUEST_ACCESS
+ /// Defined as WTS_SECURITY_LOGON.
+ /// WTS_SECURITY_LOGOFF (64 (0x40))
+ /// The right to log off.
+ /// WTS_SECURITY_LOGON (32 (0x20))
+ /// The right to log on.
+ /// WTS_SECURITY_MESSAGE (128 (0x80))
+ /// The right to send a message to the user.
+ /// WTS_SECURITY_QUERY_INFORMATION (1 (0x1))
+ /// The right to query for information.
+ /// WTS_SECURITY_REMOTE_CONTROL (16 (0x10))
+ /// The right to use remote control.
+ /// WTS_SECURITY_RESET (4 (0x4))
+ /// The right to reset information.
+ /// WTS_SECURITY_SET_INFORMATION (2 (0x2))
+ /// The right to set information.
+ /// WTS_SECURITY_USER_ACCESS
+ /// Combines these values:
+ ///
+ /// -
+ /// WTS_SECURITY_CONNECT
+ ///
+ /// -
+ /// WTS_SECURITY_CURRENT_GUEST_ACCESS
+ ///
+ /// -
+ /// WTS_SECURITY_QUERY_INFORMATION
+ ///
+ ///
+ /// WTS_SECURITY_VIRTUAL_CHANNELS (8 (0x8))
+ /// The right to use virtual channels.
+ ///
+ /// The size, in bytes, of the SECURITY_DESCRIPTOR structure referenced by the pSecurityDescriptor parameter.
+ ///
+ /// A pointer to a variable that receives the number of bytes required to store the complete security descriptor. If this number is
+ /// less than or equal to the value of the nLength parameter, the security descriptor is copied to the SECURITY_DESCRIPTOR structure
+ /// referenced by the pSecurityDescriptor parameter; otherwise, no action is taken.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ /// If the number of bytes needed for the buffer that receives the SECURITY_DESCRIPTOR structure is unknown, you can call this
+ /// method with nLength set to zero. The method will then return, in the lpnLengthNeeded parameter, the number of bytes required for
+ /// the buffer. Allocate the buffer based on this number, and then call the method again, setting pSecurityDescriptor to the newly
+ /// allocated buffer and nLength to the number returned by the first call.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsgetlistenersecuritya BOOL WTSGetListenerSecurityA(
+ // HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation,
+ // PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSGetListenerSecurityA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSGetListenerSecurity(HWTSSERVER hServer, [In, Optional] IntPtr pReserved, [Optional] uint Reserved,
+ [MarshalAs(UnmanagedType.LPTStr)] string pListenerName, SECURITY_INFORMATION SecurityInformation,
+ [Out, Optional] PSECURITY_DESCRIPTOR pSecurityDescriptor, [Optional] uint nLength, out uint lpnLengthNeeded);
+
+ /// Determines whether child sessions are enabled.
+ ///
+ /// The address of a BOOL variable that receives a nonzero value if child sessions are enabled or zero otherwise.
+ ///
+ /// Returns nonzero if the function succeeds or zero otherwise.
+ /// For more information about child sessions, see Child Sessions.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsischildsessionsenabled BOOL WTSIsChildSessionsEnabled(
+ // PBOOL pbEnabled );
+ [DllImport(Lib_WTSApi32, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSIsChildSessionsEnabled")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSIsChildSessionsEnabled([MarshalAs(UnmanagedType.Bool)] out bool pbEnabled);
+
+ /// Logs off a specified Remote Desktop Services session.
+ ///
+ /// A handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer or WTSOpenServerEx function, or specify
+ /// WTS_CURRENT_SERVER_HANDLE to indicate the RD Session Host server on which your application is running.
+ ///
+ ///
+ ///
+ /// A Remote Desktop Services session identifier. To indicate the current session, specify WTS_CURRENT_SESSION. You can use
+ /// the WTSEnumerateSessions function to retrieve the identifiers of all sessions on a specified RD Session Host server.
+ ///
+ ///
+ /// To be able to log off another user's session, you need to have the Reset permission. For more information, see Remote Desktop
+ /// Services Permissions. To modify permissions on a session, use the Remote Desktop Services Configuration administrative tool.
+ ///
+ ///
+ /// To log off sessions running on a virtual machine hosted on a RD Virtualization Host server, you must be a member of the
+ /// Administrators group on the RD Virtualization Host server.
+ ///
+ ///
+ ///
+ /// Indicates whether the operation is synchronous.
+ /// If bWait is TRUE, the function returns when the session is logged off.
+ ///
+ /// If bWait is FALSE, the function returns immediately. To verify that the session has been logged off, specify the session
+ /// identifier in a call to the WTSQuerySessionInformation function. WTSQuerySessionInformation returns zero if the session
+ /// is logged off.
+ ///
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtslogoffsession BOOL WTSLogoffSession( HANDLE hServer,
+ // DWORD SessionId, BOOL bWait );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSLogoffSession")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSLogoffSession(HWTSSERVER hServer, uint SessionId, [MarshalAs(UnmanagedType.Bool)] bool bWait);
+
+ /// Opens a handle to the specified Remote Desktop Session Host (RD Session Host) server.
+ /// Pointer to a null-terminated string specifying the NetBIOS name of the RD Session Host server.
+ ///
+ /// If the function succeeds, the return value is a handle to the specified server.
+ ///
+ /// If the function fails, it returns a handle that is not valid. You can test the validity of the handle by using it in another
+ /// function call.
+ ///
+ ///
+ ///
+ /// When you have finished using the handle returned by WTSOpenServer, release it by calling the WTSCloseServer function.
+ ///
+ /// You do not need to open a handle for operations performed on the RD Session Host server on which your application is running.
+ /// Use the constant WTS_CURRENT_SERVER_HANDLE instead.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsopenservera HANDLE WTSOpenServerA( LPSTR pServerName );
+ [DllImport(Lib_WTSApi32, SetLastError = false, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSOpenServerA")]
+ public static extern SafeHWTSSERVER WTSOpenServer([MarshalAs(UnmanagedType.LPTStr)] string pServerName);
+
+ ///
+ /// Opens a handle to the specified Remote Desktop Session Host (RD Session Host) server or Remote Desktop Virtualization Host (RD
+ /// Virtualization Host) server.
+ ///
+ /// A pointer to a null-terminated string that contains the NetBIOS name of the server.
+ ///
+ /// If the function succeeds, the return value is a handle to the specified server.
+ ///
+ /// If the function fails, it returns an invalid handle. You can test the validity of the handle by using it in another function call.
+ ///
+ ///
+ ///
+ ///
+ /// If the server specified by the pServerName parameter is an RD Session Host server, the behavior of this function is identical to
+ /// that of the WTSOpenServer function.
+ ///
+ ///
+ /// To work with sessions running on virtual machines on the RD Virtualization Host server on which the calling application is
+ /// running, specify WTS_CURRENT_SERVER_NAME for the pServerName parameter.
+ ///
+ /// When you have finished using the handle returned by this function, release it by calling the WTSCloseServer function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsopenserverexa HANDLE WTSOpenServerExA( LPSTR
+ // pServerName );
+ [DllImport(Lib_WTSApi32, SetLastError = false, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSOpenServerExA")]
+ public static extern SafeHWTSSERVER WTSOpenServerEx([MarshalAs(UnmanagedType.LPTStr)] string pServerName);
+
+ /// Retrieves configuration information for a Remote Desktop Services listener.
+ /// A handle to an RD Session Host server. Always set this parameter to WTS_CURRENT_SERVER_HANDLE.
+ /// This parameter is reserved. Always set this parameter to NULL.
+ /// This parameter is reserved. Always set this parameter to zero.
+ /// A pointer to a null-terminated string that contains the name of the listener to query.
+ /// A pointer to a WTSLISTENERCONFIG structure that receives the retrieved listener configuration information.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ /// This function does not retrieve the security descriptor for the listener. To retrieve the security descriptor, call the
+ /// WTSGetListenerSecurity function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsquerylistenerconfiga BOOL WTSQueryListenerConfigA(
+ // HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSQueryListenerConfigA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSQueryListenerConfig(HWTSSERVER hServer, [In, Optional] IntPtr pReserved, [In, Optional] uint Reserved,
+ [MarshalAs(UnmanagedType.LPTStr)] string pListenerName, out WTSLISTENERCONFIG pBuffer);
+
+ ///
+ /// Retrieves session information for the specified session on the specified Remote Desktop Session Host (RD Session Host) server.
+ /// It can be used to query session information on local and remote RD Session Host servers.
+ ///
+ ///
+ /// A handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer function, or specify
+ /// WTS_CURRENT_SERVER_HANDLE to indicate the RD Session Host server on which your application is running.
+ ///
+ ///
+ ///
+ /// A Remote Desktop Services session identifier. To indicate the session in which the calling application is running (or the
+ /// current session) specify WTS_CURRENT_SESSION. Only specify WTS_CURRENT_SESSION when obtaining session information
+ /// on the local server. If WTS_CURRENT_SESSION is specified when querying session information on a remote server, the
+ /// returned session information will be inconsistent. Do not use the returned data.
+ ///
+ ///
+ /// You can use the WTSEnumerateSessions function to retrieve the identifiers of all sessions on a specified RD Session Host server.
+ ///
+ ///
+ /// To query information for another user's session, you must have Query Information permission. For more information, see Remote
+ /// Desktop Services Permissions. To modify permissions on a session, use the Remote Desktop Services Configuration administrative tool.
+ ///
+ ///
+ ///
+ /// A value of the WTS_INFO_CLASS enumeration that indicates the type of session information to retrieve in a call to the
+ /// WTSQuerySessionInformation function.
+ ///
+ ///
+ /// A pointer to a variable that receives a pointer to the requested information. The format and contents of the data depend on the
+ /// information class specified in the WTSInfoClass parameter. To free the returned buffer, call the WTSFreeMemory function.
+ ///
+ /// A pointer to a variable that receives the size, in bytes, of the data returned in ppBuffer.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// To retrieve the session ID for the current session when Remote Desktop Services is running, call
+ /// WTSQuerySessionInformation and specify WTS_CURRENT_SESSION for the SessionId parameter and WTSSessionId for
+ /// the WTSInfoClass parameter. The session ID will be returned in the ppBuffer parameter. If Remote Desktop Services is not
+ /// running, calls to WTSQuerySessionInformation fail. In this situation, you can retrieve the current session ID by calling
+ /// the ProcessIdToSessionId function.
+ ///
+ ///
+ /// To determine whether your application is running on the physical console, you must specify WTS_CURRENT_SESSION for the
+ /// SessionId parameter, and WTSClientProtocolType as the WTSInfoClass parameter. If ppBuffer is "0", the session is attached
+ /// to the physical console.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsquerysessioninformationa BOOL
+ // WTSQuerySessionInformationA( HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR *ppBuffer, DWORD *pBytesReturned );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSQuerySessionInformationA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSQuerySessionInformation(HWTSSERVER hServer, uint SessionId, WTS_INFO_CLASS WTSInfoClass,
+ out SafeWTSMemoryHandle ppBuffer, out uint pBytesReturned);
+
+ ///
+ /// Retrieves configuration information for the specified user on the specified domain controller or Remote Desktop Session Host (RD
+ /// Session Host) server.
+ ///
+ ///
+ /// Pointer to a null-terminated string containing the name of a domain controller or an RD Session Host server. Specify
+ /// WTS_CURRENT_SERVER_NAME to indicate the RD Session Host server on which your application is running.
+ ///
+ ///
+ ///
+ /// Pointer to a null-terminated string containing the user name to query. To retrieve the default user settings for the RD Session
+ /// Host server, set this parameter to NULL.
+ ///
+ /// Windows Server 2008 and Windows Vista: Setting this parameter to NULL returns an error.
+ ///
+ ///
+ /// Specifies the type of information to retrieve. This parameter can be one of the values from the WTS_CONFIG_CLASS enumeration
+ /// type. The documentation for WTS_CONFIG_CLASS describes the format of the data returned in ppBuffer for each of the
+ /// information types.
+ ///
+ ///
+ /// Pointer to a variable that receives a pointer to the requested information. The format and contents of the data depend on the
+ /// information class specified in the WTSConfigClass parameter. To free the returned buffer, call the WTSFreeMemory function.
+ ///
+ /// Pointer to a variable that receives the size, in bytes, of the data returned in ppBuffer.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// The WTSQueryUserConfig and WTSSetUserConfig functions are passed a server name instead of a handle because user account
+ /// information often resides on a domain controller. To set user configuration information, use the primary domain controller. You
+ /// can call the NetGetDCName function to get the name of the primary domain controller. To query user configuration information,
+ /// you can use the NetGetAnyDCName function to get the name of a primary or backup domain controller.
+ ///
+ ///
+ /// Any domain controller can set or query user configuration information. Use the DsGetDcName function to retrieve the name of a
+ /// domain controller.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsqueryuserconfiga BOOL WTSQueryUserConfigA( LPSTR
+ // pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR *ppBuffer, DWORD *pBytesReturned );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSQueryUserConfigA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSQueryUserConfig([MarshalAs(UnmanagedType.LPTStr)] string pServerName, [Optional, MarshalAs(UnmanagedType.LPTStr)] string pUserName,
+ WTS_CONFIG_CLASS WTSConfigClass, out SafeWTSMemoryHandle ppBuffer, out uint pBytesReturned);
+
+ ///
+ ///
+ /// Obtains the primary access token of the logged-on user specified by the session ID. To call this function successfully, the
+ /// calling application must be running within the context of the LocalSystem account and have the SE_TCB_NAME privilege.
+ ///
+ ///
+ /// CautionWTSQueryUserToken is intended for highly trusted services. Service providers must use caution that they do
+ /// not leak user tokens when calling this function. Service providers must close token handles after they have finished using them.
+ ///
+ ///
+ ///
+ ///
+ /// A Remote Desktop Services session identifier. Any program running in the context of a service will have a session identifier of
+ /// zero (0). You can use the WTSEnumerateSessions function to retrieve the identifiers of all sessions on a specified RD Session
+ /// Host server.
+ ///
+ ///
+ /// To be able to query information for another user's session, you need to have the Query Information permission. For more
+ /// information, see Remote Desktop Services Permissions. To modify permissions on a session, use the Remote Desktop Services
+ /// Configuration administrative tool.
+ ///
+ ///
+ ///
+ /// If the function succeeds, receives a pointer to the token handle for the logged-on user. Note that you must call the CloseHandle
+ /// function to close this handle.
+ ///
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value, and the phToken parameter points to the primary token of the user.
+ ///
+ ///
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError. Among other errors,
+ /// GetLastError can return one of the following errors.
+ ///
+ ///
+ ///
+ ///
+ /// For information about primary tokens, see Access Tokens. For more information about account privileges, see Remote Desktop
+ /// Services Permissions and Authorization Constants.
+ ///
+ /// See LocalSystem account for information about the privileges associated with that account.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsqueryusertoken BOOL WTSQueryUserToken( ULONG
+ // SessionId, PHANDLE phToken );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSQueryUserToken")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSQueryUserToken(uint SessionId, out HTOKEN phToken);
+
+ /// Registers the specified window to receive session change notifications.
+ /// Handle of the window to receive session change notifications.
+ ///
+ /// Specifies which session notifications are to be received. This parameter can be one of the following values.
+ /// 0 - NOTIFY_FOR_THIS_SESSION
+ ///
+ /// Only session notifications involving the session attached to by the window identified by the hWnd parameter value are to be received.
+ ///
+ /// 1 - NOTIFY_FOR_ALL_SESSIONS
+ /// All session notifications are to be received.
+ ///
+ ///
+ /// If the function succeeds, the return value is TRUE. Otherwise, it is FALSE. To get extended error information,
+ /// call GetLastError.
+ ///
+ ///
+ ///
+ /// If this function is called before the dependent services of Remote Desktop Services have started, an
+ /// RPC_S_INVALID_BINDING error code may be returned. When the Global\TermSrvReadyEvent global event is set, all dependent
+ /// services have started and this function can be successfully called.
+ ///
+ ///
+ /// Session change notifications are sent in the form of a WM_WTSSESSION_CHANGE message. These notifications are sent only to the
+ /// windows that have registered for them using this function.
+ ///
+ ///
+ /// When a window no longer requires these notifications, it must call WTSUnRegisterSessionNotification before being destroyed. For
+ /// every call to this function, there must be a corresponding call to WTSUnRegisterSessionNotification.
+ ///
+ /// If the window handle passed in this function is already registered, the value of the dwFlags parameter is ignored.
+ /// To receive session change notifications from a service, use the HandlerEx function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsregistersessionnotification BOOL
+ // WTSRegisterSessionNotification( HWND hWnd, DWORD dwFlags );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSRegisterSessionNotification")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSRegisterSessionNotification(HWND hWnd, uint dwFlags);
+
+ /// Registers the specified window to receive session change notifications.
+ /// Handle of the server returned from WTSOpenServer or WTS_CURRENT_SERVER.
+ /// Handle of the window to receive session change notifications.
+ ///
+ ///
+ /// Specifies which session notifications are to be received. This parameter can only be NOTIFY_FOR_THIS_SESSION if hServer
+ /// is a remote server.
+ ///
+ ///
+ /// - NOTIFY_FOR_THIS_SESSION (0)
+ ///
+ /// Only session notifications involving the session attached to by the window identified by the hWnd parameter value are to be received.
+ ///
+ ///
+ /// - NOTIFY_FOR_ALL_SESSIONS (1)
+ /// All session notifications are to be received.
+ ///
+ ///
+ ///
+ ///
+ /// If the function succeeds, the return value is TRUE. Otherwise, it is FALSE. To get extended error information,
+ /// call GetLastError.
+ ///
+ ///
+ ///
+ /// If this function is called before the dependent services of Remote Desktop Services have started, an
+ /// RPC_S_INVALID_BINDING error code may be returned. When the "Global\TermSrvReadyEvent" global event is set, all dependent
+ /// services have started and this function can be successfully called.
+ ///
+ ///
+ /// Session change notifications are sent in the form of a WM_WTSSESSION_CHANGE message. These notifications are sent only to the
+ /// windows that have registered for them using this function.
+ ///
+ ///
+ /// When a window no longer requires these notifications, it must call WTSUnRegisterSessionNotificationEx before being destroyed.
+ /// For every call to this function, there must be a corresponding call to WTSUnRegisterSessionNotificationEx.
+ ///
+ /// If the window handle passed in this function is already registered, the value of the dwFlags parameter is ignored.
+ /// To receive session change notifications from a service, use the HandlerEx function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsregistersessionnotificationex BOOL
+ // WTSRegisterSessionNotificationEx( HANDLE hServer, HWND hWnd, DWORD dwFlags );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSRegisterSessionNotificationEx")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSRegisterSessionNotificationEx(HWTSSERVER hServer, HWND hWnd, uint dwFlags);
+
+ /// Displays a message box on the client desktop of a specified Remote Desktop Services session.
+ ///
+ /// A handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer function, or specify
+ /// WTS_CURRENT_SERVER_HANDLE to indicate the RD Session Host server on which your application is running.
+ ///
+ ///
+ ///
+ /// A Remote Desktop Services session identifier. To indicate the current session, specify WTS_CURRENT_SESSION. You can use
+ /// the WTSEnumerateSessions function to retrieve the identifiers of all sessions on a specified RD Session Host server.
+ ///
+ ///
+ /// To send a message to another user's session, you need to have the Message permission. For more information, see Remote Desktop
+ /// Services Permissions. To modify permissions on a session, use the Remote Desktop Services Configuration administrative tool.
+ ///
+ ///
+ /// A pointer to a null-terminated string for the title bar of the message box.
+ /// The length, in bytes, of the title bar string.
+ /// A pointer to a null-terminated string that contains the message to display.
+ /// The length, in bytes, of the message string.
+ ///
+ /// The contents and behavior of the message box. This value is typically MB_OK. For a complete list of values, see the uType
+ /// parameter of the MessageBox function.
+ ///
+ ///
+ /// The time, in seconds, that the WTSSendMessage function waits for the user's response. If the user does not respond within
+ /// the time-out interval, the pResponse parameter returns IDTIMEOUT. If the Timeout parameter is zero, WTSSendMessage
+ /// waits indefinitely for the user to respond.
+ ///
+ ///
+ /// A pointer to a variable that receives the user's response, which can be one of the following values.
+ /// IDABORT (3)
+ /// Abort
+ /// IDCANCEL (2)
+ /// Cancel
+ /// IDCONTINUE (11)
+ /// Continue
+ /// IDIGNORE (5)
+ /// Ignore
+ /// IDNO (7)
+ /// No
+ /// IDOK (1)
+ /// OK
+ /// IDRETRY (4)
+ /// Retry
+ /// IDTRYAGAIN (10)
+ /// Try Again
+ /// IDYES (6)
+ /// Yes
+ /// IDASYNC (32001 (0x7D01))
+ /// The bWait parameter was FALSE, so the function returned without waiting for a response.
+ /// IDTIMEOUT (32000 (0x7D00))
+ /// The bWait parameter was TRUE and the time-out interval elapsed.
+ ///
+ ///
+ ///
+ /// If TRUE, WTSSendMessage does not return until the user responds or the time-out interval elapses. If the Timeout
+ /// parameter is zero, the function does not return until the user responds.
+ ///
+ ///
+ /// If FALSE, the function returns immediately and the pResponse parameter returns IDASYNC. Use this method for simple
+ /// information messages (such as print job–notification messages) that do not need to return the user's response to the calling program.
+ ///
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtssendmessagea BOOL WTSSendMessageA( HANDLE hServer,
+ // DWORD SessionId, LPSTR pTitle, DWORD TitleLength, LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD
+ // *pResponse, BOOL bWait );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSSendMessageA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSSendMessage(HWTSSERVER hServer, uint SessionId, [MarshalAs(UnmanagedType.LPTStr)] string pTitle, int TitleLength,
+ [MarshalAs(UnmanagedType.LPTStr)] string pMessage, int MessageLength, uint Style, uint Timeout, out uint pResponse, [MarshalAs(UnmanagedType.Bool)] bool bWait);
+
+ /// Configures the security descriptor of a Remote Desktop Services listener.
+ /// A handle to an RD Session Host server. Always set this parameter to WTS_CURRENT_SERVER_HANDLE.
+ /// This parameter is reserved. Always set this parameter to NULL.
+ /// This parameter is reserved. Always set this parameter to zero.
+ /// A pointer to a null-terminated string that contains the name of the listener.
+ ///
+ ///
+ /// A SECURITY_INFORMATION value that specifies the security information to set. Always enable the DACL_SECURITY_INFORMATION
+ /// and SACL_SECURITY_INFORMATION flags.
+ ///
+ /// For more information about possible values, see SECURITY_INFORMATION.
+ ///
+ ///
+ ///
+ /// A pointer to a SECURITY_DESCRIPTOR structure that contains the security information associated with the listener. For more
+ /// information about possible values, see SECURITY_DESCRIPTOR. For information about STANDARD_RIGHTS_REQUIRED, see
+ /// Standard Access Rights.
+ ///
+ /// The discretionary access control list (DACL) of the security descriptor can contain one or more of the following values.
+ /// WTS_SECURITY_ALL_ACCESS
+ /// Combines these values:
+ ///
+ /// -
+ /// STANDARD_RIGHTS_REQUIRED
+ ///
+ /// -
+ /// WTS_SECURITY_CONNECT
+ ///
+ /// -
+ /// WTS_SECURITY_DISCONNECT
+ ///
+ /// -
+ /// WTS_SECURITY_LOGON
+ ///
+ /// -
+ /// WTS_SECURITY_MESSAGE
+ ///
+ /// -
+ /// WTS_SECURITY_QUERY_INFORMATION
+ ///
+ /// -
+ /// WTS_SECURITY_REMOTE_CONTROL
+ ///
+ /// -
+ /// WTS_SECURITY_RESET
+ ///
+ /// -
+ /// WTS_SECURITY_SET_INFORMATION
+ ///
+ /// -
+ /// WTS_SECURITY_VIRTUAL_CHANNELS
+ ///
+ ///
+ /// WTS_SECURITY_CONNECT (256 (0x100))
+ /// The right to connect.
+ /// WTS_SECURITY_CURRENT_GUEST_ACCESS
+ /// Combines these values:
+ ///
+ /// -
+ /// WTS_SECURITY_LOGOFF
+ ///
+ /// -
+ /// WTS_SECURITY_VIRTUAL_CHANNELS
+ ///
+ ///
+ /// WTS_SECURITY_CURRENT_USER_ACCESS
+ /// Combines these values:
+ ///
+ /// -
+ /// WTS_SECURITY_DISCONNECT
+ ///
+ /// -
+ /// WTS_SECURITY_LOGOFF
+ ///
+ /// -
+ /// WTS_SECURITY_RESET
+ ///
+ /// -
+ /// WTS_SECURITY_SET_INFORMATION
+ ///
+ /// -
+ /// WTS_SECURITY_VIRTUAL_CHANNELS
+ ///
+ ///
+ /// WTS_SECURITY_DISCONNECT (512 (0x200))
+ /// The right to disconnect.
+ /// WTS_SECURITY_GUEST_ACCESS
+ /// Defined as WTS_SECURITY_LOGON.
+ /// WTS_SECURITY_LOGOFF (64 (0x40))
+ /// The right to log off.
+ /// WTS_SECURITY_LOGON (32 (0x20))
+ /// The right to log on.
+ /// WTS_SECURITY_MESSAGE (128 (0x80))
+ /// The right to send a message to the user.
+ /// WTS_SECURITY_QUERY_INFORMATION (1 (0x1))
+ /// The right to query for information.
+ /// WTS_SECURITY_REMOTE_CONTROL (16 (0x10))
+ /// The right to use remote control.
+ /// WTS_SECURITY_RESET (4 (0x4))
+ /// The right to reset information.
+ /// WTS_SECURITY_SET_INFORMATION (2 (0x2))
+ /// The right to set information.
+ /// WTS_SECURITY_USER_ACCESS
+ /// Combines these values:
+ ///
+ /// -
+ /// WTS_SECURITY_CONNECT
+ ///
+ /// -
+ /// WTS_SECURITY_CURRENT_GUEST_ACCESS
+ ///
+ /// -
+ /// WTS_SECURITY_QUERY_INFORMATION
+ ///
+ ///
+ /// WTS_SECURITY_VIRTUAL_CHANNELS (8 (0x8))
+ /// The right to use virtual channels.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtssetlistenersecuritya BOOL WTSSetListenerSecurityA(
+ // HANDLE hServer, PVOID pReserved, DWORD Reserved, LPSTR pListenerName, SECURITY_INFORMATION SecurityInformation,
+ // PSECURITY_DESCRIPTOR pSecurityDescriptor );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSSetListenerSecurityA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSSetListenerSecurity(HWTSSERVER hServer, [In, Optional] IntPtr pReserved, [In, Optional] uint Reserved,
+ [MarshalAs(UnmanagedType.LPTStr)] string pListenerName, SECURITY_INFORMATION SecurityInformation, [In] PSECURITY_DESCRIPTOR pSecurityDescriptor);
+
+ ///
+ /// Modifies configuration information for the specified user on the specified domain controller or Remote Desktop Session Host (RD
+ /// Session Host) server.
+ ///
+ ///
+ /// Pointer to a null-terminated string containing the name of a domain controller or RD Session Host server. Specify
+ /// WTS_CURRENT_SERVER_NAME to indicate the RD Session Host server on which your application is running.
+ ///
+ /// Pointer to a null-terminated string containing the name of the user whose configuration is being set.
+ ///
+ /// Specifies the type of information to set for the user. This parameter can be one of the values from the WTS_CONFIG_CLASS
+ /// enumeration type. The documentation for WTS_CONFIG_CLASS describes the format of the data specified in ppBuffer for each
+ /// of the information types.
+ ///
+ /// Pointer to the data used to modify the specified user's configuration.
+ /// Size, in TCHARs, of the pBuffer buffer.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// The WTSQueryUserConfig and WTSSetUserConfig functions are passed a server name instead of a handle because user account
+ /// information often resides on a domain controller. To set user configuration information, use the primary domain controller. You
+ /// can call the NetGetDCName function to get the name of the primary domain controller. To query user configuration information,
+ /// you can use the NetGetAnyDCName function to get the name of a primary or backup domain controller.
+ ///
+ ///
+ /// Any domain controller can set or query user configuration information. Use the DsGetDcName function to retrieve the name of a
+ /// domain controller.
+ ///
+ ///
+ /// If the value of the WTSConfigClass parameter corresponds to an integer value in the WTS_CONFIG_CLASS enumeration, define the
+ /// value to be set as a DWORD. Then cast the value to an LPWSTR in the call to WTSSetUserConfig, as in the
+ /// following example:
+ ///
+ ///
+ /// WTSSetUserConfig( strServer.GetBuffer(0), m_strName.GetBuffer(0), WTSUserConfigfAllowLogonTerminalServer, (LPWSTR) &dwEnable, sizeof(DWORD));
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtssetuserconfiga BOOL WTSSetUserConfigA( LPSTR
+ // pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSSetUserConfigA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSSetUserConfig([MarshalAs(UnmanagedType.LPTStr)] string pServerName, [MarshalAs(UnmanagedType.LPTStr)] string pUserName,
+ WTS_CONFIG_CLASS WTSConfigClass, [MarshalAs(UnmanagedType.LPTStr)] string pBuffer, int DataLength);
+
+ ///
+ /// Shuts down (and optionally restarts) the specified Remote Desktop Session Host (RD Session Host) server.
+ ///
+ /// To shut down or restart the system, the calling process must have the SE_SHUTDOWN_NAME privilege enabled. For more
+ /// information about security privileges, see Privileges and Authorization Constants.
+ ///
+ ///
+ ///
+ /// Handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer function, or specify
+ /// WTS_CURRENT_SERVER_HANDLE to indicate the RD Session Host server on which your application is running.
+ ///
+ ///
+ /// Indicates the type of shutdown. This parameter can be one of the following values.
+ /// WTS_WSD_LOGOFF
+ ///
+ /// Forces all client sessions to log off (except the session calling WTSShutdownSystem) and disables any subsequent remote
+ /// logons. This can be used as a step before shutting down. Logons will be re-enabled when the Remote Desktop Services service is restarted.
+ ///
+ /// Use this value only on the Remote Desktop Services console.
+ /// WTS_WSD_POWEROFF
+ ///
+ /// Shuts down the system on the RD Session Host server and, on computers that support software control of AC power, turns off the
+ /// power. This is equivalent to calling ExitWindowsEx with EWX_SHUTDOWN and EWX_POWEROFF. The calling process must
+ /// have the SE_SHUTDOWN_NAME privilege enabled.
+ ///
+ /// WTS_WSD_REBOOT
+ ///
+ /// Shuts down and then restarts the system on the RD Session Host server. This is equivalent to calling ExitWindowsEx with
+ /// EWX_REBOOT. The calling process must have the SE_SHUTDOWN_NAME privilege enabled.
+ ///
+ /// WTS_WSD_SHUTDOWN
+ ///
+ /// Shuts down the system on the RD Session Host server. This is equivalent to calling the ExitWindowsEx function with
+ /// EWX_SHUTDOWN. The calling process must have the SE_SHUTDOWN_NAME privilege enabled.
+ ///
+ /// WTS_WSD_FASTREBOOT
+ /// This value is not supported currently.
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// A system shutdown terminates all users and active programs. The following steps occur during shutdown.
+ ///
+ /// -
+ /// An exit command is issued to all active user applications.
+ ///
+ /// -
+ /// If the application does not exit within a specific interval, the application is terminated.
+ ///
+ /// -
+ /// After all the applications for a user terminate, the user is logged off.
+ ///
+ /// -
+ /// After all users are logged off, an exit command is issued to all system services.
+ ///
+ /// -
+ /// If the system service does not terminate within a specific interval, the service is terminated.
+ ///
+ /// -
+ /// The file system cache is written to disk.
+ ///
+ /// -
+ /// The disks are marked read-only.
+ ///
+ /// -
+ ///
+ /// The RD Session Host server displays the message "It is now safe to turn off your computer", or the system is restarted if
+ /// WTS_WSD_REBOOT is specified. (The message is displayed on the console because all client sessions have been terminated.)
+ ///
+ ///
+ ///
+ ///
+ /// Note Because there can be many users and processes in a large multiple-user configuration, large system configurations
+ /// may take some time to shut down in an orderly fashion. It is important to allow the system to shut down completely.
+ ///
+ ///
+ /// Windows Server 2008 and Windows Vista: A call to WTSShutdownSystem does not work when Remote Connection Manager
+ /// (RCM) is disabled. This is the case when the Remote Desktop Services service is stopped.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsshutdownsystem BOOL WTSShutdownSystem( HANDLE hServer,
+ // DWORD ShutdownFlag );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSShutdownSystem")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSShutdownSystem(HWTSSERVER hServer, WTS_WSD ShutdownFlag);
+
+ ///
+ /// Starts the remote control of another Remote Desktop Services session. You must call this function from a remote session.
+ ///
+ /// A pointer to the name of the server where the session that you want remote control of exists.
+ /// The logon ID of the session that you want remote control of.
+ ///
+ /// The virtual-key code that represents the key to press to stop remote control of the session. The key that is defined in this
+ /// parameter is used with the HotkeyModifiers parameter.
+ ///
+ ///
+ ///
+ /// The virtual modifier that represents the key to press to stop remote control of the session. The virtual modifier is used with
+ /// the HotkeyVk parameter.
+ ///
+ ///
+ /// For example, if the WTSStartRemoteControlSession function is called with HotkeyVk set to VK_MULTIPLY and
+ /// HotkeyModifiers set to REMOTECONTROL_KBDCTRL_HOTKEY, the user who has remote control of the target session can press CTRL
+ /// + * to stop remote control of the session and return to their own session.
+ ///
+ /// REMOTECONTROL_KBDSHIFT_HOTKEY
+ /// The SHIFT key
+ /// REMOTECONTROL_KBDCTRL_HOTKEY
+ /// The CTRL key
+ /// REMOTECONTROL_KBDALT_HOTKEY
+ /// The ALT key
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsstartremotecontrolsessiona BOOL
+ // WTSStartRemoteControlSessionA( LPSTR pTargetServerName, ULONG TargetLogonId, BYTE HotkeyVk, USHORT HotkeyModifiers );
+ [DllImport(Lib_WTSApi32, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSStartRemoteControlSessionA")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSStartRemoteControlSession([MarshalAs(UnmanagedType.LPTStr)] string pTargetServerName, uint TargetLogonId,
+ byte HotkeyVk, REMOTECONTROL_HOTKEY HotkeyModifiers);
+
+ /// Stops a remote control session.
+ /// The logon ID of the session that you want to stop the remote control of.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsstopremotecontrolsession BOOL
+ // WTSStopRemoteControlSession( ULONG LogonId );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSStopRemoteControlSession")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSStopRemoteControlSession(uint LogonId);
+
+ /// Terminates the specified process on the specified Remote Desktop Session Host (RD Session Host) server.
+ ///
+ /// Handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer function, or specify WTS_CURRENT_SERVER_HANDLE
+ /// to indicate the RD Session Host server on which your application is running.
+ ///
+ /// Specifies the process identifier of the process to terminate.
+ /// Specifies the exit code for the terminated process.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsterminateprocess BOOL WTSTerminateProcess( HANDLE
+ // hServer, DWORD ProcessId, DWORD ExitCode );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSTerminateProcess")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSTerminateProcess(HWTSSERVER hServer, uint ProcessId, uint ExitCode);
+
+ /// Unregisters the specified window so that it receives no further session change notifications.
+ /// Handle of the window to be unregistered from receiving session notifications.
+ ///
+ /// If the function succeeds, the return value is TRUE. Otherwise, it is FALSE. To get extended error information,
+ /// call GetLastError.
+ ///
+ /// This function must be called once for every call to the WTSRegisterSessionNotification function.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsunregistersessionnotification BOOL
+ // WTSUnRegisterSessionNotification( HWND hWnd );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSUnRegisterSessionNotification")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSUnRegisterSessionNotification(HWND hWnd);
+
+ /// Unregisters the specified window so that it receives no further session change notifications.
+ /// Handle of the server returned from WTSOpenServer or WTS_CURRENT_SERVER.
+ /// Handle of the window to be unregistered from receiving session notifications.
+ ///
+ /// If the function succeeds, the return value is TRUE. Otherwise, it is FALSE. To get extended error information,
+ /// call GetLastError.
+ ///
+ /// This function must be called once for every call to the WTSRegisterSessionNotificationEx function.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsunregistersessionnotificationex BOOL
+ // WTSUnRegisterSessionNotificationEx( HANDLE hServer, HWND hWnd );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSUnRegisterSessionNotificationEx")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSUnRegisterSessionNotificationEx(HWTSSERVER hServer, HWND hWnd);
+
+ /// Closes an open virtual channel handle.
+ /// Handle to a virtual channel opened by the WTSVirtualChannelOpen function.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelclose BOOL WTSVirtualChannelClose(
+ // HANDLE hChannelHandle );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelClose")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSVirtualChannelClose(HVIRTUALCHANNEL hChannelHandle);
+
+ ///
+ /// Opens a handle to the server end of a specified virtual channel.
+ /// This function is obsolete. Instead, use the WTSVirtualChannelOpenEx function.
+ ///
+ /// This parameter must be WTS_CURRENT_SERVER_HANDLE.
+ ///
+ ///
+ /// A Remote Desktop Services session identifier. To indicate the current session, specify WTS_CURRENT_SESSION. You can use
+ /// the WTSEnumerateSessions function to retrieve the identifiers of all sessions on a specified RD Session Host server.
+ ///
+ ///
+ /// To open a virtual channel on another user's session, you need to have permission from the Virtual Channel. For more information,
+ /// see Remote Desktop Services Permissions. To modify permissions on a session, use the Remote Desktop Services Configuration
+ /// administrative tool.
+ ///
+ ///
+ ///
+ /// A pointer to a null-terminated string containing the virtual channel name. Note that this is an ANSI string even when
+ /// UNICODE is defined. The virtual channel name consists of one to CHANNEL_NAME_LEN characters, not including the terminating null.
+ ///
+ ///
+ /// If the function succeeds, the return value is a handle to the specified virtual channel.
+ /// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// When you have finished using the handle, release it by calling the WTSVirtualChannelClose function.
+ ///
+ /// For an example that shows how to gain access to a virtual channel file handle that can be used for asynchronous I/O, see WTSVirtualChannelQuery.
+ ///
+ ///
+ /// If you try to use this function to open the same virtual channel multiple times, it can cause a 10-second delay and disrupt the
+ /// established channel.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelopen HANDLE WTSVirtualChannelOpen(
+ // HANDLE hServer, DWORD SessionId, LPSTR pVirtualName );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelOpen")]
+ public static extern SafeHVIRTUALCHANNEL WTSVirtualChannelOpen(HWTSSERVER hServer, uint SessionId, [MarshalAs(UnmanagedType.LPStr)] string pVirtualName);
+
+ ///
+ /// Creates a virtual channel in a manner similar to WTSVirtualChannelOpen.
+ ///
+ /// This API supports both static virtual channel (SVC) and dynamic virtual channel (DVC) creation. If the flags parameter is zero,
+ /// it behaves the same as WTSVirtualChannelOpen. A DVC can be opened by specifying the appropriate flag. After a DVC is created,
+ /// you can use the same functions for Read, Write, Query, or Close that are used for the SVC.
+ ///
+ ///
+ ///
+ ///
+ /// A Remote Desktop Services session identifier. To indicate the current session, specify WTS_CURRENT_SESSION. You can use
+ /// the WTSEnumerateSessions function to retrieve the identifiers of all sessions on a specified RD Session Host server.
+ ///
+ ///
+ /// To be able to open a virtual channel on another user's session, you must have the Virtual Channels permission. For more
+ /// information, see Remote Desktop Services Permissions. To modify permissions on a session, use the Remote Desktop Services
+ /// Configuration administrative tool.
+ ///
+ ///
+ ///
+ ///
+ /// In the case of an SVC, points to a null-terminated string that contains the virtual channel name. The length of an SVC name is
+ /// limited to CHANNEL_NAME_LEN characters, not including the terminating null.
+ ///
+ ///
+ /// In the case of a DVC, points to a null-terminated string that contains the endpoint name of the listener. The length of a DVC
+ /// name is limited to MAX_PATH characters.
+ ///
+ ///
+ ///
+ /// To open the channel as an SVC, specify zero for this parameter. To open the channel as a DVC, specify WTS_CHANNEL_OPTION_DYNAMIC.
+ ///
+ /// When opening a DVC, you can specify a priority setting for the data that is being transferred by specifying one of the
+ /// WTS_CHANNEL_OPTION_DYNAMIC_PRI_XXX values in combination with the WTS_CHANNEL_OPTION_DYNAMIC value.
+ ///
+ ///
+ /// -
+ /// WTS_CHANNEL_OPTION_DYNAMIC_NO_COMPRESS
Disables compression for this DVC. You must specify this value in
+ /// combination with the WTS_CHANNEL_OPTION_DYNAMIC value.
+ ///
+ /// -
+ /// WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW (default)
Low priority. The data will be sent on both sides with low
+ /// priority. Use this priority level for block transfers of all sizes, where the transfer speed is not important. In almost all
+ /// (95%) cases, the channel should be opened with this flag.
+ ///
+ /// -
+ /// WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED
Medium priority. Use this priority level to send short control messages
+ /// that must have priority over the data in the low priority channels.
+ ///
+ /// -
+ /// WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH
High priority. Use this priority level for data that is critical and
+ /// directly affects the user experience. The transfer size may vary. Display data falls into this category.
+ ///
+ /// -
+ /// WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL
Real-time priority. Use this priority level only in cases where the
+ /// data transfer is absolutely critical. The data transfer size should be limited to a few hundred bytes per message.
+ ///
+ ///
+ ///
+ /// NULL on error with GetLastError set.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelopenex HANDLE WTSVirtualChannelOpenEx(
+ // DWORD SessionId, LPSTR pVirtualName, DWORD flags );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelOpenEx")]
+ public static extern SafeHVIRTUALCHANNEL WTSVirtualChannelOpenEx(uint SessionId, [MarshalAs(UnmanagedType.LPStr)] string pVirtualName, WTS_CHANNEL_OPTION flags);
+
+ /// Deletes all queued input data sent from the client to the server on a specified virtual channel.
+ /// Handle to a virtual channel opened by the WTSVirtualChannelOpen function.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelpurgeinput BOOL
+ // WTSVirtualChannelPurgeInput( HANDLE hChannelHandle );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelPurgeInput")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSVirtualChannelPurgeInput(HVIRTUALCHANNEL hChannelHandle);
+
+ /// Deletes all queued output data sent from the server to the client on a specified virtual channel.
+ /// Handle to a virtual channel opened by the WTSVirtualChannelOpen function.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelpurgeoutput BOOL
+ // WTSVirtualChannelPurgeOutput( HANDLE hChannelHandle );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelPurgeOutput")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSVirtualChannelPurgeOutput(HVIRTUALCHANNEL hChannelHandle);
+
+ /// Returns information about a specified virtual channel.
+ /// Handle to a virtual channel opened by the WTSVirtualChannelOpen function.
+ /// Specifies the type of information to get for the channel.
+ /// Pointer to a buffer that receives the requested information.
+ /// Pointer to a variable that receives the number of bytes returned in the ppBuffer parameter.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value. Call the WTSFreeMemory function with the value returned in the
+ /// ppBuffer parameter to free the temporary memory allocated by WTSVirtualChannelQuery.
+ ///
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// The following example shows how to gain access to a virtual channel file handle that can be used for asynchronous I/O. First the
+ /// code opens a virtual channel by using a call to the WTSVirtualChannelOpen function. Then the code calls the
+ /// WTSVirtualChannelQuery function, specifying the WTSVirtualFileHandle virtual class type. WTSVirtualChannelQuery
+ /// returns a file handle that you can use to perform asynchronous (overlapped) read and write operations. Finally, the code frees
+ /// the memory allocated by WTSVirtualChannelQuery with a call to the WTSFreeMemory function, and closes the virtual channel
+ /// with a call to the WTSVirtualChannelClose function.
+ ///
+ ///
+ /// Note that you should not explicitly close the file handle obtained by calling WTSVirtualChannelQuery. This is because
+ /// WTSVirtualChannelClose closes the file handle.
+ ///
+ ///
+ /// PVOID vcFileHandlePtr = NULL; DWORD len; DWORD result = ERROR_SUCCESS; HANDLE vcHandle = NULL; HANDLE vcFileHandle = NULL; // // Open a virtual channel. // vcHandle = WTSVirtualChannelOpen( WTS_CURRENT_SERVER_HANDLE, // Current TS Server WTS_CURRENT_SESSION, // Current TS Session (LPSTR) "TSTCHNL" // Channel name ); if (vcHandle == NULL) { result = GetLastError(); } // // Gain access to the underlying file handle for // asynchronous I/O. // if (result == ERROR_SUCCESS) { if (!WTSVirtualChannelQuery( vcHandle, WTSVirtualFileHandle, &vcFileHandlePtr, &len )) { result = GetLastError(); } } // // Copy the data and // free the buffer allocated by WTSVirtualChannelQuery. // if (result == ERROR_SUCCESS) { memcpy(&vcFileHandle, vcFileHandlePtr, sizeof(vcFileHandle)); WTSFreeMemory(vcFileHandlePtr); // // Use vcFileHandle for overlapped reads and writes here. // //. //. //. } // // Call WTSVirtualChannelClose to close the virtual channel. // Note: do not close the file handle. // if (vcHandle != NULL) { WTSVirtualChannelClose(vcHandle); vcFileHandle = NULL; }
+ ///
+ /// For more information about overlapped mode, see Synchronization and Overlapped Input and Output.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelquery BOOL WTSVirtualChannelQuery(
+ // HANDLE hChannelHandle, WTS_VIRTUAL_CLASS , PVOID *ppBuffer, DWORD *pBytesReturned );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelQuery")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSVirtualChannelQuery(HVIRTUALCHANNEL hChannelHandle, WTS_VIRTUAL_CLASS WTSVirtualClass, out SafeWTSMemoryHandle ppBuffer, out uint pBytesReturned);
+
+ ///
+ /// Reads data from the server end of a virtual channel.
+ /// WTSVirtualChannelRead reads the data written by a VirtualChannelWrite call at the client end of the virtual channel.
+ ///
+ /// Handle to a virtual channel opened by the WTSVirtualChannelOpen function.
+ ///
+ /// Specifies the time-out, in milliseconds. If TimeOut is zero, WTSVirtualChannelRead returns immediately if there is no
+ /// data to read. If TimeOut is INFINITE (defined in Winbase.h), the function waits indefinitely until there is data to read.
+ ///
+ ///
+ ///
+ /// Pointer to a buffer that receives a chunk of data read from the server end of the virtual channel. The maximum amount of data
+ /// that the server can receive in a single WTSVirtualChannelRead call is CHANNEL_CHUNK_LENGTH bytes. If the client's
+ /// VirtualChannelWrite call writes a larger block of data, the server must make multiple WTSVirtualChannelRead calls.
+ ///
+ ///
+ /// In certain cases, Remote Desktop Services places a CHANNEL_PDU_HEADER structure at the beginning of each chunk of data
+ /// read by the WTSVirtualChannelRead function. This will occur if the client DLL sets the
+ /// CHANNEL_OPTION_SHOW_PROTOCOL option when it calls the VirtualChannelInit function to initialize the virtual channel. This
+ /// will also occur if the channel is a dynamic virtual channel written to by using the IWTSVirtualChannel::Write method. Otherwise,
+ /// the buffer receives only the data written in the VirtualChannelWrite call.
+ ///
+ ///
+ ///
+ /// Specifies the size, in bytes, of Buffer. If the chunk of data in Buffer will be preceded by a CHANNEL_PDU_HEADER
+ /// structure, the value of this parameter should be at least CHANNEL_PDU_LENGTH. Otherwise, the value of this parameter
+ /// should be at least CHANNEL_CHUNK_LENGTH.
+ ///
+ /// Pointer to a variable that receives the number of bytes read.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// NoteWTSVirtualChannelRead is not thread safe. To access a virtual channel from multiple threads, or to do
+ /// asynchronous IO through a virtual channel, use WTSVirtualChannelQuery with WTSVirtualFileHandle.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelread BOOL WTSVirtualChannelRead( HANDLE
+ // hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelRead")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSVirtualChannelRead(HVIRTUALCHANNEL hChannelHandle, uint TimeOut, [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer,
+ uint BufferSize, out uint pBytesRead);
+
+ /// Writes data to the server end of a virtual channel.
+ /// Handle to a virtual channel opened by the WTSVirtualChannelOpen function.
+ /// Pointer to a buffer containing the data to write to the virtual channel.
+ /// Specifies the size, in bytes, of the data to write.
+ /// Pointer to a variable that receives the number of bytes written.
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// NoteWTSVirtualChannelWrite is not thread safe. To access a virtual channel from multiple threads, or to do
+ /// asynchronous IO through a virtual channel, use WTSVirtualChannelQuery with WTSVirtualFileHandle.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelwrite BOOL WTSVirtualChannelWrite(
+ // HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSVirtualChannelWrite")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSVirtualChannelWrite(HVIRTUALCHANNEL hChannelHandle, [MarshalAs(UnmanagedType.LPStr)] string Buffer, uint Length, out uint pBytesWritten);
+
+ /// Waits for a Remote Desktop Services event before returning to the caller.
+ ///
+ /// Handle to an RD Session Host server. Specify a handle opened by the WTSOpenServer function, or specify WTS_CURRENT_SERVER_HANDLE
+ /// to indicate the RD Session Host server on which your application is running.
+ ///
+ ///
+ ///
+ /// Bitmask that specifies the set of events to wait for. This mask can be WTS_EVENT_FLUSH to cause all pending
+ /// WTSWaitSystemEvent calls on the specified RD Session Host server handle to return. Or, the mask can be a combination of
+ /// the following values.
+ ///
+ /// WTS_EVENT_ALL
+ /// Wait for any event type.
+ /// WTS_EVENT_CONNECT
+ /// A client connected to a WinStation.
+ /// WTS_EVENT_CREATE
+ /// A new WinStation was created.
+ /// WTS_EVENT_DELETE
+ /// An existing WinStation was deleted.
+ /// WTS_EVENT_DISCONNECT
+ /// A client disconnected from a WinStation.
+ /// WTS_EVENT_LICENSE
+ /// The Remote Desktop Services' license state changed. This occurs when a license is added or deleted using License Manager.
+ /// WTS_EVENT_LOGOFF
+ /// A user logged off from either the Remote Desktop Services console or from a client WinStation.
+ /// WTS_EVENT_LOGON
+ /// A user logged on to the system from either the Remote Desktop Services console or from a client WinStation.
+ /// WTS_EVENT_RENAME
+ /// An existing WinStation was renamed.
+ /// WTS_EVENT_STATECHANGE
+ /// A WinStation connection state changed. For a list of connection states, see the WTS_CONNECTSTATE_CLASS enumeration type.
+ ///
+ ///
+ /// Pointer to a variable that receives a bitmask of the event or events that occurred. The returned mask can be a combination of
+ /// the values from the previous list, or it can be WTS_EVENT_NONE if the wait terminated because of a
+ /// WTSWaitSystemEvent call with WTS_EVENT_FLUSH.
+ ///
+ ///
+ /// If the function succeeds, the return value is a nonzero value.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtswaitsystemevent BOOL WTSWaitSystemEvent( HANDLE
+ // hServer, DWORD EventMask, DWORD *pEventFlags );
+ [DllImport(Lib_WTSApi32, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NF:wtsapi32.WTSWaitSystemEvent")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WTSWaitSystemEvent(HVIRTUALCHANNEL hServer, WTS_EVENT EventMask, out WTS_EVENT pEventFlags);
+
+ /// Provides a handle to a virtual channel.
+ [StructLayout(LayoutKind.Sequential)]
+ public struct HVIRTUALCHANNEL : IHandle
+ {
+ private readonly IntPtr handle;
+
+ /// Initializes a new instance of the struct.
+ /// An object that represents the pre-existing handle to use.
+ public HVIRTUALCHANNEL(IntPtr preexistingHandle) => handle = preexistingHandle;
+
+ /// Returns an invalid handle by instantiating a object with .
+ public static HVIRTUALCHANNEL NULL => new HVIRTUALCHANNEL(IntPtr.Zero);
+
+ /// Gets a value indicating whether this instance is a null handle.
+ public bool IsNull => handle == IntPtr.Zero;
+
+ /// Performs an explicit conversion from to .
+ /// The handle.
+ /// The result of the conversion.
+ public static explicit operator IntPtr(HVIRTUALCHANNEL h) => h.handle;
+
+ /// Performs an implicit conversion from to .
+ /// The pointer to a handle.
+ /// The result of the conversion.
+ public static implicit operator HVIRTUALCHANNEL(IntPtr h) => new HVIRTUALCHANNEL(h);
+
+ /// Implements the operator !=.
+ /// The first handle.
+ /// The second handle.
+ /// The result of the operator.
+ public static bool operator !=(HVIRTUALCHANNEL h1, HVIRTUALCHANNEL h2) => !(h1 == h2);
+
+ /// Implements the operator ==.
+ /// The first handle.
+ /// The second handle.
+ /// The result of the operator.
+ public static bool operator ==(HVIRTUALCHANNEL h1, HVIRTUALCHANNEL h2) => h1.Equals(h2);
+
+ ///
+ public override bool Equals(object obj) => obj is HVIRTUALCHANNEL h && handle == h.handle;
+
+ ///
+ public override int GetHashCode() => handle.GetHashCode();
+
+ ///
+ public IntPtr DangerousGetHandle() => handle;
+ }
+
+ /// Provides a handle to a WTS server.
+ [StructLayout(LayoutKind.Sequential)]
+ public struct HWTSSERVER : IHandle
+ {
+ private readonly IntPtr handle;
+
+ /// Initializes a new instance of the struct.
+ /// An object that represents the pre-existing handle to use.
+ public HWTSSERVER(IntPtr preexistingHandle) => handle = preexistingHandle;
+
+ /// Returns an invalid handle by instantiating a object with .
+ public static readonly HWTSSERVER NULL = new HWTSSERVER(IntPtr.Zero);
+
+ /// A constant representing the handle of the current WTS server.
+ public static readonly HWTSSERVER WTS_CURRENT_SERVER_HANDLE = NULL;
+
+ /// A constant representing the handle of the current WTS server.
+ public static readonly HWTSSERVER WTS_CURRENT_SERVER = NULL;
+
+ /// Gets a value indicating whether this instance is a null handle.
+ public bool IsNull => handle == IntPtr.Zero;
+
+ /// Performs an explicit conversion from to .
+ /// The handle.
+ /// The result of the conversion.
+ public static explicit operator IntPtr(HWTSSERVER h) => h.handle;
+
+ /// Performs an implicit conversion from to .
+ /// The pointer to a handle.
+ /// The result of the conversion.
+ public static implicit operator HWTSSERVER(IntPtr h) => new HWTSSERVER(h);
+
+ /// Implements the operator !=.
+ /// The first handle.
+ /// The second handle.
+ /// The result of the operator.
+ public static bool operator !=(HWTSSERVER h1, HWTSSERVER h2) => !(h1 == h2);
+
+ /// Implements the operator ==.
+ /// The first handle.
+ /// The second handle.
+ /// The result of the operator.
+ public static bool operator ==(HWTSSERVER h1, HWTSSERVER h2) => h1.Equals(h2);
+
+ ///
+ public override bool Equals(object obj) => obj is HWTSSERVER h && handle == h.handle;
+
+ ///
+ public override int GetHashCode() => handle.GetHashCode();
+
+ ///
+ public IntPtr DangerousGetHandle() => handle;
+ }
+
+ /// Contains the client network address of a Remote Desktop Services session.
+ ///
+ ///
+ /// The client network address is reported by the RDP client itself when it connects to the server. This could be different than the
+ /// address that actually connected to the server. For example, suppose there is a NAT between the client and the server. The client
+ /// can report its own IP address, but the IP address that actually connects to the server is the NAT address. For VPN connections,
+ /// the IP address might not be discoverable by the client. If it cannot be discovered, the client can report the only IP address it
+ /// has, which may be the ISP assigned address. Because the address may not be the actual network address, it should not be used as
+ /// a form of client authentication.
+ ///
+ /// The client network address is also not available in the following cases:
+ ///
+ /// -
+ /// The connection is established through a Remote Desktop Gateway.
+ ///
+ /// -
+ /// The connection is originated by the Microsoft Remote Desktop app that is available in the Store.
+ ///
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_client_address typedef struct _WTS_CLIENT_ADDRESS {
+ // DWORD AddressFamily; BYTE Address[20]; } WTS_CLIENT_ADDRESS, *PWTS_CLIENT_ADDRESS;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTS_CLIENT_ADDRESS")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct WTS_CLIENT_ADDRESS
+ {
+ /// Address family. This member can be AF_INET, AF_INET6, AF_IPX, AF_NETBIOS, or AF_UNSPEC.
+ public uint AddressFamily;
+
+ ///
+ ///
+ /// Client network address. The format of the field of Address depends on the address type as specified by the
+ /// AddressFamily member.
+ ///
+ ///
+ /// For an address family AF_INET: Address contains the IPV4 address of the client as a null-terminated string.
+ ///
+ ///
+ /// For an family AF_INET6: Address contains the IPV6 address of the client as raw byte values. (For example, the
+ /// address "FFFF::1" would be represented as the following series of byte values: "0xFF 0xFF 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ /// 0x00 0x00 0x00 0x00 0x00 0x00 0x01")
+ ///
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
+ public byte[] Address;
+ }
+
+ /// Contains information about the display of a Remote Desktop Connection (RDC) client.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_client_display typedef struct _WTS_CLIENT_DISPLAY {
+ // DWORD HorizontalResolution; DWORD VerticalResolution; DWORD ColorDepth; } WTS_CLIENT_DISPLAY, *PWTS_CLIENT_DISPLAY;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTS_CLIENT_DISPLAY")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct WTS_CLIENT_DISPLAY
+ {
+ /// Horizontal dimension, in pixels, of the client's display.
+ public uint HorizontalResolution;
+
+ /// Vertical dimension, in pixels, of the client's display.
+ public uint VerticalResolution;
+
+ ///
+ /// Color depth of the client's display. This member can be one of the following values.
+ /// 1
+ /// 4 bits per pixel.
+ /// 2
+ /// 8 bits per pixel.
+ /// 4
+ /// 16 bits per pixel.
+ /// 8
+ /// A 3-byte RGB values for a maximum of 2^24 colors.
+ /// 16
+ /// 15 bits per pixel.
+ /// 24
+ /// 24 bits per pixel.
+ /// 32
+ /// 32 bits per pixel.
+ ///
+ public uint ColorDepth;
+ }
+
+ /// Contains information about a process running on a Remote Desktop Session Host (RD Session Host) server.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_process_infoa typedef struct _WTS_PROCESS_INFOA {
+ // DWORD SessionId; DWORD ProcessId; LPSTR pProcessName; PSID pUserSid; } WTS_PROCESS_INFOA, *PWTS_PROCESS_INFOA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTS_PROCESS_INFOA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTS_PROCESS_INFO
+ {
+ /// Remote Desktop Services session identifier for the session associated with the process.
+ public uint SessionId;
+
+ /// Process identifier that uniquely identifies the process on the RD Session Host server.
+ public uint ProcessId;
+
+ /// Pointer to a null-terminated string containing the name of the executable file associated with the process.
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pProcessName;
+
+ ///
+ /// Pointer to the user Security Identifiers in the process's primary access token. For more information about SIDs and access
+ /// tokens, see Access Control.
+ ///
+ public PSID pUserSid;
+ }
+
+ ///
+ /// Contains extended information about a process running on a Remote Desktop Session Host (RD Session Host) server. This structure
+ /// is returned by the WTSEnumerateProcessesEx function when you set the pLevel parameter to one.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_process_info_exa typedef struct _WTS_PROCESS_INFO_EXA
+ // { DWORD SessionId; DWORD ProcessId; LPSTR pProcessName; PSID pUserSid; DWORD NumberOfThreads; DWORD HandleCount; DWORD
+ // PagefileUsage; DWORD PeakPagefileUsage; DWORD WorkingSetSize; DWORD PeakWorkingSetSize; LARGE_INTEGER UserTime; LARGE_INTEGER
+ // KernelTime; } WTS_PROCESS_INFO_EXA, *PWTS_PROCESS_INFO_EXA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTS_PROCESS_INFO_EXA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTS_PROCESS_INFO_EX
+ {
+ /// The Remote Desktop Services session identifier for the session associated with the process.
+ public uint SessionId;
+
+ /// The process identifier that uniquely identifies the process on the RD Session Host server.
+ public uint ProcessId;
+
+ /// A pointer to a null-terminated string that contains the name of the executable file associated with the process.
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pProcessName;
+
+ ///
+ /// A pointer to the user security identifiers (SIDs) in the primary access token of the process. For more information about
+ /// SIDs and access tokens, see Access Control and Security Identifiers.
+ ///
+ public PSID pUserSid;
+
+ /// The number of threads in the process.
+ public uint NumberOfThreads;
+
+ /// The number of handles in the process.
+ public uint HandleCount;
+
+ /// The page file usage of the process, in bytes.
+ public uint PagefileUsage;
+
+ /// The peak page file usage of the process, in bytes.
+ public uint PeakPagefileUsage;
+
+ /// The working set size of the process, in bytes.
+ public uint WorkingSetSize;
+
+ /// The peak working set size of the process, in bytes.
+ public uint PeakWorkingSetSize;
+
+ /// The amount of time, in milliseconds, the process has been running in user mode.
+ public long UserTime;
+
+ /// The amount of time, in milliseconds, the process has been running in kernel mode.
+ public long KernelTime;
+ }
+
+ /// Contains information about a specific Remote Desktop Services server.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_server_infoa typedef struct _WTS_SERVER_INFOA { LPSTR
+ // pServerName; } WTS_SERVER_INFOA, *PWTS_SERVER_INFOA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTS_SERVER_INFOA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTS_SERVER_INFO
+ {
+ /// Name of the server.
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pServerName;
+ }
+
+ ///
+ /// Contains the virtual IP address assigned to a session. This structure is returned by the WTSQuerySessionInformation function
+ /// when you specify "WTSSessionAddressV4" for the WTSInfoClass parameter.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_session_address typedef struct _WTS_SESSION_ADDRESS {
+ // DWORD AddressFamily; BYTE Address[20]; } WTS_SESSION_ADDRESS, *PWTS_SESSION_ADDRESS;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTS_SESSION_ADDRESS")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct WTS_SESSION_ADDRESS
+ {
+ /// A null-terminated string that contains the address family. Always set this member to "AF_INET".
+ public uint AddressFamily;
+
+ ///
+ /// The virtual IP address assigned to the session. The format of this address is identical to that used in the
+ /// WTS_CLIENT_ADDRESS structure.
+ ///
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
+ public byte[] Address;
+ }
+
+ /// Contains information about a client session on a Remote Desktop Session Host (RD Session Host) server.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_session_infoa typedef struct _WTS_SESSION_INFOA {
+ // DWORD SessionId; LPSTR pWinStationName; WTS_CONNECTSTATE_CLASS State; } WTS_SESSION_INFOA, *PWTS_SESSION_INFOA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTS_SESSION_INFOA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTS_SESSION_INFO
+ {
+ /// Session identifier of the session.
+ public uint SessionId;
+
+ ///
+ /// Pointer to a null-terminated string that contains the WinStation name of this session. The WinStation name is a name that
+ /// Windows associates with the session, for example, "services", "console", or "RDP-Tcp#0".
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pWinStationName;
+
+ /// A value from the WTS_CONNECTSTATE_CLASS enumeration type that indicates the session's current connection state.
+ public WTS_CONNECTSTATE_CLASS State;
+ }
+
+ ///
+ /// Contains extended information about a client session on a Remote Desktop Session Host (RD Session Host) server or Remote Desktop
+ /// Virtualization Host (RD Virtualization Host) server.
+ ///
+ ///
+ ///
+ /// The WTSEnumerateSessionsEx function returns this structure if you call the function and specify a handle to an RD Virtualization
+ /// Host server that you obtained by calling the WTSOpenServerEx function. In this case, the WTSEnumerateSessionsEx function
+ /// aggregates all the sessions running on the host itself as well as sessions running on individual virtual machines. The ExecEnvId
+ /// parameter uniquely identifies each session in the aggregated list. This identifier may be different from the actual session
+ /// identifier defined in the server or virtual machine that hosts the session, which is specified by the SessionId member.
+ ///
+ ///
+ /// The session represented by this structure could be a session running directly on the server or a session running within a
+ /// virtual machine. If the session is running within a virtual machine, the pHostName member contains the name of the
+ /// virtual machine. The pFarmName member is applicable to sessions that are hosted on virtual machines that are joined to a
+ /// RD Session Host farm.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wts_session_info_1a typedef struct _WTS_SESSION_INFO_1A {
+ // DWORD ExecEnvId; WTS_CONNECTSTATE_CLASS State; DWORD SessionId; LPSTR pSessionName; LPSTR pHostName; LPSTR pUserName; LPSTR
+ // pDomainName; LPSTR pFarmName; } WTS_SESSION_INFO_1A, *PWTS_SESSION_INFO_1A;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTS_SESSION_INFO_1A")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTS_SESSION_INFO_1
+ {
+ ///
+ /// An identifier that uniquely identifies the session within the list of sessions returned by the WTSEnumerateSessionsEx
+ /// function. For more information, see Remarks.
+ ///
+ public uint ExecEnvId;
+
+ ///
+ /// A value of the WTS_CONNECTSTATE_CLASS enumeration type that specifies the connection state of a Remote Desktop Services session.
+ ///
+ public WTS_CONNECTSTATE_CLASS State;
+
+ /// A session identifier assigned by the RD Session Host server, RD Virtualization Host server, or virtual machine.
+ public uint SessionId;
+
+ ///
+ /// A pointer to a null-terminated string that contains the name of this session. For example, "services", "console", or "RDP-Tcp#0".
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pSessionName;
+
+ ///
+ /// A pointer to a null-terminated string that contains the name of the computer that the session is running on. If the session
+ /// is running directly on an RD Session Host server or RD Virtualization Host server, the string contains NULL. If the
+ /// session is running on a virtual machine, the string contains the name of the virtual machine.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pHostName;
+
+ ///
+ /// A pointer to a null-terminated string that contains the name of the user who is logged on to the session. If no user is
+ /// logged on to the session, the string contains NULL.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pUserName;
+
+ ///
+ /// A pointer to a null-terminated string that contains the domain name of the user who is logged on to the session. If no user
+ /// is logged on to the session, the string contains NULL.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pDomainName;
+
+ ///
+ /// A pointer to a null-terminated string that contains the name of the farm that the virtual machine is joined to. If the
+ /// session is not running on a virtual machine that is joined to a farm, the string contains NULL.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string pFarmName;
+ }
+
+ /// Contains information about a Remote Desktop Connection (RDC) client.
+ ///
+ /// For the ClientAddressFamily member, AF_INET (IPv4) will return in string format, for example "127.0.0.1".
+ /// AF_INET6 (IPv6) will return in binary form.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wtsclienta typedef struct _WTSCLIENTA { CHAR
+ // ClientName[CLIENTNAME_LENGTH + 1]; CHAR Domain[DOMAIN_LENGTH + 1]; CHAR UserName[USERNAME_LENGTH + 1]; CHAR
+ // WorkDirectory[MAX_PATH + 1]; CHAR InitialProgram[MAX_PATH + 1]; BYTE EncryptionLevel; ULONG ClientAddressFamily; USHORT
+ // ClientAddress[CLIENTADDRESS_LENGTH + 1]; USHORT HRes; USHORT VRes; USHORT ColorDepth; CHAR ClientDirectory[MAX_PATH + 1]; ULONG
+ // ClientBuildNumber; ULONG ClientHardwareId; USHORT ClientProductId; USHORT OutBufCountHost; USHORT OutBufCountClient; USHORT
+ // OutBufLength; CHAR DeviceId[MAX_PATH + 1]; } WTSCLIENTA, *PWTSCLIENTA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSCLIENTA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSCLIENT
+ {
+ /// The NetBIOS name of the client computer.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CLIENTNAME_LENGTH + 1)]
+ public string ClientName;
+
+ /// The domain name of the client computer.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DOMAIN_LENGTH + 1)]
+ public string Domain;
+
+ /// The client user name.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = USERNAME_LENGTH + 1)]
+ public string UserName;
+
+ /// The folder for the initial program.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string WorkDirectory;
+
+ /// The program to start on connection.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string InitialProgram;
+
+ /// The security level of encryption.
+ public byte EncryptionLevel;
+
+ ///
+ /// The address family. This member can be AF_INET, AF_INET6, AF_IPX, AF_NETBIOS, or AF_UNSPEC.
+ ///
+ public uint ClientAddressFamily;
+
+ /// The client network address.
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = CLIENTADDRESS_LENGTH + 1)]
+ public ushort[] ClientAddress;
+
+ /// Horizontal dimension, in pixels, of the client's display.
+ public ushort HRes;
+
+ /// Vertical dimension, in pixels, of the client's display.
+ public ushort VRes;
+
+ ///
+ /// Color depth of the client's display. For possible values, see the ColorDepth member of the WTS_CLIENT_DISPLAY structure.
+ ///
+ public ushort ColorDepth;
+
+ /// The location of the client ActiveX control DLL.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string ClientDirectory;
+
+ /// The client build number.
+ public uint ClientBuildNumber;
+
+ /// Reserved.
+ public uint ClientHardwareId;
+
+ /// Reserved.
+ public ushort ClientProductId;
+
+ /// The number of output buffers on the server per session.
+ public ushort OutBufCountHost;
+
+ /// The number of output buffers on the client.
+ public ushort OutBufCountClient;
+
+ /// The length of the output buffers, in bytes.
+ public ushort OutBufLength;
+
+ /// The device ID of the network adapter.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string DeviceId;
+ }
+
+ ///
+ /// Contains information about a Remote Desktop Services session. This structure is returned by the WTSQuerySessionInformation
+ /// function when you specify "WTSConfigInfo" for the WTSInfoClass parameter.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wtsconfiginfoa typedef struct _WTSCONFIGINFOA { ULONG
+ // version; ULONG fConnectClientDrivesAtLogon; ULONG fConnectPrinterAtLogon; ULONG fDisablePrinterRedirection; ULONG
+ // fDisableDefaultMainClientPrinter; ULONG ShadowSettings; CHAR LogonUserName[USERNAME_LENGTH + 1]; CHAR LogonDomain[DOMAIN_LENGTH +
+ // 1]; CHAR WorkDirectory[MAX_PATH + 1]; CHAR InitialProgram[MAX_PATH + 1]; CHAR ApplicationName[MAX_PATH + 1]; } WTSCONFIGINFOA, *PWTSCONFIGINFOA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSCONFIGINFOA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSCONFIGINFO
+ {
+ /// This member is reserved.
+ public uint version;
+
+ /// This member is reserved.
+ public uint fConnectClientDrivesAtLogon;
+
+ /// This member is reserved.
+ public uint fConnectPrinterAtLogon;
+
+ ///
+ /// Specifies whether the client can use printer redirection.
+ /// 0
+ /// Enable client printer redirection.
+ /// 1
+ /// Disable client printer redirection.
+ ///
+ public uint fDisablePrinterRedirection;
+
+ ///
+ /// Specifies whether the printer connected to the client is the default printer for the user.
+ /// 0
+ /// The printer connected to the client is not the default printer for the user.
+ /// 1
+ /// The printer connected to the client is the default printer for the user.
+ ///
+ public uint fDisableDefaultMainClientPrinter;
+
+ ///
+ ///
+ /// The remote control setting. Remote control allows a user to remotely monitor the on-screen operations of another user. This
+ /// member can be one of the following values.
+ ///
+ /// 0
+ /// Remote control is disabled.
+ /// 1
+ /// The user of remote control has full control of the user's session, with the user's permission.
+ /// 2
+ /// The user of remote control has full control of the user's session; the user's permission is not required.
+ /// 3
+ ///
+ /// The user of remote control can view the session remotely, with the user's permission; the remote user cannot actively
+ /// control the session.
+ ///
+ /// 4
+ ///
+ /// The user of remote control can view the session remotely but not actively control the session; the user's permission is not required.
+ ///
+ ///
+ public uint ShadowSettings;
+
+ /// A null-terminated string that contains the user name used in automatic logon scenarios.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = USERNAME_LENGTH + 1)]
+ public string LogonUserName;
+
+ /// A null-terminated string that contains the domain name used in automatic logon scenarios.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DOMAIN_LENGTH + 1)]
+ public string LogonDomain;
+
+ /// A null-terminated string that contains the path of the working directory of the initial program.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string WorkDirectory;
+
+ ///
+ /// A null-terminated string that contains the name of the program to start immediately after the user logs on to the server.
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string InitialProgram;
+
+ /// This member is reserved.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string ApplicationName;
+ }
+
+ /// Contains information about a Remote Desktop Services session.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wtsinfoa typedef struct _WTSINFOA {
+ // WTS_CONNECTSTATE_CLASS State; DWORD SessionId; DWORD IncomingBytes; DWORD OutgoingBytes; DWORD IncomingFrames; DWORD
+ // OutgoingFrames; DWORD IncomingCompressedBytes; DWORD OutgoingCompressedBy; CHAR WinStationName[WINSTATIONNAME_LENGTH]; CHAR
+ // Domain[DOMAIN_LENGTH]; CHAR UserName[USERNAME_LENGTH + 1]; LARGE_INTEGER ConnectTime; LARGE_INTEGER DisconnectTime; LARGE_INTEGER
+ // LastInputTime; LARGE_INTEGER LogonTime; LARGE_INTEGER CurrentTime; } WTSINFOA, *PWTSINFOA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSINFOA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSINFO
+ {
+ /// A value of the WTS_CONNECTSTATE_CLASS enumeration type that indicates the session's current connection state.
+ public WTS_CONNECTSTATE_CLASS State;
+
+ /// The session identifier.
+ public uint SessionId;
+
+ /// Uncompressed Remote Desktop Protocol (RDP) data from the client to the server.
+ public uint IncomingBytes;
+
+ /// Uncompressed RDP data from the server to the client.
+ public uint OutgoingBytes;
+
+ /// The number of frames of RDP data sent from the client to the server since the client connected.
+ public uint IncomingFrames;
+
+ /// The number of frames of RDP data sent from the server to the client since the client connected.
+ public uint OutgoingFrames;
+
+ /// Compressed RDP data from the client to the server.
+ public uint IncomingCompressedBytes;
+
+ ///
+ public uint OutgoingCompressedBy;
+
+ /// A null-terminated string that contains the name of the WinStation for the session.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = WINSTATIONNAME_LENGTH)]
+ public string WinStationName;
+
+ /// A null-terminated string that contains the name of the domain that the user belongs to.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DOMAIN_LENGTH)]
+ public string Domain;
+
+ /// A null-terminated string that contains the name of the user who owns the session.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = USERNAME_LENGTH + 1)]
+ public string UserName;
+
+ /// The most recent client connection time.
+ public FILETIME ConnectTime;
+
+ /// The last client disconnection time.
+ public FILETIME DisconnectTime;
+
+ /// The time of the last user input in the session.
+ public FILETIME LastInputTime;
+
+ /// The time that the user logged on to the session.
+ public FILETIME LogonTime;
+
+ /// The time that the WTSINFO data structure was called.
+ public FILETIME CurrentTime;
+ }
+
+ ///
+ /// Contains a WTSINFOEX_LEVEL union that contains extended information about a Remote Desktop Services session. This structure is
+ /// returned by the WTSQuerySessionInformation function when you specify "WTSSessionInfoEx" for the WTSInfoClass parameter.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wtsinfoexa typedef struct _WTSINFOEXA { DWORD Level;
+ // WTSINFOEX_LEVEL_A Data; } WTSINFOEXA, *PWTSINFOEXA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSINFOEXA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSINFOEX
+ {
+ /// Specifies the level of information contained in the Data member. This can be the following value.
+ /// 1
+ /// The Data member is a WTSINFOEX_LEVEL1 structure.
+ ///
+ public uint Level;
+
+ /// A WTSINFOEX_LEVEL union. The type of structure contained here is specified by the Level member.
+ public WTSINFOEX_LEVEL Data;
+ }
+
+ /// Contains a WTSINFOEX_LEVEL1 structure that contains extended information about a Remote Desktop Services session.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wtsinfoex_level_a typedef union _WTSINFOEX_LEVEL_A {
+ // WTSINFOEX_LEVEL1_A WTSInfoExLevel1; } WTSINFOEX_LEVEL_A, *PWTSINFOEX_LEVEL_A;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSINFOEX_LEVEL_A")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSINFOEX_LEVEL
+ {
+ /// A WTSINFOEX_LEVEL1 structure that contains extended session information.
+ public WTSINFOEX_LEVEL1 WTSInfoExLevel1;
+ }
+
+ /// Contains extended information about a Remote Desktop Services session.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wtsinfoex_level1_a typedef struct _WTSINFOEX_LEVEL1_A {
+ // ULONG SessionId; WTS_CONNECTSTATE_CLASS SessionState; LONG SessionFlags; CHAR WinStationName[WINSTATIONNAME_LENGTH + 1]; CHAR
+ // UserName[USERNAME_LENGTH + 1]; CHAR DomainName[DOMAIN_LENGTH + 1]; LARGE_INTEGER LogonTime; LARGE_INTEGER ConnectTime;
+ // LARGE_INTEGER DisconnectTime; LARGE_INTEGER LastInputTime; LARGE_INTEGER CurrentTime; DWORD IncomingBytes; DWORD OutgoingBytes;
+ // DWORD IncomingFrames; DWORD OutgoingFrames; DWORD IncomingCompressedBytes; DWORD OutgoingCompressedBytes; } WTSINFOEX_LEVEL1_A, *PWTSINFOEX_LEVEL1_A;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSINFOEX_LEVEL1_A")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSINFOEX_LEVEL1
+ {
+ /// The session identifier.
+ public uint SessionId;
+
+ ///
+ /// A value of the WTS_CONNECTSTATE_CLASS enumeration type that specifies the connection state of a Remote Desktop Services session.
+ ///
+ public WTS_CONNECTSTATE_CLASS SessionState;
+
+ ///
+ /// The state of the session. This can be one or more of the following values.
+ /// WTS_SESSIONSTATE_UNKNOWN (4294967295 (0xFFFFFFFF))
+ /// The session state is not known.
+ /// WTS_SESSIONSTATE_LOCK (0 (0x0))
+ /// The session is locked.
+ /// WTS_SESSIONSTATE_UNLOCK (1 (0x1))
+ /// The session is unlocked.
+ ///
+ /// Windows Server 2008 R2 and Windows 7: Due to a code defect, the usage of the WTS_SESSIONSTATE_LOCK and
+ /// WTS_SESSIONSTATE_UNLOCK flags is reversed. That is, WTS_SESSIONSTATE_LOCK indicates that the session is
+ /// unlocked, and WTS_SESSIONSTATE_UNLOCK indicates the session is locked.
+ ///
+ ///
+ public WTS_SESSIONSTATE SessionFlags;
+
+ /// A null-terminated string that contains the name of the window station for the session.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = WINSTATIONNAME_LENGTH + 1)]
+ public string WinStationName;
+
+ /// A null-terminated string that contains the name of the user who owns the session.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = USERNAME_LENGTH + 1)]
+ public string UserName;
+
+ /// A null-terminated string that contains the name of the domain that the user belongs to.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DOMAIN_LENGTH + 1)]
+ public string DomainName;
+
+ ///
+ /// The time that the user logged on to the session. This value is stored as a large integer that represents the number of
+ /// 100-nanosecond intervals since January 1, 1601 Coordinated Universal Time (Greenwich Mean Time).
+ ///
+ public FILETIME LogonTime;
+
+ ///
+ /// The time of the most recent client connection to the session. This value is stored as a large integer that represents the
+ /// number of 100-nanosecond intervals since January 1, 1601 Coordinated Universal Time.
+ ///
+ public FILETIME ConnectTime;
+
+ ///
+ /// The time of the most recent client disconnection to the session. This value is stored as a large integer that represents the
+ /// number of 100-nanosecond intervals since January 1, 1601 Coordinated Universal Time.
+ ///
+ public FILETIME DisconnectTime;
+
+ ///
+ /// The time of the last user input in the session. This value is stored as a large integer that represents the number of
+ /// 100-nanosecond intervals since January 1, 1601 Coordinated Universal Time.
+ ///
+ public FILETIME LastInputTime;
+
+ ///
+ /// The time that this structure was filled. This value is stored as a large integer that represents the number of
+ /// 100-nanosecond intervals since January 1, 1601 Coordinated Universal Time.
+ ///
+ public FILETIME CurrentTime;
+
+ ///
+ /// The number of bytes of uncompressed Remote Desktop Protocol (RDP) data sent from the client to the server since the client connected.
+ ///
+ public uint IncomingBytes;
+
+ /// The number of bytes of uncompressed RDP data sent from the server to the client since the client connected.
+ public uint OutgoingBytes;
+
+ /// The number of frames of RDP data sent from the client to the server since the client connected.
+ public uint IncomingFrames;
+
+ /// The number of frames of RDP data sent from the server to the client since the client connected.
+ public uint OutgoingFrames;
+
+ /// The number of bytes of compressed RDP data sent from the client to the server since the client connected.
+ public uint IncomingCompressedBytes;
+
+ /// The number of bytes of compressed RDP data sent from the server to the client since the client connected.
+ public uint OutgoingCompressedBytes;
+ }
+
+ /// Contains information about a Remote Desktop Services listener. This structure is used by the WTSCreateListener function.
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wtslistenerconfiga typedef struct _WTSLISTENERCONFIGA {
+ // ULONG version; ULONG fEnableListener; ULONG MaxConnectionCount; ULONG fPromptForPassword; ULONG fInheritColorDepth; ULONG
+ // ColorDepth; ULONG fInheritBrokenTimeoutSettings; ULONG BrokenTimeoutSettings; ULONG fDisablePrinterRedirection; ULONG
+ // fDisableDriveRedirection; ULONG fDisableComPortRedirection; ULONG fDisableLPTPortRedirection; ULONG fDisableClipboardRedirection;
+ // ULONG fDisableAudioRedirection; ULONG fDisablePNPRedirection; ULONG fDisableDefaultMainClientPrinter; ULONG LanAdapter; ULONG
+ // PortNumber; ULONG fInheritShadowSettings; ULONG ShadowSettings; ULONG TimeoutSettingsConnection; ULONG
+ // TimeoutSettingsDisconnection; ULONG TimeoutSettingsIdle; ULONG SecurityLayer; ULONG MinEncryptionLevel; ULONG UserAuthentication;
+ // CHAR Comment[WTS_COMMENT_LENGTH + 1]; CHAR LogonUserName[USERNAME_LENGTH + 1]; CHAR LogonDomain[DOMAIN_LENGTH + 1]; CHAR
+ // WorkDirectory[MAX_PATH + 1]; CHAR InitialProgram[MAX_PATH + 1]; } WTSLISTENERCONFIGA, *PWTSLISTENERCONFIGA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSLISTENERCONFIGA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSLISTENERCONFIG
+ {
+ /// This member is reserved.
+ public uint version;
+
+ ///
+ /// Specifies whether the listener is enabled. This member can be one of the following values.
+ /// 0
+ /// The listener is disabled.
+ /// 1
+ /// The listener is enabled.
+ ///
+ public uint fEnableListener;
+
+ /// The maximum number of active connections that the listener accepts.
+ public uint MaxConnectionCount;
+
+ ///
+ /// Specifies whether the listener always prompts the user for a password. This member can be one of the following values.
+ /// 0
+ /// Prompt the user for a password only when specified by the server.
+ /// 1
+ /// Always prompt the user for a password.
+ ///
+ public uint fPromptForPassword;
+
+ ///
+ ///
+ /// Specifies whether the listener should use the color depth specified by the user. This member can be one of the following values.
+ ///
+ /// 0
+ /// Use the color depth specified by the server.
+ /// 1
+ /// Use the color depth specified by the user.
+ ///
+ public uint fInheritColorDepth;
+
+ ///
+ ///
+ /// The color depth setting for the listener. This setting only applies when the fInheritColorDepth member is zero. This
+ /// can be one of the following values.
+ ///
+ /// 1
+ /// 8 bit
+ /// 2
+ /// 15 bit
+ /// 3
+ /// 16 bit
+ /// 4
+ /// 24 bit
+ /// 5
+ /// 32 bit
+ ///
+ public uint ColorDepth;
+
+ ///
+ ///
+ /// Specifies whether the listener should use the BrokenTimeoutSettings value specified by the user. This member can be
+ /// one of the following values.
+ ///
+ /// 0
+ /// Use the BrokenTimeoutSettings value specified by server.
+ /// 1
+ /// Use the BrokenTimeoutSettings value specified by the user.
+ ///
+ public uint fInheritBrokenTimeoutSettings;
+
+ ///
+ ///
+ /// The action the listener takes when a connection or idle timer expires, or when a connection is lost due to a connection
+ /// error. This setting only applies when the fInheritBrokenTimeoutSettings member is zero. This member can be one of the
+ /// following values.
+ ///
+ /// 0
+ ///
+ /// When a connection or idle timer expires, or when a connection is lost due to a connection error, the user is disconnected
+ /// but the session remains on the server.
+ ///
+ /// 1
+ /// When a connection or idle timer expires, or when a connection is lost due to a connection error, the session is terminated.
+ ///
+ public uint BrokenTimeoutSettings;
+
+ ///
+ /// Specifies whether printer redirection is disabled. This member can be one of the following values.
+ /// 0
+ /// The user can enable printer redirection.
+ /// 1
+ /// Printer redirection is disabled.
+ ///
+ public uint fDisablePrinterRedirection;
+
+ ///
+ /// Specifies whether drive redirection is disabled. This member can be one of the following values.
+ /// 0
+ /// The user can enable drive redirection.
+ /// 1
+ /// Drive redirection is disabled.
+ ///
+ public uint fDisableDriveRedirection;
+
+ ///
+ /// Specifies whether COM port redirection is disabled. This member can be one of the following values.
+ /// 0
+ /// The user can enable COM port redirection.
+ /// 1
+ /// COM port redirection is disabled.
+ ///
+ public uint fDisableComPortRedirection;
+
+ ///
+ /// Specifies whether LPT port redirection is disabled. This member can be one of the following values.
+ /// 0
+ /// The user can enable LPT port redirection.
+ /// 1
+ /// LPT port redirection is disabled.
+ ///
+ public uint fDisableLPTPortRedirection;
+
+ ///
+ /// Specifies whether clipboard redirection is disabled. This member can be one of the following values.
+ /// 0
+ /// The user can enable clipboard redirection.
+ /// 1
+ /// Clipboard redirection is disabled.
+ ///
+ public uint fDisableClipboardRedirection;
+
+ ///
+ /// Specifies whether audio redirection is disabled. This member can be one of the following values.
+ /// 0
+ /// The user can enable audio redirection.
+ /// 1
+ /// Audio redirection is disabled.
+ ///
+ public uint fDisableAudioRedirection;
+
+ ///
+ /// Specifies whether Plug and Play redirection is disabled. This member can be one of the following values.
+ /// 0
+ /// The user can enable Plug and Play redirection.
+ /// 1
+ /// Plug and Play redirection is disabled.
+ ///
+ public uint fDisablePNPRedirection;
+
+ ///
+ /// Specifies whether the client printer is the default printer. This member can be one of the following values.
+ /// 0
+ /// The client printer is not the default printer.
+ /// 1
+ /// The client printer is the default printer.
+ ///
+ public uint fDisableDefaultMainClientPrinter;
+
+ /// The network adapter that the listener uses.
+ public uint LanAdapter;
+
+ /// The port number of the listener.
+ public uint PortNumber;
+
+ ///
+ ///
+ /// Specifies whether the listener should use the ShadowSettings value specified by the user. This member can be one of
+ /// the following values.
+ ///
+ /// 0
+ /// Use the setting specified by the server.
+ /// 1
+ /// Use the setting specified by the user.
+ ///
+ public uint fInheritShadowSettings;
+
+ ///
+ ///
+ /// The remote control setting for the listener. Remote control allows a user to remotely monitor the on-screen operations of
+ /// another user. This setting only applies when the fInheritShadowSettings member is zero. This member can be one of the
+ /// following values.
+ ///
+ /// 0
+ /// Remote control is disabled.
+ /// 1
+ /// The user of remote control has full control of the user's session, with the user's permission.
+ /// 2
+ /// The user of remote control has full control of the user's session; the user's permission is not required.
+ /// 3
+ ///
+ /// The user of remote control can view the session remotely, with the user's permission; the remote user cannot actively
+ /// control the session.
+ ///
+ /// 4
+ ///
+ /// The user of remote control can view the session remotely but not actively control the session; the user's permission is not required.
+ ///
+ ///
+ public uint ShadowSettings;
+
+ ///
+ /// The maximum connection duration, in milliseconds. Every time the user logs on, the timer is reset. A value of zero indicates
+ /// that the connection timer is disabled.
+ ///
+ public uint TimeoutSettingsConnection;
+
+ ///
+ /// The maximum duration, in milliseconds, that a server retains a disconnected session before the logon is terminated. A value
+ /// of zero indicates that the disconnection timer is disabled.
+ ///
+ public uint TimeoutSettingsDisconnection;
+
+ /// The maximum idle time, in milliseconds. A value of zero indicates that the idle timer is disabled.
+ public uint TimeoutSettingsIdle;
+
+ ///
+ /// The security layer of the listener. This member can be one of the following values.
+ /// 0
+ /// Remote Desktop Protocol (RDP) is used by the server and the client for authentication before a connection is established.
+ /// 1
+ /// The server and the client negotiate the method for authentication before a connection is established.
+ /// 2
+ ///
+ /// Transport Layer Security (TLS) protocol is used by the server and the client for authentication before a connection is established.
+ ///
+ ///
+ public uint SecurityLayer;
+
+ ///
+ /// Encryption level of the listener. This member can be one of the following values.
+ /// 1
+ ///
+ /// Data sent from the client to the server is encrypted by using 56-bit encryption. Data sent from the server to the client is
+ /// not encrypted.
+ ///
+ /// 2
+ ///
+ /// All data sent from the client to the server and from the server to the client is encrypted by using the maximum key strength
+ /// supported by the client.
+ ///
+ /// 3
+ ///
+ /// All data sent from the client to the server and from the server to the client is encrypted by using 128-bit encryption.
+ /// Clients that do not support this level of encryption cannot connect.
+ ///
+ /// 4
+ ///
+ /// All data sent from the client to the server and from the server to the client is encrypted and decrypted by using the
+ /// Federal Information Processing Standards (FIPS) encryption algorithms and Microsoft cryptographic modules.
+ ///
+ ///
+ public uint MinEncryptionLevel;
+
+ ///
+ ///
+ /// Specifies whether network-level user authentication is required before the connection is established. This member can be one
+ /// of the following values.
+ ///
+ /// 0
+ /// Network-level user authentication is not required.
+ /// 1
+ /// Network-level user authentication is required.
+ ///
+ public uint UserAuthentication;
+
+ /// A null-terminated string that contains a description of the listener.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = WTS_COMMENT_LENGTH + 1)]
+ public string Comment;
+
+ /// A null-terminated string that contains the user name used in automatic logon scenarios.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = USERNAME_LENGTH + 1)]
+ public string LogonUserName;
+
+ /// A null-terminated string that contains the domain name used in automatic logon scenarios.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DOMAIN_LENGTH + 1)]
+ public string LogonDomain;
+
+ /// A null-terminated string that contains the path of the working directory of the initial program.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string WorkDirectory;
+
+ ///
+ /// A null-terminated string that contains the name of the program to start immediately after the user logs on to the server.
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string InitialProgram;
+ }
+
+ /// A fixed length string used by
+ [PInvokeData("wtsapi32.h")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSLISTENERNAME
+ {
+ private const int WTS_LISTENER_NAME_LENGTH = 32;
+
+ /// Name of the server.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = WTS_LISTENER_NAME_LENGTH + 1)]
+ public string Name;
+
+ /// Converts to string.
+ /// A that represents this instance.
+ public override string ToString() => Name ?? "";
+
+ /// Performs an implicit conversion from to .
+ /// The n.
+ /// The resulting instance from the conversion.
+ public static implicit operator string(WTSLISTENERNAME n) => n.Name;
+
+ /// Performs an implicit conversion from to .
+ /// The n.
+ /// The resulting instance from the conversion.
+ public static implicit operator WTSLISTENERNAME(string n) => new WTSLISTENERNAME { Name = n };
+ }
+
+ ///
+ /// Contains configuration information for a user on a domain controller or Remote Desktop Session Host (RD Session Host) server.
+ /// This structure is used by the WTSQueryUserConfig and WTSSetUserConfig functions.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/ns-wtsapi32-wtsuserconfiga typedef struct _WTSUSERCONFIGA { DWORD
+ // Source; DWORD InheritInitialProgram; DWORD AllowLogonTerminalServer; DWORD TimeoutSettingsConnections; DWORD
+ // TimeoutSettingsDisconnections; DWORD TimeoutSettingsIdle; DWORD DeviceClientDrives; DWORD DeviceClientPrinters; DWORD
+ // ClientDefaultPrinter; DWORD BrokenTimeoutSettings; DWORD ReconnectSettings; DWORD ShadowingSettings; DWORD
+ // TerminalServerRemoteHomeDir; CHAR InitialProgram[MAX_PATH + 1]; CHAR WorkDirectory[MAX_PATH + 1]; CHAR
+ // TerminalServerProfilePath[MAX_PATH + 1]; CHAR TerminalServerHomeDir[MAX_PATH + 1]; CHAR
+ // TerminalServerHomeDirDrive[WTS_DRIVE_LENGTH + 1]; } WTSUSERCONFIGA, *PWTSUSERCONFIGA;
+ [PInvokeData("wtsapi32.h", MSDNShortId = "NS:wtsapi32._WTSUSERCONFIGA")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WTSUSERCONFIG
+ {
+ ///
+ /// A value of the WTS_CONFIG_SOURCE enumeration type that specifies the source of configuration information returned by the
+ /// WTSQueryUserConfig function.
+ ///
+ public WTS_CONFIG_SOURCE Source;
+
+ ///
+ ///
+ /// A value that indicates whether the client can specify the initial program. This member can be one of the following values.
+ ///
+ /// 0
+ ///
+ /// The client cannot specify the initial program. Instead, the program specified by the InitialProgram member starts
+ /// automatically when the user logs on to the server. The server logs the user off when the user exits that program.
+ ///
+ /// 1
+ /// The client can specify the initial program.
+ ///
+ public uint InheritInitialProgram;
+
+ ///
+ ///
+ /// A value that indicates whether the user account is permitted to log on to an RD Session Host server. This member can be one
+ /// of the following values.
+ ///
+ /// 0
+ /// The user cannot log on.
+ /// 1
+ /// The user can log on.
+ ///
+ public uint AllowLogonTerminalServer;
+
+ ///
+ /// The maximum connection duration, in milliseconds. One minute before the connection expires, the server notifies the user
+ /// about the pending disconnection. When the connection times out, the server takes the action specified by the
+ /// BrokenTimeoutSettings member. Every time the user logs on, the timer is reset. A value of zero indicates that the
+ /// connection timer is disabled.
+ ///
+ public uint TimeoutSettingsConnections;
+
+ ///
+ /// The maximum duration, in milliseconds, that the server retains a disconnected session before the logon is terminated. A
+ /// value of zero indicates that the disconnection timer is disabled.
+ ///
+ public uint TimeoutSettingsDisconnections;
+
+ ///
+ /// The amount of time, in milliseconds, that a connection can remain idle. If there is no keyboard or mouse activity for this
+ /// period of time, the server takes the action specified by the BrokenTimeoutSettings member. A value of zero indicates
+ /// that the idle timer is disabled.
+ ///
+ public uint TimeoutSettingsIdle;
+
+ /// This member is reserved.
+ public uint DeviceClientDrives;
+
+ ///
+ ///
+ /// A value that indicates whether the server automatically connects to previously mapped client printers when the user logs on
+ /// to the server. This member can be one of the following values.
+ ///
+ /// 0
+ /// The server does not automatically connect to previously mapped client printers.
+ /// 1
+ /// The server automatically connects to previously mapped client printers.
+ ///
+ public uint DeviceClientPrinters;
+
+ ///
+ ///
+ /// A value that indicates whether the client printer is the default printer. This member can be one of the following values.
+ ///
+ /// 0
+ /// The client printer is not the default printer.
+ /// 1
+ /// The client printer is the default printer.
+ ///
+ public uint ClientDefaultPrinter;
+
+ ///
+ ///
+ /// The action the server takes when the connection or idle timers expire, or when a connection is lost due to a connection
+ /// error. This member can be one of the following values.
+ ///
+ /// 0
+ /// The session is disconnected, but it remains on the server.
+ /// 1
+ /// The session is terminated.
+ ///
+ public uint BrokenTimeoutSettings;
+
+ ///
+ ///
+ /// A value that indicates how a disconnected session for this user can be reconnected. This member can be one of the following values.
+ ///
+ /// 0
+ /// The user can log on to any client computer to reconnect to a disconnected session.
+ /// 1
+ ///
+ /// The user must log on to the client computer originally used to establish the disconnected session. If the user logs on to a
+ /// different client computer, the user gets a new session.
+ ///
+ ///
+ public uint ReconnectSettings;
+
+ ///
+ ///
+ /// The remote control setting. Remote control allows a user to remotely monitor the on-screen operations of another user. This
+ /// member can be one of the following values.
+ ///
+ /// 0
+ /// Remote control is disabled.
+ /// 1
+ /// The user of remote control has full control of the user's session, with the user's permission.
+ /// 2
+ /// The user of remote control has full control of the user's session; the user's permission is not required.
+ /// 3
+ ///
+ /// The user of remote control can view the session remotely, with the user's permission; the remote user cannot actively
+ /// control the session.
+ ///
+ /// 4
+ ///
+ /// The user of remote control can view the session remotely but not actively control the session; the user's permission is not required.
+ ///
+ ///
+ public uint ShadowingSettings;
+
+ ///
+ ///
+ /// A value that indicates whether the TerminalServerHomeDir member contains a path to a local directory or a network
+ /// share. You cannot set this member by using the WTSSetUserConfig function. This member can be one of the following values.
+ ///
+ /// 0
+ /// The TerminalServerHomeDir member contains a path to a local directory.
+ /// 1
+ ///
+ /// The TerminalServerHomeDir member contains a path to a network share, and the TerminalServerHomeDirDrive member
+ /// contains a drive letter to which this path is mapped.
+ ///
+ ///
+ public uint TerminalServerRemoteHomeDir;
+
+ ///
+ /// A null-terminated string that contains the name of the program to start immediately after the user logs on to the server.
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string InitialProgram;
+
+ /// A null-terminated string that contains the path of the working directory for the initial program.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string WorkDirectory;
+
+ ///
+ /// A null-terminated string that contains the profile path that is assigned to the user when the user connects to the server.
+ /// The directory specified by the path must be created manually, and must exist prior to the logon.
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string TerminalServerProfilePath;
+
+ ///
+ /// A null-terminated string that contains the path to the home folder of the user's Remote Desktop Services sessions. The
+ /// folder can be a local folder or a network share.
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
+ public string TerminalServerHomeDir;
+
+ ///
+ /// A null-terminated string that contains the drive name (a drive letter followed by a colon) to which the path specified in
+ /// the TerminalServerHomeDir member is mapped. This member is only valid when the TerminalServerRemoteHomeDir
+ /// member is set to one.
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = WTS_DRIVE_LENGTH + 1)]
+ public string TerminalServerHomeDirDrive;
+ }
+
+ /// Provides a for that is disposed using .
+ public class SafeHVIRTUALCHANNEL : SafeHANDLE
+ {
+ /// Initializes a new instance of the class and assigns an existing handle.
+ /// An object that represents the pre-existing handle to use.
+ ///
+ /// to reliably release the handle during the finalization phase; otherwise, (not recommended).
+ ///
+ public SafeHVIRTUALCHANNEL(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
+
+ /// Initializes a new instance of the class.
+ private SafeHVIRTUALCHANNEL() : base() { }
+
+ /// Performs an implicit conversion from to .
+ /// The safe handle instance.
+ /// The result of the conversion.
+ public static implicit operator HVIRTUALCHANNEL(SafeHVIRTUALCHANNEL h) => h.handle;
+
+ ///
+ protected override bool InternalReleaseHandle() => WTSVirtualChannelClose(handle);
+ }
+
+ /// Provides a for that is disposed using .
+ public class SafeHWTSSERVER : SafeHANDLE
+ {
+ /// Initializes a new instance of the class and assigns an existing handle.
+ /// An object that represents the pre-existing handle to use.
+ ///
+ /// to reliably release the handle during the finalization phase; otherwise, (not recommended).
+ ///
+ public SafeHWTSSERVER(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
+
+ /// Initializes a new instance of the class.
+ private SafeHWTSSERVER() : base() { }
+
+ /// Performs an implicit conversion from to .
+ /// The safe handle instance.
+ /// The result of the conversion.
+ public static implicit operator HWTSSERVER(SafeHWTSSERVER h) => h.handle;
+
+ ///
+ protected override bool InternalReleaseHandle() { WTSCloseServer(handle); return true; }
+ }
+
+ /// Provides a for WTS memory that is disposed using .
+ public class SafeWTSMemoryHandle : SafeHANDLE
+ {
+ /// Initializes a new instance of the class and assigns an existing handle.
+ /// An object that represents the pre-existing handle to use.
+ ///
+ /// to reliably release the handle during the finalization phase; otherwise, (not recommended).
+ ///
+ public SafeWTSMemoryHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
+
+ /// Initializes a new instance of the class.
+ private SafeWTSMemoryHandle() : base() { }
+
+ ///
+ /// Extracts an array of structures of containing items. This call can cause memory exceptions if the pointer does not have sufficient allocated memory to retrieve all
+ /// the structures.
+ ///
+ /// The type of the structures to retrieve.
+ /// The number of structures to retrieve.
+ /// An array of structures of .
+ public T[] ToArray(int count) => handle.ToArray(count);
+
+ /// Returns a that represents this instance.
+ /// The size, in bytes, of the data returned in ppBuffer.
+ /// A that represents this instance.
+ public string ToString(uint allocatedBytes) => StringHelper.GetString(handle, CharSet.Auto, allocatedBytes);
+
+#if ALLOWSPAN
+ /// Creates a new span over this allocated memory.
+ /// The span representation of the structure.
+ public virtual ReadOnlySpan AsReadOnlySpan(int length) => handle.AsReadOnlySpan(length);
+
+ /// Creates a new span over this allocated memory.
+ /// The span representation of the structure.
+ public virtual Span AsSpan(int length) => handle.AsSpan(length);
+#endif
+
+ ///
+ protected override bool InternalReleaseHandle() { WTSFreeMemory(handle); return true; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Vanara.sln b/Vanara.sln
index c7267225..916feba4 100644
--- a/Vanara.sln
+++ b/Vanara.sln
@@ -261,7 +261,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.Dhcp", "PInv
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dhcp", "UnitTests\PInvoke\Dhcp\Dhcp.csproj", "{94D2C3ED-2101-439C-AAAA-452883A493B4}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.Rpc", "PInvoke\Rpc\Vanara.PInvoke.Rpc.csproj", "{4108A2DD-AD00-44D0-B926-405D65E630A3}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Rpc", "PInvoke\Rpc\Vanara.PInvoke.Rpc.csproj", "{4108A2DD-AD00-44D0-B926-405D65E630A3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.WTSApi32", "PInvoke\WTSApi32\Vanara.PInvoke.WTSApi32.csproj", "{CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -837,6 +839,12 @@ Global
{4108A2DD-AD00-44D0-B926-405D65E630A3}.DebugNoTests|Any CPU.Build.0 = Debug|Any CPU
{4108A2DD-AD00-44D0-B926-405D65E630A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4108A2DD-AD00-44D0-B926-405D65E630A3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}.DebugNoTests|Any CPU.ActiveCfg = Debug|Any CPU
+ {CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}.DebugNoTests|Any CPU.Build.0 = Debug|Any CPU
+ {CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -949,6 +957,7 @@ Global
{CB2EAE48-7503-459F-BD63-69FAE9740A20} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90}
{94D2C3ED-2101-439C-AAAA-452883A493B4} = {385CAD2D-0A5E-4F80-927B-D5499D126B90}
{4108A2DD-AD00-44D0-B926-405D65E630A3} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90}
+ {CEBC8DBE-0A4F-4A71-BEB5-8A5B28F89352} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {543FAC75-2AF1-4EF1-9609-B242B63FEED4}