[RSHELL]
[reactos.git] / base / shell / explorer-new / explorer.c
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 <shlwapi_undoc.h>
23 #include <winver.h>
24
25 HINSTANCE hExplorerInstance;
26 HMODULE hUser32;
27 HANDLE hProcessHeap;
28 HKEY hkExplorer = NULL;
29 DRAWCAPTEMP DrawCapTemp = NULL;
30
31 typedef struct _LANGCODEPAGE
32 {
33 WORD wLanguage;
34 WORD wCodePage;
35 } LANGCODEPAGE, *PLANGCODEPAGE;
36
37 LONG
38 SetWindowStyle(IN HWND hWnd,
39 IN LONG dwStyleMask,
40 IN LONG dwStyle)
41 {
42 LONG PrevStyle, Style;
43
44 ASSERT((~dwStyleMask & dwStyle) == 0);
45
46 PrevStyle = GetWindowLong(hWnd,
47 GWL_STYLE);
48 if (PrevStyle != 0 &&
49 (PrevStyle & dwStyleMask) != dwStyle)
50 {
51 Style = PrevStyle & ~dwStyleMask;
52 Style |= dwStyle;
53
54 PrevStyle = SetWindowLong(hWnd,
55 GWL_STYLE,
56 Style);
57 }
58
59 return PrevStyle;
60 }
61
62 LONG
63 SetWindowExStyle(IN HWND hWnd,
64 IN LONG dwStyleMask,
65 IN LONG dwStyle)
66 {
67 LONG PrevStyle, Style;
68
69 ASSERT((~dwStyleMask & dwStyle) == 0);
70
71 PrevStyle = GetWindowLong(hWnd,
72 GWL_EXSTYLE);
73 if (PrevStyle != 0 &&
74 (PrevStyle & dwStyleMask) != dwStyle)
75 {
76 Style = PrevStyle & ~dwStyleMask;
77 Style |= dwStyle;
78
79 PrevStyle = SetWindowLong(hWnd,
80 GWL_EXSTYLE,
81 Style);
82 }
83
84 return PrevStyle;
85 }
86
87 HMENU
88 LoadPopupMenu(IN HINSTANCE hInstance,
89 IN LPCTSTR lpMenuName)
90 {
91 HMENU hMenu, hSubMenu = NULL;
92
93 hMenu = LoadMenu(hInstance,
94 lpMenuName);
95
96 if (hMenu != NULL)
97 {
98 hSubMenu = GetSubMenu(hMenu,
99 0);
100 if (hSubMenu != NULL &&
101 !RemoveMenu(hMenu,
102 0,
103 MF_BYPOSITION))
104 {
105 hSubMenu = NULL;
106 }
107
108 DestroyMenu(hMenu);
109 }
110
111 return hSubMenu;
112 }
113
114 HMENU
115 FindSubMenu(IN HMENU hMenu,
116 IN UINT uItem,
117 IN BOOL fByPosition)
118 {
119 MENUITEMINFO mii;
120
121 mii.cbSize = sizeof(mii);
122 mii.fMask = MIIM_SUBMENU;
123
124 if (GetMenuItemInfo(hMenu,
125 uItem,
126 fByPosition,
127 &mii))
128 {
129 return mii.hSubMenu;
130 }
131
132 return NULL;
133 }
134
135 BOOL
136 GetCurrentLoggedOnUserName(OUT LPTSTR szBuffer,
137 IN DWORD dwBufferSize)
138 {
139 DWORD dwType;
140 DWORD dwSize;
141
142 /* Query the user name from the registry */
143 dwSize = (dwBufferSize * sizeof(TCHAR)) - 1;
144 if (RegQueryValueEx(hkExplorer,
145 TEXT("Logon User Name"),
146 0,
147 &dwType,
148 (LPBYTE)szBuffer,
149 &dwSize) == ERROR_SUCCESS &&
150 (dwSize / sizeof(TCHAR)) > 1 &&
151 szBuffer[0] != _T('\0'))
152 {
153 szBuffer[dwSize / sizeof(TCHAR)] = _T('\0');
154 return TRUE;
155 }
156
157 /* Fall back to GetUserName() */
158 dwSize = dwBufferSize;
159 if (!GetUserName(szBuffer,
160 &dwSize))
161 {
162 szBuffer[0] = _T('\0');
163 return FALSE;
164 }
165
166 return TRUE;
167 }
168
169 BOOL
170 FormatMenuString(IN HMENU hMenu,
171 IN UINT uPosition,
172 IN UINT uFlags,
173 ...)
174 {
175 va_list vl;
176 MENUITEMINFO mii;
177 TCHAR szBuf[128];
178 TCHAR szBufFmt[128];
179
180 /* Find the menu item and read the formatting string */
181 mii.cbSize = sizeof(mii);
182 mii.fMask = MIIM_STRING;
183 mii.dwTypeData = (LPTSTR)szBufFmt;
184 mii.cch = sizeof(szBufFmt) / sizeof(szBufFmt[0]);
185 if (GetMenuItemInfo(hMenu,
186 uPosition,
187 uFlags,
188 &mii))
189 {
190 /* Format the string */
191 va_start(vl, uFlags);
192 _vsntprintf(szBuf,
193 (sizeof(szBuf) / sizeof(szBuf[0])) - 1,
194 szBufFmt,
195 vl);
196 va_end(vl);
197 szBuf[(sizeof(szBuf) / sizeof(szBuf[0])) - 1] = _T('\0');
198
199 /* Update the menu item */
200 mii.dwTypeData = (LPTSTR)szBuf;
201 if (SetMenuItemInfo(hMenu,
202 uPosition,
203 uFlags,
204 &mii))
205 {
206 return TRUE;
207 }
208 }
209
210 return FALSE;
211 }
212
213 BOOL
214 GetExplorerRegValueSet(IN HKEY hKey,
215 IN LPCTSTR lpSubKey,
216 IN LPCTSTR lpValue)
217 {
218 TCHAR szBuffer[MAX_PATH];
219 HKEY hkSubKey;
220 DWORD dwType, dwSize;
221 BOOL Ret = FALSE;
222
223 StringCbCopy(szBuffer, sizeof(szBuffer),
224 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"));
225 if (FAILED(StringCbCat(szBuffer, sizeof(szBuffer),
226 _T("\\"))))
227 return FALSE;
228 if (FAILED(StringCbCat(szBuffer, sizeof(szBuffer),
229 lpSubKey)))
230 return FALSE;
231
232 dwSize = sizeof(szBuffer);
233 if (RegOpenKeyEx(hKey,
234 szBuffer,
235 0,
236 KEY_QUERY_VALUE,
237 &hkSubKey) == ERROR_SUCCESS)
238 {
239 ZeroMemory(szBuffer,
240 sizeof(szBuffer));
241
242 if (RegQueryValueEx(hkSubKey,
243 lpValue,
244 0,
245 &dwType,
246 (LPBYTE)szBuffer,
247 &dwSize) == ERROR_SUCCESS)
248 {
249 if (dwType == REG_DWORD && dwSize == sizeof(DWORD))
250 Ret = *((PDWORD)szBuffer) != 0;
251 else if (dwSize > 0)
252 Ret = *((PUCHAR)szBuffer) != 0;
253 }
254
255 RegCloseKey(hkSubKey);
256 }
257 return Ret;
258 }
259
260
261 static BOOL
262 SetShellReadyEvent(IN LPCTSTR lpEventName)
263 {
264 HANDLE hEvent;
265
266 hEvent = OpenEvent(EVENT_MODIFY_STATE,
267 FALSE,
268 lpEventName);
269 if (hEvent != NULL)
270 {
271 SetEvent(hEvent);
272
273 CloseHandle(hEvent);
274 return TRUE;
275 }
276
277 return FALSE;
278 }
279
280 BOOL
281 GetVersionInfoString(IN TCHAR *szFileName,
282 IN TCHAR *szVersionInfo,
283 OUT TCHAR *szBuffer,
284 IN UINT cbBufLen)
285 {
286 LPVOID lpData = NULL;
287 TCHAR szSubBlock[128];
288 TCHAR *lpszLocalBuf = NULL;
289 LANGID UserLangId;
290 PLANGCODEPAGE lpTranslate = NULL;
291 DWORD dwLen;
292 DWORD dwHandle;
293 UINT cbTranslate;
294 UINT cbLen;
295 BOOL bRet = FALSE;
296 unsigned int i;
297
298 dwLen = GetFileVersionInfoSize(szFileName, &dwHandle);
299
300 if (dwLen > 0)
301 {
302 lpData = HeapAlloc(hProcessHeap, 0, dwLen);
303
304 if (lpData != NULL)
305 {
306 if (GetFileVersionInfo(szFileName,
307 0,
308 dwLen,
309 lpData) != 0)
310 {
311 UserLangId = GetUserDefaultLangID();
312
313 VerQueryValue(lpData,
314 TEXT("\\VarFileInfo\\Translation"),
315 (LPVOID *)&lpTranslate,
316 &cbTranslate);
317
318 for (i = 0; i < cbTranslate / sizeof(LANGCODEPAGE); i++)
319 {
320 /* If the bottom eight bits of the language id's
321 match, use this version information (since this
322 means that the version information and the users
323 default language are the same). */
324 if ((lpTranslate[i].wLanguage & 0xFF) ==
325 (UserLangId & 0xFF))
326 {
327 wnsprintf(szSubBlock,
328 sizeof(szSubBlock) / sizeof(szSubBlock[0]),
329 TEXT("\\StringFileInfo\\%04X%04X\\%s"),
330 lpTranslate[i].wLanguage,
331 lpTranslate[i].wCodePage,
332 szVersionInfo);
333
334 if (VerQueryValue(lpData,
335 szSubBlock,
336 (LPVOID *)&lpszLocalBuf,
337 &cbLen) != 0)
338 {
339 _tcsncpy(szBuffer, lpszLocalBuf, cbBufLen / sizeof(*szBuffer));
340
341 bRet = TRUE;
342 break;
343 }
344 }
345 }
346 }
347 HeapFree(hProcessHeap, 0, lpData);
348 lpData = NULL;
349 }
350 }
351
352 return bRet;
353 }
354
355 static VOID
356 HideMinimizedWindows(IN BOOL bHide)
357 {
358 MINIMIZEDMETRICS mm;
359
360 mm.cbSize = sizeof(mm);
361 if (!SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
362 {
363 ERR("SystemParametersInfo failed with %lu\n", GetLastError());
364 return;
365 }
366 if (bHide)
367 mm.iArrange |= ARW_HIDE;
368 else
369 mm.iArrange &= ~ARW_HIDE;
370 if (!SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
371 ERR("SystemParametersInfo failed with %lu\n", GetLastError());
372 }
373
374 INT WINAPI
375 _tWinMain(IN HINSTANCE hInstance,
376 IN HINSTANCE hPrevInstance,
377 IN LPTSTR lpCmdLine,
378 IN INT nCmdShow)
379 {
380 ITrayWindow *Tray = NULL;
381 HANDLE hShellDesktop = NULL;
382 BOOL CreateShellDesktop = FALSE;
383
384 DbgPrint("Explorer starting... Commandline: %S\n", lpCmdLine);
385
386 /*
387 * Set our shutdown parameters: we want to shutdown the very last,
388 * but before any TaskMgr instance (which has a shutdown level of 1).
389 */
390 SetProcessShutdownParameters(2, 0);
391
392 if (GetShellWindow() == NULL)
393 CreateShellDesktop = TRUE;
394
395 if (!CreateShellDesktop)
396 {
397 EXPLORER_CMDLINE_PARSE_RESULTS parseResults = { 0 };
398
399 if (SHExplorerParseCmdLine(&parseResults))
400 return SHCreateFromDesktop(&parseResults);
401
402 if (parseResults.strPath)
403 SHFree(parseResults.strPath);
404
405 if (parseResults.pidlPath)
406 ILFree(parseResults.pidlPath);
407
408 if (parseResults.pidlRoot)
409 ILFree(parseResults.pidlRoot);
410
411 }
412
413 if (RegOpenKey(HKEY_CURRENT_USER,
414 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
415 &hkExplorer) != ERROR_SUCCESS)
416 {
417 TCHAR Message[256];
418 LoadString(hInstance, IDS_STARTUP_ERROR, Message, 256);
419 MessageBox(NULL, Message, NULL, MB_ICONERROR);
420 return 1;
421 }
422
423 hExplorerInstance = hInstance;
424 hProcessHeap = GetProcessHeap();
425 LoadAdvancedSettings();
426
427 hUser32 = GetModuleHandle(TEXT("USER32.DLL"));
428 if (hUser32 != NULL)
429 {
430 DrawCapTemp = (DRAWCAPTEMP)GetProcAddress(hUser32,
431 PROC_NAME_DRAWCAPTIONTEMP);
432 }
433
434 InitCommonControls();
435 OleInitialize(NULL);
436
437 ProcessStartupItems();
438
439 /* Initialize shell dde support */
440 ShellDDEInit(TRUE);
441
442 /* Initialize shell icons */
443 FileIconInit(TRUE);
444
445 /* Initialize CLSID_ShellWindows class */
446 WinList_Init();
447
448 if (RegisterTrayWindowClass() && RegisterTaskSwitchWndClass())
449 {
450 Tray = CreateTrayWindow();
451 /* This not only hides the minimized window captions in the bottom
452 left screen corner, but is also needed in order to receive
453 HSHELL_* notification messages (which are required for taskbar
454 buttons to work right) */
455 HideMinimizedWindows(TRUE);
456
457 if (Tray != NULL)
458 hShellDesktop = DesktopCreateWindow(Tray);
459 }
460
461 /* WinXP: Notify msgina to hide the welcome screen */
462 if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
463 SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
464
465 if (Tray != NULL)
466 {
467 RegisterHotKey(NULL, IDHK_RUN, MOD_WIN, 'R');
468 TrayMessageLoop(Tray);
469 HideMinimizedWindows(FALSE);
470 ITrayWindow_Release(Tray);
471 UnregisterTrayWindowClass();
472 }
473
474 if (hShellDesktop != NULL)
475 DesktopDestroyShellWindow(hShellDesktop);
476
477 /* FIXME - shutdown SSO Thread */
478
479 OleUninitialize();
480
481 RegCloseKey(hkExplorer);
482 hkExplorer = NULL;
483
484 return 0;
485 }