Sync with trunk r58151 to bring the latest changes from Amine and Timo.
[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 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 INT WINAPI
352 _tWinMain(IN HINSTANCE hInstance,
353 IN HINSTANCE hPrevInstance,
354 IN LPTSTR lpCmdLine,
355 IN INT nCmdShow)
356 {
357 ITrayWindow *Tray = NULL;
358 HANDLE hShellDesktop = NULL;
359 BOOL CreateShellDesktop = FALSE;
360
361 if (RegOpenKey(HKEY_CURRENT_USER,
362 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
363 &hkExplorer) != ERROR_SUCCESS)
364 {
365 TCHAR Message[256];
366 LoadString(hInstance, IDS_STARTUP_ERROR, Message, 256);
367 MessageBox(NULL, Message, NULL, MB_ICONERROR);
368 return 1;
369 }
370
371 hExplorerInstance = hInstance;
372 hProcessHeap = GetProcessHeap();
373 LoadAdvancedSettings();
374
375 hUser32 = GetModuleHandle(TEXT("USER32.DLL"));
376 if (hUser32 != NULL)
377 {
378 DrawCapTemp = (DRAWCAPTEMP)GetProcAddress(hUser32,
379 PROC_NAME_DRAWCAPTIONTEMP);
380 }
381
382 InitCommonControls();
383 OleInitialize(NULL);
384
385 if (GetShellWindow() == NULL)
386 CreateShellDesktop = TRUE;
387
388 /* FIXME - initialize SSO Thread */
389
390 if (CreateShellDesktop)
391 {
392 if (RegisterTrayWindowClass() && RegisterTaskSwitchWndClass())
393 {
394 Tray = CreateTrayWindow();
395
396 if (Tray != NULL)
397 hShellDesktop = DesktopCreateWindow(Tray);
398 }
399
400 /* WinXP: Notify msgina to hide the welcome screen */
401 if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
402 SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
403 }
404 else
405 {
406 /* A shell is already loaded. Parse the command line arguments
407 and unless we need to do something specific simply display
408 the desktop in a separate explorer window */
409 /* FIXME */
410 }
411
412 if (Tray != NULL)
413 {
414 RegisterHotKey(NULL, IDHK_RUN, MOD_WIN, 'R');
415 TrayMessageLoop(Tray);
416 ITrayWindow_Release(Tray);
417 UnregisterTrayWindowClass();
418 }
419
420 if (hShellDesktop != NULL)
421 DesktopDestroyShellWindow(hShellDesktop);
422
423 /* FIXME - shutdown SSO Thread */
424
425 OleUninitialize();
426
427 RegCloseKey(hkExplorer);
428 hkExplorer = NULL;
429
430 return 0;
431 }