Click here to Skip to main content
15,895,746 members
Articles / Programming Languages / C++

Virtual Desktop: A Simple Desktop Management Tool

Rate me:
Please Sign up or sign in to vote.
4.83/5 (46 votes)
25 Jul 2008CPOL5 min read 231.4K   11.9K   143  
This article gives you an overview of Windows Station, Windows Desktop and how to work with them. It also has a sample application (Virtual Desktop) demonstrating multiple desktop management.
#include "StdAfx.h"
#include "DesktopManager.h"
#include "SHLWAPI.h"

int CDesktopManager::m_iDesktopCount = 0;
TCHAR *CDesktopManager::m_szDesktopNames[ARRAY_SIZE] = {0};

//Function enumerates all the desktops of the windows station.
BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktopName,LPARAM lParam)
{
	try
	{
		//Adding Desktop Name To DesktopName List.
		CDesktopManager::AddDesktop(lpszDesktopName);
	}
	catch(...)
	{
		OutputDebugString(_T("\n\nException caught in EnumDesktopsProc."));
	}

	return TRUE;
}

CDesktopManager::CDesktopManager(void)
//: m_iDesktopCount(0)
{
	for(int iCount =0;iCount < ARRAY_SIZE;iCount ++)
		m_szDesktopNames[iCount] = NULL;

	//Populates all the desktop names.
	PopulateDesktopList();
}

CDesktopManager::~CDesktopManager(void)
{
	ReleaseMemory();
}

bool CDesktopManager::PopulateDesktopList(void)
{
	bool bReturn = false;
	try
	{
		HWINSTA hWindowsStation = GetProcessWindowStation();
		if(NULL == hWindowsStation)
			throw false;

		if(0 < m_iDesktopCount)
			ReleaseMemory();

		m_iDesktopCount = 0;
		bReturn = (FALSE != EnumDesktops(hWindowsStation,&EnumDesktopProc,NULL)); //m_szDesktopNames));
		//for(int i = 0;i< GetDesktopCount(); i++)
		//	OutputDebugString(m_szDesktopNames[i]);
	}
	catch(bool bThrowVal)
	{
		bReturn = bThrowVal;
	}
	catch(...)
	{
		OutputDebugString(_T("\n\nException caught in CDesktopManager::PopulateDesktopList"));
	}

	return bReturn;
}

//Returns the number of desktops in the window station.
int CDesktopManager::GetDesktopCount(void)
{
	//Refresh the list.
	PopulateDesktopList();
	return m_iDesktopCount;
}

//Release the memory to avoid memory leak.
void CDesktopManager::ReleaseMemory(void)
{
	for(int iCount =0;iCount < ARRAY_SIZE;iCount ++)
	{
		if(m_szDesktopNames[iCount] != NULL)
		{
			delete m_szDesktopNames[iCount];
			m_szDesktopNames[iCount] = NULL;
		}
	}
	m_iDesktopCount = 0;
}

//Switch between desktops.
bool CDesktopManager::SwitchDesktop(TCHAR * szDesktopName)
{
	bool bReturn = false;
	try
	{
		if (NULL == szDesktopName)
		{
			OutputDebugString(_T("\nNULL DesktopName in CDesktopManager::SwitchToDesktop"));
			throw false;
		}

		/*if( !_tcsicmp(_T("Winlogon"),szDesktopName) || !_tcsicmp(_T("Disconnect"),szDesktopName))
		{
			TCHAR szErrorMsg[ARRAY_SIZE] = {_T("You can not switch to ")};
			_tcscat_s(szErrorMsg,ARRAY_SIZE -1,szDesktopName);
			_tcscat_s(szErrorMsg,ARRAY_SIZE -1,_T(" Desktop."));
			MessageBox(NULL,szErrorMsg,_T("Virtual Desktop"),MB_ICONINFORMATION);
			throw false;
		}*/

		//Open desktop handle to switch to.
		HDESK hDesktopToSwitch = OpenDesktop(szDesktopName,DF_ALLOWOTHERACCOUNTHOOK,TRUE,GENERIC_ALL);
		if(NULL == hDesktopToSwitch)
		{
			TCHAR *pszError = NULL;
			TCHAR szErrorMsg[ARRAY_SIZE] = {0};
			int iErrorCode = GetLastError();
			if(5 == iErrorCode)
			{
				
				FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
								NULL,iErrorCode,0,(LPWSTR) &pszError,0,NULL);
				wsprintf(szErrorMsg,_T("Failed to switch to %s desktop.\n\t %s"),szDesktopName,pszError);
				MessageBox(NULL,szErrorMsg,_T("Virtual Desktop"),MB_ICONINFORMATION | MB_TOPMOST | MB_TASKMODAL);
				OutputDebugString(pszError);
			}

			wsprintf(szErrorMsg,_T("\nOpenDesktop Failed in CDesktopManager::SwitchToDesktop. Last Error : %s"),pszError);
			OutputDebugString(szErrorMsg);

			throw false;
		}

		//Switch the desktop.
		if(FALSE == ::SwitchDesktop(hDesktopToSwitch))
		{
			OutputDebugString(_T("\nSwitchDesktop Failed in CDesktopManager::SwitchToDesktop"));
			throw false;
		}
 
		//Close the desktop handle.
		CloseDesktop(hDesktopToSwitch);
		bReturn = true;
	}
	catch(bool bThrownVal)
	{
		bReturn = bThrownVal;
	}
	catch(...)
	{
		bReturn = false;
		OutputDebugString(_T("\nException caught in CDesktopManager::SwitchToDesktop"));
	}
	return bReturn;
}


//Creats new desktop.
bool CDesktopManager::CreateDesktop(TCHAR * szDesktopName)
{
	bool bReturn = false;
	try
	{
		if(NULL == szDesktopName)
		{
			OutputDebugString(_T("\nNULL DesktopName in CDesktopManager::CreateDesktop"));
			throw false;
		}

		//Setting the desktop security attributes.
		SECURITY_ATTRIBUTES sAttribute = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};
		HDESK hNewDesktop = NULL;

		//Creating a new desktop with all access.
		hNewDesktop = ::CreateDesktop(szDesktopName,NULL,NULL,DF_ALLOWOTHERACCOUNTHOOK,GENERIC_ALL,&sAttribute);

		TCHAR *pszError = NULL;
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
						NULL,GetLastError(),0,(LPWSTR) &pszError,0,NULL);
		OutputDebugString(_T("\n\t\t"));
		OutputDebugString(pszError);

		int iCount = 0;
		//Checking whether desktop name already exists.
		for(iCount = 0;iCount < m_iDesktopCount;iCount++)
			if(_tcsicmp(szDesktopName,m_szDesktopNames[iCount]) == 0)
				break;

		if(iCount >= m_iDesktopCount)
		{
			OutputDebugString(_T("\nCreating New Desktop"));

			TCHAR szExplorerFile[ARRAY_SIZE]= {0};

			GetWindowsDirectory(szExplorerFile,ARRAY_SIZE -1);
			_tcscat_s(szExplorerFile,ARRAY_SIZE -1, _T("\\Explorer.Exe"));

			LaunchApplication(szExplorerFile,szDesktopName);
		}

		//Closing the desktop handle.
		if(NULL != hNewDesktop)
			CloseDesktop(hNewDesktop);

		bReturn = PopulateDesktopList();
	}
	catch(...)
	{
		OutputDebugString(_T("Exception Caught In CDesktopManager::CreateDesktop."));
	}
	return bReturn;
}

//Returns the desktop name at specified index.
void CDesktopManager::GetDesktopName(int iIndex, TCHAR * szDesktopName)
{
	try
	{
		if (iIndex < m_iDesktopCount)
			_tcscpy_s(szDesktopName,_tcslen(m_szDesktopNames[iIndex]) + 1, m_szDesktopNames[iIndex]);
	}
	catch(...)
	{
		OutputDebugString(_T("\n\nException caught in CDesktopManager::GetDesktopName."));
	}
}

//Adds the specified desktop name into the list.
void CDesktopManager::AddDesktop(TCHAR * lpszDesktopName)
{
	try
	{
		m_szDesktopNames[m_iDesktopCount] = new TCHAR[_tcslen(lpszDesktopName) + 1];
		ZeroMemory(m_szDesktopNames[m_iDesktopCount],_tcslen(lpszDesktopName) + 1);
		_tcscpy_s(m_szDesktopNames[m_iDesktopCount],_tcslen(lpszDesktopName) + 1,lpszDesktopName);
		m_iDesktopCount++;
	}
	catch(...)
	{
		OutputDebugString(_T("\n\nException caught in CDesktopManager::AddDesktop."));
	}
}

//Checks whether the specified desktop is current active desktop(deskop of the current thread).
bool CDesktopManager::IsCurrentDesktop(TCHAR * szDesktopName)
{
	bool bReturn = false;

	try
	{
		TCHAR szCurrentDesktopName[ARRAY_SIZE] = {0};
		DWORD iOutCount = 0;
		HDESK hCurrentDesktop = GetThreadDesktop(GetCurrentThreadId());
		GetUserObjectInformation(hCurrentDesktop,UOI_NAME,szCurrentDesktopName,ARRAY_SIZE - 1,&iOutCount);

		bReturn = (_tcsicmp(szDesktopName,szCurrentDesktopName) == 0);
	}
	catch(...)
	{
		OutputDebugString(_T("\n\nException caught in CDesktopManager::IsCurrentDesktop."));
		bReturn = false;
	}

	return bReturn;
}

bool CDesktopManager::LaunchApplication(TCHAR * szApplicationFilePath, TCHAR * szDesktopName)
{
	bool bReturn = false;

	try
	{
		if(!szApplicationFilePath || !szDesktopName || !_tcslen(szApplicationFilePath) || !_tcslen(szDesktopName))
			throw _T("Invalid Argument.");

		TCHAR szDirectoryName[ARRAY_SIZE] = {0};
		TCHAR szExplorerFile[ARRAY_SIZE]= {0};

		_tcscpy_s(szDirectoryName,_tcslen(szApplicationFilePath) + 1, szApplicationFilePath);
		
		if(!PathIsExe(szApplicationFilePath))
			throw _T("Invalid File Extension");

		PathRemoveFileSpec(szDirectoryName);

		STARTUPINFO sInfo = {0};
		PROCESS_INFORMATION pInfo = {0};

		sInfo.cb = sizeof(sInfo);
		sInfo.lpDesktop = szDesktopName;

		//Lanuching a application into dekstop
		BOOL bCreateProcessReturn = CreateProcess(szApplicationFilePath,
			NULL,
			NULL,
			NULL,
			TRUE,
			NORMAL_PRIORITY_CLASS,
			NULL,
			szDirectoryName,
			&sInfo,
			&pInfo);

		TCHAR *pszError = NULL;
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,GetLastError(),0,(LPWSTR) &pszError,0,NULL);
		OutputDebugString(_T("\n\t\t"));
		OutputDebugString(pszError);

		if(bCreateProcessReturn)
			bReturn = true;
	}
	catch(TCHAR *pszError)
	{
		OutputDebugString(_T("\n\nCustom Exception caught in CDesktopManager::IsCurrentDesktop."));
		OutputDebugString(pszError);
		bReturn = false;
	}
	catch(bool)
	{
		OutputDebugString(_T("\n\nCustom Exception caught in CDesktopManager::IsCurrentDesktop."));
		bReturn = false;
	}
	catch(...)
	{
		OutputDebugString(_T("\n\nException caught in CDesktopManager::IsCurrentDesktop."));
		bReturn = false;
	}

	return bReturn;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
Hello All !
This is Mallinath S. Karkanti, from India. I'm working as a Software Developer in one of the Middle Scale Company... !

Comments and Discussions