Reactos
at master 288 lines 7.5 kB view raw
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}