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

727 lines
25 KiB
C++

////////////////////////////////////////////////////////////////////////////////
//
// File: Cmdhand.cpp
// Created: Feb 1996
// By: Martin Holladay (a-martih) and Ryan D. Marshall (a-ryanm)
//
// Project: MultiDesk - The NT Desktop Switcher
//
//
//
// Revision History:
//
// March 1997 - Add external icon capability
//
//
/*--------------------------------------------------------------------*/
/* Include Files */
/*--------------------------------------------------------------------*/
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <shellapi.h>
#include <commctrl.h>
#include "prsht.h"
#include "DeskSpc.h"
#include "Desktop.h"
#include "Registry.h"
#include "resource.h"
#include "CmdHand.h"
#include "Menu.h"
#include "User.h"
#include <saifer.h>
/*--------------------------------------------------------------------*/
/* Global Variables */
/*--------------------------------------------------------------------*/
extern APPVARS AppMember;
extern DispatchFnType CreateDisplayFn;
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
LRESULT CALLBACK TransparentMessageProc(
HWND hWnd,
UINT uMessage,
WPARAM wParam,
LPARAM lParam)
{
switch (uMessage)
{
case WM_PAINT:
{
HDC hDC;
HFONT hFont;
HBRUSH hBrush;
PAINTSTRUCT ps;
TCHAR szTitle[200];
RECT rect;
hDC = BeginPaint(hWnd, &ps);
if (hDC != NULL)
{
GetWindowText(hWnd, szTitle, sizeof(szTitle) / sizeof(TCHAR));
GetClientRect(hWnd, &rect);
hBrush = CreateSolidBrush(TRANSPARENT_BACKCOLOR);
if (hBrush != NULL)
{
FillRect(hDC, &rect, hBrush);
hFont = CreateFont(rect.bottom, 0, 0, 0, FW_DONTCARE,
TRUE, FALSE, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, TEXT("Arial"));
if (hFont != NULL)
{
SetTextColor(hDC, TRANSPARENT_TEXTCOLOR);
SetBkMode(hDC, TRANSPARENT);
HFONT hOldFont = (HFONT) SelectObject(hDC, hFont);
DrawText(hDC, szTitle, -1, &rect,
DT_TOP | DT_RIGHT | DT_END_ELLIPSIS);
SelectObject(hDC, hOldFont);
DeleteObject(hFont);
}
DeleteObject(hBrush);
}
EndPaint(hWnd, &ps);
}
return FALSE;
}
default:
return (DefWindowProc(hWnd, uMessage, wParam, lParam));
break;
}
return (0L);
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
LRESULT CALLBACK MainMessageProc(
HWND hWnd,
UINT uMessage,
WPARAM wParam,
LPARAM lParam)
{
WINDOWPOS* pWP;
UINT uCmdId;
UINT uCmdType;
UINT uCmdMsg;
HWND hTargetWnd;
static UINT s_uTaskbarRestart;
switch (uMessage)
{
case WM_CREATE:
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
RegisterHotKey(hWnd, 0x7654, MOD_ALT | MOD_CONTROL, 41); // CTRL+ALT+A
PlaceOnTaskbar(hWnd);
break;
case WM_HOTKEY:
if (wParam == 0x7654)
{
// keyboard hotkey invoked menu popup
AppMember.nX = AppMember.nY = 0;
SetWindowPos(hWnd, HWND_TOPMOST,
AppMember.nX, AppMember.nY,
AppMember.nWidth, AppMember.nHeight,
0);
HideOrRevealUI(hWnd, FALSE);
UpdateCurrentUI(hWnd);
SetActiveWindow(hWnd);
SetForegroundWindow(hWnd);
break;
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
//case WM_CONTEXTMENU:
//TODO
case WM_CLOSE:
if ((UINT) wParam == WM_NO_CLOSE)
break;
CloseRequestHandler(hWnd);
break;
case WM_ENDSESSION:
AppMember.pDesktopControl->RegSaveSettings();
ShowWindow(hWnd, SW_HIDE);
RemoveFromTaskbar(hWnd);
AppMember.pDesktopControl->RunDown();
PostThreadMessage(GetCurrentThreadId(), WM_PUMP_TERMINATE, 0, 0);
break;
case WM_NOTIFY:
{
int idCtrl = (int) wParam;
LPNMHDR lpNmhdr = (LPNMHDR) lParam;
NMLVDISPINFO *pnmv = (NMLVDISPINFO*) lParam;
if (lpNmhdr->code == LVN_GETDISPINFO &&
lpNmhdr->idFrom == IDC_DESKTOPICONLIST)
{
//
// This notification is called when the ListView needs
// to obtain information about the item that it is displaying.
//
static int nextindex = 0;
static CHAR desktopname[5][MAX_NAME_LENGTH];
// return the name of this desktop.
AppMember.pDesktopControl->GetDesktopName(pnmv->item.iItem,
desktopname[nextindex], MAX_NAME_LENGTH);
pnmv->item.pszText = desktopname[nextindex];
pnmv->item.cchTextMax = MAX_NAME_LENGTH;
pnmv->item.mask |= LVIF_TEXT;
nextindex = (nextindex + 1) % 5;
// return the state of this desktop (unused).
pnmv->item.state = 0;
pnmv->item.stateMask = 0;
pnmv->item.mask |= LVIF_STATE;
// return the icon of this desktop.
pnmv->item.iImage = AppMember.pDesktopControl->GetDesktopIconID(pnmv->item.iItem);
pnmv->item.mask |= LVIF_IMAGE;
// return the ident attribute.
#if (_WIN32_IE >= 0x0300)
pnmv->item.iIndent = 0;
pnmv->item.mask |= LVIF_INDENT;
#endif
break;
}
else if (lpNmhdr->code == LVN_ITEMACTIVATE &&
lpNmhdr->idFrom == IDC_DESKTOPICONLIST)
{
//
// This notification is called when the user has single-clicked
// an item in the listview. We use this signal to switch desktops.
//
HideOrRevealUI(hWnd, TRUE);
LPNMITEMACTIVATE lpnmia = (LPNMITEMACTIVATE)lParam;
if (lpnmia->iItem >= 0)
SwitchToDesktop(lpnmia->iItem);
break;
}
else if (lpNmhdr->code == NM_RCLICK &&
lpNmhdr->idFrom == IDC_DESKTOPICONLIST)
{
//
// This notification is triggered when the user right-clicks
// on a listview item or in the listview box.
//
LPNMITEMACTIVATE lpnmia = (LPNMITEMACTIVATE)lParam;
HMENU hPopupMenu = CreateListviewPopupMenu();
// display the popup
if (hPopupMenu != NULL)
{
RECT rect;
WORD wChoiceId;
if (lpnmia->iItem < 0)
{
// clicked off of an item, so gray the item-specific options.
EnableMenuItem(hPopupMenu, IDM_DELETE_DESKTOP, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hPopupMenu, IDM_DESKTOP_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
}
else if (lpnmia->iItem == 0)
{
// clicked on the first Desktop, cannot delete it though.
EnableMenuItem(hPopupMenu, IDM_DELETE_DESKTOP, MF_BYCOMMAND | MF_GRAYED);
}
// Display the popup and get the selected choice.
GetWindowRect(lpNmhdr->hwndFrom, &rect);
wChoiceId = (WORD) TrackPopupMenu(hPopupMenu,
TPM_CENTERALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY,
(rect.left + lpnmia->ptAction.x),
(rect.top + lpnmia->ptAction.y), 0, hWnd, NULL);
DestroyMenu(hPopupMenu);
// Handle the choice that was selected.
switch (wChoiceId)
{
case IDM_NEW_DESKTOP:
CreateNewDesktop(hWnd);
break;
case IDM_DELETE_DESKTOP:
if (lpnmia->iItem >= 0) {
DeleteDesktop(hWnd, lpnmia->iItem);
UpdateCurrentUI(hWnd);
}
break;
case IDM_DESKTOP_PROPERTIES:
if (lpnmia->iItem >= 0) {
RenameDialog(hWnd, lpnmia->iItem);
UpdateCurrentUI(hWnd);
}
break;
}
}
break;
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
case WM_THREAD_TERMINATE:
DestroyWindow(hWnd);
break;
case WM_TASKBAR:
uCmdId = (UINT) wParam;
uCmdMsg = (UINT) lParam;
if (uCmdId == IDI_TASKBAR_ICON &&
(uCmdMsg == WM_RBUTTONUP || uCmdMsg == WM_LBUTTONUP) &&
!IsWindowVisible(hWnd))
{
POINT tPoint;
GetCursorPos(&tPoint);
AppMember.nX = tPoint.x - AppMember.nWidth;
AppMember.nY = tPoint.y - AppMember.nHeight;
SetWindowPos(hWnd, HWND_TOPMOST,
AppMember.nX, AppMember.nY,
AppMember.nWidth, AppMember.nHeight,
0);
HideOrRevealUI(hWnd, FALSE);
UpdateCurrentUI(hWnd);
SetActiveWindow(hWnd);
SetForegroundWindow(hWnd);
}
break;
case WM_ACTIVATEAPP:
// We are losing focus, so hide ourself again.
if (!wParam)
HideOrRevealUI(hWnd, TRUE);
return DefWindowProc(hWnd, uMessage, wParam, lParam);
case WM_SIZE:
{
RECT rect;
GetWindowRect(hWnd, &rect);
AppMember.nX = rect.left;
AppMember.nY = rect.top;
AppMember.nWidth = rect.right - rect.left;
AppMember.nHeight = rect.bottom - rect.top;
GetClientRect(hWnd, &rect);
HWND hWndList = GetDlgItem(hWnd, IDC_DESKTOPICONLIST);
SetWindowPos(hWndList, NULL,
0, 0, (rect.right - rect.left), (rect.bottom - rect.top),
SWP_NOZORDER);
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
default:
// If Explorer has just started or restarted, then be
// sure to add ourself back to it so the user does not
// lose the ability to invoke us.
if(uMessage == s_uTaskbarRestart)
PlaceOnTaskbar(hWnd);
return DefWindowProc(hWnd, uMessage, wParam, lParam);
break;
}
return 0L;
}
/*------------------------------------------------------------------------------*/
/*
/* Create a new desktop
/*
/*------------------------------------------------------------------------------*/
void CreateNewDesktop(HWND hWnd)
{
// Use the creation wizard - or create it the old fashioned way.
if (AppMember.pDesktopControl->GetNumDesktops() < MAX_DESKTOPS)
{
UINT nDskTopNum = AppMember.pDesktopControl->GetNumDesktops();
AppMember.pDesktopControl->SaveCurrentDesktopScheme();
AppMember.pDesktopControl->AddDesktop(CreateDisplayFn, NULL);
RenameDialog(hWnd, nDskTopNum);
UpdateCurrentUI(hWnd);
}
else
{
Message(TEXT("Maximum number of desktops reached"));
}
}
//------------------------------------------------------------------------------//
//
// Delete Desktop
//
//-----------------------------------------------------------------------------//
BOOL DeleteDesktop(HWND hWnd, UINT nDesktop) // zero based
{
HWND hTargetWnd, hCurrentWnd;
UINT nResult;
assert(nDesktop >= 0 && nDesktop < AppMember.pDesktopControl->GetNumDesktops());
if (nDesktop == 0)
{
return FALSE;
}
hTargetWnd = AppMember.pDesktopControl->GetWindowDesktop(nDesktop);
nResult = AppMember.pDesktopControl->RemoveDesktop(nDesktop);
if (nResult == SUCCESS_THREAD_TERMINATION)
{
if (hTargetWnd) PostMessage(hTargetWnd, WM_THREAD_TERMINATE, 0, 0);
}
//
// Update the UI for the active desktop.
//
hCurrentWnd = AppMember.pDesktopControl->GetWindowDesktop(AppMember.pDesktopControl->GetActiveDesktop());
UpdateCurrentUI(hCurrentWnd);
return TRUE;
}
//------------------------------------------------------------------------------//
//
// Switch to desktop nDesktop Number
//
//-----------------------------------------------------------------------------//
void SwitchToDesktop(UINT nDesktop) // zero based
{
HWND hTargetWnd;
assert(nDesktop >= 0 && nDesktop < AppMember.pDesktopControl->GetNumDesktops());
//
// Switching to ourself - that is easy.
//
if (nDesktop == AppMember.pDesktopControl->GetActiveDesktop())
{
return;
}
hTargetWnd = AppMember.pDesktopControl->GetWindowDesktop(nDesktop);
UpdateCurrentUI(hTargetWnd);
AppMember.pDesktopControl->ActivateDesktop(nDesktop);
}
/*------------------------------------------------------------------------------*/
/* */
/* RenameDialogProc() - CallBack procedure for the Rename dialog within the */
/* Properties property sheet and the Rename only property sheet */
/* */
/*------------------------------------------------------------------------------*/
LRESULT CALLBACK
RenameDialogProc(HWND hWnd,
UINT nMessage,
WPARAM wParam,
LPARAM lParam)
{
static BOOL bInitialized;
UINT nBtnIndex;
CHAR szTemp[MAX_TITLELEN + 1];
UINT i;
HICON hIcon1;
UINT nCurSel;
UINT nResult;
switch (nMessage)
{
case WM_INITDIALOG:
{
//
// First position the property sheet in the center of the screen
//
HWND hParent = GetParent(hWnd);
assert(hParent);
RECT rc;
if (GetWindowRect(hParent, &rc))
{
SetWindowPos(
hParent,
HWND_TOP,
(GetSystemMetrics(SM_CXSCREEN) / 2) - ((rc.right - rc.left) / 2),
(GetSystemMetrics(SM_CYSCREEN) / 2) - ((rc.bottom - rc.top) / 2),
rc.right - rc.left,
rc.bottom - rc.top,
SWP_SHOWWINDOW);
}
//
// Now initialize the controls
//
PRENAMEINFO pRenameInfo = ((PRENAMEINFO) ((PROPSHEETPAGE *) lParam)->lParam);
nBtnIndex = pRenameInfo->nBtnIndex;
SetWindowLong(hWnd, GWL_USERDATA, (LONG) nBtnIndex);
AppMember.pDesktopControl->GetDesktopName(nBtnIndex, szTemp, MAX_TITLELEN);
SetDlgItemText(hWnd, IDC_EDIT_NAME, szTemp);
//
// Initialize the SAIFER Authorization Object name too.
// The first desktop cannot have a SAIFER object name associated with
// it since its shell has already been launched by the time
// Multidesk starts, so it always runs unmodified.
//
SendDlgItemMessage(hWnd, IDC_EDIT_SAIFER, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage(hWnd, IDC_EDIT_SAIFER, CB_ADDSTRING, 0, (LPARAM) TEXT("(No modification of trust)"));
if (nBtnIndex != 0) {
// all secondary desktops can be modified.
AppMember.pDesktopControl->GetSaiferName(nBtnIndex, szTemp, MAX_TITLELEN);
EnableWindow(GetDlgItem(hWnd, IDC_EDIT_SAIFER), TRUE);
// Fetch the list of all object names.
DWORD dwInfoBufferSize;
LPTSTR InfoBuffer = NULL;
if (!GetInformationCodeAuthzPolicy(AUTHZSCOPE_HKLM,
CodeAuthzPol_ObjectList,
0, NULL, &dwInfoBufferSize) &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
InfoBuffer = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, dwInfoBufferSize);
if (InfoBuffer != NULL)
{
if (!GetInformationCodeAuthzPolicy(AUTHZSCOPE_HKLM,
CodeAuthzPol_ObjectList,
dwInfoBufferSize, InfoBuffer, &dwInfoBufferSize))
{
HeapFree(GetProcessHeap(), 0, InfoBuffer);
InfoBuffer = NULL;
}
}
}
// Iterate through and add all of the items.
BOOL bFoundMatch = FALSE;
if (InfoBuffer != NULL)
{
DWORD dwChoiceIndex = 1;
LPCTSTR lpOneChoice = (LPCTSTR) InfoBuffer;
while (*lpOneChoice != TEXT('\0')) {
SendDlgItemMessage(hWnd, IDC_EDIT_SAIFER, CB_ADDSTRING, 0, (LPARAM) lpOneChoice);
if (!bFoundMatch && strcmp(lpOneChoice, szTemp) == 0) {
SendDlgItemMessage(hWnd, IDC_EDIT_SAIFER, CB_SETCURSEL, dwChoiceIndex, 0);
bFoundMatch = TRUE;
}
while (*lpOneChoice++) {};
dwChoiceIndex++;
}
HeapFree(GetProcessHeap(), 0, InfoBuffer);
}
if (!bFoundMatch)
SendDlgItemMessage(hWnd, IDC_EDIT_SAIFER, CB_SETCURSEL, 0, 0);
// Display a little warning if the desktop is already running.
DESKTOP_NODE *pCurrentNode = AppMember.pDesktopControl->GetDesktopNode(nBtnIndex);
if (pCurrentNode != NULL && pCurrentNode->bShellStarted)
SetDlgItemText(hWnd, IDC_SAIFER_NOTETEXT,
TEXT("(desktop shell already started. changes will take effect on next multidesk session)"));
else
SetDlgItemText(hWnd, IDC_SAIFER_NOTETEXT, TEXT(""));
} else {
// the first desktop cannot be modified.
EnableWindow(GetDlgItem(hWnd, IDC_EDIT_SAIFER), FALSE);
SetDlgItemText(hWnd, IDC_SAIFER_NOTETEXT,
TEXT("(the primary desktop cannot run with a modified token)"));
}
//
// Fill up the List Box with the loaded Icons - making the current Icon First (0)
//
HWND hListBox = GetDlgItem(hWnd, IDC_ICONLIST);
SendMessage(hListBox, WM_SETREDRAW, FALSE, 0L);
for (i = 0; i < NUM_BUILTIN_ICONS; i++)
{
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) AppMember.pDesktopControl->GetBuiltinIcon(i));
}
SendMessage(hListBox, LB_SETCURSEL,
AppMember.pDesktopControl->GetDesktopIconID(nBtnIndex), 0 );
SendMessage(hListBox, WM_SETREDRAW, TRUE, 0L);
bInitialized = TRUE;
break;
}
case WM_COMMAND:
{
if (HIWORD (wParam) == LBN_SELCHANGE && bInitialized) // Icon box
{
PropSheet_Changed(GetParent(hWnd), hWnd);
InvalidateRect(GetDlgItem(hWnd, IDC_DEFICON), NULL, TRUE);
}
else if ((HIWORD(wParam) == EN_CHANGE) && bInitialized)
{
PropSheet_Changed(GetParent(hWnd), hWnd);
}
break;
}
case WM_MEASUREITEM:
{
//
// Owner Draw List Box Control
//
MEASUREITEMSTRUCT *pMeasureItem = (MEASUREITEMSTRUCT *) lParam;
pMeasureItem->itemWidth = GetSystemMetrics(SM_CXICON) + 12;
pMeasureItem->itemHeight = GetSystemMetrics(SM_CYICON) + 4;
break;
}
case WM_DRAWITEM: // Dlg controls need redrawing
{
HWND hListBox = GetDlgItem(hWnd, IDC_ICONLIST);
DRAWITEMSTRUCT *pDrawItem = (DRAWITEMSTRUCT *) lParam;
if (wParam == IDC_DEFICON ) // Display panel sample icon
{
nCurSel = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (nCurSel == LB_ERR)
{
nCurSel = 0;
}
if (LB_ERR == SendMessage(hListBox, LB_GETTEXT, nCurSel, (LPARAM) &hIcon1))
{
nResult = GetLastError();
hIcon1 = LoadIcon(AppMember.hInstance, MAKEINTRESOURCE(IDI_MULTIDESK_ICON));
}
DrawIcon(pDrawItem->hDC,
pDrawItem->rcItem.left,
pDrawItem->rcItem.top,
(HICON) hIcon1);
UpdateWindow(hWnd);
break;
}
if (pDrawItem->itemState & ODS_SELECTED)
{
SetBkColor(pDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHT));
}
else
{
SetBkColor(pDrawItem->hDC, GetSysColor(COLOR_WINDOW));
}
ExtTextOut(pDrawItem->hDC, 0, 0, ETO_OPAQUE, &pDrawItem->rcItem, NULL, 0, NULL);
if ((int) pDrawItem->itemID >= 0)
{
DrawIcon(pDrawItem->hDC,
(pDrawItem->rcItem.left + pDrawItem->rcItem.right - GetSystemMetrics(SM_CXICON)) /2,
(pDrawItem->rcItem.bottom + pDrawItem->rcItem.top - GetSystemMetrics(SM_CYICON)) /2,
(HICON) pDrawItem->itemData);
}
if (pDrawItem->itemState & ODS_FOCUS)
{
DrawFocusRect(pDrawItem->hDC, &pDrawItem->rcItem);
}
break;
}
case WM_DESTROY:
bInitialized = FALSE;
break;
case WM_NOTIFY:
{
LPNMHDR lpNotifyMsg = (NMHDR FAR*) lParam;
switch (lpNotifyMsg->code)
{
case PSN_APPLY:
{
//
// OK or Apply button clicked, save the info -
// Get the main dialog's hwnd and update the button's title
HWND hParent = GetParent(GetParent(hWnd));
assert(hParent);
//// Get number of desktop ////
nBtnIndex = (UINT) GetWindowLong(hWnd, GWL_USERDATA);
//// Get desktop name and save it to Node ////
GetDlgItemText(hWnd, IDC_EDIT_NAME, szTemp, MAX_TITLELEN);
AppMember.pDesktopControl->SetDesktopName(nBtnIndex, szTemp);
//// Get and save the Saifer object name ////
GetDlgItemText(hWnd, IDC_EDIT_SAIFER, szTemp, MAX_TITLELEN);
AppMember.pDesktopControl->SetSaiferName(nBtnIndex, szTemp);
//// Get and save the icon for the desktop ////
HWND hListBox = GetDlgItem(hWnd, IDC_ICONLIST);
nCurSel = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
if (nCurSel != LB_ERR)
{
AppMember.pDesktopControl->SetDesktopIconID(nBtnIndex, nCurSel);
}
//
// Now update the UI
//
UpdateCurrentUI(hWnd);
break;
}
default:
break;
}
break;
}
default:
break;
}
return 0L;
}