#include "Appevent.ch"
#include "Common.ch"
#include "Xbp.ch"
#include "dll.ch"
#include "wts.ch"
#include "c:\ot4xb\ot4xb.ch"

***************************
CLASS WTSsessionInformation
***************************
PROTECTED:
    VAR _aWTSSessionInformation

EXPORTED
    VAR lLoadClientDirectory
    VAR lLoadWorkingDirectory
    VAR lIsRemoteSession

    INLINE METHOD init
    ******************
       ::lLoadClientDirectory := .F.
       ::lLoadWorkingDirectory:= .F.
    RETURN self

    INLINE METHOD create
    ********************
       ::lIsRemoteSession:= ( GetSystemMetrics( SM_REMOTESESSION ) > 0 )
    RETURN self

    INLINE METHOD destroy
    *********************
       ::_aWTSSessionInformation:= ::lLoadClientDirectory:= ::lLoadWorkingDirectory:= ::lIsRemoteSession:= nil
    RETURN self

    *****************************
    INLINE METHOD loadInformation
    *****************************
       LOCAL aDatos, nDll
       LOCAL pBuffer      := 0
       LOCAL BytesReturned:= 0

       IF ::lIsRemoteSession

          nDll:= DllLoad("WTSAPI32.DLL")

          IF nDll != 0
             ::_aWTSSessionInformation:= Array( WTSClientProtocolType + 1 )

             IF DLLCALL( nDll, DLL_STDCALL, "WTSQuerySessionInformationA", WTS_CURRENT_SERVER_HANDLE, ;
                         WTS_CURRENT_SESSION, WTSSessionId, @pBuffer, @BytesReturned ) = 1

                IF Valtype( ( aDatos:= PeekByte( pBuffer, 0, BytesReturned ) ) ) = 'A' .AND. Len( aDatos ) > 0
                   ::_aWTSSessionInformation[ WTSSessionId + 1 ]:= Ltrim( Str( aDatos[ 1 ] ) )
                ENDIF
                DLLCALL( nDll, DLL_STDCALL, "WTSFreeMemory", pBuffer )
             ENDIF

             IF DLLCALL( nDll, DLL_STDCALL, "WTSQuerySessionInformationA", WTS_CURRENT_SERVER_HANDLE, ;
                         WTS_CURRENT_SESSION, WTSClientAddress, @pbuffer, @BytesReturned ) = 1

                IF Valtype( ( aDatos:= PeekByte( pBuffer, 0, BytesReturned ) ) ) = 'A' .AND. Len( aDatos ) > 10
                   // cAddressFamily:= aDatos[  1 ]
                   ::_aWTSSessionInformation[ WTSClientAddress + 1 ]:= Ltrim( Str( aDatos[  7 ] ) ) + '.' + Ltrim( Str( aDatos[  8 ] ) )+ '.' + ;
                                                                       Ltrim( Str( aDatos[  9 ] ) ) + '.' + Ltrim( Str( aDatos[ 10 ] ) )
                ENDIF
                DLLCALL( nDll, DLL_STDCALL, "WTSFreeMemory", pBuffer )
             ENDIF

             IF ::lLoadClientDirectory .AND. DLLCALL( nDll, DLL_STDCALL, "WTSQuerySessionInformationA", WTS_CURRENT_SERVER_HANDLE, ;
                                                      WTS_CURRENT_SESSION, WTSClientDirectory, @pBuffer, @BytesReturned ) = 1

                ::_aWTSSessionInformation[ WTSClientDirectory + 1 ]:= Space( BytesReturned )
                PeekStr( pBuffer, 0, @::_aWTSSessionInformation[ WTSClientDirectory + 1 ] )
                DLLCALL( nDll, DLL_STDCALL, "WTSFreeMemory", pBuffer )
             ENDIF

             IF ::lLoadWorkingDirectory .AND. DLLCALL( nDll, DLL_STDCALL, "WTSQuerySessionInformationA", WTS_CURRENT_SERVER_HANDLE, ;
                                                       WTS_CURRENT_SESSION, WTSWorkingDirectory, @pBuffer, @BytesReturned ) = 1

                ::_aWTSSessionInformation[ WTSWorkingDirectory + 1 ]:= Space( BytesReturned )
                PeekStr( pBuffer, 0, @::_aWTSSessionInformation[ WTSWorkingDirectory + 1 ] )
                DLLCALL( nDll, DLL_STDCALL, "WTSFreeMemory", pBuffer )
             ENDIF

             DllUnLoad( nDll )
          ENDIF
       ENDIF
    RETURN self

    INLINE METHOD clientAddress
    ***************************
       IF ! ::lIsRemoteSession
          RETURN ''
       ELSEIF ::_aWTSSessionInformation = nil
          ::loadInformation()
       ENDIF
    RETURN ::_aWTSSessionInformation[ WTSClientAddress + 1 ]

    INLINE METHOD sessionId
    ***********************
       IF ! ::lIsRemoteSession
          RETURN 0
       ELSEIF ::_aWTSSessionInformation = nil
          ::loadInformation()
       ENDIF
    RETURN ::_aWTSSessionInformation[ WTSSessionId + 1 ]

    INLINE METHOD clientDirectory
    *****************************
       IF ! ::lIsRemoteSession
          RETURN ''
       ELSEIF ::_aWTSSessionInformation = nil .OR. ! ::lLoadClientDirectory 
          ::lLoadClientDirectory:= .T.
          ::loadInformation()
       ENDIF
    RETURN ::_aWTSSessionInformation[ WTSClientDirectory + 1 ]

    INLINE METHOD currentSize
    *************************
       LOCAL aSize, nDll, aDatos
       LOCAL pBuffer      := 0
       LOCAL BytesReturned:= 0

       IF ::lIsRemoteSession .AND. ( nDll:= DllLoad("WTSAPI32.DLL") ) != 0
          IF DLLCALL( nDll, DLL_STDCALL, "WTSQuerySessionInformationA", WTS_CURRENT_SERVER_HANDLE, ;
                                          WTS_CURRENT_SESSION, WTSClientDisplay, @pBuffer, @BytesReturned ) = 1

             IF Valtype( ( aDatos:= PeekByte( pBuffer, 0, BytesReturned ) ) ) = 'A' .AND. Len( aDatos ) > 0
                aSize:= { Bin2u( Chr( aDatos[ 1 ] ) + Chr( aDatos[ 2 ] ) + Chr( aDatos[ 3 ] ) + Chr( aDatos[ 4 ] ) ), ;
                          Bin2u( Chr( aDatos[ 5 ] ) + Chr( aDatos[ 6 ] ) + Chr( aDatos[ 7 ] ) + Chr( aDatos[ 8 ] ) ) }
             ENDIF
             DLLCALL( nDll, DLL_STDCALL, "WTSFreeMemory", pBuffer )
          ENDIF

          DllUnLoad( nDll )
       ENDIF
    RETURN IIF( aSize = nil, AppDesktop():currentSize(), aSize )
ENDCLASS

STATIC DLLFUNCTION GetSystemMetrics( nIndex ) USING STDCALL FROM USER32.DLL