/**
 * Windows API header module
 *
 * Translated from MinGW-w64 API
 *
 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
 * Source: $(DRUNTIMESRC core/sys/windows/_wtsapi32.d)
 */
module core.sys.windows.wtsapi32;
version (Windows):

version (ANSI) {} else version = Unicode;
pragma(lib, "wtsapi32");
import core.sys.windows.w32api;
import core.sys.windows.windef;

enum {
    WTS_CURRENT_SERVER        = null,
    WTS_CURRENT_SERVER_HANDLE = null,
    WTS_CURRENT_SERVER_NAME   = null
}

enum DWORD WTS_CURRENT_SESSION = cast(DWORD) -1;

enum {
    IDTIMEOUT = 32000,
    IDASYNC   = 32001
}

enum {
    WTS_WSD_LOGOFF     = 0x01,
    WTS_WSD_SHUTDOWN   = 0x02,
    WTS_WSD_REBOOT     = 0x04,
    WTS_WSD_POWEROFF   = 0x08,
    WTS_WSD_FASTREBOOT = 0x10
}

enum WTS_CONNECTSTATE_CLASS {
    WTSActive,
    WTSConnected,
    WTSConnectQuery,
    WTSShadow,
    WTSDisconnected,
    WTSIdle,
    WTSListen,
    WTSReset,
    WTSDown,
    WTSInit
}

struct WTS_SERVER_INFOW {
    LPWSTR pServerName;
}
alias PWTS_SERVER_INFOW = WTS_SERVER_INFOW*;

struct WTS_SERVER_INFOA {
    LPSTR pServerName;
}
alias PWTS_SERVER_INFOA = WTS_SERVER_INFOA*;

version (Unicode) {
    alias WTS_SERVER_INFO = WTS_SERVER_INFOW;
    alias PWTS_SERVER_INFO = PWTS_SERVER_INFOW;
} else {
    alias WTS_SERVER_INFO = WTS_SERVER_INFOA;
    alias PWTS_SERVER_INFO = PWTS_SERVER_INFOA;
}

struct WTS_SESSION_INFOW {
    DWORD SessionId;
    LPWSTR pWinStationName;
    WTS_CONNECTSTATE_CLASS State;
}
alias PWTS_SESSION_INFOW = WTS_SESSION_INFOW*;

struct WTS_SESSION_INFOA {
    DWORD SessionId;
    LPSTR pWinStationName;
    WTS_CONNECTSTATE_CLASS State;
}
alias PWTS_SESSION_INFOA = WTS_SESSION_INFOA*;

version (Unicode) {
    alias WTS_SESSION_INFO = WTS_SESSION_INFOW;
    alias PWTS_SESSION_INFO = PWTS_SESSION_INFOW;
} else {
    alias WTS_SESSION_INFO = WTS_SESSION_INFOA;
    alias PWTS_SESSION_INFO = PWTS_SESSION_INFOA;
}

struct WTS_PROCESS_INFOW {
    DWORD SessionId;
    DWORD ProcessId;
    LPWSTR pProcessName;
    PSID pUserSid;
}
alias PWTS_PROCESS_INFOW = WTS_PROCESS_INFOW*;

struct WTS_PROCESS_INFOA {
    DWORD SessionId;
    DWORD ProcessId;
    LPSTR pProcessName;
    PSID pUserSid;
}
alias PWTS_PROCESS_INFOA = WTS_PROCESS_INFOA*;

version (Unicode) {
    alias WTS_PROCESS_INFO = WTS_PROCESS_INFOW;
    alias PWTS_PROCESS_INFO = PWTS_PROCESS_INFOW;
} else {
    alias WTS_PROCESS_INFO = WTS_PROCESS_INFOA;
    alias PWTS_PROCESS_INFO = PWTS_PROCESS_INFOA;
}

enum {
    WTS_PROTOCOL_TYPE_CONSOLE,
    WTS_PROTOCOL_TYPE_ICA,
    WTS_PROTOCOL_TYPE_RDP
}

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, // = 24
}

struct WTS_CLIENT_ADDRESS {
    DWORD    AddressFamily;
    BYTE[20] Address;
}
alias PWTS_CLIENT_ADDRESS = WTS_CLIENT_ADDRESS*;

struct WTS_CLIENT_DISPLAY {
    DWORD HorizontalResolution;
    DWORD VerticalResolution;
    DWORD ColorDepth;
}
alias PWTS_CLIENT_DISPLAY = WTS_CLIENT_DISPLAY*;

enum WTS_CONFIG_CLASS {
    WTSUserConfigInitialProgram,
    WTSUserConfigWorkingDirectory,
    WTSUserConfigfInheritInitialProgram,
    WTSUserConfigfAllowLogonTerminalServer,
    WTSUserConfigTimeoutSettingsConnections,
    WTSUserConfigTimeoutSettingsDisconnections,
    WTSUserConfigTimeoutSettingsIdle,
    WTSUserConfigfDeviceClientDrives,
    WTSUserConfigfDeviceClientPrinters,
    WTSUserConfigfDeviceClientDefaultPrinter,
    WTSUserConfigBrokenTimeoutSettings,
    WTSUserConfigReconnectSettings,
    WTSUserConfigModemCallbackSettings,
    WTSUserConfigModemCallbackPhoneNumber,
    WTSUserConfigShadowingSettings,
    WTSUserConfigTerminalServerProfilePath,
    WTSUserConfigTerminalServerHomeDir,
    WTSUserConfigTerminalServerHomeDirDrive,
    WTSUserConfigfTerminalServerRemoteHomeDir
}

enum {
    WTS_EVENT_NONE        = 0x0,
    WTS_EVENT_CREATE      = 0x1,
    WTS_EVENT_DELETE      = 0x2,
    WTS_EVENT_RENAME      = 0x4,
    WTS_EVENT_CONNECT     = 0x8,
    WTS_EVENT_DISCONNECT  = 0x10,
    WTS_EVENT_LOGON       = 0x20,
    WTS_EVENT_LOGOFF      = 0x40,
    WTS_EVENT_STATECHANGE = 0x80,
    WTS_EVENT_LICENSE     = 0x100,
    WTS_EVENT_ALL         = 0x7fffffff,
    WTS_EVENT_FLUSH       = 0x80000000
}

enum WTS_VIRTUAL_CLASS {
    WTSVirtualClientData,
    WTSVirtualFileHandle
}

version (Unicode) {
    alias WTSEnumerateServers = WTSEnumerateServersW;
    alias WTSOpenServer = WTSOpenServerW;
    alias WTSEnumerateSessions = WTSEnumerateSessionsW;
    alias WTSEnumerateProcesses = WTSEnumerateProcessesW;
    alias WTSQuerySessionInformation = WTSQuerySessionInformationW;
    alias WTSQueryUserConfig = WTSQueryUserConfigW;
    alias WTSSetUserConfig = WTSSetUserConfigW;
    alias WTSSendMessage = WTSSendMessageW;
} else {
    alias WTSEnumerateServers = WTSEnumerateServersA;
    alias WTSOpenServer = WTSOpenServerA;
    alias WTSEnumerateSessions = WTSEnumerateSessionsA;
    alias WTSEnumerateProcesses = WTSEnumerateProcessesA;
    alias WTSQuerySessionInformation = WTSQuerySessionInformationA;
    alias WTSQueryUserConfig = WTSQueryUserConfigA;
    alias WTSSetUserConfig = WTSSetUserConfigA;
    alias WTSSendMessage = WTSSendMessageA;
}

extern(Windows) {
    WINBOOL WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount);
    WINBOOL WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version, PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount);
    HANDLE WTSOpenServerW(LPWSTR pServerName);
    HANDLE WTSOpenServerA(LPSTR pServerName);
    VOID WTSCloseServer(HANDLE hServer);
    WINBOOL WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount);
    WINBOOL WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount);
    WINBOOL WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount);
    WINBOOL WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount);
    WINBOOL WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode);
    WINBOOL WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer, DWORD* pBytesReturned);
    WINBOOL WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer, DWORD* pBytesReturned);
    WINBOOL WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer, DWORD* pBytesReturned);
    WINBOOL WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer, DWORD* pBytesReturned);
    WINBOOL WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer, DWORD DataLength);
    WINBOOL WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName, WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer, DWORD DataLength);
    WINBOOL WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle, DWORD TitleLength, LPWSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, WINBOOL bWait);
    WINBOOL WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle, DWORD TitleLength, LPSTR pMessage, DWORD MessageLength, DWORD Style, DWORD Timeout, DWORD* pResponse, WINBOOL bWait);
    WINBOOL WTSDisconnectSession(HANDLE hServer, DWORD SessionId, WINBOOL bWait);
    WINBOOL WTSLogoffSession(HANDLE hServer, DWORD SessionId, WINBOOL bWait);
    WINBOOL WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag);
    WINBOOL WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags);
    HANDLE WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName);
    WINBOOL WTSVirtualChannelClose(HANDLE hChannelHandle);
    WINBOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead);
    WINBOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten);
    WINBOOL WTSVirtualChannelPurgeInput(HANDLE hChannelHandle);
    WINBOOL WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle);
    WINBOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS, PVOID* ppBuffer, DWORD* pBytesReturned);
    VOID WTSFreeMemory(PVOID pMemory);

    WINBOOL WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags);
    WINBOOL WTSUnRegisterSessionNotification(HWND hWnd);
    WINBOOL WTSQueryUserToken(ULONG SessionId, PHANDLE phToken);
}

enum {
    NOTIFY_FOR_ALL_SESSIONS = 1,
    NOTIFY_FOR_THIS_SESSION = 0
}

enum {
    USERNAME_LENGTH       = 20,
    CLIENTNAME_LENGTH     = 20,
    CLIENTADDRESS_LENGTH  = 30,
    WINSTATIONNAME_LENGTH = 32,
    DOMAIN_LENGTH         = 17
}

static if (_WIN32_WINNT >= 0x600) {
    struct WTSCLIENTW {
        WCHAR[CLIENTNAME_LENGTH + 1]      ClientName = 0;
        WCHAR[DOMAIN_LENGTH + 1]          Domain = 0;
        WCHAR[USERNAME_LENGTH + 1]        UserName = 0;
        WCHAR[MAX_PATH + 1]               WorkDirectory = 0;
        WCHAR[MAX_PATH + 1]               InitialProgram = 0;
        BYTE                              EncryptionLevel;
        ULONG                             ClientAddressFamily;
        USHORT[CLIENTADDRESS_LENGTH + 1]  ClientAddress;
        USHORT                            HRes;
        USHORT                            VRes;
        USHORT                            ColorDepth;
        WCHAR[MAX_PATH + 1]               ClientDirectory = 0;
        ULONG                             ClientBuildNumber;
        ULONG                             ClientHardwareId;
        USHORT                            ClientProductId;
        USHORT                            OutBufCountHost;
        USHORT                            OutBufCountClient;
        USHORT                            OutBufLength;
        WCHAR[MAX_PATH + 1]               DeviceId = 0;
    }
    alias PWTSCLIENTW = WTSCLIENTW*;

    struct WTSCLIENTA {
        CHAR[CLIENTNAME_LENGTH + 1]       ClientName = 0;
        CHAR[DOMAIN_LENGTH + 1 ]          Domain = 0;
        CHAR[USERNAME_LENGTH + 1]         UserName = 0;
        CHAR[MAX_PATH + 1]                WorkDirectory = 0;
        CHAR[MAX_PATH + 1]                InitialProgram = 0;
        BYTE                              EncryptionLevel;
        ULONG                             ClientAddressFamily;
        USHORT[CLIENTADDRESS_LENGTH + 1]  ClientAddress;
        USHORT                            HRes;
        USHORT                            VRes;
        USHORT                            ColorDepth;
        CHAR[MAX_PATH + 1]                ClientDirectory = 0;
        ULONG                             ClientBuildNumber;
        ULONG                             ClientHardwareId;
        USHORT                            ClientProductId;
        USHORT                            OutBufCountHost;
        USHORT                            OutBufCountClient;
        USHORT                            OutBufLength;
        CHAR[MAX_PATH + 1]                DeviceId = 0;
    }
    alias PWTSCLIENTA = WTSCLIENTA*;

    version (Unicode) {
        alias WTSCLIENT = WTSCLIENTW;
        alias PWTSCLIENT = PWTSCLIENTW;
    } else {
        alias WTSCLIENT = WTSCLIENTA;
        alias PWTSCLIENT = PWTSCLIENTA;
    }

    struct WTSINFOW {
        WTS_CONNECTSTATE_CLASS       State;
        DWORD                        SessionId;
        DWORD                        IncomingBytes;
        DWORD                        OutgoingBytes;
        DWORD                        IncomingFrames;
        DWORD                        OutgoingFrames;
        DWORD                        IncomingCompressedBytes;
        DWORD                        OutgoingCompressedBytes;
        WCHAR[WINSTATIONNAME_LENGTH] WinStationName = 0;
        WCHAR[DOMAIN_LENGTH]         Domain = 0;
        WCHAR[USERNAME_LENGTH+1]     UserName = 0;
        LARGE_INTEGER                ConnectTime;
        LARGE_INTEGER                DisconnectTime;
        LARGE_INTEGER                LastInputTime;
        LARGE_INTEGER                LogonTime;
        LARGE_INTEGER                CurrentTime;
    }
    alias PWTSINFOW = WTSINFOW*;

    struct WTSINFOA {
        WTS_CONNECTSTATE_CLASS      State;
        DWORD                       SessionId;
        DWORD                       IncomingBytes;
        DWORD                       OutgoingBytes;
        DWORD                       IncomingFrames;
        DWORD                       OutgoingFrames;
        DWORD                       IncomingCompressedBytes;
        DWORD                       OutgoingCompressedBytes;
        CHAR[WINSTATIONNAME_LENGTH] WinStationName = 0;
        CHAR[DOMAIN_LENGTH]         Domain = 0;
        CHAR[USERNAME_LENGTH+1]     UserName = 0;
        LARGE_INTEGER               ConnectTime;
        LARGE_INTEGER               DisconnectTime;
        LARGE_INTEGER               LastInputTime;
        LARGE_INTEGER               LogonTime;
        LARGE_INTEGER               CurrentTime;
    }
    alias PWTSINFOA = WTSINFOA*;

    version (Unicode) {
        alias WTSINFO = WTSINFOW;
        alias PWTSINFO = PWTSINFOW;
    } else {
        alias WTSINFO = WTSINFOA;
        alias PWTSINFO = PWTSINFOA;
    }

    extern(Windows) {
        WINBOOL WTSConnectSessionA(
            ULONG LogonId,
            ULONG TargetLogonId,
            PSTR   pPassword,
            WINBOOL bWait
        );

        WINBOOL WTSConnectSessionW(
            ULONG LogonId,
            ULONG TargetLogonId,
            PWSTR  pPassword,
            WINBOOL bWait
        );

        WINBOOL WTSRegisterSessionNotificationEx(
            HANDLE hServer,
            HWND hWnd,
            DWORD dwFlags
        );

        WINBOOL WTSStartRemoteControlSessionA(
            LPSTR pTargetServerName,
            ULONG TargetLogonId,
            BYTE HotkeyVk,
            USHORT HotkeyModifiers
        );

        WINBOOL WTSStartRemoteControlSessionW(
            LPWSTR pTargetServerName,
            ULONG TargetLogonId,
            BYTE HotkeyVk,
            USHORT HotkeyModifiers
        );

        version (Unicode) {
            alias WTSStartRemoteControlSession = WTSStartRemoteControlSessionW;
            alias WTSConnectSession = WTSConnectSessionW;
        } else {
            alias WTSStartRemoteControlSession = WTSStartRemoteControlSessionA;
            alias WTSConnectSession = WTSConnectSessionA;
        }

        WINBOOL WTSStopRemoteControlSession(
            ULONG LogonId
        );

        WINBOOL WTSUnRegisterSessionNotificationEx(
            HANDLE hServer,
            HWND hWnd
        );

        HANDLE WTSVirtualChannelOpenEx(
            DWORD SessionId,
            LPSTR pVirtualName,
            DWORD flags
        );
    } /* extern(Windows) */
} /* static if (_WIN32_WINNT >= 0x600) */
