Reactos

Implement Utility Manager software

CORE-15974

authored by

Bișoc George and committed by
Mark Jansen
df88ea8d cb77f170

+956
+1
base/applications/CMakeLists.txt
··· 39 39 add_subdirectory(sndrec32) 40 40 add_subdirectory(sndvol32) 41 41 add_subdirectory(taskmgr) 42 + add_subdirectory(utilman) 42 43 add_subdirectory(winhlp32) 43 44 add_subdirectory(winver) 44 45 add_subdirectory(wordpad)
+13
base/applications/utilman/CMakeLists.txt
··· 1 + 2 + list(APPEND SOURCE 3 + dialog.c 4 + process.c 5 + about.c 6 + precomp.h) 7 + 8 + add_rc_deps(utilman.rc ${CMAKE_CURRENT_SOURCE_DIR}/res/utilman.ico) 9 + add_executable(utilman ${SOURCE} utilman.rc) 10 + set_module_type(utilman win32gui UNICODE) 11 + add_importlibs(utilman comdlg32 user32 gdi32 advapi32 shell32 comctl32 msvcrt kernel32 ntdll) 12 + add_pch(utilman precomp.h SOURCE) 13 + add_cd_file(TARGET utilman DESTINATION reactos/system32 FOR all)
+11
base/applications/utilman/NOTES.txt
··· 1 + ReactOS Accessibility Utility Manager 2 + ======================================= 3 + 4 + Currently the application can manage the state of the accessibility tools however there are some things which needs to be DONE in order to consider the program as fully complete. The following are: 5 + 6 + - The warning dialog is not implemented YET 7 + - The program can only control the launch/stopping states of accessibility tools, the code which manages the options for each utility is not implemented YET 8 + - Function helper which catches the Windows logo + U keys is not implemented YET 9 + - Registry configuration saver/loader is not implemented YET (XP's Utility Manager creates a key on HKEY_CURRENT_USER\Software\Microsoft with the name "Utility Manager" although the rest of other configuration values for utility options are stored elsewhere and I don't know exactly where are those) 10 + - XP's and Server 2003's main Utility Manager implementation is compiled in a DLL (+ an executable which loads the DLL in question) whereas our Utility Manager is compiled as a whole executable 11 + - On Windows Vista and later, it complains for required elevation to open a process. We need to improve our process creation code and discard ShellExecuteW()
+93
base/applications/utilman/about.c
··· 1 + /* 2 + * PROJECT: ReactOS Utility Manager (Accessibility) 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: About dialog file 5 + * COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com) 6 + */ 7 + 8 + /* INCLUDES *******************************************************************/ 9 + 10 + #include "precomp.h" 11 + 12 + /* GLOBALS ********************************************************************/ 13 + 14 + UTILMAN_GLOBALS Globals; 15 + 16 + /* FUNCTIONS ******************************************************************/ 17 + 18 + /** 19 + * @AboutDlgProc 20 + * 21 + * "About" dialog procedure. 22 + * 23 + * @param hDlg 24 + * The handle object of the dialog. 25 + * 26 + * @param Msg 27 + * Message events (in unsigned int). 28 + * 29 + * @param wParam 30 + * Message parameter (in UINT_PTR). 31 + * 32 + * @param lParam 33 + * Message paramater (in LONG_PTR). 34 + * 35 + * @return 36 + * Return TRUE if the dialog processed messages, 37 + * FALSE otherwise. 38 + * 39 + */ 40 + INT_PTR CALLBACK AboutDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) 41 + { 42 + switch (Msg) 43 + { 44 + case WM_INITDIALOG: 45 + { 46 + Globals.hIcon = LoadImageW(Globals.hInstance, 47 + MAKEINTRESOURCEW(IDI_ICON_UTILMAN), 48 + IMAGE_ICON, 49 + 0, 50 + 0, 51 + LR_DEFAULTSIZE); 52 + 53 + /* Set the icon within the dialog's title bar */ 54 + if (Globals.hIcon) 55 + { 56 + SendMessageW(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Globals.hIcon); 57 + } 58 + 59 + return TRUE; 60 + } 61 + 62 + case WM_COMMAND: 63 + { 64 + case IDOK: 65 + case IDCANCEL: 66 + DestroyIcon(Globals.hIcon); 67 + EndDialog(hDlg, FALSE); 68 + break; 69 + } 70 + } 71 + 72 + return FALSE; 73 + } 74 + 75 + /** 76 + * @ShowAboutDlg 77 + * 78 + * Display the "About" dialog. 79 + * 80 + * @param hDlgParent 81 + * The handle object of the parent dialog. 82 + * 83 + * @return 84 + * Nothing. 85 + */ 86 + VOID ShowAboutDlg(HWND hDlgParent) 87 + { 88 + /* Display the "About" dialog when the user clicks on the "About" menu item */ 89 + DialogBoxW(Globals.hInstance, 90 + MAKEINTRESOURCEW(IDD_ABOUT_DIALOG), 91 + hDlgParent, 92 + AboutDlgProc); 93 + }
+438
base/applications/utilman/dialog.c
··· 1 + /* 2 + * PROJECT: ReactOS Utility Manager (Accessibility) 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Main dialog code file 5 + * COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com) 6 + * Copyright 2019 Hermes Belusca-Maito 7 + */ 8 + 9 + /* INCLUDES *******************************************************************/ 10 + 11 + #include "precomp.h" 12 + 13 + /* GLOBALS ********************************************************************/ 14 + 15 + UTILMAN_GLOBALS Globals; 16 + 17 + /* DECLARATIONS ***************************************************************/ 18 + 19 + UTILMAN_STATE EntriesList[] = 20 + { 21 + {L"magnify.exe", IDS_MAGNIFIER, L"", FALSE}, 22 + {L"osk.exe", IDS_OSK, L"", FALSE} 23 + }; 24 + 25 + /* FUNCTIONS ******************************************************************/ 26 + 27 + /** 28 + * @InitUtilsList 29 + * 30 + * Initializes the list of accessibility utilities. 31 + * 32 + * @param[in] bInitGui 33 + * Whether we are initializing the UI list (TRUE) or the internal array (FALSE). 34 + * 35 + * @return 36 + * Nothing. 37 + */ 38 + VOID InitUtilsList(BOOL bInitGui) 39 + { 40 + UINT i; 41 + 42 + if (!bInitGui) 43 + { 44 + // TODO: Load the list dynamically from the registry key 45 + // hklm\software\microsoft\windows nt\currentversion\accessibility 46 + 47 + /* Initialize the resource utility strings only once */ 48 + for (i = 0; i < _countof(EntriesList); ++i) 49 + { 50 + LoadStringW(Globals.hInstance, EntriesList[i].uNameId, 51 + EntriesList[i].szResource, _countof(EntriesList[i].szResource)); 52 + 53 + EntriesList[i].bState = FALSE; 54 + } 55 + } 56 + else 57 + { 58 + INT iItem; 59 + BOOL bIsRunning; 60 + WCHAR szFormat[MAX_BUFFER]; 61 + 62 + /* Reset the listbox */ 63 + SendMessageW(Globals.hListDlg, LB_RESETCONTENT, 0, 0); 64 + 65 + /* Add the utilities in the listbox */ 66 + for (i = 0; i < _countof(EntriesList); ++i) 67 + { 68 + bIsRunning = IsProcessRunning(EntriesList[i].lpProgram); 69 + EntriesList[i].bState = bIsRunning; 70 + 71 + /* Load the string and append the utility's name to the format */ 72 + StringCchPrintfW(szFormat, _countof(szFormat), 73 + (bIsRunning ? Globals.szRunning : Globals.szNotRunning), 74 + EntriesList[i].szResource); 75 + 76 + /* Add the item in the listbox */ 77 + iItem = (INT)SendMessageW(Globals.hListDlg, LB_ADDSTRING, 0, (LPARAM)szFormat); 78 + if (iItem != LB_ERR) 79 + SendMessageW(Globals.hListDlg, LB_SETITEMDATA, iItem, (LPARAM)&EntriesList[i]); 80 + } 81 + } 82 + } 83 + 84 + /** 85 + * @DlgInitHandler 86 + * 87 + * Function which processes several operations for WM_INITDIALOG. 88 + * 89 + * @param[in] hDlg 90 + * The handle object of the dialog. 91 + * 92 + * @return 93 + * TRUE to inform the system that WM_INITDIALOG has been processed and 94 + * that it should set the keyboard focus to the control. 95 + * 96 + */ 97 + BOOL DlgInitHandler(IN HWND hDlg) 98 + { 99 + INT PosX, PosY; 100 + RECT rc; 101 + WCHAR szAboutDlg[MAX_BUFFER]; 102 + HMENU hSysMenu; 103 + 104 + /* Save the dialog handle */ 105 + Globals.hMainDlg = hDlg; 106 + 107 + /* Center the dialog on the screen */ 108 + GetWindowRect(hDlg, &rc); 109 + PosX = (GetSystemMetrics(SM_CXSCREEN) - rc.right) / 2; 110 + PosY = (GetSystemMetrics(SM_CYSCREEN) - rc.bottom) / 2; 111 + SetWindowPos(hDlg, 0, PosX, PosY, 0, 0, SWP_NOZORDER | SWP_NOSIZE); 112 + 113 + /* Load the icon resource */ 114 + Globals.hIcon = LoadImageW(Globals.hInstance, 115 + MAKEINTRESOURCEW(IDI_ICON_UTILMAN), 116 + IMAGE_ICON, 117 + 0, 118 + 0, 119 + LR_DEFAULTSIZE); 120 + 121 + /* Set the icon within the dialog's title bar */ 122 + if (Globals.hIcon) 123 + { 124 + SendMessageW(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Globals.hIcon); 125 + } 126 + 127 + /* Retrieve the system menu and append the "About" menu item onto it */ 128 + hSysMenu = GetSystemMenu(hDlg, FALSE); 129 + if (hSysMenu != NULL) 130 + { 131 + if (LoadStringW(Globals.hInstance, IDM_ABOUT, szAboutDlg, _countof(szAboutDlg))) 132 + { 133 + AppendMenuW(hSysMenu, MF_SEPARATOR, 0, NULL); 134 + AppendMenuW(hSysMenu, MF_STRING, IDM_ABOUT, szAboutDlg); 135 + } 136 + } 137 + 138 + /* Get the dialog items, specifically the dialog list box, the Start and Stop buttons */ 139 + Globals.hListDlg = GetDlgItem(hDlg, IDC_LISTBOX); 140 + Globals.hDlgCtlStart = GetDlgItem(hDlg, IDC_START); 141 + Globals.hDlgCtlStop = GetDlgItem(hDlg, IDC_STOP); 142 + 143 + /* Initialize the GUI listbox */ 144 + InitUtilsList(TRUE); 145 + 146 + /* Set the selection to the first item */ 147 + Globals.iSelectedIndex = 0; 148 + 149 + /* Refresh the list */ 150 + ListBoxRefreshContents(); 151 + 152 + /* Create a timer, we'll use it to control the state of our items in the listbox */ 153 + Globals.iTimer = SetTimer(hDlg, 0, 400, NULL); 154 + 155 + return TRUE; 156 + } 157 + 158 + /** 159 + * @GroupBoxUpdateTitle 160 + * 161 + * Updates the title of the groupbox. 162 + * 163 + * @return 164 + * Nothing. 165 + * 166 + */ 167 + VOID GroupBoxUpdateTitle(VOID) 168 + { 169 + WCHAR szFormat[MAX_BUFFER]; 170 + 171 + /* Format the string with the utility's name and set it to the listbox's title */ 172 + StringCchPrintfW(szFormat, _countof(szFormat), Globals.szGrpBoxTitle, EntriesList[Globals.iSelectedIndex].szResource); 173 + SetWindowTextW(GetDlgItem(Globals.hMainDlg, IDC_GROUPBOX), szFormat); 174 + } 175 + 176 + /** 177 + * @UpdateUtilityState 178 + * 179 + * Checks the state of the given accessibility tool. 180 + * 181 + * @param[in] bUtilState 182 + * State condition (boolean TRUE: started / FALSE: stopped). 183 + * 184 + * @return 185 + * Nothing. 186 + * 187 + */ 188 + VOID UpdateUtilityState(IN BOOL bUtilState) 189 + { 190 + Button_Enable(Globals.hDlgCtlStart, !bUtilState); 191 + Button_Enable(Globals.hDlgCtlStop, bUtilState); 192 + 193 + /* Update the groupbox's title based on the selected utility item */ 194 + GroupBoxUpdateTitle(); 195 + } 196 + 197 + /** 198 + * @ListBoxRefreshContents 199 + * 200 + * Handle the tasks on a periodic cycle. This function handles WM_TIMER message. 201 + * 202 + * @return 203 + * Returns 0 to inform the system that WM_TIMER has been processed. 204 + * 205 + */ 206 + INT ListBoxRefreshContents(VOID) 207 + { 208 + UINT i; 209 + INT iItem; 210 + BOOL bIsRunning; 211 + WCHAR szFormat[MAX_BUFFER]; 212 + 213 + /* Disable listbox redraw */ 214 + SendMessageW(Globals.hListDlg, WM_SETREDRAW, FALSE, 0); 215 + 216 + for (i = 0; i < _countof(EntriesList); ++i) 217 + { 218 + /* Check the utility's state */ 219 + bIsRunning = IsProcessRunning(EntriesList[i].lpProgram); 220 + if (bIsRunning != EntriesList[i].bState) 221 + { 222 + /* The utility's state has changed, save it */ 223 + EntriesList[i].bState = bIsRunning; 224 + 225 + /* Update the corresponding item in the listbox */ 226 + StringCchPrintfW(szFormat, _countof(szFormat), 227 + (bIsRunning ? Globals.szRunning : Globals.szNotRunning), 228 + EntriesList[i].szResource); 229 + 230 + SendMessageW(Globals.hListDlg, LB_DELETESTRING, (LPARAM)i, 0); 231 + iItem = SendMessageW(Globals.hListDlg, LB_INSERTSTRING, (LPARAM)i, (LPARAM)szFormat); 232 + if (iItem != LB_ERR) 233 + SendMessageW(Globals.hListDlg, LB_SETITEMDATA, iItem, (LPARAM)&EntriesList[i]); 234 + } 235 + } 236 + 237 + /* Re-enable listbox redraw */ 238 + SendMessageW(Globals.hListDlg, WM_SETREDRAW, TRUE, 0); 239 + 240 + /* 241 + * Check the previously selected item. This will help us determine what 242 + * item has been selected and set its focus selection back. Furthermore, check 243 + * the state of each accessibility tool and enable/disable the buttons. 244 + */ 245 + SendMessageW(Globals.hListDlg, LB_SETCURSEL, (WPARAM)Globals.iSelectedIndex, 0); 246 + UpdateUtilityState(EntriesList[Globals.iSelectedIndex].bState); 247 + 248 + return 0; 249 + } 250 + 251 + /** 252 + * @DlgProc 253 + * 254 + * Main dialog application procedure function. 255 + * 256 + * @param[in] hDlg 257 + * The handle object of the dialog. 258 + * 259 + * @param[in] Msg 260 + * Message events (in unsigned int). 261 + * 262 + * @param[in] wParam 263 + * Message parameter (in UINT_PTR). 264 + * 265 + * @param[in] lParam 266 + * Message paramater (in LONG_PTR). 267 + * 268 + * @return 269 + * Returns 0 to inform the system that the procedure has been handled. 270 + * 271 + */ 272 + INT_PTR APIENTRY DlgProc( 273 + IN HWND hDlg, 274 + IN UINT Msg, 275 + IN WPARAM wParam, 276 + IN LPARAM lParam) 277 + { 278 + switch (Msg) 279 + { 280 + case WM_INITDIALOG: 281 + DlgInitHandler(hDlg); 282 + return TRUE; 283 + 284 + case WM_CLOSE: 285 + KillTimer(hDlg, Globals.iTimer); 286 + DestroyIcon(Globals.hIcon); 287 + EndDialog(hDlg, FALSE); 288 + break; 289 + 290 + case WM_COMMAND: 291 + { 292 + switch (LOWORD(wParam)) 293 + { 294 + case IDC_OK: 295 + case IDC_CANCEL: 296 + EndDialog(hDlg, FALSE); 297 + break; 298 + 299 + case IDC_LISTBOX: 300 + { 301 + switch (HIWORD(wParam)) 302 + { 303 + case LBN_SELCHANGE: 304 + { 305 + /* Retrieve the index of the current selected item */ 306 + INT iIndex = SendMessageW(Globals.hListDlg, LB_GETCURSEL, 0, 0); 307 + if ((iIndex == LB_ERR) || (iIndex >= _countof(EntriesList))) 308 + break; 309 + 310 + /* Assign the selected index and check the utility's state */ 311 + Globals.iSelectedIndex = iIndex; 312 + UpdateUtilityState(EntriesList[Globals.iSelectedIndex].bState); 313 + break; 314 + } 315 + break; 316 + } 317 + break; 318 + } 319 + 320 + case IDC_START: 321 + LaunchProcess(EntriesList[Globals.iSelectedIndex].lpProgram); 322 + break; 323 + 324 + case IDC_STOP: 325 + CloseProcess(EntriesList[Globals.iSelectedIndex].lpProgram); 326 + break; 327 + 328 + default: 329 + break; 330 + } 331 + break; 332 + } 333 + 334 + case WM_TIMER: 335 + ListBoxRefreshContents(); 336 + return 0; 337 + 338 + case WM_SYSCOMMAND: 339 + { 340 + switch (LOWORD(wParam)) 341 + { 342 + case IDM_ABOUT: 343 + ShowAboutDlg(hDlg); 344 + break; 345 + } 346 + break; 347 + } 348 + } 349 + 350 + return 0; 351 + } 352 + 353 + /** 354 + * @wWinMain 355 + * 356 + * Application entry point. 357 + * 358 + * @param[in] hInstance 359 + * Application instance. 360 + * 361 + * @param[in] hPrevInstance 362 + * The previous instance of the application (not used). 363 + * 364 + * @param[in] pCmdLine 365 + * Pointer to a command line argument (in wide string -- not used). 366 + * 367 + * @param[in] nCmdShow 368 + * An integer served as a flag to note how the application will be shown (not used). 369 + * 370 + * @return 371 + * Returns 0 to let the function terminating before it enters in the message loop. 372 + * 373 + */ 374 + INT WINAPI wWinMain( 375 + IN HINSTANCE hInstance, 376 + IN HINSTANCE hPrevInstance, 377 + IN LPWSTR pCmdLine, 378 + IN INT nCmdShow) 379 + { 380 + HANDLE hMutex; 381 + DWORD dwError; 382 + INITCOMMONCONTROLSEX iccex; 383 + 384 + UNREFERENCED_PARAMETER(hPrevInstance); 385 + UNREFERENCED_PARAMETER(pCmdLine); 386 + UNREFERENCED_PARAMETER(nCmdShow); 387 + 388 + /* Create a mutant object for the program. */ 389 + hMutex = CreateMutexW(NULL, FALSE, L"Utilman"); 390 + if (hMutex) 391 + { 392 + /* Check if there's already a mutex for the program */ 393 + dwError = GetLastError(); 394 + if (dwError == ERROR_ALREADY_EXISTS) 395 + { 396 + /* 397 + The program's instance is already here. That means 398 + the program is running and we should not set a new instance 399 + and mutex object. 400 + */ 401 + CloseHandle(hMutex); 402 + return 0; 403 + } 404 + } 405 + 406 + /* Load the common controls for the program */ 407 + iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); 408 + iccex.dwICC = ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES; 409 + InitCommonControlsEx(&iccex); 410 + 411 + /* Initialize the globals */ 412 + ZeroMemory(&Globals, sizeof(Globals)); 413 + Globals.hInstance = hInstance; 414 + 415 + LoadStringW(Globals.hInstance, IDS_RUNNING, 416 + Globals.szRunning, _countof(Globals.szRunning)); 417 + LoadStringW(Globals.hInstance, IDS_NOTRUNNING, 418 + Globals.szNotRunning, _countof(Globals.szNotRunning)); 419 + LoadStringW(Globals.hInstance, IDS_GROUPBOX_OPTIONS_TITLE, 420 + Globals.szGrpBoxTitle, _countof(Globals.szGrpBoxTitle)); 421 + 422 + /* Initialize the list of accessibility utilities */ 423 + InitUtilsList(FALSE); 424 + 425 + /* Create the dialog box of the program */ 426 + DialogBoxW(hInstance, 427 + MAKEINTRESOURCEW(IDD_MAIN_DIALOG), 428 + GetDesktopWindow(), 429 + DlgProc); 430 + 431 + /* Delete the mutex */ 432 + if (hMutex) 433 + { 434 + CloseHandle(hMutex); 435 + } 436 + 437 + return 0; 438 + }
+54
base/applications/utilman/lang/en-US.rc
··· 1 + /* 2 + * PROJECT: ReactOS Utility Manager (Accessibility) 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: English (United States of America) translation resource 5 + * COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com) 6 + */ 7 + 8 + IDD_MAIN_DIALOG DIALOGEX 0, 0, 284, 183 9 + STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 10 + EXSTYLE WS_EX_CONTEXTHELP 11 + CAPTION "Accessibility Utility Manager" 12 + LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 13 + FONT 8, "MS Shell Dlg" 14 + BEGIN 15 + LISTBOX IDC_LISTBOX, 4, 4, 273, 56, LBS_STANDARD | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER 16 + CONTROL "", IDC_GROUPBOX, "Button", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 3, 62, 275, 92 17 + CONTROL "Start", IDC_START, "Button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 14, 76, 45, 16 18 + CONTROL "Stop", IDC_STOP, "Button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 69, 76, 45, 16 19 + CONTROL "Start automatically when I log in", IDC_START_LOG_IN, "Button", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 12, 101, 206, 14 20 + CONTROL "Start automatically when I look my desktop", IDC_START_DESKTOP, "Button", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 12, 118, 212, 14 21 + CONTROL "Start automatically when Utility Manager starts", IDC_START_UTILMAN, "Button", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 12, 134, 212, 13 22 + CONTROL "&OK", IDC_OK, "Button", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 160, 161, 50, 14 23 + CONTROL "&Cancel", IDC_CANCEL, "Button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 221, 161, 50, 14 24 + CONTROL "&Help", IDC_HELP_TOPICS, "Button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 98, 161, 50, 14 25 + END 26 + 27 + IDD_ABOUT_DIALOG DIALOGEX 22, 16, 210, 65 28 + CAPTION "About Accessibility Utility Manager" 29 + FONT 8, "MS Shell Dlg", 0, 0 30 + STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME 31 + BEGIN 32 + ICON IDI_ICON_UTILMAN, IDC_STATIC, 10, 10, 7, 30 33 + LTEXT "Accessibility Utility Manager\nCopyright (C) 2019 George Bișoc (fraizeraust99 at gmail dot com)", IDC_STATIC, 48, 7, 150, 36 34 + LTEXT "Copyright (C) 2019 Hermes Belusca-Maito", IDC_STATIC, 48, 33, 150, 36 35 + PUSHBUTTON "Close", IDOK, 75, 47, 44, 15 36 + END 37 + 38 + STRINGTABLE 39 + BEGIN 40 + IDS_OSK "On-Screen Keyboard" 41 + IDS_MAGNIFIER "Magnifier" 42 + END 43 + 44 + STRINGTABLE 45 + BEGIN 46 + IDS_NOTRUNNING "%s is not running" 47 + IDS_RUNNING "%s is running" 48 + IDS_GROUPBOX_OPTIONS_TITLE "Options for %s" 49 + END 50 + 51 + STRINGTABLE 52 + BEGIN 53 + IDM_ABOUT "About Accessibility Utility Manager..." 54 + END
+75
base/applications/utilman/precomp.h
··· 1 + /* 2 + * PROJECT: ReactOS Utility Manager (Accessibility) 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Pre-compiled header file 5 + * COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com) 6 + */ 7 + 8 + #ifndef _UTILMAN_H 9 + #define _UTILMAN_H 10 + 11 + /* INCLUDES ******************************************************************/ 12 + 13 + #include <stdlib.h> 14 + #include <windows.h> 15 + #include <commctrl.h> 16 + #include <tlhelp32.h> 17 + #include <windowsx.h> 18 + #include <debug.h> 19 + #include <wchar.h> 20 + #include <strsafe.h> 21 + 22 + #include "resource.h" 23 + 24 + /* DEFINES ********************************************************************/ 25 + 26 + #define MAX_BUFFER 256 27 + 28 + /* TYPES **********************************************************************/ 29 + 30 + typedef struct 31 + { 32 + HINSTANCE hInstance; 33 + HICON hIcon; 34 + UINT_PTR iTimer; 35 + INT iSelectedIndex; 36 + HWND hDlgCtlStart; 37 + HWND hDlgCtlStop; 38 + HWND hListDlg; 39 + HWND hMainDlg; 40 + WCHAR szRunning[MAX_BUFFER]; 41 + WCHAR szNotRunning[MAX_BUFFER]; 42 + WCHAR szGrpBoxTitle[MAX_BUFFER]; 43 + } UTILMAN_GLOBALS; 44 + 45 + typedef struct _UTILMAN_STATE 46 + { 47 + LPCWSTR lpProgram; 48 + UINT uNameId; 49 + WCHAR szResource[MAX_BUFFER]; 50 + BOOL bState; 51 + } UTILMAN_STATE, *PUTILMAN_STATE; 52 + 53 + /* DECLARATIONS ***************************************************************/ 54 + 55 + /* dialog.c */ 56 + BOOL DlgInitHandler(HWND hDlg); 57 + INT_PTR APIENTRY DlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam); 58 + INT ListBoxRefreshContents(VOID); 59 + VOID CheckUtilityState(BOOL bUtilState); 60 + 61 + /* process.c */ 62 + BOOL IsProcessRunning(IN LPCWSTR lpProcessName); 63 + BOOL LaunchProcess(LPCWSTR lpProcessName); 64 + BOOL CloseProcess(IN LPCWSTR lpProcessName); 65 + 66 + /* about.c */ 67 + VOID ShowAboutDlg(HWND hDlgParent); 68 + INT_PTR CALLBACK AboutDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam); 69 + 70 + /* Struct variable declaration */ 71 + extern UTILMAN_GLOBALS Globals; 72 + 73 + #endif /* _UTILMAN_H */ 74 + 75 + /* EOF */
+189
base/applications/utilman/process.c
··· 1 + /* 2 + * PROJECT: ReactOS Utility Manager (Accessibility) 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Process handling functions 5 + * COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com) 6 + */ 7 + 8 + /* INCLUDES *******************************************************************/ 9 + 10 + #include "precomp.h" 11 + 12 + /* FUNCTIONS ******************************************************************/ 13 + 14 + /** 15 + * @IsProcessRunning 16 + * 17 + * Checks if a process is running. 18 + * 19 + * @param[in] ProcName 20 + * The name of the executable process. 21 + * 22 + * @return 23 + * Returns TRUE if the given process' name is running, 24 + * FALSE otherwise. 25 + * 26 + */ 27 + BOOL IsProcessRunning(IN LPCWSTR lpProcessName) 28 + { 29 + BOOL bIsRunning = FALSE; 30 + PROCESSENTRY32W Process = {0}; 31 + 32 + /* Create a snapshot and check whether the given process' executable name is running */ 33 + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 34 + 35 + if (hSnapshot == INVALID_HANDLE_VALUE) 36 + return FALSE; 37 + 38 + Process.dwSize = sizeof(Process); 39 + 40 + /* Enumerate the processes */ 41 + if (Process32FirstW(hSnapshot, &Process)) 42 + { 43 + do 44 + { 45 + if (_wcsicmp(Process.szExeFile, lpProcessName) == 0) 46 + { 47 + /* The process we are searching for is running */ 48 + bIsRunning = TRUE; 49 + break; 50 + } 51 + } 52 + while (Process32NextW(hSnapshot, &Process)); 53 + } 54 + 55 + /* Free the handle and return */ 56 + CloseHandle(hSnapshot); 57 + return bIsRunning; 58 + } 59 + 60 + /** 61 + * @LaunchProcess 62 + * 63 + * Executes a process. 64 + * 65 + * @param[in] lpProcessName 66 + * The name of the executable process. 67 + * 68 + * @return 69 + * Returns TRUE if the process has been launched successfully, 70 + * FALSE otherwise. 71 + * 72 + */ 73 + BOOL LaunchProcess(LPCWSTR lpProcessName) 74 + { 75 + STARTUPINFOW si; 76 + PROCESS_INFORMATION pi; 77 + HANDLE hUserToken, hProcessToken; 78 + BOOL bSuccess; 79 + WCHAR ExpandedCmdLine[MAX_PATH]; 80 + 81 + /* Expand the process path string */ 82 + ExpandEnvironmentStringsW(lpProcessName, ExpandedCmdLine, ARRAYSIZE(ExpandedCmdLine)); 83 + 84 + ZeroMemory(&pi, sizeof(pi)); 85 + ZeroMemory(&si, sizeof(si)); 86 + si.cb = sizeof(si); 87 + si.dwFlags = STARTF_USESHOWWINDOW; 88 + si.wShowWindow = SW_SHOWNORMAL; 89 + 90 + /* Get the token of the parent (current) process of the application */ 91 + bSuccess = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hUserToken); 92 + if (!bSuccess) 93 + { 94 + DPRINT("OpenProcessToken() failed with error -> %lu\n", GetLastError()); 95 + return FALSE; 96 + } 97 + 98 + /* Duplicate a new token so that we can use it to create our process */ 99 + bSuccess = DuplicateTokenEx(hUserToken, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenPrimary, &hProcessToken); 100 + if (!bSuccess) 101 + { 102 + DPRINT("DuplicateTokenEx() failed with error -> %lu\n", GetLastError()); 103 + CloseHandle(hUserToken); 104 + return FALSE; 105 + } 106 + 107 + /* Finally create the process */ 108 + bSuccess = CreateProcessAsUserW(hProcessToken, 109 + NULL, 110 + ExpandedCmdLine, 111 + NULL, 112 + NULL, 113 + FALSE, 114 + 0, // DETACHED_PROCESS, NORMAL_PRIORITY_CLASS 115 + NULL, 116 + NULL, 117 + &si, 118 + &pi); 119 + 120 + if (!bSuccess) 121 + { 122 + DPRINT("CreateProcessAsUserW() failed with error -> %lu\n", GetLastError()); 123 + CloseHandle(hUserToken); 124 + CloseHandle(hProcessToken); 125 + return FALSE; 126 + } 127 + 128 + CloseHandle(pi.hProcess); 129 + CloseHandle(pi.hThread); 130 + CloseHandle(hUserToken); 131 + CloseHandle(hProcessToken); 132 + return TRUE; 133 + } 134 + 135 + /** 136 + * @CloseProcess 137 + * 138 + * Closes a process. 139 + * 140 + * @param[in] lpProcessName 141 + * The name of the executable process. 142 + * 143 + * @return 144 + * Returns TRUE if the process has been terminated successfully, 145 + * FALSE otherwise. 146 + * 147 + */ 148 + BOOL CloseProcess(IN LPCWSTR lpProcessName) 149 + { 150 + BOOL bSuccess = FALSE; 151 + PROCESSENTRY32W Process = {0}; 152 + 153 + /* Create a snapshot and check if the given process' executable name is running */ 154 + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 155 + 156 + if (hSnapshot == INVALID_HANDLE_VALUE) 157 + return FALSE; 158 + 159 + Process.dwSize = sizeof(Process); 160 + 161 + /* Enumerate the processes */ 162 + if (Process32FirstW(hSnapshot, &Process)) 163 + { 164 + do 165 + { 166 + if (_wcsicmp(Process.szExeFile, lpProcessName) == 0) 167 + { 168 + /* 169 + * We have found the process. However we must make 170 + * sure that we DO NOT kill ourselves (the process ID 171 + * matching with the current parent process ID). 172 + */ 173 + HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, Process.th32ProcessID); 174 + if ((hProcess != NULL) && (Process.th32ProcessID != GetCurrentProcessId())) 175 + { 176 + TerminateProcess(hProcess, 0); 177 + CloseHandle(hProcess); 178 + } 179 + bSuccess = TRUE; 180 + break; 181 + } 182 + } 183 + while (Process32NextW(hSnapshot, &Process)); 184 + } 185 + 186 + /* Free the handle and return */ 187 + CloseHandle(hSnapshot); 188 + return bSuccess; 189 + }
base/applications/utilman/res/utilman.ico

This is a binary file and will not be displayed.

+47
base/applications/utilman/resource.h
··· 1 + /* 2 + * PROJECT: ReactOS Utility Manager (Accessibility) 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Resource header file 5 + * COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com) 6 + */ 7 + 8 + #pragma once 9 + 10 + #define IDC_STATIC -1 11 + 12 + /* Icon resource */ 13 + #define IDI_ICON_UTILMAN 50 14 + 15 + /* List box resource */ 16 + #define IDC_LISTBOX 60 17 + 18 + /* Utility tools name strings */ 19 + #define IDS_OSK 100 20 + #define IDS_MAGNIFIER 101 21 + 22 + /* Utility state strings */ 23 + #define IDS_NOTRUNNING 150 24 + #define IDS_RUNNING 151 25 + 26 + /* Groupbox option title */ 27 + #define IDC_GROUPBOX 200 28 + #define IDS_GROUPBOX_OPTIONS_TITLE 201 29 + 30 + /* Button resources */ 31 + #define IDC_START 300 32 + #define IDC_STOP 301 33 + #define IDC_OK 302 34 + #define IDC_CANCEL 303 35 + #define IDC_HELP_TOPICS 304 36 + 37 + /* Checkbox resources */ 38 + #define IDC_START_LOG_IN 400 39 + #define IDC_START_DESKTOP 401 40 + #define IDC_START_UTILMAN 402 41 + 42 + /* System menu (About) resource */ 43 + #define IDM_ABOUT 600 44 + 45 + /* Main dialog resource */ 46 + #define IDD_MAIN_DIALOG 1000 47 + #define IDD_ABOUT_DIALOG 1050
+32
base/applications/utilman/utilman.rc
··· 1 + /* 2 + * PROJECT: ReactOS Utility Manager (Accessibility) 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Main resource file 5 + * COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com) 6 + */ 7 + 8 + /* INCLUDES ******************************************************************/ 9 + 10 + #include <windef.h> 11 + #include <winuser.h> 12 + #include "resource.h" 13 + 14 + LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 15 + 16 + #define REACTOS_STR_FILE_DESCRIPTION "ReactOS Accessibility Utility Manager" 17 + #define REACTOS_STR_INTERNAL_NAME "utilman" 18 + #define REACTOS_STR_ORIGINAL_FILENAME "utilman.exe" 19 + #include <reactos/version.rc> 20 + 21 + IDI_ICON_UTILMAN ICON "res/utilman.ico" 22 + 23 + #include <reactos/manifest_exe.rc> 24 + 25 + /* UTF-8 */ 26 + #pragma code_page(65001) 27 + 28 + #ifdef LANGUAGE_EN_US 29 + #include "lang/en-US.rc" 30 + #endif 31 + 32 + /* EOF */
+3
media/inf/shortcuts.inf
··· 50 50 [AccessibilityShortcuts] 51 51 %SystemRoot%\system32\magnify.exe, %MAGNIFY_TITLE%, %MAGNIFY_DESC%, 0, %HOMEDRIVE%%HOMEPATH% 52 52 %SystemRoot%\system32\osk.exe, %OSK_TITLE%, %OSK_DESC%, 0, %HOMEDRIVE%%HOMEPATH% 53 + %SystemRoot%\system32\utilman.exe, %UTILMAN_TITLE%, %UTILMAN_DESC%, 0, %HOMEDRIVE%%HOMEPATH% 53 54 54 55 [EntertainmentShortcuts] 55 56 %SystemRoot%\system32\mplay32.exe, %MPLAY_TITLE%, %MPLAY_DESC%, 0, %HOMEDRIVE%%HOMEPATH% ··· 133 134 WINMINE_DESC=WineMine 134 135 SPIDER_TITLE=Spider Solitaire 135 136 SPIDER_DESC=Spider Solitaire 137 + UTILMAN_TITLE=Accessibility Utility Manager 138 + UTILMAN_DESC=Launch Accessibility Utility Manager 136 139 137 140 ; Bulgarian 138 141 [Strings.0402]