2 * Copyright 2003, 2004, 2005 Martin Fuchs
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.
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.
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
25 // Martin Fuchs, 23.07.2003
27 // Credits: Thanks to Leon Finker for his explorer cabinet window example
31 #include <precomp.h> // <precomp.h> instead of "precomp.h" because the ROS build system needs this to find the precompiled header file (*.gch) in the output directory tree
35 #include <locale.h> // for setlocale()
38 #include <io.h> // for dup2()
39 #include <fcntl.h> // for _O_RDONLY
42 #include "dialogs/settings.h" // for MdiSdiDlg
44 #include "services/shellservices.h"
47 extern "C" int initialize_gdb_stub(); // start up GDB stub
50 DynamicLoadLibFct
<void(__stdcall
*)(BOOL
)> g_SHDOCVW_ShellDDEInit(TEXT("SHDOCVW"), 118);
53 ExplorerGlobals g_Globals
;
56 ExplorerGlobals::ExplorerGlobals()
64 _desktop_mode
= false;
65 _prescan_nodes
= false;
69 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
78 void ExplorerGlobals::init(HINSTANCE hInstance
)
80 _hInstance
= hInstance
;
82 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
83 _SHRestricted
= (DWORD(STDAPICALLTYPE
*)(RESTRICTIONS
)) GetProcAddress(GetModuleHandle(TEXT("SHELL32")), "SHRestricted");
90 void ExplorerGlobals::read_persistent()
92 // read configuration file
93 _cfg_dir
.printf(TEXT("%s\\ReactOS"), (LPCTSTR
)SpecialFolderFSPath(CSIDL_APPDATA
,0));
94 _cfg_path
.printf(TEXT("%s\\ros-explorer-cfg.xml"), _cfg_dir
.c_str());
96 if (!_cfg
.read(_cfg_path
)) {
97 if (_cfg
._last_error
!= XML_ERROR_NO_ELEMENTS
)
98 MessageBox(g_Globals
._hwndDesktop
, String(_cfg
._last_error_msg
.c_str()),
99 TEXT("ROS Explorer - reading user settings"), MB_OK
);
101 _cfg
.read(TEXT("explorer-cfg-template.xml"));
105 _favorites_path
.printf(TEXT("%s\\ros-explorer-bookmarks.xml"), _cfg_dir
.c_str());
107 if (!_favorites
.read(_favorites_path
)) {
108 _favorites
.import_IE_favorites(0);
109 _favorites
.write(_favorites_path
);
113 void ExplorerGlobals::write_persistent()
115 // write configuration file
116 RecursiveCreateDirectory(_cfg_dir
);
118 _cfg
.write(_cfg_path
);
119 _favorites
.write(_favorites_path
);
123 XMLPos
ExplorerGlobals::get_cfg()
125 XMLPos
cfg_pos(&_cfg
);
127 cfg_pos
.smart_create("explorer-cfg");
132 XMLPos
ExplorerGlobals::get_cfg(const char* path
)
134 XMLPos
cfg_pos(&_cfg
);
136 cfg_pos
.smart_create("explorer-cfg");
137 cfg_pos
.create_relative(path
);
143 void _log_(LPCTSTR txt
)
145 FmtString
msg(TEXT("%s\n"), txt
);
148 _fputts(msg
, g_Globals
._log
);
150 OutputDebugString(msg
);
154 bool FileTypeManager::is_exe_file(LPCTSTR ext
)
156 static const LPCTSTR s_executable_extensions
[] = {
167 TCHAR ext_buffer
[_MAX_EXT
];
172 for(s
=ext
+1,d
=ext_buffer
; (*d
=toupper(*s
)); s
++)
175 for(p
=s_executable_extensions
; *p
; p
++)
176 if (!lstrcmp(ext_buffer
, *p
))
183 const FileTypeInfo
& FileTypeManager::operator[](String ext
)
187 iterator found
= find(ext
);
189 return found
->second
;
191 FileTypeInfo
& ftype
= super::operator[](ext
);
193 ftype
._neverShowExt
= false;
196 TCHAR value
[MAX_PATH
], display_name
[MAX_PATH
];
197 LONG valuelen
= sizeof(value
);
199 if (!RegQueryValue(HKEY_CLASSES_ROOT
, ext
, value
, &valuelen
)) {
200 ftype
._classname
= value
;
202 valuelen
= sizeof(display_name
);
203 if (!RegQueryValue(HKEY_CLASSES_ROOT
, ftype
._classname
, display_name
, &valuelen
))
204 ftype
._displayname
= display_name
;
206 if (!RegOpenKey(HKEY_CLASSES_ROOT
, ftype
._classname
, &hkey
)) {
207 if (!RegQueryValueEx(hkey
, TEXT("NeverShowExt"), 0, NULL
, NULL
, NULL
))
208 ftype
._neverShowExt
= true;
217 LPCTSTR
FileTypeManager::set_type(Entry
* entry
, bool dont_hide_ext
)
219 LPCTSTR ext
= _tcsrchr(entry
->_data
.cFileName
, TEXT('.'));
222 const FileTypeInfo
& type
= (*this)[ext
];
224 if (!type
._displayname
.empty())
225 entry
->_type_name
= _tcsdup(type
._displayname
);
227 // hide some file extensions
228 if (type
._neverShowExt
&& !dont_hide_ext
) {
229 int len
= ext
- entry
->_data
.cFileName
;
230 entry
->_display_name
= (LPTSTR
) malloc((len
+1)*sizeof(TCHAR
));
231 lstrcpyn(entry
->_display_name
, entry
->_data
.cFileName
, len
+ 1);
234 if (is_exe_file(ext
))
235 entry
->_data
.dwFileAttributes
|= ATTRIBUTE_EXECUTABLE
;
249 Icon::Icon(ICON_ID id
, UINT nid
) //, int cx, int cy
252 _hicon(ResIcon(nid
)) // ResIconEx(nid, cx, cy)
256 Icon::Icon(ICON_TYPE itype
, int id
, HICON hIcon
)
263 Icon::Icon(ICON_TYPE itype
, int id
, int sys_idx
)
270 void Icon::draw(HDC hdc
, int x
, int y
, int cx
, int cy
, COLORREF bk_color
, HBRUSH bk_brush
) const
272 if (_itype
== IT_SYSCACHE
)
273 ImageList_DrawEx(g_Globals
._icon_cache
.get_sys_imagelist(), _sys_idx
, hdc
, x
, y
, cx
, cy
, bk_color
, CLR_DEFAULT
, ILD_NORMAL
);
275 DrawIconEx(hdc
, x
, y
, _hicon
, cx
, cy
, 0, bk_brush
, DI_NORMAL
);
278 HBITMAP
Icon::create_bitmap(COLORREF bk_color
, HBRUSH hbrBkgnd
, HDC hdc_wnd
) const
280 if (_itype
== IT_SYSCACHE
) {
281 HIMAGELIST himl
= g_Globals
._icon_cache
.get_sys_imagelist();
284 ImageList_GetIconSize(himl
, &cx
, &cy
);
286 HBITMAP hbmp
= CreateCompatibleBitmap(hdc_wnd
, cx
, cy
);
287 HDC hdc
= CreateCompatibleDC(hdc_wnd
);
288 HBITMAP hbmp_old
= SelectBitmap(hdc
, hbmp
);
289 ImageList_DrawEx(himl
, _sys_idx
, hdc
, 0, 0, cx
, cy
, bk_color
, CLR_DEFAULT
, ILD_NORMAL
);
290 SelectBitmap(hdc
, hbmp_old
);
295 return create_bitmap_from_icon(_hicon
, hbrBkgnd
, hdc_wnd
);
299 int Icon::add_to_imagelist(HIMAGELIST himl
, HDC hdc_wnd
, COLORREF bk_color
, HBRUSH bk_brush
) const
303 if (_itype
== IT_SYSCACHE
) {
304 HIMAGELIST himl
= g_Globals
._icon_cache
.get_sys_imagelist();
307 ImageList_GetIconSize(himl
, &cx
, &cy
);
309 HBITMAP hbmp
= CreateCompatibleBitmap(hdc_wnd
, cx
, cy
);
310 HDC hdc
= CreateCompatibleDC(hdc_wnd
);
311 HBITMAP hbmp_old
= SelectBitmap(hdc
, hbmp
);
312 ImageList_DrawEx(himl
, _sys_idx
, hdc
, 0, 0, cx
, cy
, bk_color
, CLR_DEFAULT
, ILD_NORMAL
);
313 SelectBitmap(hdc
, hbmp_old
);
316 ret
= ImageList_Add(himl
, hbmp
, 0);
320 ret
= ImageList_AddAlphaIcon(himl
, _hicon
, bk_brush
, hdc_wnd
);
325 HBITMAP
create_bitmap_from_icon(HICON hIcon
, HBRUSH hbrush_bkgnd
, HDC hdc_wnd
/*, bool big_icons*/)
327 int cx
= GetSystemMetrics(SM_CXSMICON
); //ICON_SIZE_X;
328 int cy
= GetSystemMetrics(SM_CYSMICON
); //ICON_SIZE_Y;
329 HBITMAP hbmp
= CreateCompatibleBitmap(hdc_wnd
, cx
, cy
);
332 BitmapSelection
sel(canvas
, hbmp
);
334 RECT rect
= {0, 0, cx
, cy
};
335 FillRect(canvas
, &rect
, hbrush_bkgnd
);
337 DrawIconEx(canvas
, 0, 0, hIcon
, cx
, cy
, 0, hbrush_bkgnd
, DI_NORMAL
);
342 HBITMAP
create_small_bitmap_from_icon(HICON hIcon
, HBRUSH hbrush_bkgnd
, HDC hdc_wnd
)
344 int cx
= GetSystemMetrics(SM_CXSMICON
);
345 int cy
= GetSystemMetrics(SM_CYSMICON
);
346 HBITMAP hbmp
= CreateCompatibleBitmap(hdc_wnd
, cx
, cy
);
349 BitmapSelection
sel(canvas
, hbmp
);
351 RECT rect
= {0, 0, cx
, cy
};
352 FillRect(canvas
, &rect
, hbrush_bkgnd
);
354 DrawIconEx(canvas
, 0, 0, hIcon
, cx
, cy
, 0, hbrush_bkgnd
, DI_NORMAL
);
359 int ImageList_AddAlphaIcon(HIMAGELIST himl
, HICON hIcon
, HBRUSH hbrush_bkgnd
, HDC hdc_wnd
)
361 HBITMAP hbmp
= create_bitmap_from_icon(hIcon
, hbrush_bkgnd
, hdc_wnd
);
363 int ret
= ImageList_Add(himl
, hbmp
, 0);
371 int IconCache::s_next_id
= ICID_DYNAMIC
;
374 void IconCache::init()
376 _icons
[ICID_NONE
] = Icon(IT_STATIC
, ICID_NONE
, (HICON
)0);
378 _icons
[ICID_FOLDER
] = Icon(ICID_FOLDER
, IDI_FOLDER
);
379 //_icons[ICID_DOCUMENT] = Icon(ICID_DOCUMENT, IDI_DOCUMENT);
380 _icons
[ICID_EXPLORER
] = Icon(ICID_EXPLORER
, IDI_EXPLORER
);
381 _icons
[ICID_APP
] = Icon(ICID_APP
, IDI_APPICON
);
383 _icons
[ICID_CONFIG
] = Icon(ICID_CONFIG
, IDI_CONFIG
);
384 _icons
[ICID_DOCUMENTS
] = Icon(ICID_DOCUMENTS
, IDI_DOCUMENTS
);
385 _icons
[ICID_FAVORITES
] = Icon(ICID_FAVORITES
, IDI_FAVORITES
);
386 _icons
[ICID_INFO
] = Icon(ICID_INFO
, IDI_INFO
);
387 _icons
[ICID_APPS
] = Icon(ICID_APPS
, IDI_APPS
);
388 _icons
[ICID_SEARCH
] = Icon(ICID_SEARCH
, IDI_SEARCH
);
389 _icons
[ICID_ACTION
] = Icon(ICID_ACTION
, IDI_ACTION
);
390 _icons
[ICID_SEARCH_DOC
] = Icon(ICID_SEARCH_DOC
, IDI_SEARCH_DOC
);
391 _icons
[ICID_PRINTER
] = Icon(ICID_PRINTER
, IDI_PRINTER
);
392 _icons
[ICID_NETWORK
] = Icon(ICID_NETWORK
, IDI_NETWORK
);
393 _icons
[ICID_COMPUTER
] = Icon(ICID_COMPUTER
, IDI_COMPUTER
);
394 _icons
[ICID_LOGOFF
] = Icon(ICID_LOGOFF
, IDI_LOGOFF
);
395 _icons
[ICID_BOOKMARK
] = Icon(ICID_BOOKMARK
, IDI_DOT_TRANS
);
399 const Icon
& IconCache::extract(LPCTSTR path
, bool big_icons
)
401 PathMap::iterator found
= _pathMap
.find(path
);
403 if (found
!= _pathMap
.end())
404 return _icons
[found
->second
];
409 if (SHGetFileInfo(path
, 0, &sfi
, sizeof(sfi
), SHGFI_ICON
)) {
410 const Icon
& icon
= add(sfi
.hIcon
, IT_CACHED
);
412 ///@todo limit cache size
413 _pathMap
[path
] = icon
;
418 // use system image list - the "search program dialog" needs it
419 HIMAGELIST himlSys_small
= (HIMAGELIST
) SHGetFileInfo(path
, 0, &sfi
, sizeof(sfi
), SHGFI_SYSICONINDEX
|SHGFI_SMALLICON
);
422 _himlSys_small
= himlSys_small
;
424 const Icon
& icon
= add(sfi
.iIcon
/*, IT_SYSCACHE*/);
426 ///@todo limit cache size
427 _pathMap
[path
] = icon
;
433 return _icons
[ICID_NONE
];
436 const Icon
& IconCache::extract(LPCTSTR path
, int idx
)
438 CachePair
key(path
, idx
);
442 PathIdxMap::iterator found
= _pathIdxMap
.find(key
);
444 if (found
!= _pathIdxMap
.end())
445 return _icons
[found
->second
];
449 if ((int)ExtractIconEx(path
, idx
, NULL
, &hIcon
, 1) > 0) {
450 const Icon
& icon
= add(hIcon
, IT_CACHED
);
452 _pathIdxMap
[key
] = icon
;
457 ///@todo retreive "http://.../favicon.ico" format icons
459 return _icons
[ICID_NONE
];
463 const Icon
& IconCache::extract(IExtractIcon
* pExtract
, LPCTSTR path
, int idx
, bool big_icons
)
465 HICON hIconLarge
= 0;
468 HRESULT hr
= pExtract
->Extract(path
, idx
, &hIconLarge
, &hIcon
, MAKELONG(GetSystemMetrics(SM_CXICON
), ICON_SIZE_X
));
470 if (hr
== NOERROR
) { //@@ oder SUCCEEDED(hr) ?
471 if (big_icons
) { //@@ OK?
478 DestroyIcon(hIconLarge
);
485 return _icons
[ICID_NONE
];
488 const Icon
& IconCache::add(HICON hIcon
, ICON_TYPE type
)
490 int id
= ++s_next_id
;
492 return _icons
[id
] = Icon(type
, id
, hIcon
);
495 const Icon
& IconCache::add(int sys_idx
/*, ICON_TYPE type=IT_SYSCACHE*/)
497 int id
= ++s_next_id
;
499 return _icons
[id
] = SysCacheIcon(id
, sys_idx
);
502 const Icon
& IconCache::get_icon(int id
)
507 void IconCache::free_icon(int icon_id
)
509 IconMap::iterator found
= _icons
.find(icon_id
);
511 if (found
!= _icons
.end()) {
512 Icon
& icon
= found
->second
;
520 ResString::ResString(UINT nid
)
522 TCHAR buffer
[BUFFER_LEN
];
524 int len
= LoadString(g_Globals
._hInstance
, nid
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
526 super::assign(buffer
, len
);
530 ResIcon::ResIcon(UINT nid
)
532 _hicon
= LoadIcon(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
535 SmallIcon::SmallIcon(UINT nid
)
537 _hicon
= (HICON
)LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
), IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_SHARED
);
540 ResIconEx::ResIconEx(UINT nid
, int w
, int h
)
542 _hicon
= (HICON
)LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
), IMAGE_ICON
, w
, h
, LR_SHARED
);
546 void SetWindowIcon(HWND hwnd
, UINT nid
)
548 HICON hIcon
= ResIcon(nid
);
549 (void)Window_SetIcon(hwnd
, ICON_BIG
, hIcon
);
551 HICON hIconSmall
= SmallIcon(nid
);
552 (void)Window_SetIcon(hwnd
, ICON_SMALL
, hIconSmall
);
556 ResBitmap::ResBitmap(UINT nid
)
558 _hBmp
= LoadBitmap(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
564 void explorer_show_frame(int cmdShow
, LPTSTR lpCmdLine
)
568 if (g_Globals
._hMainWnd
) {
569 if (IsIconic(g_Globals
._hMainWnd
))
570 ShowWindow(g_Globals
._hMainWnd
, SW_RESTORE
);
572 SetForegroundWindow(g_Globals
._hMainWnd
);
577 g_Globals
._prescan_nodes
= false;
579 XMLPos explorer_options
= g_Globals
.get_cfg("general/explorer");
580 XS_String mdiStr
= XMLString(explorer_options
, "mdi");
582 // If there isn't yet the "mdi" setting in the configuration, display MDI/SDI dialog.
584 Dialog::DoModal(IDD_MDI_SDI
, WINDOW_CREATOR(MdiSdiDlg
), g_Globals
._hwndDesktop
);
586 // Now read the MDI attribute again and interpret it as boolean value.
587 cmd
._mdi
= XMLBool(explorer_options
, "mdi", true);
589 cmd
._cmdShow
= cmdShow
;
591 // parse command line options, which may overwrite the MDI flag
593 cmd
.ParseCmdLine(lpCmdLine
);
595 // create main window
596 MainFrameBase::Create(cmd
);
599 bool ExplorerCmd::ParseCmdLine(LPCTSTR lpCmdLine
)
603 LPCTSTR b
= lpCmdLine
;
607 // remove leading space
608 while(_istspace((unsigned)*b
))
615 // options are separated by ','
617 if (*p
== '"') // Quote characters may appear at any position in the command line.
619 else if (*p
==',' && !quote
)
626 // remove trailing space
627 while(l
>0 && _istspace((unsigned)b
[l
-1]))
630 if (!EvaluateOption(String(b
, l
)))
643 bool ExplorerCmd::EvaluateOption(LPCTSTR option
)
647 // Remove quote characters, as they are evaluated at this point.
648 for(; *option
; ++option
)
654 if (option
[0] == '/') {
657 // option /e for windows in explorer mode
658 if (!_tcsicmp(option
, TEXT("e")))
659 _flags
|= OWM_EXPLORE
;
660 // option /root for rooted explorer windows
661 else if (!_tcsicmp(option
, TEXT("root")))
662 _flags
|= OWM_ROOTED
;
663 // non-standard options: /mdi, /sdi
664 else if (!_tcsicmp(option
, TEXT("mdi")))
666 else if (!_tcsicmp(option
, TEXT("sdi")))
680 bool ExplorerCmd::IsValidPath() const
682 if (!_path
.empty()) {
683 DWORD attribs
= GetFileAttributes(_path
);
685 if (attribs
!=INVALID_FILE_ATTRIBUTES
&& (attribs
&FILE_ATTRIBUTE_DIRECTORY
))
686 return true; // file system path
687 else if (*_path
==':' && _path
.at(1)==':')
688 return true; // text encoded IDL
696 void explorer_show_frame(int cmdShow
, LPTSTR lpCmdLine
)
699 lpCmdLine
= TEXT("explorer.exe");
701 launch_file(GetDesktopWindow(), lpCmdLine
, cmdShow
);
707 PopupMenu::PopupMenu(UINT nid
)
709 HMENU hMenu
= LoadMenu(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
710 _hmenu
= GetSubMenu(hMenu
, 0);
714 /// "About Explorer" Dialog
715 struct ExplorerAboutDlg
: public
717 OwnerDrawParent
<Dialog
>
720 typedef CtlColorParent
<
721 OwnerDrawParent
<Dialog
>
724 ExplorerAboutDlg(HWND hwnd
)
727 SetWindowIcon(hwnd
, IDI_REACTOS
);
729 new FlatButton(hwnd
, IDOK
);
731 _hfont
= CreateFont(20, 0, 0, 0, FW_BOLD
, TRUE
, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif"));
732 new ColorStatic(hwnd
, IDC_ROS_EXPLORER
, RGB(32,32,128), 0, _hfont
);
734 new HyperlinkCtrl(hwnd
, IDC_WWW
);
736 FmtString
ver_txt(ResString(IDS_EXPLORER_VERSION_STR
), (LPCTSTR
)ResString(IDS_VERSION_STR
));
737 SetWindowText(GetDlgItem(hwnd
, IDC_VERSION_TXT
), ver_txt
);
739 HWND hwnd_winver
= GetDlgItem(hwnd
, IDC_WIN_VERSION
);
740 SetWindowText(hwnd_winver
, get_windows_version_str());
741 SetWindowFont(hwnd_winver
, GetStockFont(DEFAULT_GUI_FONT
), FALSE
);
748 DeleteObject(_hfont
);
751 LRESULT
WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
759 return super::WndProc(nmsg
, wparam
, lparam
);
767 PaintCanvas
canvas(_hwnd
);
769 HICON hicon
= (HICON
) LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(IDI_REACTOS_BIG
), IMAGE_ICON
, 0, 0, LR_SHARED
);
771 DrawIconEx(canvas
, 20, 10, hicon
, 0, 0, 0, 0, DI_NORMAL
);
778 void explorer_about(HWND hwndParent
)
780 Dialog::DoModal(IDD_ABOUT_EXPLORER
, WINDOW_CREATOR(ExplorerAboutDlg
), hwndParent
);
784 static void InitInstance(HINSTANCE hInstance
)
786 CONTEXT("InitInstance");
788 setlocale(LC_COLLATE
, ""); // set collating rules to local settings for compareName
791 // register frame window class
792 g_Globals
._hframeClass
= IconWindowClass(CLASSNAME_FRAME
,IDI_EXPLORER
);
794 // register child window class
795 WindowClass(CLASSNAME_CHILDWND
, CS_CLASSDC
|CS_DBLCLKS
|CS_VREDRAW
).Register();
797 // register tree window class
798 WindowClass(CLASSNAME_WINEFILETREE
, CS_CLASSDC
|CS_DBLCLKS
|CS_VREDRAW
).Register();
801 g_Globals
._cfStrFName
= RegisterClipboardFormat(CFSTR_FILENAME
);
805 int explorer_main(HINSTANCE hInstance
, LPTSTR lpCmdLine
, int cmdShow
)
807 CONTEXT("explorer_main");
809 // initialize Common Controls library
810 CommonControlInit usingCmnCtrl
;
813 InitInstance(hInstance
);
814 } catch(COMException
& e
) {
815 HandleException(e
, GetDesktopWindow());
820 if (cmdShow
!= SW_HIDE
) {
821 /* // don't maximize if being called from the ROS desktop
822 if (cmdShow == SW_SHOWNORMAL)
823 ///@todo read window placement from registry
824 cmdShow = SW_MAXIMIZE;
827 explorer_show_frame(cmdShow
, lpCmdLine
);
831 return Window::MessageLoop();
835 // MinGW does not provide a Unicode startup routine, so we have to implement an own.
836 #if defined(__MINGW32__) && defined(UNICODE)
838 #define _tWinMain wWinMain
839 int WINAPI
wWinMain(HINSTANCE
, HINSTANCE
, LPWSTR
, int);
841 int main(int argc
, char* argv
[])
845 STARTUPINFO startupinfo
;
846 int nShowCmd
= SW_SHOWNORMAL
;
848 GetStartupInfo(&startupinfo
);
850 if (startupinfo
.dwFlags
& STARTF_USESHOWWINDOW
)
851 nShowCmd
= startupinfo
.wShowWindow
;
853 LPWSTR cmdline
= GetCommandLineW();
855 while(*cmdline
&& !_istspace((unsigned)*cmdline
))
858 while(_istspace((unsigned)*cmdline
))
861 return wWinMain(GetModuleHandle(NULL
), 0, cmdline
, nShowCmd
);
864 #endif // __MINGW && UNICODE
867 static bool SetShellReadyEvent(LPCTSTR evtName
)
869 HANDLE hEvent
= OpenEvent(EVENT_MODIFY_STATE
, FALSE
, evtName
);
880 int WINAPI
_tWinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPTSTR lpCmdLine
, int nShowCmd
)
882 CONTEXT("WinMain()");
884 BOOL any_desktop_running
= IsAnyDesktopRunning();
886 BOOL startup_desktop
;
888 // strip extended options from the front of the command line
891 while(*lpCmdLine
== '-') {
892 while(*lpCmdLine
&& !_istspace((unsigned)*lpCmdLine
))
893 ext_options
+= *lpCmdLine
++;
895 while(_istspace((unsigned)*lpCmdLine
))
899 // command line option "-install" to replace previous shell application with ROS Explorer
900 if (_tcsstr(ext_options
,TEXT("-install"))) {
901 // install ROS Explorer into the registry
902 TCHAR path
[MAX_PATH
];
904 int l
= GetModuleFileName(0, path
, MAX_PATH
);
908 if (!RegOpenKey(HKEY_LOCAL_MACHINE
, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hkey
)) {
910 ///@todo save previous shell application in config file
912 RegSetValueEx(hkey
, TEXT("Shell"), 0, REG_SZ
, (LPBYTE
)path
, l
*sizeof(TCHAR
));
916 if (!RegOpenKey(HKEY_CURRENT_USER
, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hkey
)) {
918 ///@todo save previous shell application in config file
920 RegSetValueEx(hkey
, TEXT("Shell"), 0, REG_SZ
, (LPBYTE
)TEXT(""), l
*sizeof(TCHAR
));
925 HWND shellWindow
= GetShellWindow();
930 // terminate shell process for NT like systems
931 GetWindowThreadProcessId(shellWindow
, &pid
);
932 HANDLE hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, FALSE
, pid
);
934 // On Win 9x it's sufficient to destroy the shell window.
935 DestroyWindow(shellWindow
);
937 if (TerminateProcess(hProcess
, 0))
938 WaitForSingleObject(hProcess
, INFINITE
);
940 CloseHandle(hProcess
);
943 startup_desktop
= TRUE
;
945 // create desktop window and task bar only, if there is no other shell and we are
946 // the first explorer instance
947 // MS Explorer looks additionally into the registry entry HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\shell,
948 // to decide wether it is currently configured as shell application.
949 startup_desktop
= !any_desktop_running
;
953 bool autostart
= !any_desktop_running
;
955 // disable autostart if the SHIFT key is pressed
956 if (GetAsyncKeyState(VK_SHIFT
) < 0)
959 #ifdef _DEBUG //MF: disabled for debugging
963 // If there is given the command line option "-desktop", create desktop window anyways
964 if (_tcsstr(ext_options
,TEXT("-desktop")))
965 startup_desktop
= TRUE
;
967 else if (_tcsstr(ext_options
,TEXT("-nodesktop")))
968 startup_desktop
= FALSE
;
970 // Don't display cabinet window in desktop mode
971 if (startup_desktop
&& !_tcsstr(ext_options
,TEXT("-explorer")))
975 if (_tcsstr(ext_options
,TEXT("-noautostart")))
977 else if (_tcsstr(ext_options
,TEXT("-autostart")))
981 if (_tcsstr(ext_options
,TEXT("-console"))) {
984 _dup2(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE
), _O_RDONLY
), 0);
985 _dup2(_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE
), 0), 1);
986 _dup2(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE
), 0), 2);
988 g_Globals
._log
= fdopen(1, "w");
989 setvbuf(g_Globals
._log
, 0, _IONBF
, 0);
991 LOG(TEXT("starting explorer debug log\n"));
996 if (startup_desktop
) {
997 // hide the XP login screen (Credit to Nicolas Escuder)
998 // another undocumented event: "Global\\msgina: ReturnToWelcome"
999 if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
1000 SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
1004 return 0; // no shell to launch, so exit immediatelly
1008 if (!any_desktop_running
) {
1009 // launch the shell DDE server
1010 if (g_SHDOCVW_ShellDDEInit
)
1011 (*g_SHDOCVW_ShellDDEInit
)(TRUE
);
1015 bool use_gdb_stub
= false; // !IsDebuggerPresent();
1017 if (_tcsstr(ext_options
,TEXT("-debug")))
1018 use_gdb_stub
= true;
1020 if (_tcsstr(ext_options
,TEXT("-break"))) {
1021 LOG(TEXT("debugger breakpoint"));
1029 // activate GDB remote debugging stub if no other debugger is running
1031 LOG(TEXT("waiting for debugger connection...\n"));
1033 initialize_gdb_stub();
1036 g_Globals
.init(hInstance
);
1038 // initialize COM and OLE before creating the desktop window
1041 // init common controls library
1042 CommonControlInit usingCmnCtrl
;
1044 g_Globals
.read_persistent();
1046 if (startup_desktop
) {
1049 g_Globals
._desktops
.init();
1051 g_Globals
._hwndDesktop
= DesktopWindow::Create();
1053 g_Globals
._desktops
.get_current_Desktop()->_hwndDesktop
= g_Globals
._hwndDesktop
;
1057 Thread
* pSSOThread
= NULL
;
1059 if (startup_desktop
) {
1060 // launch SSO thread to allow message processing independent from the explorer main thread
1061 pSSOThread
= new SSOThread
;
1062 pSSOThread
->Start();
1065 /**TODO launching autostart programs can be moved into a background thread. */
1067 char* argv
[] = {"", "s"}; // call startup routine in SESSION_START mode
1072 if (g_Globals
._hwndDesktop
)
1073 g_Globals
._desktop_mode
= true;
1077 int ret
= explorer_main(hInstance
, lpCmdLine
, nShowCmd
);
1080 // write configuration file
1081 g_Globals
.write_persistent();
1088 if (!any_desktop_running
) {
1089 // shutdown the shell DDE server
1090 if (g_SHDOCVW_ShellDDEInit
)
1091 (*g_SHDOCVW_ShellDDEInit
)(FALSE
);