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