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
24 HINSTANCE hExplorerInstance;
25 HANDLE hProcessHeap;
26 HKEY hkExplorer = NULL;
27 BOOL bExplorerIsShell = FALSE;
28
29 class CExplorerModule : public CComModule
30 {
31 public:
32 };
33
34 BEGIN_OBJECT_MAP(ObjectMap)
35 END_OBJECT_MAP()
36
37 CExplorerModule gModule;
38 CAtlWinModule gWinModule;
39
InitializeAtlModule(HINSTANCE hInstance,BOOL bInitialize)40 static 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
52 #if !WIN7_DEBUG_MODE
53 static BOOL
SetShellReadyEvent(IN LPCWSTR lpEventName)54 SetShellReadyEvent(IN LPCWSTR lpEventName)
55 {
56 HANDLE hEvent;
57
58 hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, lpEventName);
59 if (hEvent != NULL)
60 {
61 SetEvent(hEvent);
62
63 CloseHandle(hEvent);
64 return TRUE;
65 }
66
67 return FALSE;
68 }
69
70 static VOID
HideMinimizedWindows(IN BOOL bHide)71 HideMinimizedWindows(IN BOOL bHide)
72 {
73 MINIMIZEDMETRICS mm;
74
75 mm.cbSize = sizeof(mm);
76 if (!SystemParametersInfoW(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
77 {
78 ERR("SystemParametersInfoW failed with %lu\n", GetLastError());
79 return;
80 }
81 if (bHide)
82 mm.iArrange |= ARW_HIDE;
83 else
84 mm.iArrange &= ~ARW_HIDE;
85 if (!SystemParametersInfoW(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
86 ERR("SystemParametersInfoW failed with %lu\n", GetLastError());
87 }
88 #endif
89
90 static BOOL
IsExplorerSystemShell()91 IsExplorerSystemShell()
92 {
93 BOOL bIsSystemShell = TRUE; // Assume we are the system shell by default.
94 WCHAR szPath[MAX_PATH];
95
96 if (!GetModuleFileNameW(NULL, szPath, _countof(szPath)))
97 return FALSE;
98
99 LPWSTR szExplorer = PathFindFileNameW(szPath);
100
101 HKEY hKeyWinlogon;
102 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
103 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
104 0, KEY_READ, &hKeyWinlogon) == ERROR_SUCCESS)
105 {
106 LSTATUS Status;
107 DWORD dwType;
108 WCHAR szShell[MAX_PATH];
109 DWORD cbShell = sizeof(szShell);
110
111 // TODO: Add support for paths longer than MAX_PATH
112 Status = RegQueryValueExW(hKeyWinlogon, L"Shell", 0, &dwType, (LPBYTE)szShell, &cbShell);
113 if (Status == ERROR_SUCCESS)
114 {
115 if ((dwType != REG_SZ && dwType != REG_EXPAND_SZ) || !StrStrIW(szShell, szExplorer))
116 bIsSystemShell = FALSE;
117 }
118
119 RegCloseKey(hKeyWinlogon);
120 }
121
122 return bIsSystemShell;
123 }
124
125 #if !WIN7_COMPAT_MODE
126 static INT
StartWithCommandLine(IN HINSTANCE hInstance)127 StartWithCommandLine(IN HINSTANCE hInstance)
128 {
129 BOOL b = FALSE;
130 EXPLORER_CMDLINE_PARSE_RESULTS parseResults = { 0 };
131
132 if (SHExplorerParseCmdLine(&parseResults))
133 b = SHCreateFromDesktop(&parseResults);
134
135 if (parseResults.strPath)
136 SHFree(parseResults.strPath);
137
138 if (parseResults.pidlPath)
139 ILFree(parseResults.pidlPath);
140
141 if (parseResults.pidlRoot)
142 ILFree(parseResults.pidlRoot);
143
144 return b;
145 }
146 #endif
147
148 static INT
StartWithDesktop(IN HINSTANCE hInstance)149 StartWithDesktop(IN HINSTANCE hInstance)
150 {
151 InitializeAtlModule(hInstance, TRUE);
152
153 if (RegOpenKeyW(HKEY_CURRENT_USER,
154 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
155 &hkExplorer) != ERROR_SUCCESS)
156 {
157 WCHAR Message[256];
158 LoadStringW(hInstance, IDS_STARTUP_ERROR, Message, _countof(Message));
159 MessageBox(NULL, Message, NULL, MB_ICONERROR);
160 return 1;
161 }
162
163 hExplorerInstance = hInstance;
164 hProcessHeap = GetProcessHeap();
165
166 g_TaskbarSettings.Load();
167
168 InitCommonControls();
169 OleInitialize(NULL);
170
171 #if !WIN7_COMPAT_MODE
172 /* Initialize shell dde support */
173 _ShellDDEInit(TRUE);
174 #endif
175
176 /* Initialize shell icons */
177 FileIconInit(TRUE);
178
179 /* Initialize CLSID_ShellWindows class */
180 _WinList_Init();
181
182 CComPtr<ITrayWindow> Tray;
183 CreateTrayWindow(&Tray);
184
185 #if !WIN7_DEBUG_MODE
186 /* This not only hides the minimized window captions in the bottom
187 left screen corner, but is also needed in order to receive
188 HSHELL_* notification messages (which are required for taskbar
189 buttons to work right) */
190 HideMinimizedWindows(TRUE);
191
192 ProcessRunOnceItems(); // Must be executed before the desktop is created
193
194 HANDLE hShellDesktop = NULL;
195 if (Tray != NULL)
196 hShellDesktop = DesktopCreateWindow(Tray);
197
198 /* WinXP: Notify msgina to hide the welcome screen */
199 if (!SetShellReadyEvent(L"msgina: ShellReadyEvent"))
200 SetShellReadyEvent(L"Global\\msgina: ShellReadyEvent");
201
202 if (DoStartStartupItems(Tray))
203 {
204 ProcessStartupItems();
205 DoFinishStartupItems();
206 }
207 ReleaseStartupMutex(); // For ProcessRunOnceItems
208 #endif
209
210 if (Tray != NULL)
211 {
212 TrayMessageLoop(Tray);
213 #if !WIN7_DEBUG_MODE
214 HideMinimizedWindows(FALSE);
215 #endif
216 }
217
218 #if !WIN7_DEBUG_MODE
219 if (hShellDesktop != NULL)
220 DesktopDestroyShellWindow(hShellDesktop);
221 #endif
222
223 OleUninitialize();
224
225 RegCloseKey(hkExplorer);
226 hkExplorer = NULL;
227
228 InitializeAtlModule(hInstance, FALSE);
229
230 return 0;
231 }
232
233 INT WINAPI
_tWinMain(IN HINSTANCE hInstance,IN HINSTANCE hPrevInstance,IN LPTSTR lpCmdLine,IN INT nCmdShow)234 _tWinMain(IN HINSTANCE hInstance,
235 IN HINSTANCE hPrevInstance,
236 IN LPTSTR lpCmdLine,
237 IN INT nCmdShow)
238 {
239 /*
240 * Set our shutdown parameters: we want to shutdown the very last,
241 * but before any TaskMgr instance (which has a shutdown level of 1).
242 */
243 SetProcessShutdownParameters(2, 0);
244
245 InitRSHELL();
246
247 TRACE("Explorer starting... Command line: %S\n", lpCmdLine);
248
249 #if !WIN7_COMPAT_MODE
250 bExplorerIsShell = (GetShellWindow() == NULL) && IsExplorerSystemShell();
251
252 if (!bExplorerIsShell)
253 {
254 return StartWithCommandLine(hInstance);
255 }
256 #else
257 bExplorerIsShell = IsExplorerSystemShell();
258 #endif
259
260 return StartWithDesktop(hInstance);
261 }
262