[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
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 DbgPrint("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 DbgPrint("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 if (RegOpenKey(HKEY_CURRENT_USER,
385 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
386 &hkExplorer) != ERROR_SUCCESS)
387 {
388 TCHAR Message[256];
389 LoadString(hInstance, IDS_STARTUP_ERROR, Message, 256);
390 MessageBox(NULL, Message, NULL, MB_ICONERROR);
391 return 1;
392 }
393
394 hExplorerInstance = hInstance;
395 hProcessHeap = GetProcessHeap();
396 LoadAdvancedSettings();
397
398 hUser32 = GetModuleHandle(TEXT("USER32.DLL"));
399 if (hUser32 != NULL)
400 {
401 DrawCapTemp = (DRAWCAPTEMP)GetProcAddress(hUser32,
402 PROC_NAME_DRAWCAPTIONTEMP);
403 }
404
405 InitCommonControls();
406 OleInitialize(NULL);
407
408 ProcessStartupItems();
409
410 if (GetShellWindow() == NULL)
411 CreateShellDesktop = TRUE;
412
413 /* FIXME - initialize SSO Thread */
414
415 if (CreateShellDesktop)
416 {
417 /* Initialize shell dde support */
418 ShellDDEInit(TRUE);
419
420 /* Initialize shell icons */
421 FileIconInit(TRUE);
422
423 /* Initialize CLSID_ShellWindows class */
424 WinList_Init();
425
426 if (RegisterTrayWindowClass() && RegisterTaskSwitchWndClass())
427 {
428 Tray = CreateTrayWindow();
429 /* This not only hides the minimized window captions in the bottom
430 left screen corner, but is also needed in order to receive
431 HSHELL_* notification messages (which are required for taskbar
432 buttons to work right) */
433 HideMinimizedWindows(TRUE);
434
435 if (Tray != NULL)
436 hShellDesktop = DesktopCreateWindow(Tray);
437 }
438
439 /* WinXP: Notify msgina to hide the welcome screen */
440 if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
441 SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
442 }
443 else
444 {
445 /* A shell is already loaded. Parse the command line arguments
446 and unless we need to do something specific simply display
447 the desktop in a separate explorer window */
448 /* FIXME */
449 }
450
451 if (Tray != NULL)
452 {
453 RegisterHotKey(NULL, IDHK_RUN, MOD_WIN, 'R');
454 TrayMessageLoop(Tray);
455 HideMinimizedWindows(FALSE);
456 ITrayWindow_Release(Tray);
457 UnregisterTrayWindowClass();
458 }
459
460 if (hShellDesktop != NULL)
461 DesktopDestroyShellWindow(hShellDesktop);
462
463 /* FIXME - shutdown SSO Thread */
464
465 OleUninitialize();
466
467 RegCloseKey(hkExplorer);
468 hkExplorer = NULL;
469
470 return 0;
471 }