Make START command able to open non-executable files/directories/URLs using ShellExecute. (Bug 4055)

svn path=/trunk/; revision=40169
This commit is contained in:
Jeffrey Morlan 2009-03-22 01:51:29 +00:00
parent c999c1eb6e
commit e518029091
3 changed files with 59 additions and 63 deletions

View file

@ -265,7 +265,8 @@ static BOOL IsConsoleProcess(HANDLE Process)
typedef BOOL (WINAPI *MYEX)(LPSHELLEXECUTEINFO lpExecInfo); typedef BOOL (WINAPI *MYEX)(LPSHELLEXECUTEINFO lpExecInfo);
static HANDLE RunFile(LPTSTR filename, LPTSTR params) HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
LPTSTR directory, INT show)
{ {
SHELLEXECUTEINFO sei; SHELLEXECUTEINFO sei;
HMODULE hShell32; HMODULE hShell32;
@ -292,10 +293,11 @@ static HANDLE RunFile(LPTSTR filename, LPTSTR params)
memset(&sei, 0, sizeof sei); memset(&sei, 0, sizeof sei);
sei.cbSize = sizeof sei; sei.cbSize = sizeof sei;
sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE; sei.fMask = flags;
sei.lpFile = filename; sei.lpFile = filename;
sei.lpParameters = params; sei.lpParameters = params;
sei.nShow = SW_SHOWNORMAL; sei.lpDirectory = directory;
sei.nShow = show;
ret = hShExt(&sei); ret = hShExt(&sei);
TRACE ("RunFile: ShellExecuteExA/W returned 0x%p\n", ret); TRACE ("RunFile: ShellExecuteExA/W returned 0x%p\n", ret);
@ -499,7 +501,11 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
else else
{ {
// See if we can run this with ShellExecute() ie myfile.xls // See if we can run this with ShellExecute() ie myfile.xls
prci.hProcess = RunFile(szFullName, rest); prci.hProcess = RunFile(SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
szFullName,
rest,
NULL,
SW_SHOWNORMAL);
} }
if (prci.hProcess != NULL) if (prci.hProcess != NULL)

View file

@ -100,6 +100,7 @@ INT cmd_cls (LPTSTR);
/* Prototypes for CMD.C */ /* Prototypes for CMD.C */
INT ConvertULargeInteger(ULONGLONG num, LPTSTR des, INT len, BOOL bPutSeperator); INT ConvertULargeInteger(ULONGLONG num, LPTSTR des, INT len, BOOL bPutSeperator);
HANDLE RunFile(DWORD, LPTSTR, LPTSTR, LPTSTR, INT);
VOID ParseCommandLine (LPTSTR); VOID ParseCommandLine (LPTSTR);
struct _PARSED_COMMAND; struct _PARSED_COMMAND;
BOOL ExecuteCommand(struct _PARSED_COMMAND *Cmd); BOOL ExecuteCommand(struct _PARSED_COMMAND *Cmd);

View file

@ -37,7 +37,7 @@ static TCHAR *GetParameter(TCHAR **pPointer)
INT cmd_start (LPTSTR Rest) INT cmd_start (LPTSTR Rest)
{ {
TCHAR szFullName[CMDLINE_LENGTH]; TCHAR szFullName[CMDLINE_LENGTH];
TCHAR rest[CMDLINE_LENGTH]; TCHAR szUnquotedName[CMDLINE_LENGTH];
TCHAR *param = NULL; TCHAR *param = NULL;
TCHAR *dot; TCHAR *dot;
INT size; INT size;
@ -136,7 +136,6 @@ INT cmd_start (LPTSTR Rest)
break; break;
} }
} }
_tcscpy(rest, Rest);
/* get comspec */ /* get comspec */
comspec = cmd_alloc ( MAX_PATH * sizeof(TCHAR)); comspec = cmd_alloc ( MAX_PATH * sizeof(TCHAR));
@ -166,81 +165,56 @@ INT cmd_start (LPTSTR Rest)
nErrorLevel = 0; nErrorLevel = 0;
if(!*rest) if (!*Rest)
{ {
_tcscpy(rest,_T("\"")); Rest = _T("cmd.exe");
_tcscat(rest,comspec);
_tcscat(rest,_T("\""));
} }
else
/* Parsing the command that gets called by start, and it's parameters */ /* Parsing the command that gets called by start, and it's parameters */
{ {
BOOL bInside = FALSE; BOOL bInside = FALSE;
/* find the end of the command and put the arguments in param */ /* find the end of the command and put the arguments in param */
for(i = 0; rest[i]; i++) for (i = 0; Rest[i]; i++)
{ {
if(rest[i] == _T('\"')) if (Rest[i] == _T('\"'))
bInside = !bInside; bInside = !bInside;
if((rest[i] == _T(' ')) && !bInside) if (_istspace(Rest[i]) && !bInside)
{ {
param = &rest[i+1]; param = &Rest[i+1];
rest[i] = _T('\0'); Rest[i] = _T('\0');
break; break;
} }
} }
/* remove any slashes */
StripQuotes(rest);
} }
/* check for a drive change */ _tcscpy(szUnquotedName, Rest);
StripQuotes(szUnquotedName);
if (!_tcscmp (rest + 1, _T(":")) && _istalpha (*rest))
{
TCHAR szPath[CMDLINE_LENGTH];
_tcscpy (szPath, _T("A:"));
szPath[0] = _totupper (*rest);
SetCurrentDirectory (szPath);
GetCurrentDirectory (CMDLINE_LENGTH, szPath);
if (szPath[0] != (TCHAR)_totupper (*rest))
ConErrResPuts (STRING_FREE_ERROR1);
cmd_free(comspec);
return 0;
}
/* get the PATH environment variable and parse it */ /* get the PATH environment variable and parse it */
/* search the PATH environment variable for the binary */ /* search the PATH environment variable for the binary */
if (!SearchForExecutable (rest, szFullName)) if (SearchForExecutable(szUnquotedName, szFullName))
{ {
error_bad_command(rest); /* check if this is a .BAT or .CMD file */
dot = _tcsrchr(szFullName, _T('.'));
if (dot && (!_tcsicmp(dot, _T(".bat")) || !_tcsicmp(dot, _T(".cmd"))))
{
bBat = TRUE;
_stprintf(szFullCmdLine, _T("\"%s\" /K %s"), comspec, Rest);
TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(Rest));
}
else
{
TRACE ("[EXEC: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(Rest));
_tcscpy(szFullCmdLine, Rest);
}
cmd_free(comspec);
return 1;
}
/* check if this is a .BAT or .CMD file */
dot = _tcsrchr (szFullName, _T('.'));
if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
{
bBat = TRUE;
_stprintf(szFullCmdLine, _T("\"%s\" /K \"%s\""), comspec, szFullName);
TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
}
else
{
TRACE ("[EXEC: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
/* build command line for CreateProcess() */ /* build command line for CreateProcess() */
_tcscpy (szFullCmdLine, rest); if (param != NULL)
if( param != NULL ) {
{ _tcscat(szFullCmdLine, _T(" "));
_tcscat(szFullCmdLine, param);
_tcscat(szFullCmdLine, _T(" ") ); }
_tcscat (szFullCmdLine, param);
}
}
/* fill startup info */ /* fill startup info */
memset (&stui, 0, sizeof (STARTUPINFO)); memset (&stui, 0, sizeof (STARTUPINFO));
@ -259,9 +233,25 @@ INT cmd_start (LPTSTR Rest)
bCreate = CreateProcess (szFullName, szFullCmdLine, NULL, NULL, FALSE, bCreate = CreateProcess (szFullName, szFullCmdLine, NULL, NULL, FALSE,
CREATE_NEW_CONSOLE | Priority, NULL, lpDirectory, &stui, &prci); CREATE_NEW_CONSOLE | Priority, NULL, lpDirectory, &stui, &prci);
} }
if (bCreate) if (bCreate)
{ CloseHandle(prci.hThread);
}
else
{
/* The file name did not seem to be valid, but maybe it's actually a
* directory or URL, so we still want to pass it to ShellExecute. */
_tcscpy(szFullName, szUnquotedName);
}
if (!bCreate)
{
/* CreateProcess didn't work; try ShellExecute */
prci.hProcess = RunFile(SEE_MASK_NOCLOSEPROCESS, szFullName,
param, lpDirectory, wShowWindow);
}
if (prci.hProcess != NULL)
{
if (bWait) if (bWait)
{ {
DWORD dwExitCode; DWORD dwExitCode;
@ -269,7 +259,6 @@ INT cmd_start (LPTSTR Rest)
GetExitCodeProcess (prci.hProcess, &dwExitCode); GetExitCodeProcess (prci.hProcess, &dwExitCode);
nErrorLevel = (INT)dwExitCode; nErrorLevel = (INT)dwExitCode;
} }
CloseHandle (prci.hThread);
CloseHandle (prci.hProcess); CloseHandle (prci.hProcess);
/* Get New code page if it has change */ /* Get New code page if it has change */
InputCodePage= GetConsoleCP(); InputCodePage= GetConsoleCP();