|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
taskman.c
Abstract:
This file contains the source for the windows Task Manager. Taskman basically is a dialog box, which enumerates active windows keep in the user window manager, then sets active focus to the selected dialog box element(ie active window).
--*/
#define UNICODE
#include "taskman.h"
#include <port1632.h>
#include <shellapi.h>
#include <shlapip.h>
//LATER find correct define for NT
#if !defined(NTWIN) && !defined(DOSWIN32) && !defined(WIN16)
#define NTWIN 1
#endif
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
#define MAXPATHFIELD 260
#define INIT_MAX_FILES 4
#define FILES_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager\\Recent File List"
#define MAXFILES_ENTRY L"Max Files"
#define FILE_ENTRY L"File%lu"
#define WM_CONTENTSCHANGED (WM_USER+5)
TCHAR szPathField[MAXPATHFIELD]; TCHAR szDirField[MAXPATHFIELD]; TCHAR szTitle[MAXPATHFIELD]; TCHAR szMessage[MAXMSGBOXLEN];
TCHAR szUserHomeDir[MAXPATHFIELD]; TCHAR szWindowsDirectory[MAXPATHFIELD];
TCHAR szOOMExitMsg[64] = TEXT("Close an application and try again."); // 64
TCHAR szOOMExitTitle[32] = TEXT("Extremely Low on Memory"); // 32
TCHAR szNoRun[] = TEXT("NoRun"); // registry key for groups
HANDLE hInst;
BOOL bChangedDefaultButton;
INT_PTR APIENTRY TaskmanDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
WORD APIENTRY ExecProgram(LPTSTR lpszPath,LPTSTR lpDir,LPTSTR lpTitle); void APIENTRY SaveRecentFileList (HWND, LPTSTR);
VOID GetPathInfo(PTSTR szPath,PTSTR *pszFileName,PTSTR *pszExt,WORD *pich,BOOL *pfUnc); VOID GetFilenameFromPath(PTSTR szPath, PTSTR szFilename); VOID GetDirectoryFromPath(PTSTR szFilePath, PTSTR szDir); BOOL IsUserAdmin(); BOOL OKToExec(); BOOL TestTokenForAdmin(HANDLE Token); VOID SetDefButton(HWND hwndDlg, INT idButton);
WINUSERAPI VOID SwitchToThisWindow(HWND, BOOL); INT MyMessageBox(HWND hWnd,WORD idTitle,WORD idMessage,PWSTR psz,WORD wStyle);
INT MyX = 0; INT MyY = 0; INT dxTaskman; INT dyTaskman; INT dxScreen; INT dyScreen;
HWND ghwndDialog; BOOL fExecOK = TRUE; BOOL fMsgBox = FALSE;
PVOID Alloc( DWORD Bytes) { HANDLE hMem; PVOID Buffer;
hMem = LocalAlloc(LMEM_MOVEABLE, Bytes + sizeof(hMem));
if (hMem == NULL) { return(NULL); }
Buffer = LocalLock(hMem); if (Buffer == NULL) { LocalFree(hMem); return(NULL); }
*((PHANDLE)Buffer) = hMem;
return (PVOID)(((PHANDLE)Buffer)+1); }
BOOL Free( PVOID Buffer) { HANDLE hMem;
hMem = *(((PHANDLE)Buffer) - 1);
LocalUnlock(hMem);
return(LocalFree(hMem) == NULL); }
VOID HideWindow(HWND hwnd) { if (!fMsgBox) {
if (fExecOK) { SetDlgItemText(ghwndDialog, IDD_PATH, TEXT("")); }
// redundant? why do they do the reverse twice for show below?
ShowWindow(ghwndDialog, SW_HIDE);
SetWindowPos(ghwndDialog, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); }
// Erase dark border from depressed pushbuttons
SendMessage(GetDlgItem(hwnd, IDCANCEL), // IDCANCEL
BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); SendMessage(GetDlgItem(hwnd, IDD_TERMINATE), BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); SendMessage(GetDlgItem(hwnd, IDD_CASCADE), BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); SendMessage(GetDlgItem(hwnd, IDD_TILE), BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); SendMessage(GetDlgItem(hwnd, IDD_ARRANGEICONS), BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); }
/*
* We call HideTasklist() when we want to remove the tasklist window * from the screen but not select another window (ie. when we're about * to select another app. We call ShowWindow(SW_HIDE) directly when * we're doing something like tiling or cascading so a window other than * the tasklist will become the foreground window. */ VOID HideTasklist(VOID) { if (fExecOK) { SetDlgItemText(ghwndDialog, IDD_PATH, TEXT("")); }
SetWindowPos(ghwndDialog, HWND_TOP, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
}
VOID ShowTasklist( POINT pt) { /*
* Retract the drop down listbox. */
if (fExecOK) { SendDlgItemMessage(ghwndDialog, IDD_PATH, CB_SHOWDROPDOWN,0,0); }
SetWindowPos(ghwndDialog, HWND_TOPMOST, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE ); SetForegroundWindow(ghwndDialog);
ShowWindow(ghwndDialog, SW_NORMAL); }
/*** ActivateSelectedWindow -- Calls user, to set active window, selected
* by the user. * * * ActivateSelectedWindow(HWND hwndLB) * * ENTRY - HWND hwndLB - handle to window, which is to become the active * window, with focus. * EXIT - * SYNOPSIS - This function takes the hwnd passed into it, calls user * to set active focus to that window. * WARNINGS - * EFFECTS - * */
VOID ActivateSelectedWindow( HWND hwndLB) { INT nIndex; HWND hwndT; HWND hwndLastActive; DWORD lTemp;
/*
* Get the hwnd of the item which was selected. */ nIndex = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0); hwndT = (HWND)SendMessage(hwndLB, LB_GETITEMDATA, nIndex, 0);
if (!IsWindow(hwndT)) { /*
* We gotta make sure the window is valid before doing stuff with it. * An app may terminate itself in the background rendering these * window handles invalid. */ goto Beep; }
/*
* Switch to that task. * HACK! Activate the window in the hwndLastActive field of the WndStruct. */ hwndLastActive = GetLastActivePopup(hwndT);
if (!IsWindow(hwndLastActive)) { goto Beep; }
/*
* But only if it isn't disabled. */ lTemp = GetWindowLong(hwndLastActive, GWL_STYLE); if (!(lTemp & WS_DISABLED)) { /*
* HACK!! Use SwitchToThisWindow() to bring dialog parents as well. */ SwitchToThisWindow(hwndLastActive, TRUE);
} else { Beep: MessageBeep(0); } }
#ifdef NTWIN
/*** DoEndTask --
* * void DoEndTask( HWND hwnd ) */ VOID DoEndTask( HWND hwnd ) { TCHAR szMsgBoxText[MAXMSGBOXLEN]; TCHAR szTempField[MAXTASKNAMELEN]; INT nch;
if (!EndTask(hwnd, FALSE, FALSE)) { /* App does not want to close, ask user if
* he wants to blow it away */
InternalGetWindowText(hwnd, (LPTSTR)szTempField, MAXTASKNAMELEN);
/* Load the message box string, it is very long (greater than 255 chars
* which is why we load it in two pieces */ nch = LoadString(NULL, IDS_MSGBOXSTR1, szMsgBoxText, MAXMSGBOXLEN); LoadString(NULL, IDS_MSGBOXSTR2, &szMsgBoxText[nch], MAXMSGBOXLEN-nch);
if( MessageBox( NULL, szMsgBoxText, szTempField, MB_SETFOREGROUND | MB_SYSTEMMODAL | MB_YESNO ) == IDYES) { EndTask(hwnd, FALSE, TRUE); } } }
/*** CallEndTask -- A separate thread to instigate EndTask
* * CallEndTask( HWND hwnd ); * * ENTRY - HWND hwnd - window handle for the task to be killed * EXIT - * SYNOPSIS - This function calls EndTask on the given window to kill the * task that owns that window. * * WARNINGS - * EFFECTS - Kills the task that owns hwnd. * */
DWORD CallEndTask( HWND hwnd) { DoEndTask(hwnd);
ExitThread(0); return 0; /* placate compiler */ } #endif
/*** TaskmanDlgProc -- Dialog Procedure for Taskman Window
* * * * TaskmanDlgProc(HWND hDlg, WORD wMSG, DWORD wParam, LPARAM lParam) * * ENTRY - HWND hhDlg - handle to dialog box. * WORD wMsg - message to be acted upon. * DWORD wParam - value specific to wMsg. * LPARAM lParam - value specific to wMsg. * * EXIT - True if success, False if not. * SYNOPSIS - Dialog box message processing function. * * WARNINGS - * EFFECTS - * */
INT_PTR TaskmanDlgProc( HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { int nIndex; RECT rc; HWND hwndLB; HWND hwndNext; TCHAR szTempField[MAXTASKNAMELEN]; POINT pt; HKEY hKey; DWORD dwDisp; DWORD dwDataType, dwMaxFiles=INIT_MAX_FILES, dwMaxFilesSize, dwCount; TCHAR szFileEntry[20]; TCHAR szFullPath[MAXPATHFIELD]; #ifndef NTWIN
LONG lTemp; #endif
hwndLB = GetDlgItem(hwnd, IDD_TASKLISTBOX);
switch (wMsg) {
case WM_INITDIALOG: /*
* call private api to mark task man as a system app. This causes * it to be killed after all other non-system apps during shutdown. */ // MarkProcess(MP_SYSTEMAPP);
GetWindowRect(hwnd, &rc); dxTaskman = rc.right - rc.left; dyTaskman = rc.bottom - rc.top; dxScreen = GetSystemMetrics(SM_CXSCREEN); dyScreen = GetSystemMetrics(SM_CYSCREEN);
pt.x = (dxScreen - dxTaskman) / 2; pt.y = (dyScreen - dyTaskman) / 2;
SetWindowPos(hwnd, HWND_NOTOPMOST, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
SendDlgItemMessage(hwnd, IDD_PATH, EM_LIMITTEXT, MAXPATHFIELD-4, 0L); szPathField[0] = TEXT('\0');
bChangedDefaultButton = FALSE;
return FALSE;
case WM_SHOWWINDOW: /*
* If we're being shown fill in the listbox. We do this here * rather than in WM_ACTIVATE process so we can do it while the * dialog is still invisible. */ if (wParam != 0) { DWORD pidTaskMan = GetCurrentProcessId();
/*
* First delete any previous entries. */ while ((int)SendMessage(hwndLB, LB_DELETESTRING, 0, 0) != LB_ERR);
/*
* Search the window list for enabled top level windows. */ hwndNext = GetWindow(hwnd, GW_HWNDFIRST); while (hwndNext) {
/*
* Only add non-owned, visible, non-Taskman, Top Level Windows. */ if ((hwndNext != hwnd) && (IsWindowVisible(hwndNext)) && (!GetWindow(hwndNext, GW_OWNER))) { DWORD pidNext; GetWindowThreadProcessId(hwndNext, &pidNext); if (pidNext != pidTaskMan) { if (InternalGetWindowText(hwndNext, (LPTSTR)szTempField, MAXTASKNAMELEN)) { nIndex = (int)SendMessage(hwndLB, LB_ADDSTRING, 0, (DWORD_PTR)(LPTSTR)szTempField); SendMessage(hwndLB, LB_SETITEMDATA, nIndex, (DWORD_PTR)hwndNext); } } }
hwndNext = GetWindow(hwndNext, GW_HWNDNEXT); } SendMessage(hwndLB, LB_SETCURSEL, 0, 0);
//
// Set the default button to "Switch To"
//
SetDefButton(hwnd,IDD_SWITCH);
//
// Load the combobox with the recently used files.
//
if (GetDlgItem(hwnd, IDD_PATH)) {
//
// FIrst empty the combo box from the last time.
//
SendDlgItemMessage (hwnd, IDD_PATH, CB_RESETCONTENT, 0, 0);
//
// Load the combobox with recently used files from the registry.
//
// Query the max number of files first.
//
if (RegCreateKeyEx (HKEY_CURRENT_USER, FILES_KEY, 0, 0, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
if (dwDisp == REG_OPENED_EXISTING_KEY) {
//
// Query the max number of entries
//
dwMaxFilesSize = sizeof (DWORD);
if (RegQueryValueEx (hKey, MAXFILES_ENTRY, NULL, &dwDataType, (LPBYTE)&dwMaxFiles, &dwMaxFilesSize) == ERROR_SUCCESS) {
//
// Now Query each entry and add it to the list box.
//
for (dwCount=0; dwCount < dwMaxFiles; dwCount++) {
wsprintf (szFileEntry, FILE_ENTRY, dwCount); dwMaxFilesSize = MAXPATHFIELD+1;
if (RegQueryValueEx (hKey, szFileEntry, NULL, &dwDataType, (LPBYTE) szFullPath, &dwMaxFilesSize) == ERROR_SUCCESS) {
//
// Found an entry. Add it to the combo box.
//
SendDlgItemMessage (hwnd, IDD_PATH, CB_ADDSTRING, 0, (LPARAM)szFullPath);
} else { break; } } } } else { //
// We are working with a new key, so we need to
// set the default number of files.
//
RegSetValueEx (hKey, MAXFILES_ENTRY, 0, REG_DWORD, (CONST BYTE *) &dwMaxFiles, sizeof (DWORD)); }
//
// Close the registry key
//
RegCloseKey (hKey);
} }
//
// Disable the Run button and set the focus to the
// listbox.
//
EnableWindow(GetDlgItem(hwnd, IDD_RUN), FALSE); SetFocus(hwndLB); } break;
case WM_ACTIVATE: /*
* If we're being deactivated clear the listbox so we * can fill it in afresh when we're re-activated. */ if (wParam == 0) { /*
* If we're not already invisible, hide ourself. */ if (IsWindowVisible(hwnd)) { HideWindow(hwnd); } }
if (!bChangedDefaultButton) { SetDefButton(hwnd,IDD_SWITCH); }
break;
case WM_ACTIVATEAPP: if (wParam) return FALSE;
/*
* If we are not visible when we get this message it is because * we are already in the process of terminating. If we don't * ignore this we get into a weird race condition and the frame * of the window being activated doesn't get fully drawn. (BG) */ if (IsWindowVisible(hwnd)) { HideWindow(hwnd); } break;
#ifdef JAPAN // bug fix
//
// Do nothing. Let the progman main thread do the work.
//
#else // not JAPAN
case WM_WININICHANGE: //
// Check if the user's environment variables have changed, if so
// regenerate the environment, so that new apps started from
// taskman will have the latest environment.
//
if (lParam && (!lstrcmpi((LPTSTR)lParam, (LPTSTR) TEXT("Environment")))) { PVOID pEnv;
RegenerateUserEnvironment(&pEnv, TRUE); break; } else { return FALSE; } #endif // JAPAN
case WM_CONTENTSCHANGED: if (fExecOK) { if (GetDlgItemText(hwnd, IDD_PATH, (LPTSTR)szPathField, MAXPATHFIELD)) { EnableWindow(GetDlgItem(hwnd, IDD_RUN), TRUE); if (!bChangedDefaultButton) { SetDefButton(hwnd,IDD_RUN); bChangedDefaultButton = TRUE; } } else { EnableWindow(GetDlgItem(hwnd, IDD_RUN), FALSE); if (bChangedDefaultButton) { SetDefButton(hwnd,IDD_SWITCH); bChangedDefaultButton = FALSE; } } }
break;
case WM_COMMAND: switch(LOWORD(wParam)) {
case IDD_TASKLISTBOX:
switch(HIWORD(wParam)) {
case LBN_DBLCLK: HideTasklist(); ActivateSelectedWindow(hwndLB); break;
default: return FALSE; } break;
case IDD_PATH: PostMessage (hwnd, WM_CONTENTSCHANGED, 0, 0); break;
case IDOK: if (!bChangedDefaultButton) { goto Switchem; }
case IDD_RUN: if (fExecOK) { TCHAR szFilename[MAXPATHFIELD+4]; WORD ret;
GetDlgItemText(hwnd, IDD_PATH, szPathField, MAXPATHFIELD); DoEnvironmentSubst(szPathField, MAXPATHFIELD); GetDirectoryFromPath(szPathField, szDirField); if (*szDirField) { // Convert path into a .\foo.exe style thing.
lstrcpy(szFilename, L".\\"); // Tag the filename and params on to the end of the dot slash.
GetFilenameFromPath(szPathField, szFilename+2); if (*(szFilename+2) == L'"' ) { SheRemoveQuotes(szFilename+2); CheckEscapes(szFilename, ARRAYSIZE(szFilename)); } } else { GetFilenameFromPath(szPathField, szFilename); }
ret = ExecProgram(szFilename, szDirField, szFilename);
if (ret) { fMsgBox = TRUE; MyMessageBox( hwnd, IDS_EXECERRTITLE, ret, szPathField, MB_SYSTEMMODAL | MB_OK | MB_ICONEXCLAMATION ); fMsgBox = FALSE;
SetFocus(GetDlgItem(hwnd, IDD_PATH)); } else { GetDlgItemText(hwnd, IDD_PATH, szPathField, MAXPATHFIELD); SaveRecentFileList (hwnd, szPathField); HideWindow(hwnd); }
} break;
Switchem:
case IDD_SWITCH: HideTasklist(); ActivateSelectedWindow(hwndLB); break;
case IDCANCEL: HideWindow(hwnd); break;
case IDD_TERMINATE: /*
* Get the hwnd of the item which was selected. */ nIndex = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0); hwndNext = (HWND)SendMessage(hwndLB, LB_GETITEMDATA, nIndex, 0);
if (!IsWindow(hwndNext)) { HideWindow(hwnd); MessageBeep(0); break; }
#ifndef NTWIN /* Since NTWIN uses WM_ENDSESSION to kill the app,
* It is OK to kill it when it is disabled */ /*
* Test if the toplevel window is disabled. If it is * diabled, we don't want to send a WM_CLOSE message to * the parent. This is because the app could have a dialog * box up and it's not expecting a CLOSE message... * Nasty rips can happen... Instead, active the window so * that the user can dismis any dialog box or fix whatever * is causing the top level window to be disabled... */ lTemp = GetWindowLong(hwndNext, GWL_STYLE); if (lTemp & WS_DISABLED) { HideTasklist(); MessageBeep(0); ActivateSelectedWindow(hwndLB);
} else #endif
{ /* Always activate the window first. This prevents
* apps from going to Beep mode. Failing to do this * can cause re-entrancy problems in the app if we * do this again before activating the app. * * However, don't do this if it is a old app task. */
#ifdef WIN16 /* if NTWIN, then always do this, as is no winoldapp */
if (!IsWinoldapTask(GetTaskFromHwnd(hwndNext))) #endif
HideWindow(hwnd); ActivateSelectedWindow(hwndLB); #ifdef NTWIN
{ DWORD idt; HANDLE hThread;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CallEndTask, (LPVOID)hwndNext, 0, &idt);
if (hThread == NULL) { /*
* Can not create thread, just call EndTask * syncronously */ DoEndTask( hwndNext ); } else { CloseHandle(hThread); } } #else
EndTask(hwndNext, FALSE, FALSE); #endif
}
break;
case IDD_TILE: case IDD_CASCADE: { HWND hwndDesktop;
HideWindow(hwnd);
hwndDesktop = GetDesktopWindow();
if (wParam == IDD_CASCADE) { CascadeChildWindows(hwndDesktop, 0);
} else { /*
* If shift is down, tile vertically, else horizontally. */ TileChildWindows(hwndDesktop, ((GetKeyState(VK_SHIFT) & 0x8000) ? MDITILE_HORIZONTAL : MDITILE_VERTICAL)); } break; }
case IDD_ARRANGEICONS: /*
* Let's restore the saved bits before ArrangeIcons * FIX for Bug #4884; --SANKAR-- 10-02-89 */ HideWindow(hwnd); ArrangeIconicWindows(GetDesktopWindow()); break; }
break;
case WM_CLOSE: /*
* If wParam != 0, this is a shutdown request, so exit. */ if (wParam != 0) ExitProcess(0); return FALSE; break;
case WM_HOTKEY: if (wParam == 1) { pt.x = (dxScreen - dxTaskman) / 2; pt.y = (dyScreen - dyTaskman) / 2; ShowTasklist(pt); } break;
case WM_LOGOFF: PostQuitMessage(0); break;
default: return FALSE; }
return TRUE;
lParam; }
//*************************************************************
//
// SetDefButton()
//
// Purpose: Sets the default button
//
// Parameters: HWND hDlg - Window handle of dialog box
// INT idButton - ID of button
//
// Return: void
//
//*************************************************************
VOID SetDefButton(HWND hwndDlg, INT idButton) { LRESULT lr;
if (HIWORD(lr = SendMessage(hwndDlg, DM_GETDEFID, 0, 0)) == DC_HASDEFID) { HWND hwndOldDefButton = GetDlgItem(hwndDlg, LOWORD(lr));
SendMessage (hwndOldDefButton, BM_SETSTYLE, MAKEWPARAM(BS_PUSHBUTTON, 0), MAKELPARAM(TRUE, 0)); }
SendMessage( hwndDlg, DM_SETDEFID, idButton, 0L ); SendMessage( GetDlgItem(hwndDlg, idButton), BM_SETSTYLE, MAKEWPARAM( BS_DEFPUSHBUTTON, 0 ), MAKELPARAM( TRUE, 0 ));
}
/*** SaveRecentFileList -- Save the list of recently used files
* * void APIENTRY SaveRecentFileList (HWND hwnd, LPTSTR szCurrentFile); * * * * ENTRY - HWND hwnd - handle to dialog box. * LPTSTR szCurrentFile - pointer to selected filename * * EXIT - * SYNOPSIS - * * WARNINGS - * EFFECTS - * */
void APIENTRY SaveRecentFileList (HWND hwnd, LPTSTR szCurrentFile) { HKEY hKey; DWORD dwDisp; DWORD dwDataType, dwMaxFiles=INIT_MAX_FILES, dwMaxFilesSize, dwCount; TCHAR szFileEntry[20]; DWORD dwEnd=0; DWORD dwFileNum=0; DWORD dwDup; static TCHAR szRecentFilePath[MAXPATHFIELD+1];
//
// Open registry key
//
if ( RegCreateKeyEx (HKEY_CURRENT_USER, FILES_KEY, 0, 0, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp) != ERROR_SUCCESS) { return; }
//
// Query the max number of files to save first.
//
dwMaxFilesSize = sizeof (DWORD);
RegQueryValueEx (hKey, MAXFILES_ENTRY, NULL, &dwDataType, (LPBYTE)&dwMaxFiles, &dwMaxFilesSize);
//
// If the user request 0 entries, then exit now.
//
if (dwMaxFiles == 0) { RegCloseKey (hKey); return; }
//
// Find out how many items are in the list box.
//
dwEnd = (DWORD)SendDlgItemMessage (hwnd, IDD_PATH, CB_GETCOUNT, 0, 0);
//
// If the max number of items we want to save is less than the
// number of entries, then change the ending point.
//
if (dwMaxFiles < dwEnd) { dwEnd = dwMaxFiles; }
//
// Add the first entry (the current file)
//
wsprintf (szFileEntry, FILE_ENTRY, dwFileNum++); dwMaxFilesSize = MAXPATHFIELD+1;
RegSetValueEx (hKey, szFileEntry, 0, REG_SZ, (CONST BYTE *)szCurrentFile, sizeof (TCHAR) * (lstrlen (szCurrentFile)+1));
//
// Check for a duplicate string.
//
dwDup = (DWORD)SendDlgItemMessage (hwnd, IDD_PATH, CB_FINDSTRING, (WPARAM) -1, (LPARAM) szCurrentFile);
//
// If we already have dwMaxFiles in the list and we don't have any
// duplicates, then we only want to save dwMaxFiles - 1 entries
// (drop the last entry).
//
//
if ( (dwEnd == dwMaxFiles) && (dwDup == CB_ERR) ) { dwEnd--; }
//
// Now loop through the remaining entries
//
for (dwCount=0; dwCount < dwEnd; dwCount++) {
//
// Check to see if we are at the duplicate entry. If
// so skip on to the next item.
//
if ((dwDup != CB_ERR) && (dwCount == dwDup)) { continue; }
//
// Get an entry out of the listbox.
//
SendDlgItemMessage (hwnd, IDD_PATH, CB_GETLBTEXT, (WPARAM) dwCount, (LPARAM) szRecentFilePath);
//
// If we get a NULL string, break out of the loop.
//
if (!(*szRecentFilePath) || !szRecentFilePath) { break; }
//
// Build the entry name
//
wsprintf (szFileEntry, FILE_ENTRY, dwFileNum); dwMaxFilesSize = MAXPATHFIELD+1;
//
// Save the entry
//
RegSetValueEx (hKey, szFileEntry, 0, REG_SZ,(CONST BYTE *) szRecentFilePath, sizeof (TCHAR) * (lstrlen (szRecentFilePath)+1));
//
// Increment our current file number
//
dwFileNum++; }
//
// Close the key
//
RegCloseKey (hKey);
}
/*** Main -- Program entry point (was WinMain).
* * * * Main(int argc, char *argv[], char *envp[]) * * ENTRY - int argc - argument count. * char *argv[] - argument list. * char *envp[] - environment. * * EXIT - TRUE if success, FALSE if not. * SYNOPSIS - Parses command line, for position to place dialog box, if no * position (came from ctl/esc) then center on screen. * Also make sure only one instance of taskman. * * WARNINGS - * EFFECTS - */
INT __cdecl main( INT argc, CHAR *argv[], CHAR *envp[]) { MSG msg;
/*
* First set the priority of taskman so it is higher than foreground apps * that spin in loops - this way it'll always come up when you hit * ctrl-esc. */ hInst = GetModuleHandle(NULL);
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
{ //
// Set the working set size to 200k.
//
QUOTA_LIMITS QuotaLimits; NTSTATUS status;
status = NtQueryInformationProcess( NtCurrentProcess(), ProcessQuotaLimits, &QuotaLimits, sizeof(QUOTA_LIMITS), NULL ); if (NT_SUCCESS(status)) { QuotaLimits.MinimumWorkingSetSize = 300 * 1024; QuotaLimits.MaximumWorkingSetSize = 372 * 1024;
NtSetInformationProcess( NtCurrentProcess(), ProcessQuotaLimits, &QuotaLimits, sizeof(QUOTA_LIMITS) ); } }
/*
* Taskman will work in the windows directory, and switch to the * original directory (home directory) before execing programs. * This is to prevent weird popups if a UNC original directory is * disconnected. */
GetCurrentDirectory(MAXPATHFIELD, szUserHomeDir); GetWindowsDirectory(szWindowsDirectory, MAXPATHFIELD); SetCurrentDirectory(szWindowsDirectory);
fExecOK = OKToExec(); if (!IsUserAdmin() && !fExecOK) { ghwndDialog = CreateDialog(hInst, MAKEINTRESOURCE(WMPTASKMANDLG), NULL, TaskmanDlgProc); } else { ghwndDialog = CreateDialog(hInst, MAKEINTRESOURCE(PWRTASKMANDLG), NULL, TaskmanDlgProc); }
if (ghwndDialog == NULL) return 0;
LoadString(hInst, IDS_OOMEXITTITLE, szOOMExitTitle, 32); LoadString(hInst, IDS_OOMEXITMSG, szOOMExitMsg, 64);
if (!RegisterHotKey(ghwndDialog, 1, MOD_CONTROL, VK_ESCAPE) || !RegisterTasklist(ghwndDialog)) { goto exit; }
while (GetMessage(&msg, (HWND)NULL, (UINT)0, (UINT)0)) { if (!IsDialogMessage(ghwndDialog, &msg)) { if ((msg.message == WM_SYSCOMMAND) && (msg.wParam == SC_TASKLIST)) { POINT pt;
GetCursorPos(&pt); pt.x = max(pt.x - (dyTaskman / 2), 0); pt.x = min(pt.x, dxScreen - dxTaskman); pt.y = max(pt.y - (GetSystemMetrics(SM_CYCAPTION) * 2), 0); pt.y = min(pt.y, dyScreen - dyTaskman);
ShowTasklist(pt); } else {
//
// We need to have a regular message loop in order
// to handle the DDE messages generated by spawning
// an application via an association.
//
TranslateMessage (&msg); DispatchMessage (&msg); }
} }
exit: DestroyWindow(ghwndDialog); return 0;
argc; argv; envp; }
WORD APIENTRY ExecProgram( LPTSTR lpszPath, LPTSTR lpDir, LPTSTR lpTitle ) { WORD ret; HCURSOR hCursor; LPTSTR lpP; TCHAR cSeparator; TCHAR lpReservedFormat[] = TEXT("dde.%d,hotkey.%d"); TCHAR lpReserved[100]; // used for DDE request of icons from console apps
// add for passing the hotkey associated with an item.
HANDLE hProcess;
ret = 0;
/*
* Set the current directory to the user's home directory if possible. */ SetCurrentDirectory(szUserHomeDir);
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
/* Don't mess with the mouse state; unless we're on a mouseless system.
*/ if (!GetSystemMetrics(SM_MOUSEPRESENT)) ShowCursor(TRUE);
/* skip leading spaces
*/ while (*lpszPath == TEXT(' ')) lpszPath++;
/* skip past path
*/ lpP = lpszPath; if (*lpszPath == TEXT('"')) { cSeparator = TEXT('"'); lpP++; } else { cSeparator = TEXT(' '); }
for (; *lpP && *lpP != cSeparator; lpP = CharNext(lpP)) ; if (*lpP == TEXT('"')) { lpP++; }
/* if stuff on end, separate it
*/ if (*lpP) *lpP++ = 0;
/* Try to exec 'szCommandLine'. */
/*changed order, since wPendINstance is a 32b HANDLE, and ret is WORD*/ if (!lpP) lpP = TEXT("");
wsprintf(lpReserved, lpReservedFormat, 0, 0);
ret = (WORD)RealShellExecute(ghwndDialog, NULL, lpszPath, lpP, lpDir, NULL, lpTitle, lpReserved, (WORD)SW_SHOWNORMAL, &hProcess);
/*BUG BUG these are DOS exec function return codes, no map yet to NT return codes!*/ switch (ret) { case 0: case SE_ERR_OOM: // 8
ret = IDS_NOMEMORYMSG; break;
case SE_ERR_FNF: // 2
ret = IDS_FILENOTFOUNDMSG; break;
case SE_ERR_PNF: // 3
ret = IDS_BADPATHMSG; break;
case 4: ret = IDS_MANYOPENFILESMSG; break;
case 5: ret = IDS_ACCESSDENIED; break;
case 10: ret = IDS_NEWWINDOWSMSG; break;
case 12: ret = IDS_OS2APPMSG; break;
case 15: /* KERNEL has already put up a messagebox for this one. */ ret = 0; break;
case 16: ret = IDS_MULTIPLEDSMSG; break;
case 18: ret = IDS_PMODEONLYMSG; break;
case 19: ret = IDS_COMPRESSEDEXE; break;
case 20: ret = IDS_INVALIDDLL; break;
case SE_ERR_SHARE: ret = IDS_SHAREERROR; break;
case SE_ERR_ASSOCINCOMPLETE: ret = IDS_ASSOCINCOMPLETE; break;
case SE_ERR_DDETIMEOUT: case SE_ERR_DDEFAIL: case SE_ERR_DDEBUSY: ret = IDS_DDEFAIL; break;
case SE_ERR_NOASSOC: ret = IDS_NOASSOCMSG; break;
default: ret = 0; break; }
if (!GetSystemMetrics(SM_MOUSEPRESENT)) { /*
* We want to turn the mouse off here on mouseless systems, but * the mouse will already have been turned off by USER if the * app has GP'd so make sure everything's kosher. */ if (ShowCursor(FALSE) != -1) ShowCursor(TRUE); }
SetCursor(hCursor);
/*
* Reset the working directory to the windows directory. */ SetCurrentDirectory(szWindowsDirectory);
return(ret); }
VOID GetDirectoryFromPath( PTSTR szFilePath, PTSTR szDir) { PTSTR pFileName; PTSTR pExt; WORD ich; BOOL fUnc;
*szDir = TEXT('\0');
/* Get info about file path. */ GetPathInfo(szFilePath, &pFileName, &pExt, &ich, &fUnc);
/* UNC paths don't (conceptually to Progman) have a directory component. */ if (fUnc) return;
/* Does it have a directory component ? */ if (pFileName != szFilePath) { // Yep.
/* copy path to temp. */ if (*szFilePath == TEXT('"')) { szFilePath++; } lstrcpy(szDir, szFilePath); /* check path style. */ if (ich <= 3 && *(szDir+1) == TEXT(':')) { /*
* The path is "c:\foo.c" or "c:foo.c" style. * Don't remove the last slash/colon, just the filename. */ szDir[pFileName-szFilePath] = TEXT('\0'); }
else if (ich == 1) { /*
* something like "\foo.c" * Don't remove the last slash/colon, just the filename. */ szDir[pFileName-szFilePath] = TEXT('\0'); } else { /*
* The filepath is a full normal path. * Could be something like "..\foo.c" or ".\foo.c" though. * Stomp on the last slash to get just the path. */ szDir[pFileName-szFilePath-1] = TEXT('\0'); } }
/* else just a filename with no path. */ }
VOID GetFilenameFromPath( PTSTR szPath, PTSTR szFilename) { DWORD dummy; PTSTR pFileName; BOOL fUNC;
GetPathInfo(szPath, &pFileName, (PTSTR*) &dummy, (WORD*) &dummy, &fUNC);
/* If it's a UNC then the 'filename' part is the whole thing. */ if (fUNC || (szPath == pFileName)) lstrcpy(szFilename, szPath); else { if (*szPath == TEXT('"')) { *szFilename++ = TEXT('"'); } lstrcpy(szFilename, pFileName); } }
VOID GetPathInfo( PTSTR szPath, PTSTR *pszFileName, PTSTR *pszExt, WORD *pich, BOOL *pfUnc) { TCHAR *pch; // Temp variable.
WORD ich = 0; // Temp.
BOOL InQuotes;
*pszExt = NULL; // If no extension, return NULL.
*pszFileName = szPath; // If no seperate filename component, return path.
*pich = 0; *pfUnc = FALSE; // Default to not UNC style.
//
// Check if path is in quotes.
//
if (InQuotes = (*szPath == TEXT('"'))) { szPath++; }
// Check for UNC style paths.
if (*szPath == TEXT('\\') && *(szPath+1) == TEXT('\\')) *pfUnc = TRUE;
// Search forward to find the last backslash or colon in the path.
// While we're at it, look for the last dot.
for (pch = szPath; *pch; pch = CharNext(pch)) {
if ((*pch == TEXT(' ')) && (!InQuotes)) { // Found a space - stop here.
break; } if (*pch == TEXT('"')) { // Found a the second quote - stop here.
pch++; break; } if (*pch == TEXT('\\') || *pch == TEXT(':')) { // Found it, record ptr to it and it's index.
*pszFileName = pch+1; *pich = ich + (WORD)1; } if (*pch == TEXT('.')) { // Found a dot.
*pszExt = pch; } ich++; }
/* Check that the last dot is part of the last filename. */ if (*pszExt < *pszFileName) *pszExt = NULL; }
BOOL IsUserAdmin() { BOOL UserIsAdmin = FALSE; HANDLE Token; PSID AdminAliasSid = NULL; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
//
// Get the token of the current process.
//
if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &Token) ) { return(FALSE); }
UserIsAdmin = TestTokenForAdmin(Token);
CloseHandle(Token);
return(UserIsAdmin); }
BOOL TestTokenForAdmin( HANDLE Token ) { NTSTATUS Status; DWORD InfoLength; PTOKEN_GROUPS TokenGroupList; DWORD GroupIndex; PSID AdminSid; BOOL FoundAdmin; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
//
// Get a list of groups in the token
//
Status = NtQueryInformationToken( Token, // Handle
TokenGroups, // TokenInformationClass
NULL, // TokenInformation
0, // TokenInformationLength
&InfoLength // ReturnLength
);
if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_TOO_SMALL)) { return(FALSE); }
TokenGroupList = Alloc(InfoLength);
if (TokenGroupList == NULL) { return(FALSE); }
Status = NtQueryInformationToken( Token, // Handle
TokenGroups, // TokenInformationClass
TokenGroupList, // TokenInformation
InfoLength, // TokenInformationLength
&InfoLength // ReturnLength
);
if (!NT_SUCCESS(Status)) { LocalFree(TokenGroupList); return(FALSE); }
//
// Create the admin sid
//
Status = RtlAllocateAndInitializeSid( &SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
if (!NT_SUCCESS(Status)) { Free(TokenGroupList); return(FALSE); }
//
// Search group list for admin alias
//
FoundAdmin = FALSE;
for (GroupIndex=0; GroupIndex < TokenGroupList->GroupCount; GroupIndex++ ) { if (RtlEqualSid(TokenGroupList->Groups[GroupIndex].Sid, AdminSid)) { FoundAdmin = TRUE; break; } }
//
// Tidy up
//
RtlFreeSid(AdminSid); Free(TokenGroupList);
return(FoundAdmin); }
BOOL OKToExec() { TCHAR szRestrict[] = TEXT("Restrictions"); TCHAR szProgramManager[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager"); HKEY hkeyProgramManager = NULL; // progman.ini key
HKEY hkeyPMRestrict = NULL; DWORD cbData, dwType; BOOL fNoRun = FALSE;
/*
* Create/Open the registry keys corresponding to progman.ini sections. */ if (!RegCreateKeyEx(HKEY_CURRENT_USER, szProgramManager, 0, szProgramManager, 0, KEY_READ | KEY_WRITE, NULL, &hkeyProgramManager, NULL)) {
RegCreateKeyEx(hkeyProgramManager, szRestrict, 0, szProgramManager, 0, KEY_READ, NULL, &hkeyPMRestrict, NULL);
} else { return(FALSE); }
if (hkeyPMRestrict) { cbData = sizeof(fNoRun); RegQueryValueEx(hkeyPMRestrict, szNoRun, 0, &dwType, (LPBYTE)&fNoRun, &cbData); }
if (hkeyPMRestrict) { RegCloseKey(hkeyPMRestrict); hkeyPMRestrict = NULL; }
RegCloseKey(hkeyProgramManager);
return(!fNoRun);
}
INT MyMessageBox( HWND hWnd, WORD idTitle, WORD idMessage, PWSTR psz, WORD wStyle) { WCHAR szTempField[MAXMSGBOXLEN]; INT iMsgResult;
if (!LoadString(hInst, idTitle, szTitle, ARRAYSIZE(szTitle))){ goto MessageBoxOOM; } if (idMessage < 32){ if (!LoadString(hInst, IDS_UNKNOWNMSG, szTempField, ARRAYSIZE(szTempField))){ goto MessageBoxOOM; } wsprintf(szMessage, szTempField, idMessage); } else{ if (!LoadString(hInst, idMessage, szTempField, ARRAYSIZE(szTempField))) goto MessageBoxOOM;
if (psz) { wsprintf(szMessage, szTempField, (LPTSTR)psz); } else lstrcpy(szMessage, szTempField); }
iMsgResult = MessageBox(hWnd, szMessage, szTitle, wStyle );
if (iMsgResult == -1){
MessageBoxOOM: MessageBox(hWnd, szOOMExitMsg, szOOMExitTitle, MB_SYSTEMMODAL | MB_ICONHAND | MB_OK); }
return(iMsgResult); }
|