Index: base/applications/taskmgr/CMakeLists.txt =================================================================== --- base/applications/taskmgr/CMakeLists.txt (revision 65470) +++ base/applications/taskmgr/CMakeLists.txt (working copy) @@ -23,6 +23,6 @@ add_executable(taskmgr ${SOURCE} taskmgr.rc) set_module_type(taskmgr win32gui UNICODE) -add_importlibs(taskmgr advapi32 user32 gdi32 shell32 shlwapi comctl32 msvcrt kernel32 ntdll) +add_importlibs(taskmgr advapi32 user32 gdi32 shell32 shlwapi comctl32 msvcrt kernel32 ntdll psapi) add_pch(taskmgr precomp.h SOURCE) add_cd_file(TARGET taskmgr DESTINATION reactos/system32 FOR all) Index: base/applications/taskmgr/endproc.c =================================================================== --- base/applications/taskmgr/endproc.c (revision 65470) +++ base/applications/taskmgr/endproc.c (working copy) @@ -3,8 +3,9 @@ * * endproc.c * - * Copyright (C) 1999 - 2001 Brian Palmer - * 2005 Klemens Friedl + * Copyright (C) 1999 - 2001 Brian Palmer + * 2005 Klemens Friedl + * 2014 Ismael Ferreras Morezuelas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +23,8 @@ */ #include "precomp.h" +#include +#include void ProcessPage_OnEndProcess(void) { @@ -35,31 +38,196 @@ if (dwProcessId == 0) return; + hProcess = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId); + + /* forbid killing system processes even if we have privileges -- sigh, windows kludge! */ + if (hProcess && IsSystemProcess(hProcess)) + { + LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256); + LoadStringW(hInst, IDS_MSG_CLOSESYSTEMPROCESS, strErrorText, 256); + MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONWARNING|MB_TOPMOST); + return; + } + + /* if this is a standard process just ask for confirmation before doing it */ LoadStringW(hInst, IDS_MSG_WARNINGTERMINATING, strErrorText, 256); LoadStringW(hInst, IDS_MSG_TASKMGRWARNING, szTitle, 256); - if (MessageBoxW(hMainWnd, strErrorText, szTitle, MB_YESNO|MB_ICONWARNING) != IDYES) + if (MessageBoxW(hMainWnd, strErrorText, szTitle, MB_YESNO|MB_ICONWARNING|MB_TOPMOST) != IDYES) return; - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); - + /* no such process or not enough privileges to open its token */ if (!hProcess) { GetLastErrorText(strErrorText, 260); LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256); - MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP); + MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP|MB_TOPMOST); return; } + /* try to kill it, and notify the user if didn't work */ if (!TerminateProcess(hProcess, 1)) { GetLastErrorText(strErrorText, 260); LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256); - MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP); + MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP|MB_TOPMOST); } CloseHandle(hProcess); } +BOOL IsSystemProcess(HANDLE hProcess) +{ + static const LPWSTR pDosPrefixSymbol = L"\\??\\"; + static const LPWSTR pSystemRootPrefix = L"\\SystemRoot\\System32\\"; + + DWORD result; + + HANDLE hProcessf; + HANDLE hSystem32; + + BY_HANDLE_FILE_INFORMATION bhfiProcessPath = {0}; + BY_HANDLE_FILE_INFORMATION bhfiSystem32 = {0}; + + WCHAR szProcessFilename[MAX_PATH] = {0}; + WCHAR szProcessPath[MAX_PATH] = {0}; + WCHAR szProcessTmp[MAX_PATH] = {0}; + WCHAR szSystem32[MAX_PATH] = {0}; + + LPWSTR pFilename = NULL; + LPWSTR pPrefix = NULL; + UINT i; + + static const LPWSTR system_process_list[5] = + { + L"smss.exe", + L"csrss.exe", + L"winlogon.exe", + L"services.exe", + L"lsass.exe", + }; + + static const UINT system_process_count = sizeof(system_process_list) / sizeof(system_process_list[0]); + + + + /* return early if the process handle does not exist */ + if (!hProcess) + return FALSE; + + /* get the path to %windir%\system32 to compare against later */ + GetSystemDirectoryW(szSystem32, sizeof(szSystem32)); + + /* retrieve the full path to that process' executable */ + result = GetModuleFileNameExW(hProcess, + NULL, + szProcessTmp, + sizeof(szProcessTmp)); + + if (!result) + return FALSE; + + /* remove the damn broken DOS \??\ prefix manually, + for lack of a better alternative */ + + /* Quoting from Windows Internals (Page 147 in 4th edition): + + "Windows subsystem DLLs prefix names passed by Windows + applications that reference objects in \DosDevices with \?? + (for example, C:\Windows becomes \??\C:\Windows)." */ + + pPrefix = wcsstr(szProcessTmp, pDosPrefixSymbol); + + if (pPrefix && (szProcessTmp - pPrefix) == 0) + { + pPrefix += wcslen(pDosPrefixSymbol); + wcscpy(szProcessPath, pPrefix); + } + else + { + wcscpy(szProcessPath, szProcessTmp); + } + + /* do more of the same for the \SystemRoot\System32\ in smss.exe */ + pPrefix = wcsstr(szProcessTmp, pSystemRootPrefix); + + if (pPrefix && (szProcessTmp - pPrefix) == 0) + { + pPrefix += wcslen(pSystemRootPrefix); + wsprintf(szProcessPath, L"%s\\%s", szSystem32, pPrefix); + } + + /* get the filename portion of the fixed process path and store it for later */ + pFilename = PathFindFileNameW(szProcessPath); + + if(!pFilename) + return FALSE; + + wcscpy(szProcessFilename, pFilename); + + /* get rid of the filename part, leaving just the bare folder */ + PathRemoveFileSpecW(szProcessPath); + + if (!result) + return FALSE; + + /* open a handle to both folders and let's proceed to compare them */ + hSystem32 = CreateFileW(szSystem32, + 0, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + hProcessf = CreateFileW(szProcessPath, + 0, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if (hSystem32 == INVALID_HANDLE_VALUE || hProcessf == INVALID_HANDLE_VALUE) + return FALSE; + + + /* the best way to compare two files (or folders) is to see if their file system index is identical */ + result = GetFileInformationByHandle(hProcessf, &bhfiProcessPath); + + if (!result) + return FALSE; + + CloseHandle(hProcessf); + + + result = GetFileInformationByHandle(hSystem32, &bhfiSystem32); + + if (!result) + return FALSE; + + CloseHandle(hSystem32); + + + /* is that the same as %windir%\system32? if not... just bail out */ + if (bhfiSystem32.dwVolumeSerialNumber != bhfiProcessPath.dwVolumeSerialNumber || + bhfiSystem32.nFileIndexHigh != bhfiProcessPath.nFileIndexHigh || + bhfiSystem32.nFileIndexLow != bhfiProcessPath.nFileIndexLow) + { + return FALSE; + } + + /* finally, is this one of those uglily hardcoded executables? if so, it's one of us! */ + for (i=0;i