|
|
////////////////////////////////////////////////////////////////////////////////
//
// File: Desktop.cpp
// Created: Jan 1996
// By: Ryan Marshall (a-ryanm) and Martin Holladay (a-martih)
//
// Project: Resource Kit Desktop Switcher (MultiDesk)
//
//
// Revision History:
//
// March 1997 - Add external icon capability
//
////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <shellapi.h>
#include <lmaccess.h>
#include <lmapibuf.h>
#include <stdlib.h>
#include <sddl.h>
#include "Deskspc.h"
#include "Desktop.h"
#include "Registry.h"
#include "resource.h"
#include <saifer.h>
extern APPVARS AppMember;
BOOL __SetDesktopScheme(PDESKTOP_SCHEME pDS); BOOL __GetDesktopScheme(PDESKTOP_SCHEME pDS); BOOL __UpdateDesktopRegistry(PDESKTOP_SCHEME pDS); BOOL __CopyDesktopScheme(PDESKTOP_SCHEME pDS1, PDESKTOP_SCHEME pDS2); HICON __LoadBuiltinIcon(UINT nIconNumber, HINSTANCE hDeskInstance); BOOL __CreateDefaultName(UINT DeskNum, LPTSTR DesktopName);
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Constructor for CDestop class. */ /* */ /*------------------------------------------------------------------------------*/
CDesktop::CDesktop() { BeginRundown = FALSE;
//
// Set the default desktop
//
DefaultDesktop = GetThreadDesktop(GetCurrentThreadId());
//
// Intialize our default icons
//
ZeroMemory((PVOID) DefaultIconArray, (sizeof(HICON) * NUM_BUILTIN_ICONS)); }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Destructor for CDestop class. */ /* */ /*------------------------------------------------------------------------------*/
CDesktop::~CDesktop() { UINT i;
// Need to cleanup DesktopList; closing the hDesktop in each node
// and then delete node memory using GlobalFree(). In addition deletion
// must start at the end of the list sawing off last node one at a time.
//
GlobalFree(m_DesktopList);
//
// Close up our default icons
//
for (i = 0; i < NUM_BUILTIN_ICONS; i++) { if (DefaultIconArray[i]) DestroyIcon(DefaultIconArray[i]); } }
/*------------------------------------------------------------------------------*/ /*------------------------------- PUBLIC FUNCTIONS -----------------------------*/ /*------------------------------------------------------------------------------*/
UINT CDesktop::InitializeDesktops ( DispatchFnType CreateDisplayFn, HINSTANCE hInstance ) { UINT ii; UINT RegNumOfDesktops; BOOL m_bFirstTime = TRUE;
//
// Set the hInstance and get the default icons
//
hDeskInstance = hInstance;
for (ii = 0; ii < NUM_BUILTIN_ICONS; ii++) DefaultIconArray[ii] = __LoadBuiltinIcon(ii+1, hDeskInstance);
//
// Get Information from the registry.
//
if (Profile_GetNewContext(&RegNumOfDesktops)) { m_bFirstTime = FALSE; }
if ((RegNumOfDesktops > 32) || (RegNumOfDesktops < 1)) { m_bFirstTime = TRUE; }
//// Allocate the first node ////
m_DesktopList = (PDESKTOP_NODE) GlobalAlloc(GMEM_FIXED, sizeof(DESKTOP_NODE)); assert(m_DesktopList != NULL);
//// Fill in default values for first node ////
m_DesktopList->nextDN = NULL; m_DesktopList->DS.Initialized = FALSE; m_DesktopList->ThreadId = GetCurrentThreadId(); m_DesktopList->bThread = TRUE; m_DesktopList->hWnd = NULL; m_DesktopList->hDesktop = GetThreadDesktop(GetCurrentThreadId()); m_DesktopList->nIconID = 0; m_DesktopList->RealDesktopName[0] = TEXT('\0'); __GetDesktopScheme(&(m_DesktopList->DS));
//
// Set some environ vars to init states
//
NumOfDesktops = 1; CurrentDesktop = 0;
if (m_bFirstTime) { // No old registry info, create default desktops
//
// Set desktop 0's name
//
__CreateDefaultName(1, m_DesktopList->DesktopName);
if (DEFAULT_NUM_DESKTOPS > 1) { for (ii = 1; ii < DEFAULT_NUM_DESKTOPS; ii++) { AddDesktop(CreateDisplayFn, NULL); } } } else { // Registry info present
//
// Set desktop 0's name
//
if ( !Profile_LoadDesktopContext(0, m_DesktopList->DesktopName, m_DesktopList->SaiferName, &m_DesktopList->nIconID) ) { __CreateDefaultName(1, m_DesktopList->DesktopName); m_DesktopList->nIconID = 0; }
for (ii = 1; ii < RegNumOfDesktops; ii++) { TCHAR DesktopName[MAX_NAME_LENGTH]; TCHAR SaiferName[MAX_NAME_LENGTH]; UINT nIconID;
AddDesktop(CreateDisplayFn, NULL);
//// Place registry info into the node for this desktop ////
if (Profile_LoadDesktopContext(ii, DesktopName, SaiferName, &nIconID) ) { // Successfully got all info from registry
SetDesktopName(ii, DesktopName); SetDesktopIconID(ii, nIconID); SetSaiferName(ii, SaiferName); } else { // Could not get all info from registry
__CreateDefaultName(ii+1, DesktopName); SetDesktopName(ii, DesktopName); SetDesktopIconID(ii, ii); SetSaiferName(ii, TEXT("")); } if (!GetRegColorStruct(ii)) DuplicateDefaultScheme(ii); } // End for loop
} return NumOfDesktops; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Access the default desktop handle. */ /* */ /* Returns: The default desktop handle. */ /* */ /*------------------------------------------------------------------------------*/
HDESK CDesktop::GetDefaultDesktop(VOID) const { return DefaultDesktop; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Access the number of desktops. */ /* */ /* Returns: The number of desktops. */ /* */ /*------------------------------------------------------------------------------*/
UINT CDesktop::GetNumDesktops(VOID) const { return NumOfDesktops; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Determine the currently active desktop. */ /* */ /* Returns: The active desktop. */ /* */ /*------------------------------------------------------------------------------*/
UINT CDesktop::GetActiveDesktop(VOID) const { return CurrentDesktop; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Creates a new desktop. */ /* */ /* Returns: The index number of the newly created desktop. Zero if error. */ /* */ /*------------------------------------------------------------------------------*/
UINT CDesktop::AddDesktop ( DispatchFnType CreateDisplayFn, LPSECURITY_ATTRIBUTES lpSA, UINT uTemplate ) { PDESKTOP_NODE pCurrentNode; TCHAR szMessage[MAX_PATH]; PTHREAD_DATA pData; HDESK hDesktop; LUID UniqueId; UINT i; TCHAR UniqueDesktopName[MAX_NAME_LENGTH];
//// Create Desktop ////
if (AllocateLocallyUniqueId(&UniqueId)) { wsprintf(UniqueDesktopName, TEXT("%d"), UniqueId.LowPart); hDesktop = CreateDesktop( UniqueDesktopName, NULL, NULL, 0, MAXIMUM_ALLOWED, lpSA);
if (hDesktop == NULL) { if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) { wsprintf(szMessage, TEXT("Not enough memory to create destkop.\n\nError: %d\n"), GetLastError()); MessageBox(NULL, szMessage, TEXT("MultiDesk Desktop Not Created"), MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OK); } return 0; } } else { return 0; }
//// Walk the desktop node list to find end
//// Then add new node to end of list
i = 1; pCurrentNode = m_DesktopList;
while (pCurrentNode) { if ( !pCurrentNode->nextDN ) // Found end of list; let's add new node
{ NumOfDesktops++; pCurrentNode->nextDN = (PDESKTOP_NODE) GlobalAlloc(GMEM_FIXED, sizeof(DESKTOP_NODE)); pCurrentNode = pCurrentNode->nextDN; pCurrentNode->hDesktop = hDesktop; pCurrentNode->hWnd = NULL; pCurrentNode->nextDN = NULL; pCurrentNode->ThreadId = 0; pCurrentNode->DS.Initialized = FALSE;
if ( 0 == uTemplate ) { __CopyDesktopScheme(&(m_DesktopList->DS), &(pCurrentNode->DS)); } else { DESKTOP_NODE * pNode; pNode = GetDesktopNode(uTemplate); if ( pNode->DS.Initialized ) { __CopyDesktopScheme(&(pNode->DS), &(pCurrentNode->DS)); } else { __CopyDesktopScheme(&(m_DesktopList->DS), &(pCurrentNode->DS)); } }
lstrcpy(pCurrentNode->RealDesktopName, UniqueDesktopName); __CreateDefaultName(NumOfDesktops, pCurrentNode->DesktopName); pCurrentNode->SaiferName[0] = TEXT('\0'); pCurrentNode->lpSA = lpSA; pCurrentNode->nIconID = i; pCurrentNode->bThread = TRUE; pCurrentNode->bShellStarted = FALSE;
//// Alllocate THREAD_DATA struct and fill in.
pData = (PTHREAD_DATA)GlobalAlloc(GMEM_FIXED, sizeof(THREAD_DATA)); pData->hDesktop = hDesktop; pData->hDefaultDesktop = DefaultDesktop; pData->CreateDisplayFn = CreateDisplayFn; lstrcpy(pData->RealDesktopName, UniqueDesktopName);
//// Start the thread to run this desktop ////
HANDLE hThread;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadInit, (LPVOID)pData, 0, &(pCurrentNode->ThreadId)); CloseHandle(hThread); }
i++; pCurrentNode = pCurrentNode->nextDN; }
return NumOfDesktops; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Returns pointer to desktop node given number of desktop. */ /* */ /*------------------------------------------------------------------------------*/
DESKTOP_NODE *CDesktop::GetDesktopNode( UINT uNode ) { DESKTOP_NODE * pNode = NULL; DESKTOP_NODE * pWalker = m_DesktopList; UINT uNumDesktops = GetNumDesktops(); UINT ii;
if ( uNode < uNumDesktops ) { for ( ii = 0; ii < uNode; ii++ ) { pWalker = pWalker->nextDN; } pNode = pWalker; }
return pNode; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Save scheme settings of current desktop to desktop node */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::SaveCurrentDesktopScheme() { DESKTOP_NODE * pNodeWalker; UINT ii; BOOL rVal = FALSE;
ii = 0; pNodeWalker = m_DesktopList;
while (pNodeWalker) { if (ii == CurrentDesktop) { __GetDesktopScheme(&(pNodeWalker->DS)); rVal = TRUE; } ii++; pNodeWalker = pNodeWalker->nextDN; }
return rVal; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Removes an old desktop. */ /* */ /* Returns: The number of remaining desktops. Zero if error. */ /* User GetLastError() to retrieve error information. */ /* */ /*------------------------------------------------------------------------------*/
UINT CDesktop::RemoveDesktop(UINT DesktopNumber) { PDESKTOP_NODE pCurrentNode; PDESKTOP_NODE pPreviousNode; BOOL Found; UINT ii; UINT rValue = 0;
//
// Return an error if trying to delete desktop zero.
//
if ((DesktopNumber == 0) || (NumOfDesktops == 1)) { SetLastError(ERROR_CANNOT_DELETE_DESKTOP_ZERO); return 0; }
//
// Return an error if an invalid desktop number
//
if (DesktopNumber > (NumOfDesktops - 1)) { SetLastError(ERROR_INVALID_DESKTOP_NUMBER); return 0; }
//
// If we are deleting the active desktop. Switch to desktop zero.
//
if (DesktopNumber == CurrentDesktop) { if (!ActivateDesktop(0)) { SetLastError(ERROR_CANNOT_DELETE_ACTIVE_DESKTOP); return FALSE; } }
//
// Find the data structure; walk the linked list of desktops
//
Found = FALSE; ii = 1; pPreviousNode = m_DesktopList; pCurrentNode = m_DesktopList->nextDN;
while (pCurrentNode && (!Found)) { if (DesktopNumber == ii) { //
// Full Context desktop
//
if (pCurrentNode->bThread) { PostThreadMessage(pCurrentNode->ThreadId, WM_KILL_APPS, (WPARAM) pCurrentNode->hDesktop, (LPARAM) pCurrentNode->hWnd); Sleep(100); rValue = SUCCESS_THREAD_TERMINATION; } else { //
// BUGBUG: Kill all virtual apps
//
rValue = SUCCESS_VIRTUAL_MOVE; }
NumOfDesktops--; pPreviousNode->nextDN = pCurrentNode->nextDN;
GlobalFree(pCurrentNode); // Destroy Node of removed desktop!!!
Found = TRUE; } else { // Advance along list of nodes
ii++; pPreviousNode = pCurrentNode; pCurrentNode = pCurrentNode->nextDN; } } // End while LOOP
return rValue; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Kill all programs on a desktop. */ /* */ /*------------------------------------------------------------------------------*/
static BOOL CALLBACK __EnumWindowsForClose(HWND hWnd, LPARAM lParam) { TCHAR szClass[MAX_NAME_LENGTH]; HWND hDesktopWnd;
//
// Make sure that it isn't the desktop window
//
hDesktopWnd = (HWND) lParam; if (hDesktopWnd == hWnd) { return TRUE; } GetClassName(hWnd, szClass, MAX_NAME_LENGTH); if (szClass[0] == TEXT('#')) { return TRUE; }
//
// Send a close message to the app
//
PostMessage(hWnd, WM_CLOSE, (WPARAM) WM_NO_CLOSE, 0);
return TRUE; }
static BOOL CALLBACK __EnumWindowsForQuit(HWND hWnd, LPARAM lParam) { TCHAR szClass[MAX_NAME_LENGTH]; HWND hDesktopWnd;
//
// Make sure that it isn't the desktop window
//
hDesktopWnd = (HWND) lParam; if (hDesktopWnd == hWnd) return TRUE;
//
// Extract the Class Name
//
GetClassName(hWnd, szClass, MAX_NAME_LENGTH); if (szClass[0] == TEXT('#')) return TRUE;
//
// Send a quit message to the app
//
PostMessage(hWnd, WM_QUIT, (WPARAM) WM_NO_CLOSE, 0);
return TRUE; }
BOOL CDesktop::KillAppsOnDesktop(HDESK hDesk, HWND hWnd) { HWND hDesktopWnd;
hDesktopWnd = GetDesktopWindow();
EnumDesktopWindows(hDesk, (WNDENUMPROC) __EnumWindowsForClose, (LPARAM) hDesktopWnd); Sleep(0); EnumDesktopWindows(hDesk, (WNDENUMPROC) __EnumWindowsForQuit, (LPARAM) hDesktopWnd);
return TRUE; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Switches to an existing desktop. */ /* */ /* Returns: The index number of the newly created desktop. Zero if error. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::ActivateDesktop(UINT DesktopNumber) { PDESKTOP_NODE pCurrentNode; BOOL Success; UINT i; PROCESS_INFORMATION pi; STARTUPINFO sui; TCHAR szShellPath[MAX_PATH + 1];
//
// Return immediately if trying to switch to ourself.
//
if (CurrentDesktop == DesktopNumber) { return FALSE; }
//// Save desktop scheme for current desktop ////
SaveCurrentDesktopScheme();
//
// Active the new desktop
//
i = 0; pCurrentNode = m_DesktopList; while (pCurrentNode) { if (i == DesktopNumber) { Success = SwitchDesktop(pCurrentNode->hDesktop); if (Success) { CurrentDesktop = i;
// Start Explorer if necessary - skipping 0 == default desktop
if (!pCurrentNode->bShellStarted && CurrentDesktop != 0) { HANDLE hToken = NULL;
lstrcpy(szShellPath, TEXT("EXPLORER.EXE")); ZeroMemory((PVOID)&sui, sizeof(sui));
sui.lpDesktop = pCurrentNode->RealDesktopName; sui.cb = sizeof(sui); sui.lpReserved = NULL; sui.lpTitle = NULL; sui.dwFlags = STARTF_USESHOWWINDOW; sui.wShowWindow = SW_SHOW; sui.cbReserved2 = 0; sui.cbReserved2 = NULL;
#if 1
if (pCurrentNode->SaiferName[0] != TEXT('\0')) { HAUTHZOBJECT hAuthzObj; if (CreateCodeAuthzObject( AUTHZSCOPE_HKCU, pCurrentNode->SaiferName, AUTHZ_OPENEXISTING, &hAuthzObj) || CreateCodeAuthzObject( AUTHZSCOPE_HKLM, pCurrentNode->SaiferName, AUTHZ_OPENEXISTING, &hAuthzObj)) { if (ComputeAccessTokenFromCodeAuthzObject( hAuthzObj, NULL, // source token
&hToken, // target token
0)) // no flags
{ // We successfully got the Restricted Token
// to use, so it had better be non-null.
assert(hToken != NULL); } CloseCodeAuthzObject(hAuthzObj); } if (hToken == NULL) { CurrentDesktop = 0; SwitchDesktop(m_DesktopList->hDesktop); PostThreadMessage(m_DesktopList->ThreadId, WM_THREAD_SCHEME_UPDATE, 0, 0); Message(TEXT("The SAIFER Object Name specified for this " "desktop could not be successfully found or instantianted.")); return FALSE; } }
if (hToken != NULL) { Success = CreateProcessAsUser( hToken, NULL, szShellPath, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_SEPARATE_WOW_VDM, NULL, NULL, &sui, &pi); CloseHandle(hToken); } else #endif
Success = CreateProcess( NULL, szShellPath, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_SEPARATE_WOW_VDM, NULL, NULL, &sui, &pi);
pCurrentNode->bShellStarted = Success;
if (Success) { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } else { CurrentDesktop = 0; SwitchDesktop(m_DesktopList->hDesktop); PostThreadMessage(m_DesktopList->ThreadId, WM_THREAD_SCHEME_UPDATE, 0, 0); Message(TEXT("The Windows shell could not be successfully launched.")); return FALSE; }
}
PostThreadMessage(pCurrentNode->ThreadId, WM_THREAD_SCHEME_UPDATE, 0, 0); }
return Success; }
i++; pCurrentNode = pCurrentNode->nextDN; } // End while LOOP
return FALSE; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Sets a desktop name. (Rename) */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::SetDesktopName(UINT DesktopNumber, LPCTSTR DesktopName) { UINT i; BOOL Found; PDESKTOP_NODE pCurrentNode;
//
// Verify valid string.
//
if ((!DesktopName) || (lstrlen(DesktopName) > MAX_NAME_LENGTH)) return FALSE;
//
// Change the name in our data structure.
//
i = 0; Found = FALSE; pCurrentNode = m_DesktopList; while (pCurrentNode && !Found) { if (i == DesktopNumber) { lstrcpy(pCurrentNode->DesktopName, DesktopName); Found = TRUE; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return Found; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets a desktop name. (Rename) */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::GetDesktopName(UINT DesktopNumber, LPTSTR DesktopName, UINT size) const { UINT i; BOOL Found; PDESKTOP_NODE pCurrentNode;
//
// Get the name from our data structure.
//
i = 0; Found = FALSE; pCurrentNode = m_DesktopList; while (pCurrentNode && !Found) { if (i == DesktopNumber) { if ((UINT) lstrlen(pCurrentNode->DesktopName) > size) return FALSE;
lstrcpy(DesktopName, pCurrentNode->DesktopName); Found = TRUE; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return Found; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Sets a desktop SAIFER authorization object name. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::SetSaiferName(UINT DesktopNumber, LPCTSTR SaiferName) { UINT i; BOOL Found; PDESKTOP_NODE pCurrentNode;
//
// Verify valid string.
//
if ((!SaiferName) || (lstrlen(SaiferName) > MAX_NAME_LENGTH)) return FALSE;
//
// Change the name in our data structure.
//
i = 0; Found = FALSE; pCurrentNode = m_DesktopList; while (pCurrentNode && !Found) { if (i == DesktopNumber) { lstrcpy(pCurrentNode->SaiferName, SaiferName); Found = TRUE; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return Found; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets a desktop SAIFER authorization object name. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::GetSaiferName(UINT DesktopNumber, LPTSTR SaiferName, UINT size) const { UINT i; BOOL Found; PDESKTOP_NODE pCurrentNode;
//
// Get the name from our data structure.
//
i = 0; Found = FALSE; pCurrentNode = m_DesktopList; while (pCurrentNode && !Found) { if (i == DesktopNumber) { if ((UINT) lstrlen(pCurrentNode->SaiferName) > size) return FALSE;
lstrcpy(SaiferName, pCurrentNode->SaiferName); Found = TRUE; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return Found; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets the icon for a particular desktop */ /* */ /*------------------------------------------------------------------------------*/
HICON CDesktop::GetDesktopIcon(UINT nDesktopNumber) const { UINT i; PDESKTOP_NODE pCurrentNode;
//
// Get the name from our data structure.
//
i = 0; pCurrentNode = m_DesktopList; while (pCurrentNode) { if (i == nDesktopNumber) { assert(pCurrentNode->nIconID >= 0 && pCurrentNode->nIconID < NUM_BUILTIN_ICONS); return DefaultIconArray[pCurrentNode->nIconID]; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return FALSE; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets the icon ID for a particular desktop */ /* */ /*------------------------------------------------------------------------------*/
UINT CDesktop::GetDesktopIconID(UINT nDesktopNumber) const { UINT i; PDESKTOP_NODE pCurrentNode;
//
// Get the name from our data structure.
//
i = 0; pCurrentNode = m_DesktopList; while (pCurrentNode) { if (i == nDesktopNumber) { return pCurrentNode->nIconID; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return 0; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Sets the Desktop Icon */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::SetDesktopIconID(UINT DesktopNumber, UINT nIconID) { UINT i; BOOL Found; PDESKTOP_NODE pCurrentNode;
//
// Change the name in our data structure.
//
i = 0; Found = FALSE; pCurrentNode = m_DesktopList; while (pCurrentNode && !Found) { if (i == DesktopNumber) { pCurrentNode->nIconID = nIconID; Found = TRUE; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return Found; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Sets the threads main window. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::SetThreadWindow(DWORD ThreadId, HWND hWnd) { PDESKTOP_NODE pCurrentNode;
pCurrentNode = m_DesktopList; while (pCurrentNode) { if (pCurrentNode->ThreadId == ThreadId) { pCurrentNode->hWnd = hWnd; } pCurrentNode = pCurrentNode->nextDN; }
return FALSE; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets the threads main window. */ /* */ /*------------------------------------------------------------------------------*/
HWND CDesktop::GetThreadWindow(DWORD ThreadId) const { PDESKTOP_NODE pCurrentNode;
pCurrentNode = m_DesktopList; while (pCurrentNode) { if (pCurrentNode->ThreadId == ThreadId) { return pCurrentNode->hWnd; } pCurrentNode = pCurrentNode->nextDN; }
return 0; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets the desktop id of a given thread. */ /* */ /*------------------------------------------------------------------------------*/
UINT CDesktop::GetThreadDesktopID(DWORD ThreadId) const { PDESKTOP_NODE pCurrentNode; UINT i;
i = 0; pCurrentNode = m_DesktopList; while (pCurrentNode) { if (pCurrentNode->ThreadId == ThreadId) { return i; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return 0; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets the threads main window. */ /* */ /*------------------------------------------------------------------------------*/
HWND CDesktop::GetWindowDesktop(UINT DesktopNumber) const { PDESKTOP_NODE pCurrentNode; UINT i;
i = 0; pCurrentNode = m_DesktopList; while (pCurrentNode) { if (DesktopNumber == i) { return pCurrentNode->hWnd; }
i++; pCurrentNode = pCurrentNode->nextDN; }
return 0; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets the real desktop name. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::GetRealDesktopName(HWND hWnd, LPTSTR szRealDesktopName) const { PDESKTOP_NODE pCurrentNode;
pCurrentNode = m_DesktopList; while (pCurrentNode) { if (pCurrentNode->hWnd == hWnd) { if (pCurrentNode->RealDesktopName[0]) lstrcpy(szRealDesktopName, pCurrentNode->RealDesktopName); else szRealDesktopName[0] = TEXT('\0'); }
pCurrentNode = pCurrentNode->nextDN; }
return 0; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Evaluate the setting of a desktop scheme. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::FindSchemeAndSet(VOID) { PDESKTOP_NODE pCurrentNode; UINT i;
if (!BeginRundown) { i = 0; pCurrentNode = m_DesktopList; while (pCurrentNode) { if (i == CurrentDesktop) { if (pCurrentNode->ThreadId == GetCurrentThreadId()) { //
// Set the desktop scheme
//
return __SetDesktopScheme(&(pCurrentNode->DS)); } }
i++; pCurrentNode = pCurrentNode->nextDN; } } else { //
// Set the desktop scheme to that of desktop 1
//
__SetDesktopScheme(&(m_DesktopList->DS)); }
return FALSE; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Copies the scheme from desktop 0 to desktop n. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::DuplicateDefaultScheme(UINT DesktopNumber) { PDESKTOP_NODE pCurrentNode; BOOL Success = FALSE; UINT i;
i = 0; pCurrentNode = m_DesktopList; while (pCurrentNode) { if (i == DesktopNumber) Success = __CopyDesktopScheme(&(m_DesktopList->DS), &(pCurrentNode->DS));
i++; pCurrentNode = pCurrentNode->nextDN; }
return Success; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets the color struct from registry for desktop n. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::GetRegColorStruct(UINT DesktopNumber) { PDESKTOP_NODE pCurrentNode; BOOL Success = FALSE; UINT i;
i = 0; pCurrentNode = m_DesktopList; while (pCurrentNode) { if (i == DesktopNumber) Success = GetDesktopSchemeRegistry(DesktopNumber, &(pCurrentNode->DS));
i++; pCurrentNode = pCurrentNode->nextDN; }
return Success; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Save off the schemes to the registry. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::RegSaveSettings(VOID) { PDESKTOP_NODE pCurrentNode; UINT ii;
//
// Set Global settings
//
Profile_SetNewContext(NumOfDesktops);
//
// Dump settings desktop by desktop
//
ii = 0; pCurrentNode = m_DesktopList;
while (pCurrentNode) { Profile_SaveDesktopContext(ii, pCurrentNode->DesktopName, pCurrentNode->SaiferName, pCurrentNode->nIconID); SetDesktopSchemeRegistry(ii, &(pCurrentNode->DS));
ii++; pCurrentNode = pCurrentNode->nextDN; }
return TRUE; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Destroy the windows one by one. */ /* */ /*------------------------------------------------------------------------------*/
BOOL CDesktop::RunDown(VOID) { PDESKTOP_NODE pCurrentNode; BOOL Success;
BeginRundown = TRUE;
//
// Set desktop schemes to that of desktop 1
//
pCurrentNode = m_DesktopList->nextDN; while (pCurrentNode) { //
// Set the desktop scheme
//
PostThreadMessage(pCurrentNode->ThreadId, WM_THREAD_SCHEME_UPDATE, 0, 0); pCurrentNode = pCurrentNode->nextDN; }
//
// Remove the desktops
//
while (NumOfDesktops > 1) { Success = RemoveDesktop(NumOfDesktops - 1); }
//
// Flush to registry
//
__UpdateDesktopRegistry(&(m_DesktopList->DS));
return TRUE; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Create a default desktop name. */ /* */ /*------------------------------------------------------------------------------*/
static BOOL __CreateDefaultName(UINT DeskNum, LPTSTR DesktopName) { wsprintf(DesktopName, TEXT("Desktop %d"), DeskNum);
return TRUE; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Gets the default icons. */ /* */ /*------------------------------------------------------------------------------*/
static HICON __LoadBuiltinIcon(UINT nIconNumber, HINSTANCE hDeskInstance) { UINT resid;
assert(NUM_BUILTIN_ICONS == 27); switch(nIconNumber) { case 1: resid = IDI_WIN_ICON01; break; case 2: resid = IDI_WIN_ICON02; break; case 3: resid = IDI_WIN_ICON03; break; case 4: resid = IDI_WIN_ICON04; break; case 5: resid = IDI_WIN_ICON05; break; case 6: resid = IDI_WIN_ICON06; break; case 7: resid = IDI_WIN_ICON07; break; case 8: resid = IDI_WIN_ICON08; break; case 9: resid = IDI_WIN_ICON09; break; case 10: resid = IDI_WIN_ICON10; break; case 11: resid = IDI_WIN_ICON11; break; case 12: resid = IDI_WIN_ICON12; break; case 13: resid = IDI_WIN_ICON13; break; case 14: resid = IDI_WIN_ICON14; break; case 15: resid = IDI_WIN_ICON15; break; case 16: resid = IDI_WIN_ICON16; break; case 17: resid = IDI_WIN_ICON17; break; case 18: resid = IDI_WIN_ICON18; break; case 19: resid = IDI_WIN_ICON19; break; case 20: resid = IDI_WIN_ICON20; break; case 21: resid = IDI_WIN_ICON21; break; case 22: resid = IDI_WIN_ICON22; break; case 23: resid = IDI_WIN_ICON23; break; case 24: resid = IDI_WIN_ICON24; break; case 25: resid = IDI_WIN_ICON25; break; case 26: resid = IDI_WIN_ICON26; break; case 27: resid = IDI_WIN_ICON27; break; default: return NULL; } return LoadIcon(hDeskInstance, MAKEINTRESOURCE(resid)); }
HICON CDesktop::GetBuiltinIcon(UINT nIconNumber) const { if (nIconNumber < NUM_BUILTIN_ICONS) return DefaultIconArray[nIconNumber]; else return NULL; }
/*------------------------------------------------------------------------------*/ /* */ /* Purpose: Create a new desktop. */ /* */ /*------------------------------------------------------------------------------*/
VOID ThreadInit(LPVOID hData) { USEROBJECTFLAGS uof; PTHREAD_DATA ptd; BOOL Success; DWORD Err;
//
// Passed-in data
//
ptd = (THREAD_DATA*)hData;
//
// Inheiritance and flags
//
uof.fInherit = TRUE; uof.fReserved = FALSE; uof.dwFlags = DF_ALLOWOTHERACCOUNTHOOK;
Success = SetUserObjectInformation (ptd->hDesktop, UOI_FLAGS, (LPVOID)&uof, sizeof(uof));
//
// Assign the thread to its desktop
//
Success = SetThreadDesktop(ptd->hDesktop); Err = GetLastError();
//
// Begin the Display dialog and start the shell.
//
ptd->CreateDisplayFn();
//
// End the thread
//
SetThreadDesktop(ptd->hDefaultDesktop); Success = CloseDesktop(ptd->hDesktop); GlobalFree(ptd);
return; }
/*------------------------------------------------------------------------------*/ /*----------------------------- PROTECTED FUNCTIONS ----------------------------*/ /*------------------------------------------------------------------------------*/
BOOL CDesktop::GetDesktopSchemeRegistry(UINT DesktopNumber, PDESKTOP_SCHEME pDS) { BOOL bSuccess = FALSE;
assert(pDS);
bSuccess = Profile_LoadScheme(DesktopNumber, pDS);
pDS->Initialized = bSuccess; return bSuccess; }
BOOL CDesktop::SetDesktopSchemeRegistry(UINT DesktopNumber, PDESKTOP_SCHEME pDS) { BOOL bSuccess = FALSE;
assert(pDS); if (!pDS->Initialized) return FALSE;
bSuccess = Profile_SaveScheme(DesktopNumber, pDS);
return bSuccess; }
static BOOL __SetDesktopScheme(PDESKTOP_SCHEME pDS) { //
// Check if structure has been filled in
//
assert(pDS); if (!pDS->Initialized) return FALSE;
//
// Structure has info - Lets update the desktop scheme
//
Reg_SetSysColors(pDS->dwColor); Reg_SetWallpaper(pDS->szWallpaper, pDS->szTile); Reg_SetPattern(pDS->szPattern); Reg_SetScreenSaver(pDS->szScreenSaver, pDS->szSecure, pDS->szTimeOut, pDS->szActive);
//
// Now invalidate the Wallpaper and Pattern
//
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pDS->szWallpaper, SPIF_SENDCHANGE); SystemParametersInfo(SPI_SETDESKPATTERN, 0, pDS->szPattern, SPIF_SENDCHANGE);
return TRUE; }
static BOOL __GetDesktopScheme(PDESKTOP_SCHEME pDS) { //
// Read the color settings from the desktop and fill in the structure
//
assert(pDS);
if (Reg_GetSysColors(pDS->dwColor) && Reg_GetWallpaper(pDS->szWallpaper, pDS->szTile) && Reg_GetPattern(pDS->szPattern) && Reg_GetScreenSaver(pDS->szScreenSaver, pDS->szSecure, pDS->szTimeOut, pDS->szActive)) { //
// Structure filled!
//
pDS->Initialized = TRUE; return TRUE; }
return FALSE; }
static BOOL __UpdateDesktopRegistry(PDESKTOP_SCHEME pDS) {
//
// Update the registry
//
assert(pDS); Reg_UpdateColorRegistry(pDS->dwColor);
return TRUE; }
static BOOL __CopyDesktopScheme(PDESKTOP_SCHEME pDS1, PDESKTOP_SCHEME pDS2) {
UINT i;
//
// Copy the contents of pDS1 into pDS2
//
assert(pDS2 != NULL); assert(pDS1 != NULL);
if (!pDS1->Initialized) { pDS2->Initialized = FALSE; return FALSE; }
//
// Copy the strings over
//
lstrcpy(pDS2->szWallpaper, pDS1->szWallpaper); lstrcpy(pDS2->szTile, pDS1->szTile); lstrcpy(pDS2->szPattern, pDS1->szPattern); lstrcpy(pDS2->szScreenSaver, pDS1->szScreenSaver); lstrcpy(pDS2->szSecure, pDS1->szSecure); lstrcpy(pDS2->szTimeOut, pDS1->szTimeOut); lstrcpy(pDS2->szActive, pDS1->szActive);
//
// Copy the colors over
//
for (i = 0; i < NUM_COLOR_ELEMENTS; i++) { pDS2->dwColor[i] = pDS1->dwColor[i]; }
pDS2->Initialized = TRUE; return TRUE; }
|