text: //WinQLDesktop.cpp
  
  // Copyright Querysoft Limited 2013, 2017
  //
  // Permission is hereby granted, free of charge, to any person or organization
  // obtaining a copy of the software and accompanying documentation covered by
  // this license (the "Software") to use, reproduce, display, distribute,
  // execute, and transmit the Software, and to prepare derivative works of the
  // Software, and to permit third-parties to whom the Software is furnished to
  // do so, all subject to the following:
  // 
  // The copyright notices in the Software and this entire statement, including
  // the above license grant, this restriction and the following disclaimer,
  // must be included in all copies of the Software, in whole or in part, and
  // all derivative works of the Software, unless such copies or derivative
  // works are solely in the form of machine-executable object code generated by
  // a source language processor.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  // DEALINGS IN THE SOFTWARE.
  
  #include "WinQL/Application/ErrorSystem/WinQLError.h"
  #include "WinQL/GUI/Desktop.h"
  #include "WinQAPI/User32.h"
  
  //--------------------------------------------------------------------------------
  namespace nsWin32
  {
  	using namespace ::nsWinQAPI;
  
  	__QCMP_DECLARE_PERTHREAD CDesktopHandleMap* p_tDesktopHandleMap = 0;
  
  	__QOR_IMPLEMENT_OCLASS_LUID( CDesktop );
  
  	//--------------------------------------------------------------------------------
  	void CDesktop::Uninit()
  	{
  		_WINQ_FCONTEXT( "CDesktopHelper::Uninit" );
  
  		CDesktopHandleMap* pMap = p_tDesktopHandleMap;
  
  		if( pMap && !( m_Handle.IsNull() ) )
  		{
  			pMap->Remove( m_Handle.Ref() );
  		}
  	}
  
  	//--------------------------------------------------------------------------------
  	void CDesktop::Init()
  	{
  		_WINQ_FCONTEXT( "CDesktop::Init" );
  
  		CDesktopHandleMap* pMap = p_tDesktopHandleMap;
  
  		if( pMap == 0 )
  		{
  			pMap = new CDesktopHandleMap;
  		}
  
  		if( !( m_Handle.IsNull() ) )
  		{
  			pMap->Add( m_Handle.Ref(), this );
  		}
  
  		if( p_tDesktopHandleMap == 0 )
  		{
  			p_tDesktopHandleMap = pMap;
  		}
  	}
  
  	__QCMP_WARNING_PUSH
  	__QCMP_WARNING_DISABLE( __QCMP_WARN_THIS_USED_IN_BASE_INIT_LIST, "Safe usage: stored in member for later use" )
  	
  	//--------------------------------------------------------------------------------
  	CDesktop::CDesktop( CDesktopHandle::refType hDesktop ) : m_User32Library( CUser32::Instance() )
  	,	m_Handle( this, hDesktop->AsHandle().ptr() )
  	{
  		_WINQ_FCONTEXT( "CDesktop::CDesktop" );
  		m_bNeedsClose = false;
  		__QOR_PROTECT
  		{
  			Init();
  		}__QOR_ENDPROTECT		
  	}
  
  	//--------------------------------------------------------------------------------
  	// Gets the desktop attached to the calling thread
  	CDesktop::CDesktop() : m_User32Library( CUser32::Instance() )
  	,	m_Handle( this, 0 )
  	{				
  		_WINQ_FCONTEXT( "CDesktop::CDesktop" );
  		m_bNeedsClose = false;
  		__QOR_PROTECT
  		{
  			m_Handle = m_User32Library.GetThreadDesktop( CKernel32::GetCurrentThreadId() );
  			Init();
  		}__QOR_ENDPROTECT		
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktop::refType CDesktop::ThreadDesktop( void )
  	{
  		_WINQ_SFCONTEXT( "CDesktop::TreadDesktop" );
  		return refType( new CDesktop() );
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktop::CDesktop( const TCHAR* lpszDesktop, unsigned long dwFlags, bool fInherit, unsigned long dwDesiredAccess ) : m_User32Library( CUser32::Instance() )
  	,	m_Handle( this, 0 )
  	{
  		_WINQ_FCONTEXT( "CDesktop::CDesktop" );
  		__QOR_PROTECT
  		{
  			m_Handle = m_User32Library.OpenDesktop( lpszDesktop, dwFlags, fInherit, dwDesiredAccess );
  		}__QOR_ENDPROTECT
  		m_bNeedsClose = true;
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktop::CDesktop( const TCHAR* lpszDesktop, const TCHAR* lpszDevice, nsWin32::LPDEVMODE pDevmode, unsigned long dwFlags, unsigned long dwDesiredAccess, nsWin32::LPSECURITY_ATTRIBUTES lpsa ) : m_User32Library( CUser32::Instance() )
  	,	m_Handle( this, 0 )
  	{
  		_WINQ_FCONTEXT( "CDesktop::CDesktop" );
  		__QOR_PROTECT
  		{
  			m_Handle = m_User32Library.CreateDesktop( lpszDesktop, lpszDevice, reinterpret_cast< ::LPDEVMODE >( pDevmode ), dwFlags, dwDesiredAccess, reinterpret_cast< ::LPSECURITY_ATTRIBUTES >( lpsa ) );
  		}__QOR_ENDPROTECT
  		m_bNeedsClose = true;
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktop::CDesktop( const TCHAR* lpszDesktop, const TCHAR* lpszDevice, nsWin32::LPDEVMODE pDevmode, unsigned long dwFlags, unsigned long dwDesiredAccess, nsWin32::LPSECURITY_ATTRIBUTES lpsa, unsigned long ulHeapSize, void* pvoid ) : m_User32Library( CUser32::Instance() )
  	,	m_Handle( this, 0 )
  	{
  		_WINQ_FCONTEXT( "CDesktop::CDesktop" );
  		__QOR_PROTECT
  		{
  			m_Handle = m_User32Library.CreateDesktopEx( lpszDesktop, lpszDevice, reinterpret_cast< ::LPDEVMODE >( pDevmode ), dwFlags, dwDesiredAccess, reinterpret_cast< ::LPSECURITY_ATTRIBUTES >( lpsa ), ulHeapSize, pvoid );
  		}__QOR_ENDPROTECT
  		m_bNeedsClose = true;
  	}
  
  	__QCMP_WARNING_POP
  
  	//--------------------------------------------------------------------------------
  	CDesktop::refType CDesktop::Open( const TCHAR* szDesktop, unsigned long ulFlags, bool bInherit, unsigned long ulDesiredAccess )
  	{
  		_WINQ_SFCONTEXT( "CDesktop::Open" );
  		return refType( new CDesktop( szDesktop, ulFlags, bInherit, ulDesiredAccess ), true );
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktop::refType CDesktop::CreateEx( const TCHAR* lpszDesktop, const TCHAR* lpszDevice, nsWin32::LPDEVMODE pDevmode, unsigned long dwFlags, unsigned long dwDesiredAccess, nsWin32::LPSECURITY_ATTRIBUTES lpsa, unsigned long ulHeapSize, void* pvoid )
  	{
  		_WINQ_SFCONTEXT( "CDesktop::CreateEx" );
  		return refType( new CDesktop( lpszDesktop, lpszDevice, pDevmode, dwFlags, dwDesiredAccess, lpsa, ulHeapSize, pvoid ), true );
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktop::refType CDesktop::Create( TCHAR* lpszDesktop, const TCHAR* lpszDevice, nsWin32::LPDEVMODE pDevmode, unsigned long dwFlags, unsigned long dwDesiredAccess, nsWin32::LPSECURITY_ATTRIBUTES lpsa )
  	{
  		_WINQ_SFCONTEXT( "CDesktop::Create" );
  		return refType( new CDesktop( lpszDesktop, lpszDevice, pDevmode, dwFlags, dwDesiredAccess, lpsa ), true );
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktop::~CDesktop()
  	{	
  		_WINQ_FCONTEXT( "CDesktop::~CDesktop" );
  		__QOR_PROTECT
  		{
  			Uninit();
  			if( m_bNeedsClose )
  			{
  				m_User32Library.CloseDesktop( reinterpret_cast< ::HDESK >( m_Handle.Use() ) );
  			}
  		}__QOR_ENDPROTECT
  	}
  
  	//--------------------------------------------------------------------------------
  	CTString CDesktop::GetName( void )
  	{					
  		_WINQ_FCONTEXT( "CDesktop::GetName" );
  		__QOR_PROTECT
  		{
  			nsCodeQOR::CTLRef< byte > RefData( 0, true );
  			bool bResult = GetInformation( nsWin32::CUserObject::UOI_Name, RefData );
  			if( bResult )
  			{
  				nsCodeQOR::CTLRef< CTString::char_type > RefString( reinterpret_cast< CTString::char_type* >( RefData.operator byte *() ), false );
  				CTString strName( RefString );
  				return strName;
  			}
  			else
  			{
  				return CTString();
  			}
  		}__QOR_ENDPROTECT
  	}
  
  	//--------------------------------------------------------------------------------
  	bool CDesktop::GetFlags( nsWin32::USEROBJECTFLAGS& Flags )
  	{
  		_WINQ_FCONTEXT( "CDesktop::GetFlags" );
  		bool bResult = false;
  		__QOR_PROTECT
  		{
  			nsCodeQOR::CTLRef< byte > RefData( 0, true );
  			bResult = GetInformation( nsWin32::CUserObject::UOI_Flags, RefData );
  			if( bResult )
  			{
  				Flags = *( reinterpret_cast< nsWin32::USEROBJECTFLAGS* >( RefData.operator byte *() ) );
  			}
  		}__QOR_ENDPROTECT
  		return bResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	bool CDesktop::SetFlags( nsWin32::USEROBJECTFLAGS& Flags )
  	{
  		_WINQ_FCONTEXT( "CDesktop::SetFlags" );
  		bool bResult = false;
  		__QOR_PROTECT
  		{
  			nsCodeQOR::CTLRef< byte > RefData( reinterpret_cast< byte* >( &Flags ), false );
  			bResult = SetInformation( nsWin32::CUserObject::UOI_Flags, RefData, sizeof( nsWin32::USEROBJECTFLAGS ) );
  		}__QOR_ENDPROTECT
  		return bResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	CTString CDesktop::GetType()
  	{
  		_WINQ_FCONTEXT( "CDesktop::GetType" );
  		__QOR_PROTECT
  		{
  			nsCodeQOR::CTLRef< byte > RefData( 0, true );
  			bool bResult = GetInformation( nsWin32::CUserObject::UOI_Type, RefData );
  			if( bResult )
  			{
  				nsCodeQOR::CTLRef< CTString::char_type > RefString( reinterpret_cast< CTString::char_type* >( RefData.operator byte *() ), false );
  				CTString strType( RefString );
  				return strType;
  			}
  			else
  			{
  				return CTString();
  			}
  		}__QOR_ENDPROTECT
  	}
  	//--------------------------------------------------------------------------------
  	CSID CDesktop::GetSID()
  	{
  		_WINQ_FCONTEXT( "CDesktop::GetSID" );
  		void* pResult = 0;
  		__QOR_PROTECT
  		{
  			nsCodeQOR::CTLRef< byte > RefData( 0, true );
  			bool bResult = GetInformation( nsWin32::CUserObject::UOI_User_SID, RefData );
  			if( bResult )
  			{
  				pResult = reinterpret_cast< void* >( RefData.operator byte *() );
  			}
  		}__QOR_ENDPROTECT
  		CSID Sid( pResult );
  		return Sid;
  	}
  
  	//--------------------------------------------------------------------------------
  	bool CDesktop::SwitchTo()
  	{
  		_WINQ_FCONTEXT( "CDesktop::SwitchTo" );
  		bool bResult = false;
  		__QOR_PROTECT
  		{
  			bResult = m_User32Library.SwitchDesktop( reinterpret_cast< ::HDESK >( m_Handle.Use() ) ) ? true : false;
  		}__QOR_ENDPROTECT
  		return bResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	bool CDesktop::AttachToCurrentThread()
  	{
  		_WINQ_FCONTEXT( "CDesktop::AttachToCurrentThread" );
  		bool bResult = false;
  		__QOR_PROTECT
  		{
  			bResult = m_User32Library.SetThreadDesktop( reinterpret_cast< ::HDESK >( m_Handle.Use() ) ) ? true : false;
  		}__QOR_ENDPROTECT
  		return bResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	int CDesktop::InstanceEnumWindowProc( void* hWindow )
  	{
  		_WINQ_FCONTEXT( "CDesktop::InstanceEnumWindowProc" );
  
  		COSWindow::refType refWindow( COSWindow::FromHandle( hWindow ) );
  		return (*mfpWindowEnumProc)( refWindow, m_EnumCookie ) ? 1 : 0;
  	}
  
  	//--------------------------------------------------------------------------------
  	int CDesktop::EnumWindowProc( void* Handle, Cmp_long_ptr lParam )
  	{
  		_WINQ_SFCONTEXT( "CDesktop::EnumWindows" );
  		int iResult = 0;
  		CDesktop* pDesktop = reinterpret_cast< CDesktop* >( lParam );
  		if( pDesktop != 0 )
  		{
  			iResult = pDesktop->InstanceEnumWindowProc( Handle );
  		}
  		return iResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	bool CDesktop::EnumWindows( OSWindowEnumProc fpWindowEnumProc, Cmp_long_ptr cookie )
  	{
  		_WINQ_FCONTEXT( "CDesktop::EnumWindows" );
  		bool bResult = false;
  		__QOR_PROTECT
  		{
  			CTObjectLock< CDesktop > Lock( this );
  			m_EnumCookie = cookie;
  			mfpWindowEnumProc = fpWindowEnumProc;
  			bResult = m_User32Library.EnumDesktopWindows( reinterpret_cast< ::HDESK >( m_Handle.Use() ), reinterpret_cast< ::WNDENUMPROC >( &CDesktop::EnumWindowProc ), reinterpret_cast< Cmp_long_ptr >( this ) ) ? true : false;
  		}__QOR_ENDPROTECT
  		return bResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	bool CDesktop::EnumWindows( nsWin32::WindowEnumProc lpfn, Cmp_long_ptr lParam )
  	{
  		_WINQ_FCONTEXT( "CDesktop::	" );
  		bool bResult = false;
  		__QOR_PROTECT
  		{
  			CTObjectLock< CDesktop > Lock( this );
  			bResult = m_User32Library.EnumDesktopWindows( reinterpret_cast< ::HDESK >( m_Handle.Use() ), reinterpret_cast< ::WNDENUMPROC >( lpfn ), lParam ) ? true : false;
  		}__QOR_ENDPROTECT
  		return bResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	bool CDesktop::GetInformation( int nIndex, nsCodeQOR::CTLRef< byte >& RefData )
  	{
  		_WINQ_FCONTEXT( "CDesktop::GetInformation" );
  		bool bResult = false;
  		byte* pvInfo;
  		__QOR_PROTECT
  		{
  			unsigned long ulLen = 0;
  			bResult = m_User32Library.GetUserObjectInformation( m_Handle.Use(), nIndex, 0, 0, &ulLen ) ? true : false;
  
  			if( bResult == false )
  			{
  				pvInfo = new byte[ ulLen ];
  				bResult = m_User32Library.GetUserObjectInformation( m_Handle.Use(), nIndex, pvInfo, ulLen, 0) ? true : false;
  				nsCodeQOR::CTLRef< byte > tmpRef( pvInfo, true );
  				RefData = tmpRef;
  			}
  		}__QOR_ENDPROTECT
  		return bResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	bool CDesktop::SetInformation( int nIndex, const void* pvInfo, unsigned long nLength )
  	{
  		_WINQ_FCONTEXT( "CDesktop::SetInformation" );
  		bool bResult = false;
  		__QOR_PROTECT
  		{
  			bResult = m_User32Library.SetUserObjectInformation( m_Handle.Use(), nIndex, const_cast< ::PVOID >( pvInfo ), nLength ) ? true : false;
  		}__QOR_ENDPROTECT
  		return bResult;
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktopHandle::refType CDesktop::Handle()
  	{
  		_WINQ_FCONTEXT( "CDesktop::Handle" );
  		return m_Handle.Ref();
  	}
  
  	//--------------------------------------------------------------------------------
  	CDesktop::refType CDesktop::FromHandle( CDesktopHandle::refType hDesktop )
  	{
  		_WINQ_SFCONTEXT( "CDesktop::FromHandle" );
  		CDesktop* pDesktop = 0;
  		bool bOwningRef = false;
  		__QOR_PROTECT
  		{
  			pDesktop = hDesktop->Object< CDesktop >();
  			
  			if( pDesktop == 0 && p_tDesktopHandleMap != 0 )
  			{
  				pDesktop = p_tDesktopHandleMap->FindHandle( hDesktop );
  			}
  
  			if( pDesktop == 0 )
  			{
  				pDesktop = new CDesktop( hDesktop );
  				bOwningRef = true;
  			}
  
  		}__QOR_ENDPROTECT
  
  		return refType( pDesktop, bOwningRef );
  	}
  
  
  }//nsWin32
  
  