1638 lines
42 KiB
C
1638 lines
42 KiB
C
/*++
|
|
|
|
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);
|
|
}
|