reactos/base/applications/utilman/umandlg/umandlg.c
Bișoc George 975d417b34
[UTILMAN] Move most of the code in a library (#2530)
Windows XP and Server 2003 Utility Manager has a dedicated library for the resources and other stuff. Utility Manager is just a simple process that loads it. Hence create a library for the program, UManDlg.dll, and move the resources and other stuff there.

In addition to that, use ExtractIconW to get the icon resource from the program (the DLL doesn't share icons by default) and remove the icon resource from the "About" dialog window. Also change the encoding type of other translation files to UTF-8 (which were previously set with UTF-8 with BOM).
2020-04-17 13:42:47 +03:00

457 lines
13 KiB
C

/*
* PROJECT: ReactOS Utility Manager Resources DLL (UManDlg.dll)
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Main DLL code file
* COPYRIGHT: Copyright 2019-2020 Bișoc George (fraizeraust99 at gmail dot com)
* Copyright 2019 Hermes Belusca-Maito
*/
/* INCLUDES *******************************************************************/
#include "umandlg.h"
/* GLOBALS ********************************************************************/
UTILMAN_GLOBALS Globals;
/* DECLARATIONS ***************************************************************/
UTILMAN_STATE EntriesList[] =
{
{L"magnify.exe", IDS_MAGNIFIER, L"", FALSE},
{L"osk.exe", IDS_OSK, L"", FALSE}
};
/* FUNCTIONS ******************************************************************/
/**
* @InitUtilsList
*
* Initializes the list of accessibility utilities.
*
* @param[in] bInitGui
* Whether we are initializing the UI list (TRUE) or the internal array (FALSE).
*
* @return
* Nothing.
*/
VOID InitUtilsList(BOOL bInitGui)
{
UINT i;
if (!bInitGui)
{
// TODO: Load the list dynamically from the registry key
// hklm\software\microsoft\windows nt\currentversion\accessibility
/* Initialize the resource utility strings only once */
for (i = 0; i < _countof(EntriesList); ++i)
{
LoadStringW(Globals.hInstance, EntriesList[i].uNameId,
EntriesList[i].szResource, _countof(EntriesList[i].szResource));
EntriesList[i].bState = FALSE;
}
}
else
{
INT iItem;
BOOL bIsRunning;
WCHAR szFormat[MAX_BUFFER];
/* Reset the listbox */
SendMessageW(Globals.hListDlg, LB_RESETCONTENT, 0, 0);
/* Add the utilities in the listbox */
for (i = 0; i < _countof(EntriesList); ++i)
{
bIsRunning = IsProcessRunning(EntriesList[i].lpProgram);
EntriesList[i].bState = bIsRunning;
/* Load the string and append the utility's name to the format */
StringCchPrintfW(szFormat, _countof(szFormat),
(bIsRunning ? Globals.szRunning : Globals.szNotRunning),
EntriesList[i].szResource);
/* Add the item in the listbox */
iItem = (INT)SendMessageW(Globals.hListDlg, LB_ADDSTRING, 0, (LPARAM)szFormat);
if (iItem != LB_ERR)
SendMessageW(Globals.hListDlg, LB_SETITEMDATA, iItem, (LPARAM)&EntriesList[i]);
}
}
}
/**
* @DlgInitHandler
*
* Function which processes several operations for WM_INITDIALOG.
*
* @param[in] hDlg
* The handle object of the dialog.
*
* @return
* TRUE to inform the system that WM_INITDIALOG has been processed and
* that it should set the keyboard focus to the control.
*
*/
BOOL DlgInitHandler(IN HWND hDlg)
{
INT PosX, PosY;
RECT rc;
WCHAR szAboutDlg[MAX_BUFFER];
WCHAR wszAppPath[MAX_BUFFER];
HMENU hSysMenu;
/* Save the dialog handle */
Globals.hMainDlg = hDlg;
/* Center the dialog on the screen */
GetWindowRect(hDlg, &rc);
PosX = (GetSystemMetrics(SM_CXSCREEN) - rc.right) / 2;
PosY = (GetSystemMetrics(SM_CYSCREEN) - rc.bottom) / 2;
SetWindowPos(hDlg, 0, PosX, PosY, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
/* Extract the icon resource from the executable process */
GetModuleFileNameW(NULL, wszAppPath, _countof(wszAppPath));
Globals.hIcon = ExtractIconW(Globals.hInstance, wszAppPath, 0);
/* Set the icon within the dialog's title bar */
if (Globals.hIcon)
{
SendMessageW(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Globals.hIcon);
}
/* Retrieve the system menu and append the "About" menu item onto it */
hSysMenu = GetSystemMenu(hDlg, FALSE);
if (hSysMenu != NULL)
{
if (LoadStringW(Globals.hInstance, IDM_ABOUT, szAboutDlg, _countof(szAboutDlg)))
{
AppendMenuW(hSysMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hSysMenu, MF_STRING, IDM_ABOUT, szAboutDlg);
}
}
/* Get the dialog items, specifically the dialog list box, the Start and Stop buttons */
Globals.hListDlg = GetDlgItem(hDlg, IDC_LISTBOX);
Globals.hDlgCtlStart = GetDlgItem(hDlg, IDC_START);
Globals.hDlgCtlStop = GetDlgItem(hDlg, IDC_STOP);
/* Initialize the GUI listbox */
InitUtilsList(TRUE);
/* Set the selection to the first item */
Globals.iSelectedIndex = 0;
/* Refresh the list */
ListBoxRefreshContents();
/* Create a timer, we'll use it to control the state of our items in the listbox */
Globals.iTimer = SetTimer(hDlg, 0, 400, NULL);
return TRUE;
}
/**
* @GroupBoxUpdateTitle
*
* Updates the title of the groupbox.
*
* @return
* Nothing.
*
*/
VOID GroupBoxUpdateTitle(VOID)
{
WCHAR szFormat[MAX_BUFFER];
/* Format the string with the utility's name and set it to the listbox's title */
StringCchPrintfW(szFormat, _countof(szFormat), Globals.szGrpBoxTitle, EntriesList[Globals.iSelectedIndex].szResource);
SetWindowTextW(GetDlgItem(Globals.hMainDlg, IDC_GROUPBOX), szFormat);
}
/**
* @UpdateUtilityState
*
* Checks the state of the given accessibility tool.
*
* @param[in] bUtilState
* State condition (boolean TRUE: started / FALSE: stopped).
*
* @return
* Nothing.
*
*/
VOID UpdateUtilityState(IN BOOL bUtilState)
{
Button_Enable(Globals.hDlgCtlStart, !bUtilState);
Button_Enable(Globals.hDlgCtlStop, bUtilState);
/* Update the groupbox's title based on the selected utility item */
GroupBoxUpdateTitle();
}
/**
* @ListBoxRefreshContents
*
* Handle the tasks on a periodic cycle. This function handles WM_TIMER message.
*
* @return
* Returns 0 to inform the system that WM_TIMER has been processed.
*
*/
INT ListBoxRefreshContents(VOID)
{
UINT i;
INT iItem;
BOOL bIsRunning;
WCHAR szFormat[MAX_BUFFER];
/* Disable listbox redraw */
SendMessageW(Globals.hListDlg, WM_SETREDRAW, FALSE, 0);
for (i = 0; i < _countof(EntriesList); ++i)
{
/* Check the utility's state */
bIsRunning = IsProcessRunning(EntriesList[i].lpProgram);
if (bIsRunning != EntriesList[i].bState)
{
/* The utility's state has changed, save it */
EntriesList[i].bState = bIsRunning;
/* Update the corresponding item in the listbox */
StringCchPrintfW(szFormat, _countof(szFormat),
(bIsRunning ? Globals.szRunning : Globals.szNotRunning),
EntriesList[i].szResource);
SendMessageW(Globals.hListDlg, LB_DELETESTRING, (LPARAM)i, 0);
iItem = SendMessageW(Globals.hListDlg, LB_INSERTSTRING, (LPARAM)i, (LPARAM)szFormat);
if (iItem != LB_ERR)
SendMessageW(Globals.hListDlg, LB_SETITEMDATA, iItem, (LPARAM)&EntriesList[i]);
}
}
/* Re-enable listbox redraw */
SendMessageW(Globals.hListDlg, WM_SETREDRAW, TRUE, 0);
/*
* Check the previously selected item. This will help us determine what
* item has been selected and set its focus selection back. Furthermore, check
* the state of each accessibility tool and enable/disable the buttons.
*/
SendMessageW(Globals.hListDlg, LB_SETCURSEL, (WPARAM)Globals.iSelectedIndex, 0);
UpdateUtilityState(EntriesList[Globals.iSelectedIndex].bState);
return 0;
}
/**
* @DlgProc
*
* Main dialog application procedure function.
*
* @param[in] hDlg
* The handle object of the dialog.
*
* @param[in] Msg
* Message events (in unsigned int).
*
* @param[in] wParam
* Message parameter (in UINT_PTR).
*
* @param[in] lParam
* Message paramater (in LONG_PTR).
*
* @return
* Returns 0 to inform the system that the procedure has been handled.
*
*/
INT_PTR APIENTRY DlgProc(
IN HWND hDlg,
IN UINT Msg,
IN WPARAM wParam,
IN LPARAM lParam)
{
switch (Msg)
{
case WM_INITDIALOG:
DlgInitHandler(hDlg);
return TRUE;
case WM_CLOSE:
KillTimer(hDlg, Globals.iTimer);
DestroyIcon(Globals.hIcon);
EndDialog(hDlg, FALSE);
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_OK:
case IDC_CANCEL:
EndDialog(hDlg, FALSE);
break;
case IDC_LISTBOX:
{
switch (HIWORD(wParam))
{
case LBN_SELCHANGE:
{
/* Retrieve the index of the current selected item */
INT iIndex = SendMessageW(Globals.hListDlg, LB_GETCURSEL, 0, 0);
if ((iIndex == LB_ERR) || (iIndex >= _countof(EntriesList)))
break;
/* Assign the selected index and check the utility's state */
Globals.iSelectedIndex = iIndex;
UpdateUtilityState(EntriesList[Globals.iSelectedIndex].bState);
break;
}
break;
}
break;
}
case IDC_START:
LaunchProcess(EntriesList[Globals.iSelectedIndex].lpProgram);
break;
case IDC_STOP:
CloseProcess(EntriesList[Globals.iSelectedIndex].lpProgram);
break;
default:
break;
}
break;
}
case WM_TIMER:
ListBoxRefreshContents();
return 0;
case WM_SYSCOMMAND:
{
switch (LOWORD(wParam))
{
case IDM_ABOUT:
ShowAboutDlg(hDlg);
break;
}
break;
}
}
return 0;
}
/**
* @UManStartDlg
*
* Executes the dialog initialization mechanism and starts Utility Manager.
* The function is exported for use by the main process.
*
* @return
* Returns TRUE when the operation has succeeded, FALSE otherwise.
*
*/
BOOL WINAPI UManStartDlg(VOID)
{
HANDLE hMutex;
DWORD dwError;
INITCOMMONCONTROLSEX iccex;
/* Create a mutant object for the program. */
hMutex = CreateMutexW(NULL, FALSE, L"Utilman");
if (hMutex)
{
/* Check if there's already a mutex for the program */
dwError = GetLastError();
if (dwError == ERROR_ALREADY_EXISTS)
{
/*
The program's instance is already here. That means
the program is running and we should not set a new instance
and mutex object.
*/
CloseHandle(hMutex);
return FALSE;
}
}
/* Load the common controls for the program */
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC = ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES;
InitCommonControlsEx(&iccex);
LoadStringW(Globals.hInstance, IDS_RUNNING,
Globals.szRunning, _countof(Globals.szRunning));
LoadStringW(Globals.hInstance, IDS_NOTRUNNING,
Globals.szNotRunning, _countof(Globals.szNotRunning));
LoadStringW(Globals.hInstance, IDS_GROUPBOX_OPTIONS_TITLE,
Globals.szGrpBoxTitle, _countof(Globals.szGrpBoxTitle));
/* Initialize the list of accessibility utilities */
InitUtilsList(FALSE);
/* Create the dialog box of the program */
DialogBoxW(Globals.hInstance,
MAKEINTRESOURCEW(IDD_MAIN_DIALOG),
GetDesktopWindow(),
DlgProc);
/* Delete the mutex */
if (hMutex)
{
CloseHandle(hMutex);
}
return TRUE;
}
/**
* @DllMain
*
* Core routine of the Utility Manager's library.
*
* @param[in] hDllInstance
* The entry point instance of the library.
*
* @param[in] fdwReason
* The reason argument to indicate the motive DllMain
* is being called.
*
* @param[in] lpvReserved
* Reserved.
*
* @return
* Returns TRUE when main call initialization has succeeded, FALSE
* otherwise.
*
*/
BOOL WINAPI DllMain(IN HINSTANCE hDllInstance,
IN DWORD fdwReason,
IN LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
/* We don't care for DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications */
DisableThreadLibraryCalls(hDllInstance);
/* Initialize the globals */
ZeroMemory(&Globals, sizeof(Globals));
Globals.hInstance = hDllInstance;
break;
}
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}