import "oaidl.idl";
import "ocidl.idl";
import "wtypes.idl";

import "wtsdefs.h";

/*****************************************************************
 * INTERFACES
 ******************************************************************/

interface IWTSProtocolListener;
interface IWTSProtocolListenerCallback;
interface IWTSProtocolConnection;
interface IWTSProtocolConnectionCallback;
interface IWTSProtocolLicenseConnection;
interface IWTSProtocolShadowConnection;
interface IWTSProtocolShadowCallback;
interface IWTSProtocolLogonErrorRedirector;

[
    object,
    uuid(F9EAF6CC-ED79-4f01-821D-1F881B9F66CC),
    pointer_default(unique)
]
interface IWTSProtocolManager : IUnknown
{
    HRESULT
    CreateListener(
        [in, string]                WCHAR         *wszListenerName,
        [out]                       IWTSProtocolListener **pProtocolListener
    );

    HRESULT
    NotifyServiceStateChange(
        [in]                        WTS_SERVICE_STATE    *pTSServiceStateChange
        );

    HRESULT
    NotifySessionOfServiceStart(
        [in]                        WTS_SESSION_ID   *SessionId
        );

    HRESULT
    NotifySessionOfServiceStop(
        [in]                        WTS_SESSION_ID   *SessionId
        );

    HRESULT
    NotifySessionStateChange(
        [in]                        WTS_SESSION_ID   *SessionId,
        [in]                        ULONG   EventId
        );
};

[
    object,
    uuid(23083765-45f0-4394-8f69-32b2bc0ef4ca),
    pointer_default(unique)
]
interface IWTSProtocolListener : IUnknown
{
    HRESULT
    StartListen( 
        [in] IWTSProtocolListenerCallback           *pCallback
        );

    HRESULT
    StopListen();
};

[
    object,
    uuid(23083765-1a2d-4de2-97de-4a35f260f0b3),
    pointer_default(unique)
]
interface IWTSProtocolListenerCallback : IUnknown
{
    // Inform RCM of an incoming connection request
    HRESULT OnConnected( 
        [in]  IWTSProtocolConnection *pConnection,
        [out] IWTSProtocolConnectionCallback **pCallback );
};

[
    object,
    uuid(23083765-9095-4648-98bf-ef81c914032d),
    pointer_default(unique)
]
interface IWTSProtocolConnection : IUnknown
{
    /* ----------------------------------------------------
     * Following functions will be called in the sequence
     * defined below
     * ---------------------------------------------------*/

    // To get the LogonUI error redirector interface
    // Fail the call if error redirection is not desired
    HRESULT
    GetLogonErrorRedirector(
        [out] IWTSProtocolLogonErrorRedirector **ppLogonErrorRedir
        );

    // Provide policy data to the protocol to prepare it for Accept
    HRESULT 
    SendPolicyData(
        [in] WTS_POLICY_DATA *pPolicyData
        );

    // Initial response from RCM after receiving a connection request
    // RCM is asking protocol to go ahead with the connection sequence
    HRESULT 
    AcceptConnection();

    // Ask for client data
    HRESULT
    GetClientData( 
        [out] WTS_CLIENT_DATA *pClientData
        );

    // Request for user credential if available
    // Today we only support username/password credentials
    HRESULT
    GetUserCredentials(
        [out] WTS_USER_CREDENTIAL *pUserCreds
        );

    // Get instance of IWTSProtocolLicenseConnection 
    // It will be used to perform licensing handshake
    HRESULT
    GetLicenseConnection(
        [out]   IWTSProtocolLicenseConnection   **ppLicenseConnection
        );

    // Allow protocol to provide an existing session to reconnect.
    // This is done before arbitration. If the call fails, session
    // will be created and RCM will do arbitration.
    HRESULT 
    AuthenticateClientToSession( 
        [out]   WTS_SESSION_ID  *SessionId 
        );

    // CREATE TEMP SESSION if AuthenticateClientToSession fails

    // Session is created, Notify of Session ID and GUID
    HRESULT
    NotifySessionId(
        [in]    WTS_SESSION_ID   *SessionId
        );

    // Get handles to input/output devices which will be passed to win32k
    HRESULT
    GetProtocolHandles(
        [out]   HANDLE_PTR   *pKeyboardHandle,
        [out]   HANDLE_PTR   *pMouseHandle,
        [out]   HANDLE_PTR   *pBeepHandle,
        [out]   HANDLE_PTR   *pVideoHandle
        );

    // Notify Winlogon has connected
    HRESULT
    ConnectNotify(
        [in]    ULONG  SessionId
        );

    // Check with protocol if used should be allowed to log on
    HRESULT
    IsUserAllowedToLogon(
        [in]            ULONG           SessionId,
        [in]            HANDLE_PTR      UserToken,
        [in, string]    WCHAR           *pDomainName,
        [in, string]    WCHAR           *pUserName 
        );

    // This is called after arbitration. The protocol is allowed to 
    // choose the session to be reconnected. 
    // Protocol extension should return E_NOTIMPL if it want to use default
    // RCM session arbitration.    
    HRESULT 
    SessionArbitrationEnumeration(
        [in]                                        HANDLE_PTR  hUserToken,
        [in]                                        BOOL        bSingleSessionPerUserEnabled,
        [out, size_is(*pdwSessionIdentifierCount)]  ULONG       *pSessionIdArray,
        [in,out]                                    ULONG       *pdwSessionIdentifierCount 
        );

    // Notify that user have logged on
    HRESULT
    LogonNotify(
        [in]        HANDLE_PTR      hClientToken,
        [in,string] WCHAR           *wszUserName,
        [in,string] WCHAR           *wszDomainName,
        [in]        WTS_SESSION_ID  *SessionId
        );

    // At this point, user properties (GP) must have been merged
    // Send updated policy data so that protocol can provide
    // updated user data, if desired
    HRESULT
    GetUserData(
        [in]      WTS_POLICY_DATA *pPolicyData,
        [in, out] WTS_USER_DATA   *pClientData
        );

    // Notify of session disconnect
    HRESULT
    DisconnectNotify();

    // Close connection. Last call before connection object is removed.
    HRESULT
    Close();

    /* ----------------------------------------------------
     * Following functions can be called at any time
     * ---------------------------------------------------*/

    // Get performance data from protocol
    HRESULT
    GetProtocolStatus(
        [out] WTS_PROTOCOL_STATUS *pProtocolStatus
        );

    // Get last time input was received
    HRESULT
    GetLastInputTime(
        [out] ULONG64 *pLastInputTime
        );

    // Send error message to client
    HRESULT
    SetErrorInfo(
        [in] ULONG  ulError
        );

    // Send beep
    HRESULT
    SendBeep(
        [in] ULONG  Frequency,
        [in] ULONG  Duration 
        );

    // Create Virtual channels
    HRESULT
    CreateVirtualChannel(
        [in,string] CHAR    *szEndpointName,
        [in]        BOOL    bStatic,
        [in]        ULONG   RequestedPriority,
        [out]       ULONG_PTR *phChannel 
        );

    // Used to query properties from the protocol:
    // - The QueryType GUID specifies what property to query
    // - A number of WTS_PPROPERTY_VALUEs are passed in to help in querying (optional)
    // - Protocol replies with a bunch of WTS_PPROPERTY_VALUEs (optional)
    // Properties and structures are defined in tsproperty.w
    HRESULT
    QueryProperty(
        [in]                                    GUID                QueryType,
        [in]                                    ULONG               ulNumEntriesIn,
        [in]                                    ULONG               ulNumEntriesOut,
        [in,optional,size_is(ulNumEntriesIn)]   PWTS_PROPERTY_VALUE pPropertyEntriesIn,
        [out,optional,size_is(ulNumEntriesOut)] PWTS_PROPERTY_VALUE pPropertyEntriesOut 
        );

    // To get shadow connection object from the protocol
    HRESULT
    GetShadowConnection(
        [out] IWTSProtocolShadowConnection **ppShadowConnection
        );
};

[
    object,
    uuid(23083765-75eb-41fe-b4fb-e086242afa0f),
    pointer_default(unique)
]
interface IWTSProtocolConnectionCallback : IUnknown
{
    // This is a signal from the protocol that it is
    // ready with client data and RCM should go ahead
    // with the connection sequence
    HRESULT OnReady();

    // Inform RCM of disconnect
    HRESULT BrokenConnection(
        [in] ULONG Reason, 
        [in] ULONG Source
        );

    // Stop display updates. 
    // This call will be forwarded to win32k.
    HRESULT StopScreenUpdates();

    // Redraw the window. Generally called after StopScreenUpdates.
    // This call will be forwarded to win32k.
    // Passing NULL as parameter will redraw the whole window
    HRESULT RedrawWindow( 
        [in, optional] WTS_SMALL_RECT *rect 
        );

    // This will generate a DrvDisplayIOCtl call to DD from win32k
    // Win32k will pass the data supplied in this call to DD.
    //
    // DD must implement the DrvDisplayIOCtl call with following signature:
    //      BOOL APIENTRY DrvDisplayIOCtl(PVOID, ULONG);
    //
    HRESULT DisplayIOCtl(
        [in] WTS_DISPLAY_IOCTL *DisplayIOCtl
        );
};

[
    object,
    uuid(ee3b0c14-37fb-456b-bab3-6d6cd51e13bf),
    pointer_default(unique)
]
interface IWTSProtocolShadowConnection : IUnknown
{
    // This is to inform of shadow start.
    // RCM will also change the state of the session on the shadow client.
    HRESULT
    Start(
        [in,string]                     WCHAR       *pTargetServerName,
        [in]                            DWORD       TargetSessionId,
        [in]                            BYTE        HotKeyVk,
        [in]                            USHORT      HotkeyModifiers,
        [in]                            IWTSProtocolShadowCallback   *pShadowCallback
        );

    // This is to inform of shadow stop if RCM detects it.
    // RCM will also change the state of the session on the shadow client.
    HRESULT
    Stop();

    HRESULT
    DoTarget(
        [in,size_is(Param1Size)]    PBYTE       pParam1,
        [in]                        DWORD       Param1Size,
        [in,size_is(Param2Size)]    PBYTE       pParam2,
        [in]                        DWORD       Param2Size,
        [in,size_is(Param3Size)]    PBYTE       pParam3,
        [in]                        DWORD       Param3Size,
        [in,size_is(Param4Size)]    PBYTE       pParam4,
        [in]                        DWORD       Param4Size,
        [in,string]                 WCHAR       *pClientName
        );
};

[
    object,
    uuid(503a2504-aae5-4ab1-93e0-6d1c4bc6f71a),
    pointer_default(unique)
]
interface IWTSProtocolShadowCallback : IUnknown
{
    // This is to inform RCM that shadow ended. 
    // This will revert state of the session on the shadow client.
    HRESULT
    StopShadow();

    // This call will send a RPC message to target to start shadow
    HRESULT InvokeTargetShadow(
        [in,ptr,string]             WCHAR       *pTargetServerName,
        [in]                        ULONG       TargetSessionId,
        [in,size_is(Param1Size)]    PBYTE       pParam1,
        [in]                        DWORD       Param1Size,
        [in,size_is(Param2Size)]    PBYTE       pParam2,
        [in]                        DWORD       Param2Size,
        [in,size_is(Param3Size)]    PBYTE       pParam3,
        [in]                        DWORD       Param3Size,
        [in,size_is(Param4Size)]    PBYTE       pParam4,
        [in]                        DWORD       Param4Size,
        [in,string]                 WCHAR       *pClientName
        );
};

[
    object,
    uuid(23083765-178c-4079-8e4a-fea6496a4d70),
    pointer_default(unique)
]
interface IWTSProtocolLicenseConnection : IUnknown
{
    // Used to request licensing capabilities from the client
    HRESULT
    RequestLicensingCapabilities(
        [out]       PWTS_LICENSE_CAPABILITIES   ppLicenseCapabilities,
        [in, out]   ULONG                       *pcbLicenseCapabilities
        );

    // Used to send license from server.
    //
    // The pClientLicense can be one of the following structures:
    //      - Server_New_License 
    //      - Platform_Challenge
    //      - Server_License_Request
    //      - Server_Upgrade_License
    // * For more details on the structures and wire formats, please
    // * refer to [MS-RDPBCGR] - 
    // * http://msdn.microsoft.com/en-us/library/cc241880(PROT.10).aspx
    //
    HRESULT
    SendClientLicense(
        [in,size_is(cbClientLicense)] PBYTE  pClientLicense,
        [in]                          ULONG  cbClientLicense
        );

    // Used to get license from server.
    //
    // The client responds to server by filling on the following 
    // structures in ppClientLicense:
    //      - Client_License_Info 
    //      - Client_New_License_Request
    //      - Client_Platform_Challenge_Response
    // * For more details on the structures and wire formats, please
    // * refer to [MS-RDPBCGR] - 
    // * http://msdn.microsoft.com/en-us/library/cc241880(PROT.10).aspx
    //
    HRESULT
    RequestClientLicense(
        [in, size_is( Reserve2 )]           PBYTE Reserve1,
        [in]                                ULONG Reserve2,
        [out, size_is(*pcbClientLicense)] PBYTE ppClientLicense,
        [in, out]                           ULONG *pcbClientLicense
        );

    // Used to notify whether the licensing handshake succeeded or not.
    //
    // ulComplete = 1 means success, failure otherwise
    //
    HRESULT
    ProtocolComplete(
        [in] ULONG                          ulComplete
        );
        
};

[
    object,
    uuid(FD9B61A7-2916-4627-8DEE-4328711AD6CB),
    pointer_default(unique)
]
interface IWTSProtocolLogonErrorRedirector : IUnknown
{
    //=============================================================================
    //
    // OnBeginPainting()
    //
    // Purpose:
    //      LogonUI is notifying that it is goinging to start painting.
    // Parameters:
    //      NONE
    //
    // Return values:
    //      S_OK or error code
    //
    //=============================================================================
    HRESULT
    OnBeginPainting();

    //====================================================================================================
    //
    // RedirectStatus()
    //
    // Purpose:
    //      LogonUI uses this method to update about logon status.
    // Parameters:
    //      pszMessage - Logon Status Message
    //      pResponse  - Response to this method. 
    //                   This is of the enum type WTS_LOGON_ERROR_REDIRECTOR_RESPONSE. 
    //                   The valid responses are:
    //                   WTS_LOGON_ERR_INVALID            = 0,
    //                   WTS_LOGON_ERR_NOT_HANDLED        = The call not handled by the redirector and
    //                                                      should be handled normally by LogonUI.
    //                   WTS_LOGON_ERR_HANDLED_SHOW       = The call was handled by the redirector.
    //                                                      LogonUI should paint itself normally.
    //                   WTS_LOGON_ERR_HANDLED_DONT_SHOW  = The call was handled by the redirector 
    //                                                      and should not be passed to the next redirector.
    //                                                      LogonUI will attempt to gather credentials again.
    //                   WTS_LOGON_ERR_HANDLED_DONT_SHOW_START_OVER
    //                                           = The call was handled by the redirector 
    //                                             and should not be passed to the next redirector.
    //                                             LogonUI will NOT attempt to gather credentials again.
    //                                             Valid only when returned from RedirectLogonError.
    //
    // Return values:
    //      S_OK or error code
    //
    //====================================================================================================
    HRESULT
    RedirectStatus(
        [in, string] LPCWSTR pszMessage,
        [out]        WTS_LOGON_ERROR_REDIRECTOR_RESPONSE* pResponse);

    //=============================================================================
    //
    // RedirectMessage()
    //
    // Purpose:
    //      LogonUI uses this method to redirect logon message.
    // Parameters:
    //      pszCaption  - Caption of the message
    //      pszMessage  - Text of the message
    //      uType       - Message Box type (See MessageBox)
    //      pResponse   - Response to this method. 
    //                    Refer to comment for WinStationRedirectLogonStatus.
    //
    // Return values:
    //      S_OK or error code
    //
    //=============================================================================
    HRESULT
    RedirectMessage(
        [in, string] LPCWSTR pszCaption,
        [in, string] LPCWSTR pszMessage,
        [in]         UINT uType,
        [out]        WTS_LOGON_ERROR_REDIRECTOR_RESPONSE* pResponse);

    //=============================================================================
    //
    // RedirectLogonError()
    //
    // Purpose:
    //      LogonUI uses this method to redirect logon error.
    // Parameters:
    //      ntsStatus       - Status of the logon operation (See LsaLogonUser).
    //      ntsSubStatus    - Sub status of the logon operation (See LsaLogonUser).
    //      pszCaption      - Caption of the message
    //      pszMessage      - Text of the message
    //      uType           - Message Box type (See MessageBox)
    //      pResponse       - Response to this method. 
    //                        Refer to comment for WinStationRedirectLogonStatus.
    //
    // Return values:
    //      S_OK or error code
    //
    //=============================================================================
    HRESULT
    RedirectLogonError(
        [in]         LONG ntsStatus,
        [in]         LONG ntsSubstatus,
        [in, string] LPCWSTR pszCaption,
        [in, string] LPCWSTR pszMessage,
        [in]         UINT uType,
        [out]        WTS_LOGON_ERROR_REDIRECTOR_RESPONSE* pResponse);
};