windows-nt/Source/XPSP1/NT/ds/security/winsafer/test/desktops/desktop.cpp
2020-09-26 16:20:57 +08:00

1573 lines
47 KiB
C++

////////////////////////////////////////////////////////////////////////////////
//
// 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;
}