2 * PROJECT: ReactOS Utility Manager Resources DLL (UManDlg.dll)
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Main DLL code file
5 * COPYRIGHT: Copyright 2019-2020 George Bișoc (george.bisoc@reactos.org)
6 * Copyright 2019 Hermes Belusca-Maito
9 /* INCLUDES *******************************************************************/
13 /* GLOBALS ********************************************************************/
15 UTILMAN_GLOBALS Globals
;
17 /* DECLARATIONS ***************************************************************/
19 UTILMAN_STATE EntriesList
[] =
21 {L
"magnify.exe", IDS_MAGNIFIER
, L
"", FALSE
},
22 {L
"osk.exe", IDS_OSK
, L
"", FALSE
}
25 /* FUNCTIONS ******************************************************************/
30 * Initializes the list of accessibility utilities.
33 * Whether we are initializing the UI list (TRUE) or the internal array (FALSE).
38 VOID
InitUtilsList(IN BOOL bInitGui
)
44 // TODO: Load the list dynamically from the registry key
45 // hklm\software\microsoft\windows nt\currentversion\accessibility
47 /* Initialize the resource utility strings only once */
48 for (i
= 0; i
< _countof(EntriesList
); ++i
)
50 LoadStringW(Globals
.hInstance
, EntriesList
[i
].uNameId
,
51 EntriesList
[i
].szResource
, _countof(EntriesList
[i
].szResource
));
53 EntriesList
[i
].bState
= FALSE
;
60 WCHAR szFormat
[MAX_BUFFER
];
62 /* Reset the listbox */
63 SendMessageW(Globals
.hListDlg
, LB_RESETCONTENT
, 0, 0);
65 /* Add the utilities in the listbox */
66 for (i
= 0; i
< _countof(EntriesList
); ++i
)
68 bIsRunning
= IsProcessRunning(EntriesList
[i
].lpszProgram
);
69 EntriesList
[i
].bState
= bIsRunning
;
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
);
76 /* Add the item in the listbox */
77 iItem
= (INT
)SendMessageW(Globals
.hListDlg
, LB_ADDSTRING
, 0, (LPARAM
)szFormat
);
79 SendMessageW(Globals
.hListDlg
, LB_SETITEMDATA
, iItem
, (LPARAM
)&EntriesList
[i
]);
87 * Function which processes several operations for WM_INITDIALOG.
90 * The handle object of the dialog.
93 * TRUE to inform the system that WM_INITDIALOG has been processed and
94 * that it should set the keyboard focus to the control.
97 BOOL
DlgInitHandler(IN HWND hDlg
)
101 WCHAR szAboutDlg
[MAX_BUFFER
];
102 WCHAR szAppPath
[MAX_BUFFER
];
105 /* Save the dialog handle */
106 Globals
.hMainDlg
= hDlg
;
108 /* Center the dialog on the screen */
109 GetWindowRect(hDlg
, &rc
);
110 PosX
= (GetSystemMetrics(SM_CXSCREEN
) - rc
.right
) / 2;
111 PosY
= (GetSystemMetrics(SM_CYSCREEN
) - rc
.bottom
) / 2;
112 SetWindowPos(hDlg
, 0, PosX
, PosY
, 0, 0, SWP_NOZORDER
| SWP_NOSIZE
);
114 /* Extract the icon resource from the executable process */
115 GetModuleFileNameW(NULL
, szAppPath
, _countof(szAppPath
));
116 Globals
.hIcon
= ExtractIconW(Globals
.hInstance
, szAppPath
, 0);
118 /* Set the icon within the dialog's title bar */
121 SendMessageW(hDlg
, WM_SETICON
, ICON_SMALL
, (LPARAM
)Globals
.hIcon
);
124 /* Retrieve the system menu and append the "About" menu item onto it */
125 hSysMenu
= GetSystemMenu(hDlg
, FALSE
);
126 if (hSysMenu
!= NULL
)
128 if (LoadStringW(Globals
.hInstance
, IDM_ABOUT
, szAboutDlg
, _countof(szAboutDlg
)))
130 AppendMenuW(hSysMenu
, MF_SEPARATOR
, 0, NULL
);
131 AppendMenuW(hSysMenu
, MF_STRING
, IDM_ABOUT
, szAboutDlg
);
135 /* Get the dialog items, specifically the dialog list box, the Start and Stop buttons */
136 Globals
.hListDlg
= GetDlgItem(hDlg
, IDC_LISTBOX
);
137 Globals
.hDlgCtlStart
= GetDlgItem(hDlg
, IDC_START
);
138 Globals
.hDlgCtlStop
= GetDlgItem(hDlg
, IDC_STOP
);
140 /* Initialize the GUI listbox */
143 /* Set the selection to the first item */
144 Globals
.iSelectedIndex
= 0;
146 /* Refresh the list */
147 ListBoxRefreshContents();
149 /* Create a timer, we'll use it to control the state of our items in the listbox */
150 Globals
.iTimer
= SetTimer(hDlg
, 0, 400, NULL
);
158 * Displays the Shell "About" dialog box.
160 * @param[in] hDlgParent
161 * A handle to the parent dialog window.
167 VOID
ShowAboutDlg(IN HWND hDlgParent
)
169 WCHAR szApp
[MAX_BUFFER
];
170 WCHAR szAuthors
[MAX_BUFFER
];
172 LoadStringW(Globals
.hInstance
, IDS_APP_NAME
, szApp
, _countof(szApp
));
173 LoadStringW(Globals
.hInstance
, IDS_AUTHORS
, szAuthors
, _countof(szAuthors
));
175 ShellAboutW(hDlgParent
, szApp
, szAuthors
, Globals
.hIcon
);
179 * @GroupBoxUpdateTitle
181 * Updates the title of the groupbox.
187 VOID
GroupBoxUpdateTitle(VOID
)
189 WCHAR szFormat
[MAX_BUFFER
];
191 /* Format the string with the utility's name and set it to the listbox's title */
192 StringCchPrintfW(szFormat
, _countof(szFormat
), Globals
.szGrpBoxTitle
, EntriesList
[Globals
.iSelectedIndex
].szResource
);
193 SetWindowTextW(GetDlgItem(Globals
.hMainDlg
, IDC_GROUPBOX
), szFormat
);
197 * @UpdateUtilityState
199 * Checks the state of the given accessibility tool.
201 * @param[in] bUtilState
202 * State condition (boolean TRUE: started / FALSE: stopped).
208 VOID
UpdateUtilityState(IN BOOL bUtilState
)
210 Button_Enable(Globals
.hDlgCtlStart
, !bUtilState
);
211 Button_Enable(Globals
.hDlgCtlStop
, bUtilState
);
213 /* Update the groupbox's title based on the selected utility item */
214 GroupBoxUpdateTitle();
218 * @ListBoxRefreshContents
220 * Handle the tasks on a periodic cycle. This function handles WM_TIMER message.
223 * Returns 0 to inform the system that WM_TIMER has been processed.
226 INT
ListBoxRefreshContents(VOID
)
231 WCHAR szFormat
[MAX_BUFFER
];
233 /* Disable listbox redraw */
234 SendMessageW(Globals
.hListDlg
, WM_SETREDRAW
, FALSE
, 0);
236 for (i
= 0; i
< _countof(EntriesList
); ++i
)
238 /* Check the utility's state */
239 bIsRunning
= IsProcessRunning(EntriesList
[i
].lpszProgram
);
240 if (bIsRunning
!= EntriesList
[i
].bState
)
242 /* The utility's state has changed, save it */
243 EntriesList
[i
].bState
= bIsRunning
;
245 /* Update the corresponding item in the listbox */
246 StringCchPrintfW(szFormat
, _countof(szFormat
),
247 (bIsRunning
? Globals
.szRunning
: Globals
.szNotRunning
),
248 EntriesList
[i
].szResource
);
250 SendMessageW(Globals
.hListDlg
, LB_DELETESTRING
, (LPARAM
)i
, 0);
251 iItem
= SendMessageW(Globals
.hListDlg
, LB_INSERTSTRING
, (LPARAM
)i
, (LPARAM
)szFormat
);
253 SendMessageW(Globals
.hListDlg
, LB_SETITEMDATA
, iItem
, (LPARAM
)&EntriesList
[i
]);
257 /* Re-enable listbox redraw */
258 SendMessageW(Globals
.hListDlg
, WM_SETREDRAW
, TRUE
, 0);
261 * Check the previously selected item. This will help us determine what
262 * item has been selected and set its focus selection back. Furthermore, check
263 * the state of each accessibility tool and enable/disable the buttons.
265 SendMessageW(Globals
.hListDlg
, LB_SETCURSEL
, (WPARAM
)Globals
.iSelectedIndex
, 0);
266 UpdateUtilityState(EntriesList
[Globals
.iSelectedIndex
].bState
);
274 * Main dialog application procedure function.
277 * The handle object of the dialog.
280 * Message events (in unsigned int).
283 * Message parameter (in UINT_PTR).
286 * Message parameter (in LONG_PTR).
289 * Returns 0 to inform the system that the procedure has been handled.
292 INT_PTR APIENTRY
DlgProc(
301 DlgInitHandler(hDlg
);
305 KillTimer(hDlg
, Globals
.iTimer
);
306 DestroyIcon(Globals
.hIcon
);
307 EndDialog(hDlg
, FALSE
);
312 switch (LOWORD(wParam
))
316 EndDialog(hDlg
, FALSE
);
321 switch (HIWORD(wParam
))
325 /* Retrieve the index of the current selected item */
326 INT iIndex
= SendMessageW(Globals
.hListDlg
, LB_GETCURSEL
, 0, 0);
327 if ((iIndex
== LB_ERR
) || (iIndex
>= _countof(EntriesList
)))
330 /* Assign the selected index and check the utility's state */
331 Globals
.iSelectedIndex
= iIndex
;
332 UpdateUtilityState(EntriesList
[Globals
.iSelectedIndex
].bState
);
341 LaunchProcess(EntriesList
[Globals
.iSelectedIndex
].lpszProgram
);
345 CloseProcess(EntriesList
[Globals
.iSelectedIndex
].lpszProgram
);
355 ListBoxRefreshContents();
360 switch (LOWORD(wParam
))
376 * Executes the dialog initialization mechanism and starts Utility Manager.
377 * The function is exported for use by the main process.
380 * Returns TRUE when the operation has succeeded, FALSE otherwise.
383 BOOL WINAPI
UManStartDlg(VOID
)
387 INITCOMMONCONTROLSEX iccex
;
389 /* Create a mutant object for the program. */
390 hMutex
= CreateMutexW(NULL
, FALSE
, L
"Utilman");
393 /* Check if there's already a mutex for the program */
394 dwError
= GetLastError();
395 if (dwError
== ERROR_ALREADY_EXISTS
)
398 The program's instance is already here. That means
399 the program is running and we should not set a new instance
407 /* Load the common controls for the program */
408 iccex
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
409 iccex
.dwICC
= ICC_STANDARD_CLASSES
| ICC_WIN95_CLASSES
;
410 InitCommonControlsEx(&iccex
);
412 LoadStringW(Globals
.hInstance
, IDS_RUNNING
,
413 Globals
.szRunning
, _countof(Globals
.szRunning
));
414 LoadStringW(Globals
.hInstance
, IDS_NOTRUNNING
,
415 Globals
.szNotRunning
, _countof(Globals
.szNotRunning
));
416 LoadStringW(Globals
.hInstance
, IDS_GROUPBOX_OPTIONS_TITLE
,
417 Globals
.szGrpBoxTitle
, _countof(Globals
.szGrpBoxTitle
));
419 /* Initialize the list of accessibility utilities */
420 InitUtilsList(FALSE
);
422 /* Create the dialog box of the program */
423 DialogBoxW(Globals
.hInstance
,
424 MAKEINTRESOURCEW(IDD_MAIN_DIALOG
),
428 /* Delete the mutex */
440 * Core routine of the Utility Manager's library.
442 * @param[in] hDllInstance
443 * The entry point instance of the library.
445 * @param[in] fdwReason
446 * The reason argument to indicate the motive DllMain
449 * @param[in] lpvReserved
453 * Returns TRUE when main call initialization has succeeded, FALSE
457 BOOL WINAPI
DllMain(IN HINSTANCE hDllInstance
,
459 IN LPVOID lpvReserved
)
463 case DLL_PROCESS_ATTACH
:
465 /* We don't care for DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications */
466 DisableThreadLibraryCalls(hDllInstance
);
468 /* Initialize the globals */
469 ZeroMemory(&Globals
, sizeof(Globals
));
470 Globals
.hInstance
= hDllInstance
;
474 case DLL_PROCESS_DETACH
: