From dcefb85f617a5c34376fb5870a7809703715ed57 Mon Sep 17 00:00:00 2001 From: dahall Date: Tue, 22 Dec 2020 16:26:55 -0700 Subject: [PATCH] Added WTSApi32 library --- PInvoke/WTSApi32/Vanara.PInvoke.WTSApi32.csproj | 19 + PInvoke/WTSApi32/WTSApi32.cs | 3717 +++++++++++++++++++++++ Vanara.sln | 11 +- 3 files changed, 3746 insertions(+), 1 deletion(-) create mode 100644 PInvoke/WTSApi32/Vanara.PInvoke.WTSApi32.csproj create mode 100644 PInvoke/WTSApi32/WTSApi32.cs 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}