implemented command line parser for Explorer
Modified: trunk/reactos/subsys/system/explorer/doc/TODO.txt
Modified: trunk/reactos/subsys/system/explorer/explorer.cpp
Modified: trunk/reactos/subsys/system/explorer/explorer.h
Modified: trunk/reactos/subsys/system/explorer/shell/filechild.cpp
Modified: trunk/reactos/subsys/system/explorer/shell/mainframe.cpp
Modified: trunk/reactos/subsys/system/explorer/shell/mainframe.h
Modified: trunk/reactos/subsys/system/explorer/shell/shellbrowser.cpp

Modified: trunk/reactos/subsys/system/explorer/doc/TODO.txt
--- trunk/reactos/subsys/system/explorer/doc/TODO.txt	2005-10-05 20:36:23 UTC (rev 18283)
+++ trunk/reactos/subsys/system/explorer/doc/TODO.txt	2005-10-05 23:05:13 UTC (rev 18284)
@@ -7,7 +7,6 @@
 - implement Drag Drop from the tree view.
 - activate accelerator keys like <DEL> in shell view folders
 - program manager "progman" DDE server
-- command line parameters like "/e,/root,c:\" and "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}" (launch of control panel)
 - Windows-key combos
 - Application Desktop Toolbars
 - hide CVS subdirectories, may be even implement a CVS managment plugin

Modified: trunk/reactos/subsys/system/explorer/explorer.cpp
--- trunk/reactos/subsys/system/explorer/explorer.cpp	2005-10-05 20:36:23 UTC (rev 18283)
+++ trunk/reactos/subsys/system/explorer/explorer.cpp	2005-10-05 23:05:13 UTC (rev 18284)
@@ -533,8 +533,10 @@
 
 #ifndef ROSSHELL
 
-void explorer_show_frame(int cmdshow, LPTSTR lpCmdLine)
+void explorer_show_frame(int cmdShow, LPTSTR lpCmdLine)
 {
+	ExplorerCmd cmd;
+
 	if (g_Globals._hMainWnd) {
 		if (IsIconic(g_Globals._hMainWnd))
 			ShowWindow(g_Globals._hMainWnd, SW_RESTORE);
@@ -553,21 +555,121 @@
 	if (mdiStr.empty())
 		Dialog::DoModal(IDD_MDI_SDI, WINDOW_CREATOR(MdiSdiDlg), g_Globals._hwndDesktop);
 
-	 // Now read the setting again and interpret it as boolean value.
-	bool mdi = XMLBool(explorer_options, "mdi", true);
+	 // Now read the MDI attribute again and interpret it as boolean value.
+	cmd._mdi = XMLBool(explorer_options, "mdi", true);
 
+	cmd._cmdShow = cmdShow;
+
+	 // parse command line options, which may overwrite the MDI flag
+	cmd.ParseCmdLine(lpCmdLine);
+
 	 // create main window
-	MainFrameBase::Create(lpCmdLine, mdi, cmdshow);
+	MainFrameBase::Create(cmd);
 }
 
+bool ExplorerCmd::ParseCmdLine(LPCTSTR lpCmdLine)
+{
+	bool ok = true;
+
+	LPCTSTR b = lpCmdLine;
+	LPCTSTR p = b;
+
+	while(*b) {
+		 // remove leading space
+		while(_istspace((unsigned)*b))
+			++b;
+
+		p = b;
+
+		bool quote = false;
+
+		 // options are separated by ','
+		for(; *p; ++p) {
+			if (*p == '"')	// Quote characters may appear at any position in the command line.
+				quote = !quote;
+			else if (*p==',' && !quote)
+				break;
+		}
+
+		if (p > b) {
+			int l = p - b;
+
+			 // remove trailing space
+			while(l>0 && _istspace((unsigned)b[l-1]))
+				--l;
+
+			if (!EvaluateOption(String(b, l)))
+				ok = false;
+
+			if (*p)
+				++p;
+
+			b = p;
+		}
+	}
+
+	return ok;
+}
+
+bool ExplorerCmd::EvaluateOption(LPCTSTR option)
+{
+	String opt_str;
+
+	 // Remove quote characters, as they are evaluated at this point.
+	for(; *option; ++option)
+		if (*option != '"')
+			opt_str += *option;
+
+	option = opt_str;
+
+	if (option[0] == '/') {
+		++option;
+
+		 // option /e for windows in explorer mode
+		if (!_tcsicmp(option, TEXT("e")))
+			_flags |= OWM_EXPLORE;
+		 // option /root for rooted explorer windows
+		else if (!_tcsicmp(option, TEXT("root")))
+			_flags |= OWM_ROOTED;
+		 // non-standard options: /mdi, /sdi
+		else if (!_tcsicmp(option, TEXT("mdi")))
+			_mdi = true;
+		else if (!_tcsicmp(option, TEXT("sdi")))
+			_mdi = false;
+		else
+			return false;
+	} else {
+		if (!_path.empty())
+			return false;
+
+		_path = opt_str;
+	}
+
+	return true;
+}
+
+bool ExplorerCmd::IsValidPath() const
+{
+	if (!_path.empty()) {
+		DWORD attribs = GetFileAttributes(_path);
+
+		if (attribs!=INVALID_FILE_ATTRIBUTES && (attribs&FILE_ATTRIBUTE_DIRECTORY))
+			return true;	// file system path
+		else if (*_path==':' && _path.at(1)==':')
+			return true;	// text encoded IDL
+	}
+
+	return false;
+}
+
 #else
 
-void explorer_show_frame(int cmdshow, LPTSTR lpCmdLine)
+void explorer_show_frame(int cmdShow, LPTSTR lpCmdLine)
 {
 	if (!lpCmdLine)
 		lpCmdLine = TEXT("explorer.exe");
 
-	launch_file(GetDesktopWindow(), lpCmdLine, cmdshow);
+	launch_file(GetDesktopWindow(), lpCmdLine, cmdShow);
 }
 
 #endif
@@ -671,7 +773,7 @@
 }
 
 
-int explorer_main(HINSTANCE hInstance, LPTSTR lpCmdLine, int cmdshow)
+int explorer_main(HINSTANCE hInstance, LPTSTR lpCmdLine, int cmdShow)
 {
 	CONTEXT("explorer_main");
 
@@ -686,14 +788,14 @@
 	}
 
 #ifndef ROSSHELL
-	if (cmdshow != SW_HIDE) {
+	if (cmdShow != SW_HIDE) {
 /*	// don't maximize if being called from the ROS desktop
-		if (cmdshow == SW_SHOWNORMAL)
+		if (cmdShow == SW_SHOWNORMAL)
 				///@todo read window placement from registry
-			cmdshow = SW_MAXIMIZE;
+			cmdShow = SW_MAXIMIZE;
 */
 
-		explorer_show_frame(cmdshow, lpCmdLine);
+		explorer_show_frame(cmdShow, lpCmdLine);
 	}
 #endif
 
@@ -721,10 +823,10 @@
 
 	LPWSTR cmdline = GetCommandLineW();
 
-	while(*cmdline && !_istspace(*cmdline))
+	while(*cmdline && !_istspace((unsigned)*cmdline))
 		++cmdline;
 
-	while(_istspace(*cmdline))
+	while(_istspace((unsigned)*cmdline))
 		++cmdline;
 
 	return wWinMain(GetModuleHandle(NULL), 0, cmdline, nShowCmd);
@@ -929,17 +1031,12 @@
 #ifndef ROSSHELL
 	if (g_Globals._hwndDesktop)
 		g_Globals._desktop_mode = true;
-
-	/**TODO fix command line handling */
-	if (*lpCmdLine=='"' && lpCmdLine[_tcslen(lpCmdLine)-1]=='"') {
-		++lpCmdLine;
-		lpCmdLine[_tcslen(lpCmdLine)-1] = '\0';
-	}
 #endif
 
 
 	int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);
 
+
 	 // write configuration file
 	g_Globals.write_persistent();
 

Modified: trunk/reactos/subsys/system/explorer/explorer.h
--- trunk/reactos/subsys/system/explorer/explorer.h	2005-10-05 20:36:23 UTC (rev 18283)
+++ trunk/reactos/subsys/system/explorer/explorer.h	2005-10-05 23:05:13 UTC (rev 18284)
@@ -72,6 +72,42 @@
 #include "shell/filechild.h"
 #include "shell/shellbrowser.h"
 
+
 #ifndef ROSSHELL
+
+ /// Explorer command line parser
+ // for commands like "/e,/root,c:\"
+ // or "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}" (launch of control panel)
+struct ExplorerCmd
+{
+	ExplorerCmd()
+	 :	_flags(0),
+		_cmdShow(SW_SHOWNORMAL),
+		_mdi(false),
+		_valid_path(false)
+	{
+	}
+
+	ExplorerCmd(LPCTSTR url, bool mdi)
+	 :	_path(url),
+		_flags(0),
+		_cmdShow(SW_SHOWNORMAL),
+		_mdi(mdi),
+		_valid_path(true)	//@@
+	{
+	}
+
+	bool	ParseCmdLine(LPCTSTR lpCmdLine);
+	bool	EvaluateOption(LPCTSTR option);
+	bool	IsValidPath() const;
+
+	String	_path;
+	int		_flags;	// OPEN_WINDOW_MODE
+	int		_cmdShow;
+	bool	_mdi;
+	bool	_valid_path;
+};
+
 #include "shell/mainframe.h"
+
 #endif

Modified: trunk/reactos/subsys/system/explorer/shell/filechild.cpp
--- trunk/reactos/subsys/system/explorer/shell/filechild.cpp	2005-10-05 20:36:23 UTC (rev 18283)
+++ trunk/reactos/subsys/system/explorer/shell/filechild.cpp	2005-10-05 23:05:13 UTC (rev 18284)
@@ -228,6 +228,8 @@
 		_root._entry->_data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
 
 
+		///@todo use OWM_ROOTED flag
+
 		if (info._open_mode & OWM_EXPLORE)	///@todo Is not-explore-mode for FileChildWindow completely implemented?
 			_left_hwnd = *(_left=new Pane(_hwnd, IDW_TREE_LEFT, IDW_HEADER_LEFT, _root._entry, true, COL_CONTENT));
 

Modified: trunk/reactos/subsys/system/explorer/shell/mainframe.cpp
--- trunk/reactos/subsys/system/explorer/shell/mainframe.cpp	2005-10-05 20:36:23 UTC (rev 18283)
+++ trunk/reactos/subsys/system/explorer/shell/mainframe.cpp	2005-10-05 23:05:13 UTC (rev 18284)
@@ -38,12 +38,12 @@
 #include "../dialogs/settings.h"	// for MdiSdiDlg
 
 
-HWND MainFrameBase::Create(LPCTSTR path, bool mdi, UINT cmdshow)
+HWND MainFrameBase::Create(const ExplorerCmd& cmd)
 {
 	HWND hFrame;
 
-#ifndef _NO_MDI	///@todo implement command line option to switch between MDI and SDI
-	if (mdi)
+#ifndef _NO_MDI
+	if (cmd._mdi)
 		hFrame = MDIMainFrame::Create();
 	else
 #endif
@@ -54,32 +54,20 @@
 
 		g_Globals._hMainWnd = hFrame;
 
-		if (path) {
-			static String sPath = path;	// copy path to avoid accessing freed memory
-			path = sPath;
-		}
-
 		if (hwndOld)
 			DestroyWindow(hwndOld);
 
-		ShowWindow(hFrame, cmdshow);
+		ShowWindow(hFrame, cmd._cmdShow);
 		UpdateWindow(hFrame);
 
-		bool valid_dir = false;
-
-		if (path) {
-			DWORD attribs = GetFileAttributes(path);
-
-			if (attribs!=INVALID_FILE_ATTRIBUTES && (attribs&FILE_ATTRIBUTE_DIRECTORY))
-				valid_dir = true;
-			else if (*path==':' || *path=='"')
-				valid_dir = true;
-		}
-
 		 // Open the first child window after initializing the application
-		if (valid_dir)
-			PostMessage(hFrame, PM_OPEN_WINDOW, 0, (LPARAM)path);
-		else
+		if (cmd.IsValidPath()) {
+			 // We use the static s_path variable to store the path string in order 
+			 // to avoid accessing prematurely freed memory in the PostMessage handlers.
+			static String s_path = cmd._path;
+
+			PostMessage(hFrame, PM_OPEN_WINDOW, cmd._flags, (LPARAM)(LPCTSTR)s_path);
+		} else
 			PostMessage(hFrame, PM_OPEN_WINDOW, OWM_EXPLORE|OWM_DETAILS, 0);
 	}
 
@@ -989,7 +977,7 @@
 			create_info._pos.rcNormalPosition.right = CW_USEDEFAULT;
 			create_info._pos.rcNormalPosition.bottom = CW_USEDEFAULT;
 
-			create_info._open_mode = (OPEN_WINDOW_MODE)wparam;
+			create_info._open_mode = wparam;
 
 		//	FileChildWindow::create(_hmdiclient, create_info);
 			return (LRESULT)MDIShellBrowserChild::create(create_info);
@@ -1149,7 +1137,7 @@
 		break;
 
 	  case ID_VIEW_SDI:
-		MainFrameBase::Create(NULL, false);
+		MainFrameBase::Create(ExplorerCmd());
 		break;
 
 	  case IDW_COMMANDBAR:
@@ -1516,7 +1504,7 @@
 			root_path = path;
 		}
 
-		jump_to(root_path, (OPEN_WINDOW_MODE)wparam);	//@todo content of 'path' not used any more
+		jump_to(root_path, wparam);	//@todo content of 'path' not used any more
 		return TRUE;}	// success
 
 	  default: def:
@@ -1530,7 +1518,7 @@
 {
 	switch(id) {
 	  case ID_VIEW_MDI:
-		MainFrameBase::Create(_url, true);
+		MainFrameBase::Create(ExplorerCmd(_url, true));
 		break;
 
 	  case IDW_COMMANDBAR:
@@ -1632,6 +1620,8 @@
 		delete _shellBrowser.release();
 	}
 
+	///@todo use OWM_ROOTED flag
+
 	 // create explorer treeview
 	if (_shellpath_info._open_mode & OWM_EXPLORE) {
 		if (!_left_hwnd) {

Modified: trunk/reactos/subsys/system/explorer/shell/mainframe.h
--- trunk/reactos/subsys/system/explorer/shell/mainframe.h	2005-10-05 20:36:23 UTC (rev 18283)
+++ trunk/reactos/subsys/system/explorer/shell/mainframe.h	2005-10-05 23:05:13 UTC (rev 18284)
@@ -27,9 +27,16 @@
 
 
 #define	PM_OPEN_WINDOW			(WM_APP+0x07)
-enum OPEN_WINDOW_MODE {OWM_EXPLORE=1, OWM_DETAILS=2, OWM_PIDL=4, OWM_SEPARATE=8};
 
+enum OPEN_WINDOW_MODE {
+	OWM_EXPLORE=1,	/// window in explore mode
+	OWM_ROOTED=2,	/// "rooted" window with special shell namespace root
+	OWM_DETAILS=4,	/// view files in detail mode
+	OWM_PIDL=8,		/// path is given as PIDL, otherwise as LPCTSTR
+	OWM_SEPARATE=16	/// open separate subfolder windows
+};
 
+
  /// Explorer frame window base class
 struct MainFrameBase : public PreTranslateWindow
 {
@@ -38,7 +45,7 @@
 	MainFrameBase(HWND hwnd);
 	~MainFrameBase();
 
-	static HWND Create(LPCTSTR path, bool mdi=true, UINT cmdshow=SW_SHOWNORMAL);
+	static HWND Create(const ExplorerCmd& cmd);
 	static int OpenShellFolders(LPIDA pida, HWND hFrameWnd);
 
 	WindowHandle _hwndrebar;

Modified: trunk/reactos/subsys/system/explorer/shell/shellbrowser.cpp
--- trunk/reactos/subsys/system/explorer/shell/shellbrowser.cpp	2005-10-05 20:36:23 UTC (rev 18283)
+++ trunk/reactos/subsys/system/explorer/shell/shellbrowser.cpp	2005-10-05 23:05:13 UTC (rev 18284)
@@ -112,17 +112,17 @@
 	if (!_cur_dir)
 		_cur_dir = static_cast<ShellDirectory*>(_root._entry);
 
-/*@todo
-	we should call read_tree() here to iterate through the hierarchy and open all folders from shell_info._root_shell_path to shell_info._shell_path
-	_root._entry->read_tree(shell_info._root_shell_path.get_folder(), info._shell_path, SORT_NAME);
-	-> see FileChildWindow::FileChildWindow()
-*/
+	//LOG(FmtString(TEXT("ShellBrowser::jump_to(): pidl=%s"), (LPCTSTR)FileSysShellPath(pidl)));
 
-	LOG(FmtString(TEXT("ShellBrowser::jump_to(): pidl=%s"), (LPCTSTR)FileSysShellPath(pidl)));
-
 	if (_cur_dir) {
 		static DynamicFct<LPITEMIDLIST(WINAPI*)(LPCITEMIDLIST, LPCITEMIDLIST)> ILFindChild(TEXT("SHELL32"), 24);
 
+/*@todo
+	we should call read_tree() here to iterate through the hierarchy and open all folders from _create_info._root_shell_path (_cur_dir) to _create_info._shell_path (pidl)
+	_root._entry->read_tree(_create_info._root_shell_path.get_folder(), info._shell_path, SORT_NAME);
+	-> see FileChildWindow::FileChildWindow()_create_info._shell_path
+*/
+
 		LPCITEMIDLIST child_pidl;
 
 		if (ILFindChild)
@@ -582,7 +582,7 @@
 			break;
 
 		  case ID_VIEW_SDI:
-			MainFrameBase::Create(_url, false);
+			MainFrameBase::Create(ExplorerCmd(_url, false));
 			break;
 
 		  default:
@@ -606,6 +606,8 @@
 		delete _shellBrowser.release();
 	}
 
+	///@todo use OWM_ROOTED flag
+
 	 // create explorer treeview
 	if (_create_info._open_mode & OWM_EXPLORE) {
 		if (!_left_hwnd) {