Reactos
1/*
2 * ReactOS Explorer
3 *
4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "precomp.h"
22#include <browseui_undoc.h>
23
24HINSTANCE hExplorerInstance;
25HANDLE hProcessHeap;
26HKEY hkExplorer = NULL;
27BOOL bExplorerIsShell = FALSE;
28
29class CExplorerModule : public CComModule
30{
31public:
32};
33
34BEGIN_OBJECT_MAP(ObjectMap)
35END_OBJECT_MAP()
36
37CExplorerModule gModule;
38CAtlWinModule gWinModule;
39
40static VOID InitializeAtlModule(HINSTANCE hInstance, BOOL bInitialize)
41{
42 if (bInitialize)
43 {
44 gModule.Init(ObjectMap, hInstance, NULL);
45 }
46 else
47 {
48 gModule.Term();
49 }
50}
51
52static void
53InitializeServerAdminUI()
54{
55 HKEY hKey = SHGetShellKey(SHKEY_Root_HKCU | SHKEY_Key_Explorer, L"Advanced", TRUE);
56 if (!hKey)
57 return;
58
59 DWORD value, size = sizeof(value), type;
60 DWORD error = SHGetValueW(hKey, NULL, L"ServerAdminUI", &type, &value, &size);
61 if (error || type != REG_DWORD || size != sizeof(value))
62 {
63 // The value doesn't exist or is invalid, calculate and apply a default value
64 value = IsOS(OS_ANYSERVER) && IsUserAnAdmin();
65 SHSetValueW(hKey, NULL, L"ServerAdminUI", REG_DWORD, &value, sizeof(value));
66 if (value)
67 {
68 // TODO: Apply registry tweaks with RegInstallW; RegServerAdmin in the REGINST resource in shell32.
69 #if !ROSPOLICY_SHELL_NODEFKEYBOARDCUES
70 SystemParametersInfo(SPI_SETKEYBOARDCUES, 0, IntToPtr(TRUE), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
71 #endif
72 }
73 }
74 RegCloseKey(hKey);
75}
76
77#if !WIN7_DEBUG_MODE
78static BOOL
79SetShellReadyEvent(IN LPCWSTR lpEventName)
80{
81 HANDLE hEvent;
82
83 hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, lpEventName);
84 if (hEvent != NULL)
85 {
86 SetEvent(hEvent);
87
88 CloseHandle(hEvent);
89 return TRUE;
90 }
91
92 return FALSE;
93}
94
95static VOID
96HideMinimizedWindows(IN BOOL bHide)
97{
98 MINIMIZEDMETRICS mm;
99
100 mm.cbSize = sizeof(mm);
101 if (!SystemParametersInfoW(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
102 {
103 ERR("SystemParametersInfoW failed with %lu\n", GetLastError());
104 return;
105 }
106 if (bHide)
107 mm.iArrange |= ARW_HIDE;
108 else
109 mm.iArrange &= ~ARW_HIDE;
110 if (!SystemParametersInfoW(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
111 ERR("SystemParametersInfoW failed with %lu\n", GetLastError());
112}
113#endif
114
115static BOOL
116IsExplorerSystemShell()
117{
118 BOOL bIsSystemShell = TRUE; // Assume we are the system shell by default.
119 WCHAR szPath[MAX_PATH];
120
121 if (!GetModuleFileNameW(NULL, szPath, _countof(szPath)))
122 return FALSE;
123
124 LPWSTR szExplorer = PathFindFileNameW(szPath);
125
126 HKEY hKeyWinlogon;
127 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
128 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
129 0, KEY_READ, &hKeyWinlogon) == ERROR_SUCCESS)
130 {
131 LSTATUS Status;
132 DWORD dwType;
133 WCHAR szShell[MAX_PATH];
134 DWORD cbShell = sizeof(szShell);
135
136 // TODO: Add support for paths longer than MAX_PATH
137 Status = RegQueryValueExW(hKeyWinlogon, L"Shell", 0, &dwType, (LPBYTE)szShell, &cbShell);
138 if (Status == ERROR_SUCCESS)
139 {
140 if ((dwType != REG_SZ && dwType != REG_EXPAND_SZ) || !StrStrIW(szShell, szExplorer))
141 bIsSystemShell = FALSE;
142 }
143
144 RegCloseKey(hKeyWinlogon);
145 }
146
147 return bIsSystemShell;
148}
149
150#if !WIN7_COMPAT_MODE
151static INT
152StartWithCommandLine(IN HINSTANCE hInstance)
153{
154 BOOL b = FALSE;
155 EXPLORER_CMDLINE_PARSE_RESULTS parseResults = { 0 };
156
157 if (SHExplorerParseCmdLine(&parseResults))
158 b = SHCreateFromDesktop(&parseResults);
159
160 if (parseResults.strPath)
161 SHFree(parseResults.strPath);
162
163 if (parseResults.pidlPath)
164 ILFree(parseResults.pidlPath);
165
166 if (parseResults.pidlRoot)
167 ILFree(parseResults.pidlRoot);
168
169 return b;
170}
171#endif
172
173static INT
174StartWithDesktop(IN HINSTANCE hInstance)
175{
176 InitializeAtlModule(hInstance, TRUE);
177
178 if (RegOpenKeyW(HKEY_CURRENT_USER,
179 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
180 &hkExplorer) != ERROR_SUCCESS)
181 {
182 WCHAR Message[256];
183 LoadStringW(hInstance, IDS_STARTUP_ERROR, Message, _countof(Message));
184 MessageBox(NULL, Message, NULL, MB_ICONERROR);
185 return 1;
186 }
187
188 hExplorerInstance = hInstance;
189 hProcessHeap = GetProcessHeap();
190
191 g_TaskbarSettings.Load();
192
193 InitCommonControls();
194 OleInitialize(NULL);
195
196#if !WIN7_COMPAT_MODE
197 /* Initialize shell dde support */
198 _ShellDDEInit(TRUE);
199#endif
200
201 /* Initialize shell icons */
202 FileIconInit(TRUE);
203
204 /* Initialize CLSID_ShellWindows class */
205 _WinList_Init();
206
207 InitializeServerAdminUI();
208
209 CComPtr<ITrayWindow> Tray;
210 CreateTrayWindow(&Tray);
211
212#if !WIN7_DEBUG_MODE
213 /* This not only hides the minimized window captions in the bottom
214 left screen corner, but is also needed in order to receive
215 HSHELL_* notification messages (which are required for taskbar
216 buttons to work right) */
217 HideMinimizedWindows(TRUE);
218
219 ProcessRunOnceItems(); // Must be executed before the desktop is created
220
221 HANDLE hShellDesktop = NULL;
222 if (Tray != NULL)
223 hShellDesktop = DesktopCreateWindow(Tray);
224
225 /* WinXP: Notify msgina to hide the welcome screen */
226 if (!SetShellReadyEvent(L"msgina: ShellReadyEvent"))
227 SetShellReadyEvent(L"Global\\msgina: ShellReadyEvent");
228
229 if (DoStartStartupItems(Tray))
230 {
231 ProcessStartupItems();
232 DoFinishStartupItems();
233 }
234 ReleaseStartupMutex(); // For ProcessRunOnceItems
235#endif
236
237 if (Tray != NULL)
238 {
239 TrayMessageLoop(Tray);
240#if !WIN7_DEBUG_MODE
241 HideMinimizedWindows(FALSE);
242#endif
243 }
244
245#if !WIN7_DEBUG_MODE
246 if (hShellDesktop != NULL)
247 DesktopDestroyShellWindow(hShellDesktop);
248#endif
249
250 OleUninitialize();
251
252 RegCloseKey(hkExplorer);
253 hkExplorer = NULL;
254
255 InitializeAtlModule(hInstance, FALSE);
256
257 return 0;
258}
259
260INT WINAPI
261_tWinMain(IN HINSTANCE hInstance,
262 IN HINSTANCE hPrevInstance,
263 IN LPTSTR lpCmdLine,
264 IN INT nCmdShow)
265{
266 /*
267 * Set our shutdown parameters: we want to shutdown the very last,
268 * but before any TaskMgr instance (which has a shutdown level of 1).
269 */
270 SetProcessShutdownParameters(2, 0);
271
272 InitRSHELL();
273
274 TRACE("Explorer starting... Command line: %S\n", lpCmdLine);
275
276#if !WIN7_COMPAT_MODE
277 bExplorerIsShell = (GetShellWindow() == NULL) && IsExplorerSystemShell();
278
279 if (!bExplorerIsShell)
280 {
281 return StartWithCommandLine(hInstance);
282 }
283#else
284 bExplorerIsShell = IsExplorerSystemShell();
285#endif
286
287 return StartWithDesktop(hInstance);
288}