Add support for explorer to load the desk.cpl when right clicking on background.
[reactos.git] / reactos / subsys / system / explorer / explorer.cpp
1 /*
2 * Copyright 2003, 2004 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
22 //
23 // explorer.cpp
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27 // Credits: Thanks to Leon Finker for his explorer cabinet window example
28 //
29
30
31 #include "precomp.h"
32
33 #include "explorer_intres.h"
34
35 #include <locale.h> // for setlocale()
36
37 #ifndef __WINE__
38 #include <io.h> // for dup2()
39 #include <fcntl.h> // for _O_RDONLY
40 #endif
41
42 #include "dialogs/settings.h" // for MdiSdiDlg
43
44
45 extern "C" int initialize_gdb_stub(); // start up GDB stub
46
47
48 ExplorerGlobals g_Globals;
49
50
51 ExplorerGlobals::ExplorerGlobals()
52 {
53 _hInstance = 0;
54 _hframeClass = 0;
55 _cfStrFName = 0;
56 _hMainWnd = 0;
57 _prescan_nodes = false;
58 _desktop_mode = false;
59 _log = NULL;
60 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
61 _SHRestricted = 0;
62 #endif
63 _hwndDesktopBar = 0;
64 _hwndShellView = 0;
65 _hwndDesktop = 0;
66 }
67
68
69 void ExplorerGlobals::init(HINSTANCE hInstance)
70 {
71 _hInstance = hInstance;
72
73 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
74 _SHRestricted = (DWORD(STDAPICALLTYPE*)(RESTRICTIONS)) GetProcAddress(GetModuleHandle(TEXT("SHELL32")), "SHRestricted");
75 #endif
76
77 _icon_cache.init();
78 }
79
80
81 void ExplorerGlobals::read_persistent()
82 {
83 // read configuration file
84 _cfg_dir.printf(TEXT("%s\\ReactOS"), (LPCTSTR)SpecialFolderFSPath(CSIDL_APPDATA,0));
85 _cfg_path.printf(TEXT("%s\\ros-explorer-cfg.xml"), _cfg_dir.c_str());
86
87 if (!_cfg.read(_cfg_path)) {
88 if (_cfg._last_error != XML_ERROR_NO_ELEMENTS)
89 MessageBox(g_Globals._hwndDesktop, String(_cfg._last_error_msg.c_str()),
90 TEXT("ROS Explorer - reading user settings"), MB_OK);
91
92 _cfg.read(TEXT("explorer-cfg-template.xml"));
93 }
94
95 // read bookmarks
96 _favorites_path.printf(TEXT("%s\\ros-explorer-bookmarks.xml"), _cfg_dir.c_str());
97
98 if (!_favorites.read(_favorites_path)) {
99 _favorites.import_IE_favorites(0);
100 _favorites.write(_favorites_path);
101 }
102 }
103
104 void ExplorerGlobals::write_persistent()
105 {
106 // write configuration file
107 RecursiveCreateDirectory(_cfg_dir);
108
109 _cfg.write(_cfg_path);
110 _favorites.write(_favorites_path);
111 }
112
113
114 XMLPos ExplorerGlobals::get_cfg()
115 {
116 XMLPos cfg_pos(&_cfg);
117
118 cfg_pos.smart_create("explorer-cfg");
119
120 return cfg_pos;
121 }
122
123 XMLPos ExplorerGlobals::get_cfg(const char* path)
124 {
125 XMLPos cfg_pos(&_cfg);
126
127 cfg_pos.smart_create("explorer-cfg");
128 cfg_pos.create_relative(path);
129
130 return cfg_pos;
131 }
132
133
134 void _log_(LPCTSTR txt)
135 {
136 FmtString msg(TEXT("%s\n"), txt);
137
138 if (g_Globals._log)
139 _fputts(msg, g_Globals._log);
140
141 OutputDebugString(msg);
142 }
143
144
145 bool FileTypeManager::is_exe_file(LPCTSTR ext)
146 {
147 static const LPCTSTR s_executable_extensions[] = {
148 TEXT("COM"),
149 TEXT("EXE"),
150 TEXT("BAT"),
151 TEXT("CMD"),
152 TEXT("CMM"),
153 TEXT("BTM"),
154 TEXT("AWK"),
155 0
156 };
157
158 TCHAR ext_buffer[_MAX_EXT];
159 const LPCTSTR* p;
160 LPCTSTR s;
161 LPTSTR d;
162
163 for(s=ext+1,d=ext_buffer; (*d=toupper(*s)); s++)
164 ++d;
165
166 for(p=s_executable_extensions; *p; p++)
167 if (!lstrcmp(ext_buffer, *p))
168 return true;
169
170 return false;
171 }
172
173
174 const FileTypeInfo& FileTypeManager::operator[](String ext)
175 {
176 #ifndef __WINE__ ///@todo _tcslwr() for Wine
177 _tcslwr((LPTSTR)ext.c_str());
178 #endif
179
180 iterator found = find(ext);
181 if (found != end())
182 return found->second;
183
184 FileTypeInfo& ftype = super::operator[](ext);
185
186 ftype._neverShowExt = false;
187
188 HKEY hkey;
189 TCHAR value[MAX_PATH], display_name[MAX_PATH];
190 LONG valuelen = sizeof(value);
191
192 if (!RegQueryValue(HKEY_CLASSES_ROOT, ext, value, &valuelen)) {
193 ftype._classname = value;
194
195 valuelen = sizeof(display_name);
196 if (!RegQueryValue(HKEY_CLASSES_ROOT, ftype._classname, display_name, &valuelen))
197 ftype._displayname = display_name;
198
199 if (!RegOpenKey(HKEY_CLASSES_ROOT, ftype._classname, &hkey)) {
200 if (!RegQueryValueEx(hkey, TEXT("NeverShowExt"), 0, NULL, NULL, NULL))
201 ftype._neverShowExt = true;
202
203 RegCloseKey(hkey);
204 }
205 }
206
207 return ftype;
208 }
209
210 LPCTSTR FileTypeManager::set_type(Entry* entry, bool dont_hide_ext)
211 {
212 LPCTSTR ext = _tcsrchr(entry->_data.cFileName, TEXT('.'));
213
214 if (ext) {
215 const FileTypeInfo& type = (*this)[ext];
216
217 if (!type._displayname.empty())
218 entry->_type_name = _tcsdup(type._displayname);
219
220 // hide some file extensions
221 if (type._neverShowExt && !dont_hide_ext) {
222 int len = ext - entry->_data.cFileName;
223 entry->_display_name = (LPTSTR) malloc((len+1)*sizeof(TCHAR));
224 _tcsncpy(entry->_display_name, entry->_data.cFileName, len);
225 entry->_display_name[len] = TEXT('\0');
226 }
227
228 if (is_exe_file(ext))
229 entry->_data.dwFileAttributes |= ATTRIBUTE_EXECUTABLE;
230 }
231
232 return ext;
233 }
234
235
236 Icon::Icon()
237 : _id(ICID_UNKNOWN),
238 _itype(IT_STATIC),
239 _hicon(0)
240 {
241 }
242
243 Icon::Icon(ICON_ID id, UINT nid)
244 : _id(id),
245 _itype(IT_STATIC),
246 _hicon(SmallIcon(nid))
247 {
248 }
249
250 Icon::Icon(ICON_TYPE itype, int id, HICON hIcon)
251 : _id((ICON_ID)id),
252 _itype(itype),
253 _hicon(hIcon)
254 {
255 }
256
257 Icon::Icon(ICON_TYPE itype, int id, int sys_idx)
258 : _id((ICON_ID)id),
259 _itype(itype),
260 _sys_idx(sys_idx)
261 {
262 }
263
264 void Icon::draw(HDC hdc, int x, int y, int cx, int cy, COLORREF bk_color, HBRUSH bk_brush) const
265 {
266 if (_itype == IT_SYSCACHE)
267 ImageList_DrawEx(g_Globals._icon_cache.get_sys_imagelist(), _sys_idx, hdc, x, y, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
268 else
269 DrawIconEx(hdc, x, y, _hicon, cx, cy, 0, bk_brush, DI_NORMAL);
270 }
271
272 HBITMAP Icon::create_bitmap(COLORREF bk_color, HBRUSH hbrBkgnd, HDC hdc_wnd) const
273 {
274 if (_itype == IT_SYSCACHE) {
275 HIMAGELIST himl = g_Globals._icon_cache.get_sys_imagelist();
276
277 int cx, cy;
278 ImageList_GetIconSize(himl, &cx, &cy);
279
280 HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
281 HDC hdc = CreateCompatibleDC(hdc_wnd);
282 HBITMAP hbmp_old = SelectBitmap(hdc, hbmp);
283 ImageList_DrawEx(himl, _sys_idx, hdc, 0, 0, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
284 SelectBitmap(hdc, hbmp_old);
285 DeleteDC(hdc);
286
287 return hbmp;
288 } else
289 return create_bitmap_from_icon(_hicon, hbrBkgnd, hdc_wnd);
290 }
291
292
293 int Icon::add_to_imagelist(HIMAGELIST himl, HDC hdc_wnd, COLORREF bk_color, HBRUSH bk_brush) const
294 {
295 int ret;
296
297 if (_itype == IT_SYSCACHE) {
298 HIMAGELIST himl = g_Globals._icon_cache.get_sys_imagelist();
299
300 int cx, cy;
301 ImageList_GetIconSize(himl, &cx, &cy);
302
303 HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
304 HDC hdc = CreateCompatibleDC(hdc_wnd);
305 HBITMAP hbmp_old = SelectBitmap(hdc, hbmp);
306 ImageList_DrawEx(himl, _sys_idx, hdc, 0, 0, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
307 SelectBitmap(hdc, hbmp_old);
308 DeleteDC(hdc);
309
310 ret = ImageList_Add(himl, hbmp, 0);
311
312 DeleteObject(hbmp);
313 } else
314 ret = ImageList_AddAlphaIcon(himl, _hicon, bk_brush, hdc_wnd);
315
316 return ret;
317 }
318
319 HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
320 {
321 int cx = GetSystemMetrics(SM_CXSMICON);
322 int cy = GetSystemMetrics(SM_CYSMICON);
323 HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
324
325 MemCanvas canvas;
326 BitmapSelection sel(canvas, hbmp);
327
328 RECT rect = {0, 0, cx, cy};
329 FillRect(canvas, &rect, hbrush_bkgnd);
330
331 DrawIconEx(canvas, 0, 0, hIcon, cx, cy, 0, hbrush_bkgnd, DI_NORMAL);
332
333 return hbmp;
334 }
335
336 int ImageList_AddAlphaIcon(HIMAGELIST himl, HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
337 {
338 HBITMAP hbmp = create_bitmap_from_icon(hIcon, hbrush_bkgnd, hdc_wnd);
339
340 int ret = ImageList_Add(himl, hbmp, 0);
341
342 DeleteObject(hbmp);
343
344 return ret;
345 }
346
347
348 int IconCache::s_next_id = ICID_DYNAMIC;
349
350
351 void IconCache::init()
352 {
353 _icons[ICID_NONE] = Icon(IT_STATIC, ICID_NONE, (HICON)0);
354
355 _icons[ICID_FOLDER] = Icon(ICID_FOLDER, IDI_FOLDER);
356 //_icons[ICID_DOCUMENT] = Icon(ICID_DOCUMENT, IDI_DOCUMENT);
357 _icons[ICID_EXPLORER] = Icon(ICID_EXPLORER, IDI_EXPLORER);
358 _icons[ICID_APP] = Icon(ICID_APP, IDI_APPICON);
359
360 _icons[ICID_CONFIG] = Icon(ICID_CONFIG, IDI_CONFIG);
361 _icons[ICID_DOCUMENTS] = Icon(ICID_DOCUMENTS, IDI_DOCUMENTS);
362 _icons[ICID_FAVORITES] = Icon(ICID_FAVORITES, IDI_FAVORITES);
363 _icons[ICID_INFO] = Icon(ICID_INFO, IDI_INFO);
364 _icons[ICID_APPS] = Icon(ICID_APPS, IDI_APPS);
365 _icons[ICID_SEARCH] = Icon(ICID_SEARCH, IDI_SEARCH);
366 _icons[ICID_ACTION] = Icon(ICID_ACTION, IDI_ACTION);
367 _icons[ICID_SEARCH_DOC] = Icon(ICID_SEARCH_DOC, IDI_SEARCH_DOC);
368 _icons[ICID_PRINTER] = Icon(ICID_PRINTER, IDI_PRINTER);
369 _icons[ICID_NETWORK] = Icon(ICID_NETWORK, IDI_NETWORK);
370 _icons[ICID_COMPUTER] = Icon(ICID_COMPUTER, IDI_COMPUTER);
371 _icons[ICID_LOGOFF] = Icon(ICID_LOGOFF, IDI_LOGOFF);
372 _icons[ICID_BOOKMARK] = Icon(ICID_BOOKMARK, IDI_DOT_TRANS);
373 }
374
375
376 const Icon& IconCache::extract(const String& path)
377 {
378 PathMap::iterator found = _pathMap.find(path);
379
380 if (found != _pathMap.end())
381 return _icons[found->second];
382
383 SHFILEINFO sfi;
384
385 #if 1 // use system image list
386 HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
387
388 if (himlSys) {
389 _himlSys = himlSys;
390
391 const Icon& icon = add(sfi.iIcon/*, IT_SYSCACHE*/);
392 #else
393 if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) {
394 const Icon& icon = add(sfi.hIcon, IT_CACHED);
395 #endif
396
397 ///@todo limit cache size
398 _pathMap[path] = icon;
399
400 return icon;
401 } else
402 return _icons[ICID_NONE];
403 }
404
405 const Icon& IconCache::extract(LPCTSTR path, int idx)
406 {
407 CachePair key(path, idx);
408
409 #ifndef __WINE__ ///@todo _tcslwr() for Wine
410 _tcslwr((LPTSTR)key.first.c_str());
411 #endif
412
413 PathIdxMap::iterator found = _pathIdxMap.find(key);
414
415 if (found != _pathIdxMap.end())
416 return _icons[found->second];
417
418 HICON hIcon;
419
420 if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) {
421 const Icon& icon = add(hIcon, IT_CACHED);
422
423 _pathIdxMap[key] = icon;
424
425 return icon;
426 } else {
427
428 ///@todo retreive "http://.../favicon.ico" format icons
429
430 return _icons[ICID_NONE];
431 }
432 }
433
434 const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx)
435 {
436 HICON hIconLarge = 0;
437 HICON hIcon;
438
439 HRESULT hr = pExtract->Extract(path, idx, &hIconLarge, &hIcon, MAKELONG(0/*GetSystemMetrics(SM_CXICON)*/,GetSystemMetrics(SM_CXSMICON)));
440
441 if (hr == NOERROR) { //@@ oder SUCCEEDED(hr) ?
442 if (hIconLarge)
443 DestroyIcon(hIconLarge);
444
445 if (hIcon)
446 return add(hIcon);
447 }
448
449 return _icons[ICID_NONE];
450 }
451
452 const Icon& IconCache::add(HICON hIcon, ICON_TYPE type)
453 {
454 int id = ++s_next_id;
455
456 return _icons[id] = Icon(type, id, hIcon);
457 }
458
459 const Icon& IconCache::add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/)
460 {
461 int id = ++s_next_id;
462
463 return _icons[id] = SysCacheIcon(id, sys_idx);
464 }
465
466 const Icon& IconCache::get_icon(int id)
467 {
468 return _icons[id];
469 }
470
471 void IconCache::free_icon(int icon_id)
472 {
473 IconMap::iterator found = _icons.find(icon_id);
474
475 if (found != _icons.end()) {
476 Icon& icon = found->second;
477
478 if (icon.destroy())
479 _icons.erase(found);
480 }
481 }
482
483
484 ResString::ResString(UINT nid)
485 {
486 TCHAR buffer[BUFFER_LEN];
487
488 int len = LoadString(g_Globals._hInstance, nid, buffer, sizeof(buffer)/sizeof(TCHAR));
489
490 super::assign(buffer, len);
491 }
492
493
494 ResIcon::ResIcon(UINT nid)
495 {
496 _hicon = LoadIcon(g_Globals._hInstance, MAKEINTRESOURCE(nid));
497 }
498
499 SmallIcon::SmallIcon(UINT nid)
500 {
501 _hicon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
502 }
503
504 ResIconEx::ResIconEx(UINT nid, int w, int h)
505 {
506 _hicon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, w, h, LR_SHARED);
507 }
508
509
510 void SetWindowIcon(HWND hwnd, UINT nid)
511 {
512 HICON hIcon = ResIcon(nid);
513 Window_SetIcon(hwnd, ICON_BIG, hIcon);
514
515 HICON hIconSmall = SmallIcon(nid);
516 Window_SetIcon(hwnd, ICON_SMALL, hIconSmall);
517 }
518
519
520 ResBitmap::ResBitmap(UINT nid)
521 {
522 _hBmp = LoadBitmap(g_Globals._hInstance, MAKEINTRESOURCE(nid));
523 }
524
525
526 void explorer_show_frame(int cmdshow, LPTSTR lpCmdLine)
527 {
528 if (g_Globals._hMainWnd) {
529 if (IsIconic(g_Globals._hMainWnd))
530 ShowWindow(g_Globals._hMainWnd, SW_RESTORE);
531 else
532 SetForegroundWindow(g_Globals._hMainWnd);
533
534 return;
535 }
536
537 g_Globals._prescan_nodes = false;
538
539 XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
540 XS_String mdiStr = XMLString(explorer_options, "mdi");
541
542 if (mdiStr.empty())
543 Dialog::DoModal(IDD_MDI_SDI, WINDOW_CREATOR(MdiSdiDlg), g_Globals._hwndDesktop);
544
545 bool mdi = XMLBool(explorer_options, "mdi", true);
546
547 // create main window
548 MainFrameBase::Create(lpCmdLine, mdi, cmdshow);
549 }
550
551
552 PopupMenu::PopupMenu(UINT nid)
553 {
554 HMENU hMenu = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(nid));
555 _hmenu = GetSubMenu(hMenu, 0);
556 }
557
558
559 /// "About Explorer" Dialog
560 struct ExplorerAboutDlg : public
561 CtlColorParent<
562 OwnerDrawParent<Dialog>
563 >
564 {
565 typedef CtlColorParent<
566 OwnerDrawParent<Dialog>
567 > super;
568
569 ExplorerAboutDlg(HWND hwnd)
570 : super(hwnd)
571 {
572 SetWindowIcon(hwnd, IDI_REACTOS);
573
574 new FlatButton(hwnd, IDOK);
575
576 _hfont = CreateFont(20, 0, 0, 0, FW_BOLD, TRUE, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif"));
577 new ColorStatic(hwnd, IDC_ROS_EXPLORER, RGB(32,32,128), 0, _hfont);
578
579 new HyperlinkCtrl(hwnd, IDC_WWW);
580
581 FmtString ver_txt(ResString(IDS_EXPLORER_VERSION_STR), (LPCTSTR)ResString(IDS_VERSION_STR));
582 SetWindowText(GetDlgItem(hwnd, IDC_VERSION_TXT), ver_txt);
583
584 HWND hwnd_winver = GetDlgItem(hwnd, IDC_WIN_VERSION);
585 SetWindowText(hwnd_winver, get_windows_version_str());
586 SetWindowFont(hwnd_winver, GetStockFont(DEFAULT_GUI_FONT), FALSE);
587
588 CenterWindow(hwnd);
589 }
590
591 ~ExplorerAboutDlg()
592 {
593 DeleteObject(_hfont);
594 }
595
596 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
597 {
598 switch(nmsg) {
599 case WM_PAINT:
600 Paint();
601 break;
602
603 default:
604 return super::WndProc(nmsg, wparam, lparam);
605 }
606
607 return 0;
608 }
609
610 void Paint()
611 {
612 PaintCanvas canvas(_hwnd);
613
614 HICON hicon = (HICON) LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(IDI_REACTOS_BIG), IMAGE_ICON, 0, 0, LR_SHARED);
615
616 DrawIconEx(canvas, 20, 10, hicon, 0, 0, 0, 0, DI_NORMAL);
617 }
618
619 protected:
620 HFONT _hfont;
621 };
622
623 void explorer_about(HWND hwndParent)
624 {
625 Dialog::DoModal(IDD_ABOUT_EXPLORER, WINDOW_CREATOR(ExplorerAboutDlg), hwndParent);
626 }
627
628
629 static void InitInstance(HINSTANCE hInstance)
630 {
631 CONTEXT("InitInstance");
632
633 setlocale(LC_COLLATE, ""); // set collating rules to local settings for compareName
634
635 // register frame window class
636 g_Globals._hframeClass = IconWindowClass(CLASSNAME_FRAME,IDI_EXPLORER);
637
638 // register child window class
639 WindowClass(CLASSNAME_CHILDWND, CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW).Register();
640
641 // register tree window class
642 WindowClass(CLASSNAME_WINEFILETREE, CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW).Register();
643
644 g_Globals._cfStrFName = RegisterClipboardFormat(CFSTR_FILENAME);
645 }
646
647
648 int explorer_main(HINSTANCE hInstance, LPTSTR lpCmdLine, int cmdshow)
649 {
650 CONTEXT("explorer_main");
651
652 // initialize Common Controls library
653 CommonControlInit usingCmnCtrl;
654
655 try {
656 InitInstance(hInstance);
657 } catch(COMException& e) {
658 HandleException(e, GetDesktopWindow());
659 return -1;
660 }
661
662 if (cmdshow != SW_HIDE) {
663 /* // don't maximize if being called from the ROS desktop
664 if (cmdshow == SW_SHOWNORMAL)
665 ///@todo read window placement from registry
666 cmdshow = SW_MAXIMIZE;
667 */
668
669 explorer_show_frame(cmdshow, lpCmdLine);
670 }
671
672 return Window::MessageLoop();
673 }
674
675
676 // MinGW does not provide a Unicode startup routine, so we have to implement an own.
677 #if defined(__MINGW32__) && defined(UNICODE)
678
679 #define _tWinMain wWinMain
680 int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int);
681
682 int main(int argc, char* argv[])
683 {
684 CONTEXT("main");
685
686 STARTUPINFO startupinfo;
687 int nShowCmd = SW_SHOWNORMAL;
688
689 GetStartupInfo(&startupinfo);
690
691 if (startupinfo.dwFlags & STARTF_USESHOWWINDOW)
692 nShowCmd = startupinfo.wShowWindow;
693
694 LPWSTR cmdline = GetCommandLineW();
695
696 while(*cmdline && !_istspace(*cmdline))
697 ++cmdline;
698
699 while(_istspace(*cmdline))
700 ++cmdline;
701
702 return wWinMain(GetModuleHandle(NULL), 0, cmdline, nShowCmd);
703 }
704
705 #endif // __MINGW && UNICODE
706
707
708 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
709 {
710 CONTEXT("WinMain()");
711
712 BOOL any_desktop_running = IsAnyDesktopRunning();
713
714 BOOL startup_desktop;
715
716 // command line option "-install" to replace previous shell application with ROS Explorer
717 if (_tcsstr(lpCmdLine,TEXT("-install"))) {
718 // install ROS Explorer into the registry
719 TCHAR path[MAX_PATH];
720
721 int l = GetModuleFileName(0, path, MAX_PATH);
722 if (l) {
723 HKEY hkey;
724
725 if (!RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hkey)) {
726
727 ///@todo save previous shell application in config file
728
729 RegSetValueEx(hkey, TEXT("Shell"), 0, REG_SZ, (LPBYTE)path, l*sizeof(TCHAR));
730 RegCloseKey(hkey);
731 }
732 }
733
734 HWND shellWindow = GetShellWindow();
735
736 if (shellWindow) {
737 DWORD pid;
738
739 // terminate shell process for NT like systems
740 GetWindowThreadProcessId(shellWindow, &pid);
741 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
742
743 // On Win 9x it's sufficient to destroy the shell window.
744 DestroyWindow(shellWindow);
745
746 if (TerminateProcess(hProcess, 0))
747 WaitForSingleObject(hProcess, INFINITE);
748
749 CloseHandle(hProcess);
750 }
751
752 startup_desktop = TRUE;
753 } else
754 // create desktop window and task bar only, if there is no other shell and we are
755 // the first explorer instance
756 startup_desktop = !any_desktop_running;
757
758 bool autostart = !any_desktop_running;
759
760 // disable autostart if the SHIFT key is pressed
761 if (GetAsyncKeyState(VK_SHIFT) < 0)
762 autostart = false;
763
764 #ifdef _DEBUG //MF: disabled for debugging
765 autostart = false;
766 #endif
767
768 // If there is given the command line option "-desktop", create desktop window anyways
769 if (_tcsstr(lpCmdLine,TEXT("-desktop")))
770 startup_desktop = TRUE;
771 else if (_tcsstr(lpCmdLine,TEXT("-nodesktop")))
772 startup_desktop = FALSE;
773
774 // Don't display cabinet window in desktop mode
775 if (startup_desktop && !_tcsstr(lpCmdLine,TEXT("-explorer")))
776 nShowCmd = SW_HIDE;
777
778 if (_tcsstr(lpCmdLine,TEXT("-noautostart")))
779 autostart = false;
780 else if (_tcsstr(lpCmdLine,TEXT("-autostart")))
781 autostart = true;
782
783 #ifndef __WINE__
784 if (_tcsstr(lpCmdLine,TEXT("-console"))) {
785 AllocConsole();
786
787 _dup2(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_RDONLY), 0);
788 _dup2(_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), 0), 1);
789 _dup2(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), 0), 2);
790
791 g_Globals._log = fdopen(1, "w");
792 setvbuf(g_Globals._log, 0, _IONBF, 0);
793
794 LOG(TEXT("starting explorer debug log\n"));
795 }
796 #endif
797
798 bool use_gdb_stub = false; // !IsDebuggerPresent();
799
800 if (_tcsstr(lpCmdLine,TEXT("-debug")))
801 use_gdb_stub = true;
802
803 if (_tcsstr(lpCmdLine,TEXT("-break"))) {
804 LOG(TEXT("debugger breakpoint"));
805 #ifdef _MSC_VER
806 __asm int 3
807 #else
808 asm("int3");
809 #endif
810 }
811
812 // activate GDB remote debugging stub if no other debugger is running
813 if (use_gdb_stub) {
814 LOG(TEXT("waiting for debugger connection...\n"));
815
816 initialize_gdb_stub();
817 }
818
819 g_Globals.init(hInstance);
820
821 // initialize COM and OLE before creating the desktop window
822 OleInit usingCOM;
823
824 // init common controls library
825 CommonControlInit usingCmnCtrl;
826
827 g_Globals.read_persistent();
828
829 if (startup_desktop) {
830 g_Globals._desktops.init();
831
832 g_Globals._hwndDesktop = DesktopWindow::Create();
833 #ifdef _USE_HDESK
834 g_Globals._desktops.get_current_Desktop()->_hwndDesktop = g_Globals._hwndDesktop;
835 #endif
836
837 if (autostart) {
838 char* argv[] = {"", "s"}; // call startup routine in SESSION_START mode
839 startup(2, argv);
840 }
841 }
842
843 /**TODO fix command line handling */
844 if (*lpCmdLine=='"' && lpCmdLine[_tcslen(lpCmdLine)-1]=='"') {
845 ++lpCmdLine;
846 lpCmdLine[_tcslen(lpCmdLine)-1] = '\0';
847 }
848
849 if (g_Globals._hwndDesktop)
850 g_Globals._desktop_mode = true;
851
852 int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);
853
854 // write configuration file
855 g_Globals.write_persistent();
856
857 return ret;
858 }