d008cae4abdff35ac8b59675b576c0a94081f0bc
[reactos.git] / base / applications / control / control.c
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
14 #include <windef.h>
15 #include <winbase.h>
16 #include <winuser.h>
17 #include <winreg.h>
18 #include <shellapi.h>
19 #include <strsafe.h>
20
21 #include "resource.h"
22
23 #define MAX_VALUE_NAME 16383
24
25 /*
26 * Macro for calling "rundll32.exe"
27 * According to MSDN, ShellExecute returns a value greater than 32
28 * if the operation was successful.
29 */
30 #define RUNDLL(param) \
31 ((INT_PTR)ShellExecuteW(NULL, L"open", L"rundll32.exe", (param), NULL, SW_SHOWDEFAULT) > 32)
32
33 VOID
34 WINAPI
35 Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
36
37 static INT
38 OpenShellFolder(LPWSTR lpFolderCLSID)
39 {
40 WCHAR szParameters[MAX_PATH];
41
42 /*
43 * Open a shell folder using "explorer.exe". The passed CLSIDs
44 * are all subfolders of the "Control Panel" shell folder.
45 */
46 StringCbCopy(szParameters, sizeof(szParameters), L"/n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}");
47 StringCbCat(szParameters,sizeof(szParameters), lpFolderCLSID);
48
49 return (INT_PTR)ShellExecuteW(NULL,
50 L"open",
51 L"explorer.exe",
52 szParameters,
53 NULL,
54 SW_SHOWDEFAULT) > 32;
55 }
56
57 static INT
58 RunControlPanel(LPCWSTR lpCmd)
59 {
60 /*
61 * Old method:
62 *
63 WCHAR szParameters[MAX_PATH];
64 wcscpy(szParameters, L"shell32.dll,Control_RunDLL ");
65 wcscat(szParameters, lpCmd);
66 return RUNDLL(szParameters);
67 */
68
69 /* New method: */
70 Control_RunDLLW(GetDesktopWindow(), 0, lpCmd, SW_SHOW);
71 return 1;
72 }
73
74 INT
75 WINAPI
76 wWinMain(HINSTANCE hInstance,
77 HINSTANCE hPrevInstance,
78 LPWSTR lpCmdLine,
79 INT nCmdShow)
80 {
81 HKEY hKey;
82
83 /* Show the control panel window if no argument or "panel" was passed */
84 if (*lpCmdLine == 0 || !_wcsicmp(lpCmdLine, L"panel"))
85 return OpenShellFolder(L"");
86
87 /* Check one of the built-in control panel handlers */
88 if (!_wcsicmp(lpCmdLine, L"admintools")) return OpenShellFolder(L"\\::{D20EA4E1-3957-11d2-A40B-0C5020524153}");
89 else if (!_wcsicmp(lpCmdLine, L"color")) return RunControlPanel(L"desk.cpl"); /* TODO: Switch to the "Apperance" tab */
90 else if (!_wcsicmp(lpCmdLine, L"date/time")) return RunControlPanel(L"timedate.cpl");
91 else if (!_wcsicmp(lpCmdLine, L"desktop")) return RunControlPanel(L"desk.cpl");
92 else if (!_wcsicmp(lpCmdLine, L"folders")) return RUNDLL(L"shell32.dll,Options_RunDLL");
93 else if (!_wcsicmp(lpCmdLine, L"fonts")) return OpenShellFolder(L"\\::{D20EA4E1-3957-11d2-A40B-0C5020524152}");
94 else if (!_wcsicmp(lpCmdLine, L"infrared")) return RunControlPanel(L"irprops.cpl");
95 else if (!_wcsicmp(lpCmdLine, L"international")) return RunControlPanel(L"intl.cpl");
96 else if (!_wcsicmp(lpCmdLine, L"keyboard")) return RunControlPanel(L"main.cpl @1");
97 else if (!_wcsicmp(lpCmdLine, L"mouse")) return RunControlPanel(L"main.cpl @0");
98 else if (!_wcsicmp(lpCmdLine, L"netconnections")) return OpenShellFolder(L"\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}");
99 else if (!_wcsicmp(lpCmdLine, L"netware")) return RunControlPanel(L"nwc.cpl");
100 else if (!_wcsicmp(lpCmdLine, L"ports")) return RunControlPanel(L"sysdm.cpl"); /* TODO: Switch to the "Computer Name" tab */
101 else if (!_wcsicmp(lpCmdLine, L"printers")) return OpenShellFolder(L"\\::{2227A280-3AEA-1069-A2DE-08002B30309D}");
102 else if (!_wcsicmp(lpCmdLine, L"scannercamera")) return OpenShellFolder(L"\\::{E211B736-43FD-11D1-9EFB-0000F8757FCD}");
103 else if (!_wcsicmp(lpCmdLine, L"schedtasks")) return OpenShellFolder(L"\\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}");
104 else if (!_wcsicmp(lpCmdLine, L"telephony")) return RunControlPanel(L"telephon.cpl");
105 else if (!_wcsicmp(lpCmdLine, L"userpasswords")) return RunControlPanel(L"nusrmgr.cpl"); /* Graphical User Account Manager */
106 else if (!_wcsicmp(lpCmdLine, L"userpasswords2")) return RUNDLL(L"netplwiz.dll,UsersRunDll"); /* Dialog based advanced User Account Manager */
107
108 /* It is none of them, so look for a handler in the registry */
109 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
110 L"Software\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls",
111 0,
112 KEY_QUERY_VALUE,
113 &hKey) == ERROR_SUCCESS)
114 {
115 DWORD dwIndex;
116
117 for (dwIndex = 0; ; ++dwIndex)
118 {
119 DWORD dwDataSize;
120 DWORD dwValueSize = MAX_VALUE_NAME;
121 WCHAR szValueName[MAX_VALUE_NAME];
122
123 /* Get the value name and data size */
124 if (RegEnumValueW(hKey,
125 dwIndex,
126 szValueName,
127 &dwValueSize,
128 0,
129 NULL,
130 NULL,
131 &dwDataSize) != ERROR_SUCCESS)
132 {
133 break;
134 }
135
136 /* Check if the parameter is the value name */
137 if (!_wcsicmp(lpCmdLine, szValueName))
138 {
139 /*
140 * Allocate memory for the data plus two more characters,
141 * so we can quote the file name if required.
142 */
143 LPWSTR pszData;
144 pszData = HeapAlloc(GetProcessHeap(),
145 0,
146 dwDataSize + 2 * sizeof(WCHAR));
147 ++pszData;
148
149 /*
150 * This value is the one we are looking for, so get the data.
151 * It is the path to a .cpl file.
152 */
153 if (RegQueryValueExW(hKey,
154 szValueName,
155 0,
156 NULL,
157 (LPBYTE)pszData,
158 &dwDataSize) == ERROR_SUCCESS)
159 {
160 INT nReturnValue;
161
162 /* Quote the file name if required */
163 if (*pszData != L'\"')
164 {
165 *(--pszData) = L'\"';
166 pszData[dwDataSize / sizeof(WCHAR)] = L'\"';
167 pszData[(dwDataSize / sizeof(WCHAR)) + 1] = 0;
168 }
169
170 nReturnValue = RunControlPanel(pszData);
171 HeapFree(GetProcessHeap(), 0, pszData);
172 RegCloseKey(hKey);
173
174 return nReturnValue;
175 }
176
177 HeapFree(GetProcessHeap(), 0, pszData);
178 }
179 }
180
181 RegCloseKey(hKey);
182 }
183
184 /*
185 * It's none of the known parameters, so interpret the parameter
186 * as the file name of a control panel applet.
187 */
188 return RunControlPanel(lpCmdLine);
189 }