Click here to Skip to main content
12,690,575 members (32,883 online)
Click here to Skip to main content

Stats

153.4K views
9.1K downloads
138 bookmarked
Posted

Virtual Desktop: A Simple Desktop Management Tool

, 25 Jul 2008 CPOL
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)

Share

About the Author

Malli_S
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... !

You may also be interested in...

Pro
Pro
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170117.1 | Last Updated 25 Jul 2008
Article Copyright 2007 by Malli_S
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid