ReactOS 0.4.17-dev-966-gf06eace
control.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS System Control Panel
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: ReactOS System Control Panel
5 * COPYRIGHT: Copyright 2004 Gero Kuehn (reactos.filter@gkware.com)
6 * Copyright 2008 Colin Finck (colin@reactos.org)
7 * Copyright 2014 Hermès Bélusca-Maïto (hermes.belusca-maito@reactos.org)
8 */
9
10#include <stdio.h>
11
12#define WIN32_NO_STATUS
13#define COBJMACROS
14
15
16#include <windef.h>
17#include <winbase.h>
18#include <winuser.h>
19#include <winreg.h>
20#include <shellapi.h>
21#include <strsafe.h>
22#include <objbase.h>
23#include <shobjidl.h>
24#include <shlguid.h>
25#include <shlwapi.h>
26
27#include "resource.h"
28
29#define MAX_VALUE_NAME 16383
30
31/*
32 * Macro for calling "rundll32.exe"
33 * According to MSDN, ShellExecute returns a value greater than 32
34 * if the operation was successful.
35 */
36#define RUNDLL(param) \
37 ((INT_PTR)ShellExecuteW(NULL, L"open", L"rundll32.exe", (param), NULL, SW_SHOWDEFAULT) > 32)
38#define ShellExec(file, params) \
39 ((INT_PTR)ShellExecuteW(NULL, NULL, (file), (params), NULL, SW_SHOWDEFAULT) > 32)
40
41VOID
44
45static BOOL
47{
48 if (*Arg == '/' || *Arg == '-')
49 {
50 return !lstrcmpiW(Arg+1, Switch);
51 }
52 return FALSE;
53}
54
55static HRESULT
57{
59 if (SUCCEEDED(hr))
60 {
61 IOpenControlPanel *pOCP;
62 hr = CoCreateInstance(&CLSID_OpenControlPanel, NULL, CLSCTX_INPROC_SERVER,
63 &IID_IOpenControlPanel, (void**)&pOCP);
64 if (SUCCEEDED(hr))
65 {
66 hr = IOpenControlPanel_Open(pOCP, Name, Page, NULL);
67 IOpenControlPanel_Release(pOCP);
68 }
70 }
71 return hr;
72}
73
74static INT
75OpenShellFolder(LPWSTR lpFolderCLSID)
76{
77 WCHAR szParameters[MAX_PATH];
78
79 /*
80 * Open a shell folder using "explorer.exe". If Explorer shell is not
81 * available, use ReactOS's alternative file browser instead.
82 * The passed CLSIDs are all subfolders of the "Control Panel" shell folder.
83 */
84 StringCbCopyW(szParameters, sizeof(szParameters), L"/n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}");
85 StringCbCatW(szParameters, sizeof(szParameters), lpFolderCLSID);
86
88 L"open",
89 GetShellWindow() ? L"explorer.exe" : L"filebrowser.exe",
90 szParameters,
91 NULL,
92 SW_SHOWDEFAULT) > 32;
93}
94
95static INT
97{
98 WCHAR szParameters[MAX_PATH];
99 StringCchCopyW(szParameters, ARRAYSIZE(szParameters), L"shell32.dll,Control_RunDLL ");
100 if (FAILED(StringCchCatW(szParameters, ARRAYSIZE(szParameters), lpCmd)))
101 return 0;
102
103 return RUNDLL(szParameters);
104}
105
106static BOOL
108{
110
112 PathAppendW(szPath, L"lusrmgr.msc");
114 return TRUE;
115
116 /*
117 * TODO: OpenControlPanelItem(L"Microsoft.UserAccounts", NULL) on Vista+ (needs usercpl.dll)
118 * See: https://learn.microsoft.com/en-us/windows/win32/shell/controlpanel-canonical-names#user-accounts
119 */
120
122 PathAppendW(szPath, L"nusrmgr.cpl"); /* The name used on WinXP */
124 return TRUE;
125
126 return RunControlPanel(L"usrmgr.cpl"); /* ROS specific name (CORE-10226) */
127}
128
129INT
130WINAPI
132 HINSTANCE hPrevInstance,
133 LPWSTR lpCmdLine,
134 INT nCmdShow)
135{
136 HKEY hKey;
137 LPWSTR *argv;
138 int argc;
139
140 /* Show the control panel window if no argument or "panel" was passed */
141 if (*lpCmdLine == 0 || !_wcsicmp(lpCmdLine, L"panel"))
142 return OpenShellFolder(L"");
143
144 /* Map legacy control panels */
145 if (!_wcsicmp(lpCmdLine, L"sticpl.cpl")) lpCmdLine = (LPWSTR) L"scannercamera";
146
147 /* Check one of the built-in control panel handlers */
148 if (!_wcsicmp(lpCmdLine, L"admintools")) return OpenShellFolder(L"\\::{D20EA4E1-3957-11d2-A40B-0C5020524153}");
149 else if (!_wcsicmp(lpCmdLine, L"color")) return RunControlPanel(L"desk.cpl,,2");
150 else if (!_wcsicmp(lpCmdLine, L"date/time")) return RunControlPanel(L"timedate.cpl");
151 else if (!_wcsicmp(lpCmdLine, L"desktop")) return RunControlPanel(L"desk.cpl");
152 else if (!_wcsicmp(lpCmdLine, L"folders")) return RUNDLL(L"shell32.dll,Options_RunDLL");
153 else if (!_wcsicmp(lpCmdLine, L"fonts")) return OpenShellFolder(L"\\::{D20EA4E1-3957-11d2-A40B-0C5020524152}");
154 else if (!_wcsicmp(lpCmdLine, L"infrared")) return RunControlPanel(L"irprops.cpl");
155 else if (!_wcsicmp(lpCmdLine, L"international")) return RunControlPanel(L"intl.cpl");
156 else if (!_wcsicmp(lpCmdLine, L"keyboard")) return RunControlPanel(L"main.cpl @1");
157 else if (!_wcsicmp(lpCmdLine, L"mouse")) return RunControlPanel(L"main.cpl @0");
158 else if (!_wcsicmp(lpCmdLine, L"netconnections")) return OpenShellFolder(L"\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}");
159 else if (!_wcsicmp(lpCmdLine, L"netware")) return RunControlPanel(L"nwc.cpl");
160 else if (!_wcsicmp(lpCmdLine, L"ports")) return RunControlPanel(L"sysdm.cpl,,1");
161 else if (!_wcsicmp(lpCmdLine, L"printers")) return OpenShellFolder(L"\\::{2227A280-3AEA-1069-A2DE-08002B30309D}");
162 else if (!_wcsicmp(lpCmdLine, L"scannercamera")) return OpenShellFolder(L"\\::{E211B736-43FD-11D1-9EFB-0000F8757FCD}");
163 else if (!_wcsicmp(lpCmdLine, L"schedtasks")) return OpenShellFolder(L"\\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}");
164 else if (!_wcsicmp(lpCmdLine, L"telephony")) return RunControlPanel(L"telephon.cpl");
165 else if (!_wcsicmp(lpCmdLine, L"userpasswords")) return OpenUserAccounts(); /* Graphical User Account Manager */
166 else if (!_wcsicmp(lpCmdLine, L"userpasswords2")) return RUNDLL(L"netplwiz.dll,UsersRunDll"); /* Dialog based advanced User Account Manager */
167
168 /* https://learn.microsoft.com/en-us/windows/win32/shell/executing-control-panel-items#windows-vista-canonical-names */
169 argv = CommandLineToArgvW(lpCmdLine, &argc);
170 if (argv)
171 {
172 UINT argi = 0;
173 HRESULT hr = -1;
174 if (argc >= 2 && IsSwitch(L"name", argv[argi + 0]))
175 {
176 LPCWSTR pszPage = NULL;
177 if (argc >= 4 && IsSwitch(L"page", argv[argi + 2]))
178 {
179 pszPage = argv[argi + 3];
180 }
181 hr = OpenControlPanelItem(argv[argi + 1], pszPage);
182 }
184 if (hr != -1)
185 {
186 return SUCCEEDED(hr);
187 }
188 }
189
190 /* It is none of them, so look for a handler in the registry */
192 L"Software\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls",
193 0,
195 &hKey) == ERROR_SUCCESS)
196 {
197 DWORD dwIndex;
198
199 for (dwIndex = 0; ; ++dwIndex)
200 {
201 DWORD dwDataSize;
202 DWORD dwValueSize = MAX_VALUE_NAME;
203 WCHAR szValueName[MAX_VALUE_NAME];
204
205 /* Get the value name and data size */
207 dwIndex,
208 szValueName,
209 &dwValueSize,
210 0,
211 NULL,
212 NULL,
213 &dwDataSize) != ERROR_SUCCESS)
214 {
215 break;
216 }
217
218 /* Check if the parameter is the value name */
219 if (!_wcsicmp(lpCmdLine, szValueName))
220 {
221 /*
222 * Allocate memory for the data plus two more characters,
223 * so we can quote the file name if required.
224 */
225 LPWSTR pszData;
226 pszData = HeapAlloc(GetProcessHeap(),
227 0,
228 dwDataSize + 2 * sizeof(WCHAR));
229 ++pszData;
230
231 /*
232 * This value is the one we are looking for, so get the data.
233 * It is the path to a .cpl file.
234 */
236 szValueName,
237 0,
238 NULL,
239 (LPBYTE)pszData,
240 &dwDataSize) == ERROR_SUCCESS)
241 {
242 INT nReturnValue;
243
244 /* Quote the file name if required */
245 if (*pszData != L'\"')
246 {
247 *(--pszData) = L'\"';
248 pszData[dwDataSize / sizeof(WCHAR)] = L'\"';
249 pszData[(dwDataSize / sizeof(WCHAR)) + 1] = 0;
250 }
251
252 nReturnValue = RunControlPanel(pszData);
253 HeapFree(GetProcessHeap(), 0, pszData);
255
256 return nReturnValue;
257 }
258
259 HeapFree(GetProcessHeap(), 0, pszData);
260 }
261 }
262
264 }
265
266 /*
267 * It's none of the known parameters, so interpret the parameter
268 * as the file name of a control panel applet.
269 */
270 return RunControlPanel(lpCmdLine);
271}
HWND hWnd
Definition: settings.c:17
static BOOL OpenUserAccounts(VOID)
Definition: control.c:107
static BOOL IsSwitch(LPCWSTR Switch, LPCWSTR Arg)
Definition: control.c:46
static HRESULT OpenControlPanelItem(LPCWSTR Name, LPCWSTR Page)
Definition: control.c:56
static INT OpenShellFolder(LPWSTR lpFolderCLSID)
Definition: control.c:75
#define ShellExec(file, params)
Definition: control.c:38
#define RUNDLL(param)
Definition: control.c:36
static INT RunControlPanel(LPCWSTR lpCmd)
Definition: control.c:96
#define MAX_VALUE_NAME
Definition: control.c:29
INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nCmdShow)
Definition: control.c:131
VOID WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow)
Definition: control.c:1177
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ARRAYSIZE(a)
Definition: cat.c:25
HINSTANCE hInstance
Definition: charmap.c:19
HRESULT hr
Definition: delayimp.cpp:582
#define ERROR_SUCCESS
Definition: deptool.c:10
LPWSTR Name
Definition: desk.c:124
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2830
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: combase.c:2842
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, IUnknown *outer, DWORD cls_context, REFIID riid, void **obj)
Definition: combase.c:1685
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2331
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4171
BOOL WINAPI PathFileExistsW(const WCHAR *path)
Definition: path.c:2583
MonoAssembly int argc
Definition: metahost.c:107
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:164
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:531
BOOL WINAPI IsOS(DWORD feature)
Definition: main.c:2392
WCHAR **WINAPI CommandLineToArgvW(const WCHAR *cmdline, int *numargs)
Definition: main.c:294
#define L(x)
Definition: resources.c:13
HINSTANCE hInst
Definition: dxdiag.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
unsigned int UINT
Definition: sysinfo.c:13
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
LPCWSTR szPath
Definition: env.c:37
#define argv
Definition: mplay32.c:18
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1305
#define PathAppendW
Definition: pathcch.h:310
short WCHAR
Definition: pedump.c:58
#define OS_ANYSERVER
Definition: shlwapi.h:255
#define SW_SHOWDEFAULT
Definition: winuser.h:791
HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpVerb, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
Definition: shlexec.cpp:2787
#define _countof(array)
Definition: sndvol32.h:70
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:166
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
STRSAFEAPI StringCbCatW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:342
Definition: ftp_var.h:139
int32_t INT_PTR
Definition: typedefs.h:64
const uint16_t * LPCWSTR
Definition: typedefs.h:57
unsigned char * LPBYTE
Definition: typedefs.h:53
uint16_t * LPWSTR
Definition: typedefs.h:56
int32_t INT
Definition: typedefs.h:58
HWND WINAPI GetShellWindow(void)
Definition: input.c:974
#define WINAPI
Definition: msvc.h:6
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12