2 * Copyright 2003, 2004 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
21 // Explorer clone, lean version
25 // Martin Fuchs, 23.07.2003
27 // Credits: Thanks to Leon Finker for his explorer window example
33 #include "explorer_intres.h"
35 #include <locale.h> // for setlocale()
38 ExplorerGlobals g_Globals
;
41 ExplorerGlobals::ExplorerGlobals()
47 _prescan_nodes
= false;
48 _desktop_mode
= false;
50 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
59 void ExplorerGlobals::init(HINSTANCE hInstance
)
61 _hInstance
= hInstance
;
63 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
64 _SHRestricted
= (DWORD(STDAPICALLTYPE
*)(RESTRICTIONS
)) GetProcAddress(GetModuleHandle(TEXT("SHELL32")), "SHRestricted");
71 void _log_(LPCTSTR txt
)
73 FmtString
msg(TEXT("%s\n"), txt
);
76 _fputts(msg
, g_Globals
._log
);
78 OutputDebugString(msg
);
82 bool FileTypeManager::is_exe_file(LPCTSTR ext
)
84 static const LPCTSTR s_executable_extensions
[] = {
95 TCHAR ext_buffer
[_MAX_EXT
];
100 for(s
=ext
+1,d
=ext_buffer
; (*d
=toupper(*s
)); s
++)
103 for(p
=s_executable_extensions
; *p
; p
++)
104 if (!lstrcmp(ext_buffer
, *p
))
111 const FileTypeInfo
& FileTypeManager::operator[](String ext
)
113 _tcslwr((LPTSTR
)ext
.c_str());
115 iterator found
= find(ext
);
117 return found
->second
;
119 FileTypeInfo
& ftype
= super::operator[](ext
);
121 ftype
._neverShowExt
= false;
124 TCHAR value
[MAX_PATH
], display_name
[MAX_PATH
];;
125 LONG valuelen
= sizeof(value
);
127 if (!RegQueryValue(HKEY_CLASSES_ROOT
, ext
, value
, &valuelen
)) {
128 ftype
._classname
= value
;
130 valuelen
= sizeof(display_name
);
131 if (!RegQueryValue(HKEY_CLASSES_ROOT
, ftype
._classname
, display_name
, &valuelen
))
132 ftype
._displayname
= display_name
;
134 if (!RegOpenKey(HKEY_CLASSES_ROOT
, ftype
._classname
, &hkey
)) {
135 if (!RegQueryValueEx(hkey
, TEXT("NeverShowExt"), 0, NULL
, NULL
, NULL
))
136 ftype
._neverShowExt
= true;
145 LPCTSTR
FileTypeManager::set_type(Entry
* entry
, bool dont_hide_ext
)
147 LPCTSTR ext
= _tcsrchr(entry
->_data
.cFileName
, TEXT('.'));
150 const FileTypeInfo
& type
= (*this)[ext
];
152 if (!type
._displayname
.empty())
153 entry
->_type_name
= _tcsdup(type
._displayname
);
155 // hide some file extensions
156 if (type
._neverShowExt
&& !dont_hide_ext
) {
157 int len
= ext
- entry
->_data
.cFileName
;
158 entry
->_display_name
= (LPTSTR
) malloc((len
+1)*sizeof(TCHAR
));
159 _tcsncpy(entry
->_display_name
, entry
->_data
.cFileName
, len
);
160 entry
->_display_name
[len
] = TEXT('\0');
163 if (is_exe_file(ext
))
164 entry
->_data
.dwFileAttributes
|= ATTRIBUTE_EXECUTABLE
;
178 Icon::Icon(ICON_ID id
, UINT nid
)
181 _hicon(SmallIcon(nid
))
185 Icon::Icon(ICON_TYPE itype
, int id
, HICON hIcon
)
192 Icon::Icon(ICON_TYPE itype
, int id
, int sys_idx
)
199 void Icon::draw(HDC hdc
, int x
, int y
, int cx
, int cy
, COLORREF bk_color
, HBRUSH bk_brush
) const
201 if (_itype
== IT_SYSCACHE
)
202 ImageList_DrawEx(g_Globals
._icon_cache
.get_sys_imagelist(), _sys_idx
, hdc
, x
, y
, cx
, cy
, bk_color
, CLR_DEFAULT
, ILD_NORMAL
);
204 DrawIconEx(hdc
, x
, y
, _hicon
, cx
, cy
, 0, bk_brush
, DI_NORMAL
);
207 HBITMAP
Icon::create_bitmap(COLORREF bk_color
, HBRUSH hbrBkgnd
, HDC hdc_wnd
) const
209 if (_itype
== IT_SYSCACHE
) {
210 HIMAGELIST himl
= g_Globals
._icon_cache
.get_sys_imagelist();
213 ImageList_GetIconSize(himl
, &cx
, &cy
);
215 HBITMAP hbmp
= CreateCompatibleBitmap(hdc_wnd
, cx
, cy
);
216 HDC hdc
= CreateCompatibleDC(hdc_wnd
);
217 HBITMAP hbmp_old
= SelectBitmap(hdc
, hbmp
);
218 ImageList_DrawEx(himl
, _sys_idx
, hdc
, 0, 0, cx
, cy
, bk_color
, CLR_DEFAULT
, ILD_NORMAL
);
219 SelectBitmap(hdc
, hbmp_old
);
223 return create_bitmap_from_icon(_hicon
, hbrBkgnd
, hdc_wnd
);
226 HBITMAP
create_bitmap_from_icon(HICON hIcon
, HBRUSH hbrush_bkgnd
, HDC hdc_wnd
)
228 HBITMAP hbmp
= CreateCompatibleBitmap(hdc_wnd
, 16, 16);
231 BitmapSelection
sel(canvas
, hbmp
);
233 RECT rect
= {0, 0, 16, 16};
234 FillRect(canvas
, &rect
, hbrush_bkgnd
);
236 DrawIconEx(canvas
, 0, 0, hIcon
, 16, 16, 0, hbrush_bkgnd
, DI_NORMAL
);
242 int IconCache::s_next_id
= ICID_DYNAMIC
;
245 void IconCache::init()
247 _icons
[ICID_NONE
] = Icon(IT_STATIC
, ICID_NONE
, (HICON
)0);
249 _icons
[ICID_FOLDER
] = Icon(ICID_FOLDER
, IDI_FOLDER
);
250 //_icons[ICID_DOCUMENT] = Icon(ICID_DOCUMENT, IDI_DOCUMENT);
251 _icons
[ICID_EXPLORER
] = Icon(ICID_EXPLORER
, IDI_EXPLORER
);
252 _icons
[ICID_APP
] = Icon(ICID_APP
, IDI_APPICON
);
254 _icons
[ICID_CONFIG
] = Icon(ICID_CONFIG
, IDI_CONFIG
);
255 _icons
[ICID_DOCUMENTS
] = Icon(ICID_DOCUMENTS
, IDI_DOCUMENTS
);
256 _icons
[ICID_FAVORITES
] = Icon(ICID_FAVORITES
, IDI_FAVORITES
);
257 _icons
[ICID_INFO
] = Icon(ICID_INFO
, IDI_INFO
);
258 _icons
[ICID_APPS
] = Icon(ICID_APPS
, IDI_APPS
);
259 _icons
[ICID_SEARCH
] = Icon(ICID_SEARCH
, IDI_SEARCH
);
260 _icons
[ICID_ACTION
] = Icon(ICID_ACTION
, IDI_ACTION
);
261 _icons
[ICID_SEARCH_DOC
] = Icon(ICID_SEARCH_DOC
, IDI_SEARCH_DOC
);
262 _icons
[ICID_PRINTER
] = Icon(ICID_PRINTER
, IDI_PRINTER
);
263 _icons
[ICID_NETWORK
] = Icon(ICID_NETWORK
, IDI_NETWORK
);
264 _icons
[ICID_COMPUTER
] = Icon(ICID_COMPUTER
, IDI_COMPUTER
);
265 _icons
[ICID_LOGOFF
] = Icon(ICID_LOGOFF
, IDI_LOGOFF
);
269 const Icon
& IconCache::extract(const String
& path
)
271 PathMap::iterator found
= _pathMap
.find(path
);
273 if (found
!= _pathMap
.end())
274 return _icons
[found
->second
];
278 #if 1 // use system image list
279 HIMAGELIST himlSys
= (HIMAGELIST
) SHGetFileInfo(path
, 0, &sfi
, sizeof(sfi
), SHGFI_SYSICONINDEX
|SHGFI_SMALLICON
);
284 const Icon
& icon
= add(sfi
.iIcon
/*, IT_SYSCACHE*/);
286 if (SHGetFileInfo(path
, 0, &sfi
, sizeof(sfi
), SHGFI_ICON
|SHGFI_SMALLICON
)) {
287 const Icon
& icon
= add(sfi
.hIcon
, IT_CACHED
);
290 ///@todo limit cache size
291 _pathMap
[path
] = icon
;
295 return _icons
[ICID_NONE
];
298 const Icon
& IconCache::extract(LPCTSTR path
, int idx
)
300 CachePair
key(path
, idx
);
302 _tcslwr((LPTSTR
)key
.first
.c_str());
304 PathIdxMap::iterator found
= _pathIdxMap
.find(key
);
306 if (found
!= _pathIdxMap
.end())
307 return _icons
[found
->second
];
311 if ((int)ExtractIconEx(path
, idx
, NULL
, &hIcon
, 1) > 0) {
312 const Icon
& icon
= add(hIcon
, IT_CACHED
);
314 _pathIdxMap
[key
] = icon
;
318 return _icons
[ICID_NONE
];
321 const Icon
& IconCache::extract(IExtractIcon
* pExtract
, LPCTSTR path
, int idx
)
323 HICON hIconLarge
= 0;
326 HRESULT hr
= pExtract
->Extract(path
, idx
, &hIconLarge
, &hIcon
, MAKELONG(0/*GetSystemMetrics(SM_CXICON)*/,GetSystemMetrics(SM_CXSMICON
)));
330 DestroyIcon(hIconLarge
);
336 return _icons
[ICID_NONE
];
339 const Icon
& IconCache::add(HICON hIcon
, ICON_TYPE type
)
341 int id
= ++s_next_id
;
343 return _icons
[id
] = Icon(type
, id
, hIcon
);
346 const Icon
& IconCache::add(int sys_idx
/*, ICON_TYPE type=IT_SYSCACHE*/)
348 int id
= ++s_next_id
;
350 return _icons
[id
] = SysCacheIcon(id
, sys_idx
);
353 const Icon
& IconCache::get_icon(int id
)
358 void IconCache::free_icon(int icon_id
)
360 IconMap::iterator found
= _icons
.find(icon_id
);
362 if (found
!= _icons
.end()) {
363 Icon
& icon
= found
->second
;
371 ResString::ResString(UINT nid
)
373 TCHAR buffer
[BUFFER_LEN
];
375 int len
= LoadString(g_Globals
._hInstance
, nid
, buffer
, sizeof(buffer
)/sizeof(TCHAR
));
377 super::assign(buffer
, len
);
381 ResIcon::ResIcon(UINT nid
)
383 _hicon
= LoadIcon(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
386 SmallIcon::SmallIcon(UINT nid
)
388 _hicon
= (HICON
)LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
), IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_SHARED
);
391 ResIconEx::ResIconEx(UINT nid
, int w
, int h
)
393 _hicon
= (HICON
)LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
), IMAGE_ICON
, w
, h
, LR_SHARED
);
397 void SetWindowIcon(HWND hwnd
, UINT nid
)
399 HICON hIcon
= ResIcon(nid
);
400 Window_SetIcon(hwnd
, ICON_BIG
, hIcon
);
402 HICON hIconSmall
= SmallIcon(nid
);
403 Window_SetIcon(hwnd
, ICON_SMALL
, hIconSmall
);
407 ResBitmap::ResBitmap(UINT nid
)
409 _hBmp
= LoadBitmap(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
413 void explorer_show_frame(int cmdshow
, LPTSTR lpCmdLine
)
415 if (g_Globals
._hMainWnd
) {
416 if (IsIconic(g_Globals
._hMainWnd
))
417 ShowWindow(g_Globals
._hMainWnd
, SW_RESTORE
);
419 SetForegroundWindow(g_Globals
._hMainWnd
);
424 g_Globals
._prescan_nodes
= false;
426 // create main window
427 HWND hMainFrame
= MainFrame::Create();
430 g_Globals
._hMainWnd
= hMainFrame
;
432 ShowWindow(hMainFrame
, cmdshow
);
433 UpdateWindow(hMainFrame
);
435 bool valid_dir
= false;
438 DWORD attribs
= GetFileAttributes(lpCmdLine
);
440 if (attribs
!=INVALID_FILE_ATTRIBUTES
&& (attribs
&FILE_ATTRIBUTE_DIRECTORY
))
442 else if (*lpCmdLine
==':' || *lpCmdLine
=='"')
446 // Open the first child window after initializing the application
448 PostMessage(hMainFrame
, PM_OPEN_WINDOW
, 0, (LPARAM
)lpCmdLine
);
450 PostMessage(hMainFrame
, PM_OPEN_WINDOW
, 0/*OWM_EXPLORE|OWM_DETAILS*/, 0);
455 PopupMenu::PopupMenu(UINT nid
)
457 HMENU hMenu
= LoadMenu(g_Globals
._hInstance
, MAKEINTRESOURCE(nid
));
458 _hmenu
= GetSubMenu(hMenu
, 0);
462 /// "About Explorer" Dialog
463 struct ExplorerAboutDlg
: public
465 OwnerDrawParent
<Dialog
>
468 typedef CtlColorParent
<
469 OwnerDrawParent
<Dialog
>
472 ExplorerAboutDlg(HWND hwnd
)
475 SetWindowIcon(hwnd
, IDI_REACTOS
);
477 new FlatButton(hwnd
, IDOK
);
479 _hfont
= CreateFont(20, 0, 0, 0, FW_BOLD
, TRUE
, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif"));
480 new ColorStatic(hwnd
, IDC_ROS_EXPLORER
, RGB(32,32,128), 0, _hfont
);
482 new HyperlinkCtrl(hwnd
, IDC_WWW
);
489 DeleteObject(_hfont
);
492 LRESULT
WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
500 return super::WndProc(nmsg
, wparam
, lparam
);
508 PaintCanvas
canvas(_hwnd
);
510 HICON hicon
= (HICON
) LoadImage(g_Globals
._hInstance
, MAKEINTRESOURCE(IDI_REACTOS_BIG
), IMAGE_ICON
, 0, 0, LR_SHARED
);
512 DrawIconEx(canvas
, 20, 10, hicon
, 0, 0, 0, 0, DI_NORMAL
);
519 void explorer_about(HWND hwndParent
)
521 Dialog::DoModal(IDD_ABOUT_EXPLORER
, WINDOW_CREATOR(ExplorerAboutDlg
), hwndParent
);
525 static void InitInstance(HINSTANCE hInstance
)
527 CONTEXT("InitInstance");
529 setlocale(LC_COLLATE
, ""); // set collating rules to local settings for compareName
531 // register frame window class
532 g_Globals
._hframeClass
= IconWindowClass(CLASSNAME_FRAME
,IDI_EXPLORER
);
534 // register child windows class
535 WindowClass(CLASSNAME_CHILDWND
, CS_CLASSDC
|CS_DBLCLKS
|CS_VREDRAW
).Register();
537 // register tree windows class
538 WindowClass(CLASSNAME_WINEFILETREE
, CS_CLASSDC
|CS_DBLCLKS
|CS_VREDRAW
).Register();
540 g_Globals
._cfStrFName
= RegisterClipboardFormat(CFSTR_FILENAME
);
544 int explorer_main(HINSTANCE hInstance
, LPTSTR lpCmdLine
, int cmdshow
)
546 CONTEXT("explorer_main");
548 // initialize Common Controls library
549 CommonControlInit usingCmnCtrl
;
552 InitInstance(hInstance
);
553 } catch(COMException
& e
) {
554 HandleException(e
, GetDesktopWindow());
558 if (cmdshow
!= SW_HIDE
) {
559 /* // don't maximize if being called from the ROS desktop
560 if (cmdshow == SW_SHOWNORMAL)
561 ///@todo read window placement from registry
562 cmdshow = SW_MAXIMIZE;
565 explorer_show_frame(cmdshow
, lpCmdLine
);
568 return Window::MessageLoop();
572 // MinGW does not provide a Unicode startup routine, so we have to implement an own.
573 #if defined(__MINGW32__) && defined(UNICODE)
575 #define _tWinMain wWinMain
576 int WINAPI
wWinMain(HINSTANCE
, HINSTANCE
, LPWSTR
, int);
578 int main(int argc
, char* argv
[])
582 STARTUPINFO startupinfo
;
583 int nShowCmd
= SW_SHOWNORMAL
;
585 GetStartupInfo(&startupinfo
);
587 if (startupinfo
.dwFlags
& STARTF_USESHOWWINDOW
)
588 nShowCmd
= startupinfo
.wShowWindow
;
590 LPWSTR cmdline
= GetCommandLineW();
592 while(*cmdline
&& !_istspace(*cmdline
))
595 return wWinMain(GetModuleHandle(NULL
), 0, cmdline
, nShowCmd
);
598 #endif // __MINGW && UNICODE
601 int WINAPI
_tWinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPTSTR lpCmdLine
, int nShowCmd
)
603 CONTEXT("WinMain()");
605 BOOL any_desktop_running
= IsAnyDesktopRunning();
607 BOOL startup_desktop
;
609 // command line option "-install" to replace previous shell application with ROS Explorer
610 if (_tcsstr(lpCmdLine
,TEXT("-install"))) {
611 // install ROS Explorer into the registry
612 TCHAR path
[MAX_PATH
];
614 int l
= GetModuleFileName(0, path
, MAX_PATH
);
618 if (!RegOpenKey(HKEY_LOCAL_MACHINE
, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hkey
)) {
620 ///@todo save previous shell application in config file
622 RegSetValueEx(hkey
, TEXT("Shell"), 0, REG_SZ
, (LPBYTE
)path
, l
*sizeof(TCHAR
));
627 HWND shellWindow
= GetShellWindow();
632 // terminate shell process for NT like systems
633 GetWindowThreadProcessId(shellWindow
, &pid
);
634 HANDLE hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, FALSE
, pid
);
636 // On Win 9x it's sufficient to destroy the shell window.
637 DestroyWindow(shellWindow
);
639 if (TerminateProcess(hProcess
, 0))
640 WaitForSingleObject(hProcess
, INFINITE
);
642 CloseHandle(hProcess
);
645 startup_desktop
= TRUE
;
647 // create desktop window and task bar only, if there is no other shell and we are
648 // the first explorer instance
649 startup_desktop
= !any_desktop_running
;
651 bool autostart
= !any_desktop_running
;
653 // disable autostart if the SHIFT key is pressed
654 if (GetAsyncKeyState(VK_SHIFT
) < 0)
657 #ifdef _DEBUG //MF: disabled for debugging
661 // If there is given the command line option "-desktop", create desktop window anyways
662 if (_tcsstr(lpCmdLine
,TEXT("-desktop")))
663 startup_desktop
= TRUE
;
664 else if (_tcsstr(lpCmdLine
,TEXT("-nodesktop")))
665 startup_desktop
= FALSE
;
667 // Don't display cabinet window in desktop mode
668 if (startup_desktop
&& !_tcsstr(lpCmdLine
,TEXT("-explorer")))
671 if (_tcsstr(lpCmdLine
,TEXT("-noautostart")))
674 g_Globals
.init(hInstance
);
676 // initialize COM and OLE before creating the desktop window
679 if (startup_desktop
) {
680 g_Globals
._desktops
.init();
682 g_Globals
._hwndDesktop
= DesktopWindow::Create();
685 char* argv
[] = {"", "s"}; // call startup routine in SESSION_START mode
690 /**TODO fix command line handling */
691 if (*lpCmdLine
=='"' && lpCmdLine
[_tcslen(lpCmdLine
)-1]=='"') {
693 lpCmdLine
[_tcslen(lpCmdLine
)-1] = '\0';
696 if (g_Globals
._hwndDesktop
)
697 g_Globals
._desktop_mode
= true;
699 int ret
= explorer_main(hInstance
, lpCmdLine
, nShowCmd
);