more rosshell separations
[reactos.git] / reactos / subsys / system / explorer / explorer.cpp
1 /*
2 * Copyright 2003, 2004, 2005 Martin Fuchs
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19
20 //
21 // Explorer clone, lean version
22 //
23 // explorer.cpp
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27 // Credits: Thanks to Leon Finker for his explorer window example
28 //
29
30
31 #include "precomp.h"
32
33 #include "explorer_intres.h"
34
35 #include <locale.h> // for setlocale()
36
37
38 DynamicLoadLibFct<void(__stdcall*)(BOOL)> g_SHDOCVW_ShellDDEInit(TEXT("SHDOCVW"), 118);
39
40
41 ExplorerGlobals g_Globals;
42
43
44 ExplorerGlobals::ExplorerGlobals()
45 {
46 _hInstance = 0;
47 _cfStrFName = 0;
48
49 #ifndef ROSSHELL
50 _hframeClass = 0;
51 _hMainWnd = 0;
52 _desktop_mode = false;
53 _prescan_nodes = false;
54 #endif
55
56 _log = NULL;
57 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
58 _SHRestricted = 0;
59 #endif
60 _hwndDesktopBar = 0;
61 _hwndShellView = 0;
62 _hwndDesktop = 0;
63 }
64
65
66 void ExplorerGlobals::init(HINSTANCE hInstance)
67 {
68 _hInstance = hInstance;
69
70 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
71 _SHRestricted = (DWORD(STDAPICALLTYPE*)(RESTRICTIONS)) GetProcAddress(GetModuleHandle(TEXT("SHELL32")), "SHRestricted");
72 #endif
73
74 _icon_cache.init();
75 }
76
77
78 void _log_(LPCTSTR txt)
79 {
80 FmtString msg(TEXT("%s\n"), txt);
81
82 if (g_Globals._log)
83 _fputts(msg, g_Globals._log);
84
85 OutputDebugString(msg);
86 }
87
88
89 bool FileTypeManager::is_exe_file(LPCTSTR ext)
90 {
91 static const LPCTSTR s_executable_extensions[] = {
92 TEXT("COM"),
93 TEXT("EXE"),
94 TEXT("BAT"),
95 TEXT("CMD"),
96 TEXT("CMM"),
97 TEXT("BTM"),
98 TEXT("AWK"),
99 0
100 };
101
102 TCHAR ext_buffer[_MAX_EXT];
103 const LPCTSTR* p;
104 LPCTSTR s;
105 LPTSTR d;
106
107 for(s=ext+1,d=ext_buffer; (*d=toupper(*s)); s++)
108 ++d;
109
110 for(p=s_executable_extensions; *p; p++)
111 if (!lstrcmp(ext_buffer, *p))
112 return true;
113
114 return false;
115 }
116
117
118 const FileTypeInfo& FileTypeManager::operator[](String ext)
119 {
120 _tcslwr((LPTSTR)ext.c_str());
121
122 iterator found = find(ext);
123 if (found != end())
124 return found->second;
125
126 FileTypeInfo& ftype = super::operator[](ext);
127
128 ftype._neverShowExt = false;
129
130 HKEY hkey;
131 TCHAR value[MAX_PATH], display_name[MAX_PATH];;
132 LONG valuelen = sizeof(value);
133
134 if (!RegQueryValue(HKEY_CLASSES_ROOT, ext, value, &valuelen)) {
135 ftype._classname = value;
136
137 valuelen = sizeof(display_name);
138 if (!RegQueryValue(HKEY_CLASSES_ROOT, ftype._classname, display_name, &valuelen))
139 ftype._displayname = display_name;
140
141 if (!RegOpenKey(HKEY_CLASSES_ROOT, ftype._classname, &hkey)) {
142 if (!RegQueryValueEx(hkey, TEXT("NeverShowExt"), 0, NULL, NULL, NULL))
143 ftype._neverShowExt = true;
144
145 RegCloseKey(hkey);
146 }
147 }
148
149 return ftype;
150 }
151
152 LPCTSTR FileTypeManager::set_type(Entry* entry, bool dont_hide_ext)
153 {
154 LPCTSTR ext = _tcsrchr(entry->_data.cFileName, TEXT('.'));
155
156 if (ext) {
157 const FileTypeInfo& type = (*this)[ext];
158
159 if (!type._displayname.empty())
160 entry->_type_name = _tcsdup(type._displayname);
161
162 // hide some file extensions
163 if (type._neverShowExt && !dont_hide_ext) {
164 int len = ext - entry->_data.cFileName;
165 entry->_display_name = (LPTSTR) malloc((len+1)*sizeof(TCHAR));
166 _tcsncpy(entry->_display_name, entry->_data.cFileName, len);
167 entry->_display_name[len] = TEXT('\0');
168 }
169
170 if (is_exe_file(ext))
171 entry->_data.dwFileAttributes |= ATTRIBUTE_EXECUTABLE;
172 }
173
174 return ext;
175 }
176
177
178 Icon::Icon()
179 : _id(ICID_UNKNOWN),
180 _itype(IT_STATIC),
181 _hicon(0)
182 {
183 }
184
185 Icon::Icon(ICON_ID id, UINT nid)
186 : _id(id),
187 _itype(IT_STATIC),
188 _hicon(SmallIcon(nid))
189 {
190 }
191
192 Icon::Icon(ICON_TYPE itype, int id, HICON hIcon)
193 : _id((ICON_ID)id),
194 _itype(itype),
195 _hicon(hIcon)
196 {
197 }
198
199 Icon::Icon(ICON_TYPE itype, int id, int sys_idx)
200 : _id((ICON_ID)id),
201 _itype(itype),
202 _sys_idx(sys_idx)
203 {
204 }
205
206 void Icon::draw(HDC hdc, int x, int y, int cx, int cy, COLORREF bk_color, HBRUSH bk_brush) const
207 {
208 if (_itype == IT_SYSCACHE)
209 ImageList_DrawEx(g_Globals._icon_cache.get_sys_imagelist(), _sys_idx, hdc, x, y, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
210 else
211 DrawIconEx(hdc, x, y, _hicon, cx, cy, 0, bk_brush, DI_NORMAL);
212 }
213
214 HBITMAP Icon::create_bitmap(COLORREF bk_color, HBRUSH hbrBkgnd, HDC hdc_wnd) const
215 {
216 if (_itype == IT_SYSCACHE) {
217 HIMAGELIST himl = g_Globals._icon_cache.get_sys_imagelist();
218
219 int cx, cy;
220 ImageList_GetIconSize(himl, &cx, &cy);
221
222 HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
223 HDC hdc = CreateCompatibleDC(hdc_wnd);
224 HBITMAP hbmp_old = SelectBitmap(hdc, hbmp);
225 ImageList_DrawEx(himl, _sys_idx, hdc, 0, 0, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
226 SelectBitmap(hdc, hbmp_old);
227 DeleteDC(hdc);
228 return hbmp;
229 } else
230 return create_bitmap_from_icon(_hicon, hbrBkgnd, hdc_wnd);
231 }
232
233 HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
234 {
235 HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, 16, 16);
236
237 MemCanvas canvas;
238 BitmapSelection sel(canvas, hbmp);
239
240 RECT rect = {0, 0, 16, 16};
241 FillRect(canvas, &rect, hbrush_bkgnd);
242
243 DrawIconEx(canvas, 0, 0, hIcon, 16, 16, 0, hbrush_bkgnd, DI_NORMAL);
244
245 return hbmp;
246 }
247
248
249 int IconCache::s_next_id = ICID_DYNAMIC;
250
251
252 void IconCache::init()
253 {
254 _icons[ICID_NONE] = Icon(IT_STATIC, ICID_NONE, (HICON)0);
255
256 _icons[ICID_FOLDER] = Icon(ICID_FOLDER, IDI_FOLDER);
257 //_icons[ICID_DOCUMENT] = Icon(ICID_DOCUMENT, IDI_DOCUMENT);
258 _icons[ICID_EXPLORER] = Icon(ICID_EXPLORER, IDI_EXPLORER);
259 _icons[ICID_APP] = Icon(ICID_APP, IDI_APPICON);
260
261 _icons[ICID_CONFIG] = Icon(ICID_CONFIG, IDI_CONFIG);
262 _icons[ICID_DOCUMENTS] = Icon(ICID_DOCUMENTS, IDI_DOCUMENTS);
263 _icons[ICID_FAVORITES] = Icon(ICID_FAVORITES, IDI_FAVORITES);
264 _icons[ICID_INFO] = Icon(ICID_INFO, IDI_INFO);
265 _icons[ICID_APPS] = Icon(ICID_APPS, IDI_APPS);
266 _icons[ICID_SEARCH] = Icon(ICID_SEARCH, IDI_SEARCH);
267 _icons[ICID_ACTION] = Icon(ICID_ACTION, IDI_ACTION);
268 _icons[ICID_SEARCH_DOC] = Icon(ICID_SEARCH_DOC, IDI_SEARCH_DOC);
269 _icons[ICID_PRINTER] = Icon(ICID_PRINTER, IDI_PRINTER);
270 _icons[ICID_NETWORK] = Icon(ICID_NETWORK, IDI_NETWORK);
271 _icons[ICID_COMPUTER] = Icon(ICID_COMPUTER, IDI_COMPUTER);
272 _icons[ICID_LOGOFF] = Icon(ICID_LOGOFF, IDI_LOGOFF);
273 }
274
275
276 const Icon& IconCache::extract(const String& path)
277 {
278 PathMap::iterator found = _pathMap.find(path);
279
280 if (found != _pathMap.end())
281 return _icons[found->second];
282
283 SHFILEINFO sfi;
284
285 #if 1 // use system image list
286 HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
287
288 if (himlSys) {
289 _himlSys = himlSys;
290
291 const Icon& icon = add(sfi.iIcon/*, IT_SYSCACHE*/);
292 #else
293 if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) {
294 const Icon& icon = add(sfi.hIcon, IT_CACHED);
295 #endif
296
297 ///@todo limit cache size
298 _pathMap[path] = icon;
299
300 return icon;
301 } else
302 return _icons[ICID_NONE];
303 }
304
305 const Icon& IconCache::extract(LPCTSTR path, int idx)
306 {
307 CachePair key(path, idx);
308
309 _tcslwr((LPTSTR)key.first.c_str());
310
311 PathIdxMap::iterator found = _pathIdxMap.find(key);
312
313 if (found != _pathIdxMap.end())
314 return _icons[found->second];
315
316 HICON hIcon;
317
318 if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) {
319 const Icon& icon = add(hIcon, IT_CACHED);
320
321 _pathIdxMap[key] = icon;
322
323 return icon;
324 } else
325 return _icons[ICID_NONE];
326 }
327
328 const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx)
329 {
330 HICON hIconLarge = 0;
331 HICON hIcon;
332
333 HRESULT hr = pExtract->Extract(path, idx, &hIconLarge, &hIcon, MAKELONG(0/*GetSystemMetrics(SM_CXICON)*/,GetSystemMetrics(SM_CXSMICON)));
334
335 if (hr == NOERROR) {
336 if (hIconLarge)
337 DestroyIcon(hIconLarge);
338
339 if (hIcon)
340 return add(hIcon);
341 }
342
343 return _icons[ICID_NONE];
344 }
345
346 const Icon& IconCache::add(HICON hIcon, ICON_TYPE type)
347 {
348 int id = ++s_next_id;
349
350 return _icons[id] = Icon(type, id, hIcon);
351 }
352
353 const Icon& IconCache::add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/)
354 {
355 int id = ++s_next_id;
356
357 return _icons[id] = SysCacheIcon(id, sys_idx);
358 }
359
360 const Icon& IconCache::get_icon(int id)
361 {
362 return _icons[id];
363 }
364
365 void IconCache::free_icon(int icon_id)
366 {
367 IconMap::iterator found = _icons.find(icon_id);
368
369 if (found != _icons.end()) {
370 Icon& icon = found->second;
371
372 if (icon.destroy())
373 _icons.erase(found);
374 }
375 }
376
377
378 ResString::ResString(UINT nid)
379 {
380 TCHAR buffer[BUFFER_LEN];
381
382 int len = LoadString(g_Globals._hInstance, nid, buffer, sizeof(buffer)/sizeof(TCHAR));
383
384 super::assign(buffer, len);
385 }
386
387
388 ResIcon::ResIcon(UINT nid)
389 {
390 _hicon = LoadIcon(g_Globals._hInstance, MAKEINTRESOURCE(nid));
391 }
392
393 SmallIcon::SmallIcon(UINT nid)
394 {
395 _hicon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
396 }
397
398 ResIconEx::ResIconEx(UINT nid, int w, int h)
399 {
400 _hicon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, w, h, LR_SHARED);
401 }
402
403
404 void SetWindowIcon(HWND hwnd, UINT nid)
405 {
406 HICON hIcon = ResIcon(nid);
407 Window_SetIcon(hwnd, ICON_BIG, hIcon);
408
409 HICON hIconSmall = SmallIcon(nid);
410 Window_SetIcon(hwnd, ICON_SMALL, hIconSmall);
411 }
412
413
414 ResBitmap::ResBitmap(UINT nid)
415 {
416 _hBmp = LoadBitmap(g_Globals._hInstance, MAKEINTRESOURCE(nid));
417 }
418
419
420 #ifndef ROSSHELL
421
422 void explorer_show_frame(int cmdshow, LPTSTR lpCmdLine)
423 {
424 if (g_Globals._hMainWnd) {
425 if (IsIconic(g_Globals._hMainWnd))
426 ShowWindow(g_Globals._hMainWnd, SW_RESTORE);
427 else
428 SetForegroundWindow(g_Globals._hMainWnd);
429
430 return;
431 }
432
433 g_Globals._prescan_nodes = false;
434
435 // create main window
436 HWND hMainFrame = MainFrame::Create();
437
438 if (hMainFrame) {
439 g_Globals._hMainWnd = hMainFrame;
440
441 ShowWindow(hMainFrame, cmdshow);
442 UpdateWindow(hMainFrame);
443
444 bool valid_dir = false;
445
446 if (lpCmdLine) {
447 DWORD attribs = GetFileAttributes(lpCmdLine);
448
449 if (attribs!=INVALID_FILE_ATTRIBUTES && (attribs&FILE_ATTRIBUTE_DIRECTORY))
450 valid_dir = true;
451 else if (*lpCmdLine==':' || *lpCmdLine=='"')
452 valid_dir = true;
453 }
454
455 // Open the first child window after initializing the application
456 if (valid_dir)
457 PostMessage(hMainFrame, PM_OPEN_WINDOW, 0, (LPARAM)lpCmdLine);
458 else
459 PostMessage(hMainFrame, PM_OPEN_WINDOW, 0/*OWM_EXPLORE|OWM_DETAILS*/, 0);
460 }
461 }
462
463 #else
464
465 void explorer_show_frame(int cmdshow, LPTSTR lpCmdLine)
466 {
467 if (!lpCmdLine)
468 lpCmdLine = TEXT("explorer.exe");
469
470 launch_file(GetDesktopWindow(), lpCmdLine, cmdshow);
471 }
472
473 #endif
474
475
476 PopupMenu::PopupMenu(UINT nid)
477 {
478 HMENU hMenu = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(nid));
479 _hmenu = GetSubMenu(hMenu, 0);
480 }
481
482
483 /// "About Explorer" Dialog
484 struct ExplorerAboutDlg : public
485 CtlColorParent<
486 OwnerDrawParent<Dialog>
487 >
488 {
489 typedef CtlColorParent<
490 OwnerDrawParent<Dialog>
491 > super;
492
493 ExplorerAboutDlg(HWND hwnd)
494 : super(hwnd)
495 {
496 SetWindowIcon(hwnd, IDI_REACTOS);
497
498 new FlatButton(hwnd, IDOK);
499
500 _hfont = CreateFont(20, 0, 0, 0, FW_BOLD, TRUE, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif"));
501 new ColorStatic(hwnd, IDC_ROS_EXPLORER, RGB(32,32,128), 0, _hfont);
502
503 new HyperlinkCtrl(hwnd, IDC_WWW);
504
505 FmtString ver_txt(ResString(IDS_EXPLORER_VERSION_STR), (LPCTSTR)ResString(IDS_VERSION_STR));
506 SetWindowText(GetDlgItem(hwnd, IDC_VERSION_TXT), ver_txt);
507
508 CenterWindow(hwnd);
509 }
510
511 ~ExplorerAboutDlg()
512 {
513 DeleteObject(_hfont);
514 }
515
516 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
517 {
518 switch(nmsg) {
519 case WM_PAINT:
520 Paint();
521 break;
522
523 default:
524 return super::WndProc(nmsg, wparam, lparam);
525 }
526
527 return 0;
528 }
529
530 void Paint()
531 {
532 PaintCanvas canvas(_hwnd);
533
534 HICON hicon = (HICON) LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(IDI_REACTOS_BIG), IMAGE_ICON, 0, 0, LR_SHARED);
535
536 DrawIconEx(canvas, 20, 10, hicon, 0, 0, 0, 0, DI_NORMAL);
537 }
538
539 protected:
540 HFONT _hfont;
541 };
542
543 void explorer_about(HWND hwndParent)
544 {
545 Dialog::DoModal(IDD_ABOUT_EXPLORER, WINDOW_CREATOR(ExplorerAboutDlg), hwndParent);
546 }
547
548
549 static void InitInstance(HINSTANCE hInstance)
550 {
551 CONTEXT("InitInstance");
552
553 setlocale(LC_COLLATE, ""); // set collating rules to local settings for compareName
554
555 #ifndef ROSSHELL
556 // register frame window class
557 g_Globals._hframeClass = IconWindowClass(CLASSNAME_FRAME,IDI_EXPLORER);
558
559 // register child windows class
560 WindowClass(CLASSNAME_CHILDWND, CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW).Register();
561
562 // register tree windows class
563 WindowClass(CLASSNAME_WINEFILETREE, CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW).Register();
564 #endif
565
566 g_Globals._cfStrFName = RegisterClipboardFormat(CFSTR_FILENAME);
567 }
568
569
570 int explorer_main(HINSTANCE hInstance, LPTSTR lpCmdLine, int cmdshow)
571 {
572 CONTEXT("explorer_main");
573
574 // initialize Common Controls library
575 CommonControlInit usingCmnCtrl;
576
577 try {
578 InitInstance(hInstance);
579 } catch(COMException& e) {
580 HandleException(e, GetDesktopWindow());
581 return -1;
582 }
583
584 #ifndef ROSSHELL
585 if (cmdshow != SW_HIDE) {
586 /* // don't maximize if being called from the ROS desktop
587 if (cmdshow == SW_SHOWNORMAL)
588 ///@todo read window placement from registry
589 cmdshow = SW_MAXIMIZE;
590 */
591
592 explorer_show_frame(cmdshow, lpCmdLine);
593 }
594 #endif
595
596 return Window::MessageLoop();
597 }
598
599
600 // MinGW does not provide a Unicode startup routine, so we have to implement an own.
601 #if defined(__MINGW32__) && defined(UNICODE)
602
603 #define _tWinMain wWinMain
604 int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int);
605
606 int main(int argc, char* argv[])
607 {
608 CONTEXT("main");
609
610 STARTUPINFO startupinfo;
611 int nShowCmd = SW_SHOWNORMAL;
612
613 GetStartupInfo(&startupinfo);
614
615 if (startupinfo.dwFlags & STARTF_USESHOWWINDOW)
616 nShowCmd = startupinfo.wShowWindow;
617
618 LPWSTR cmdline = GetCommandLineW();
619
620 while(*cmdline && !_istspace(*cmdline))
621 ++cmdline;
622
623 return wWinMain(GetModuleHandle(NULL), 0, cmdline, nShowCmd);
624 }
625
626 #endif // __MINGW && UNICODE
627
628
629 static bool SetShellReadyEvent(LPCTSTR evtName)
630 {
631 HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, evtName);
632 if (!hEvent)
633 return false;
634
635 SetEvent(hEvent);
636 CloseHandle(hEvent);
637
638 return true;
639 }
640
641
642 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
643 {
644 CONTEXT("WinMain()");
645
646 BOOL any_desktop_running = IsAnyDesktopRunning();
647
648 BOOL startup_desktop;
649
650 // command line option "-install" to replace previous shell application with ROS Explorer
651 if (_tcsstr(lpCmdLine,TEXT("-install"))) {
652 // install ROS Explorer into the registry
653 TCHAR path[MAX_PATH];
654
655 int l = GetModuleFileName(0, path, MAX_PATH);
656 if (l) {
657 HKEY hkey;
658
659 if (!RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hkey)) {
660
661 ///@todo save previous shell application in config file
662
663 RegSetValueEx(hkey, TEXT("Shell"), 0, REG_SZ, (LPBYTE)path, l*sizeof(TCHAR));
664 RegCloseKey(hkey);
665 }
666 }
667
668 HWND shellWindow = GetShellWindow();
669
670 if (shellWindow) {
671 DWORD pid;
672
673 // terminate shell process for NT like systems
674 GetWindowThreadProcessId(shellWindow, &pid);
675 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
676
677 // On Win 9x it's sufficient to destroy the shell window.
678 DestroyWindow(shellWindow);
679
680 if (TerminateProcess(hProcess, 0))
681 WaitForSingleObject(hProcess, INFINITE);
682
683 CloseHandle(hProcess);
684 }
685
686 startup_desktop = TRUE;
687 } else {
688 // create desktop window and task bar only, if there is no other shell and we are
689 // the first explorer instance
690 // MS Explorer looks additionally into the registry entry HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\shell,
691 // to decide wether it is currently configured as shell application.
692 startup_desktop = !any_desktop_running;
693 }
694
695
696 bool autostart = !any_desktop_running;
697
698 // disable autostart if the SHIFT key is pressed
699 if (GetAsyncKeyState(VK_SHIFT) < 0)
700 autostart = false;
701
702 #ifdef _DEBUG //MF: disabled for debugging
703 autostart = false;
704 #endif
705
706 // If there is given the command line option "-desktop", create desktop window anyways
707 if (_tcsstr(lpCmdLine,TEXT("-desktop")))
708 startup_desktop = TRUE;
709 #ifndef ROSSHELL
710 else if (_tcsstr(lpCmdLine,TEXT("-nodesktop")))
711 startup_desktop = FALSE;
712
713 // Don't display cabinet window in desktop mode
714 if (startup_desktop && !_tcsstr(lpCmdLine,TEXT("-explorer")))
715 nShowCmd = SW_HIDE;
716 #endif
717
718 if (_tcsstr(lpCmdLine,TEXT("-noautostart")))
719 autostart = false;
720
721 if (startup_desktop) {
722 // hide the XP login screen (Credit to Nicolas Escuder)
723 // another undocumented event: "Global\\msgina: ReturnToWelcome"
724 if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
725 SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
726
727 // launch the shell DDE server
728 if (g_SHDOCVW_ShellDDEInit)
729 (*g_SHDOCVW_ShellDDEInit)(TRUE);
730 }
731 #ifdef ROSSHELL
732 else
733 return 0; // no shell to launch, so exit immediatelly
734 #endif
735
736
737 g_Globals.init(hInstance);
738
739 // initialize COM and OLE before creating the desktop window
740 OleInit usingCOM;
741
742 if (startup_desktop) {
743 g_Globals._desktops.init();
744
745 g_Globals._hwndDesktop = DesktopWindow::Create();
746
747 /**TODO launching autostart programs can be moved into a background thread. */
748 if (autostart) {
749 char* argv[] = {"", "s"}; // call startup routine in SESSION_START mode
750 startup(2, argv);
751 }
752 }
753
754 #ifndef ROSSHELL
755 /**TODO fix command line handling */
756 if (*lpCmdLine=='"' && lpCmdLine[_tcslen(lpCmdLine)-1]=='"') {
757 ++lpCmdLine;
758 lpCmdLine[_tcslen(lpCmdLine)-1] = '\0';
759 }
760
761 if (g_Globals._hwndDesktop)
762 g_Globals._desktop_mode = true;
763 #endif
764
765 int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);
766
767 // shutdown the shell DDE server
768 if (g_SHDOCVW_ShellDDEInit)
769 (*g_SHDOCVW_ShellDDEInit)(FALSE);
770
771 return ret;
772 }