2 * START.C - start internal command.
7 * 24-Jul-1999 (Eric Kohl)
10 * 30-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
11 * Remove all hardcoded strings in En.rc
16 #ifdef INCLUDE_CMD_START
18 /* Find the end of an option, and turn it into a nul-terminated string
19 * in place. (It's moved back one character, to make room for the nul) */
20 static TCHAR
*GetParameter(TCHAR
**pPointer
)
22 BOOL bInQuote
= FALSE
;
23 TCHAR
*start
= *pPointer
;
25 for (p
= start
; *p
; p
++)
27 if (!bInQuote
&& (*p
== _T('/') || _istspace(*p
)))
29 bInQuote
^= (*p
== _T('"'));
37 INT
cmd_start (LPTSTR Rest
)
39 TCHAR szFullName
[CMDLINE_LENGTH
];
40 TCHAR szUnquotedName
[CMDLINE_LENGTH
];
48 TCHAR szFullCmdLine
[CMDLINE_LENGTH
];
49 PROCESS_INFORMATION prci
;
52 DWORD dwCreationFlags
= CREATE_NEW_CONSOLE
| CREATE_UNICODE_ENVIRONMENT
;
54 DWORD dwCreationFlags
= CREATE_NEW_CONSOLE
;
56 DWORD dwAffinityMask
= 0;
57 LPTSTR lpTitle
= NULL
;
58 LPTSTR lpDirectory
= NULL
;
59 LPTSTR lpEnvironment
= NULL
;
60 WORD wShowWindow
= SW_SHOWNORMAL
;
68 else if (*Rest
== _T('"') && !lpTitle
)
70 lpTitle
= GetParameter(&Rest
);
73 else if (*Rest
== L
'/')
77 option
= GetParameter(&Rest
);
78 if (*option
== _T('?'))
80 ConOutResPaging(TRUE
,STRING_START_HELP1
);
83 else if (_totupper(*option
) == _T('D'))
85 lpDirectory
= option
+ 1;
88 while (_istspace(*Rest
))
90 lpDirectory
= GetParameter(&Rest
);
92 StripQuotes(lpDirectory
);
94 else if (_totupper(*option
) == _T('I'))
96 /* rest of the option is apparently ignored */
97 lpEnvironment
= lpOriginalEnvironment
;
99 else if (!_tcsicmp(option
, _T("MIN")))
101 wShowWindow
= SW_MINIMIZE
;
103 else if (!_tcsicmp(option
, _T("MAX")))
105 wShowWindow
= SW_MAXIMIZE
;
107 else if (!_tcsicmp(option
, _T("AFFINITY")))
110 while (_istspace(*Rest
))
112 option
= GetParameter(&Rest
);
113 /* Affinity mask is given in hexadecimal */
114 dwAffinityMask
= _tcstoul(option
, &end
, 16);
115 if (*end
!= _T('\0') || dwAffinityMask
== 0 ||
116 dwAffinityMask
== (DWORD
)-1)
118 ConErrResPrintf(STRING_ERROR_INVALID_PARAM_FORMAT
, option
);
121 dwCreationFlags
|= CREATE_SUSPENDED
;
123 else if (!_tcsicmp(option
, _T("B")))
125 dwCreationFlags
&= ~CREATE_NEW_CONSOLE
;
126 dwCreationFlags
|= CREATE_NEW_PROCESS_GROUP
;
128 else if (!_tcsicmp(option
, _T("LOW")))
130 dwCreationFlags
|= IDLE_PRIORITY_CLASS
;
132 else if (!_tcsicmp(option
, _T("NORMAL")))
134 dwCreationFlags
|= NORMAL_PRIORITY_CLASS
;
136 else if (!_tcsicmp(option
, _T("HIGH")))
138 dwCreationFlags
|= HIGH_PRIORITY_CLASS
;
140 else if (!_tcsicmp(option
, _T("REALTIME")))
142 dwCreationFlags
|= REALTIME_PRIORITY_CLASS
;
144 else if (!_tcsicmp(option
, _T("ABOVENORMAL")))
146 dwCreationFlags
|= ABOVE_NORMAL_PRIORITY_CLASS
;
148 else if (!_tcsicmp(option
, _T("BELOWNORMAL")))
150 dwCreationFlags
|= BELOW_NORMAL_PRIORITY_CLASS
;
152 else if (!_tcsicmp(option
, _T("SEPARATE")))
154 dwCreationFlags
|= CREATE_SEPARATE_WOW_VDM
;
156 else if (!_tcsicmp(option
, _T("SHARED")))
158 dwCreationFlags
|= CREATE_SHARED_WOW_VDM
;
160 else if (!_tcsicmp(option
, _T("W")) ||
161 !_tcsicmp(option
, _T("WAIT")))
167 ConErrResPrintf(STRING_TYPE_ERROR1
, option
);
173 /* It's not an option - must be the beginning of
174 * the actual command. Leave the loop. */
180 comspec
= cmd_alloc ( MAX_PATH
* sizeof(TCHAR
));
183 error_out_of_memory();
187 size
= GetEnvironmentVariable (_T("COMSPEC"), comspec
, MAX_PATH
);
188 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND
)
190 _tcscpy(comspec
, _T("cmd"));
196 LPTSTR Oldcomspec
= comspec
;
197 comspec
= cmd_realloc(comspec
,size
* sizeof(TCHAR
) );
200 cmd_free(Oldcomspec
);
203 size
= GetEnvironmentVariable (_T("COMSPEC"), comspec
, size
);
211 Rest
= _T("cmd.exe");
214 /* Parsing the command that gets called by start, and it's parameters */
216 BOOL bInside
= FALSE
;
218 /* find the end of the command and put the arguments in param */
219 for (i
= 0; Rest
[i
]; i
++)
221 if (Rest
[i
] == _T('\"'))
223 if (_istspace(Rest
[i
]) && !bInside
)
232 _tcscpy(szUnquotedName
, Rest
);
233 StripQuotes(szUnquotedName
);
235 /* get the PATH environment variable and parse it */
236 /* search the PATH environment variable for the binary */
237 if (SearchForExecutable(szUnquotedName
, szFullName
))
239 /* check if this is a .BAT or .CMD file */
240 dot
= _tcsrchr(szFullName
, _T('.'));
241 if (dot
&& (!_tcsicmp(dot
, _T(".bat")) || !_tcsicmp(dot
, _T(".cmd"))))
244 _stprintf(szFullCmdLine
, _T("\"%s\" /K %s"), comspec
, Rest
);
245 TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName
), debugstr_aw(Rest
));
249 TRACE ("[EXEC: %s %s]\n", debugstr_aw(szFullName
), debugstr_aw(Rest
));
250 _tcscpy(szFullCmdLine
, szFullName
);
253 /* build command line for CreateProcess() */
256 _tcsncat(szFullCmdLine
, _T(" "), CMDLINE_LENGTH
- _tcslen(szFullCmdLine
));
257 _tcsncat(szFullCmdLine
, param
, CMDLINE_LENGTH
- _tcslen(szFullCmdLine
));
260 /* fill startup info */
261 memset (&stui
, 0, sizeof (STARTUPINFO
));
262 stui
.cb
= sizeof (STARTUPINFO
);
263 stui
.dwFlags
= STARTF_USESHOWWINDOW
;
264 stui
.lpTitle
= lpTitle
;
265 stui
.wShowWindow
= wShowWindow
;
267 bCreate
= CreateProcess(bBat
? comspec
: szFullName
,
268 szFullCmdLine
, NULL
, NULL
, TRUE
, dwCreationFlags
,
269 lpEnvironment
, lpDirectory
, &stui
, &prci
);
274 SetProcessAffinityMask(prci
.hProcess
, dwAffinityMask
);
275 ResumeThread(prci
.hThread
);
277 CloseHandle(prci
.hThread
);
282 /* The file name did not seem to be valid, but maybe it's actually a
283 * directory or URL, so we still want to pass it to ShellExecute. */
284 _tcscpy(szFullName
, szUnquotedName
);
289 /* CreateProcess didn't work; try ShellExecute */
290 DWORD flags
= SEE_MASK_NOCLOSEPROCESS
;
291 if (!(dwCreationFlags
& CREATE_NEW_CONSOLE
))
292 flags
|= SEE_MASK_NO_CONSOLE
;
293 prci
.hProcess
= RunFile(flags
, szFullName
, param
, lpDirectory
, wShowWindow
);
296 if (prci
.hProcess
!= NULL
)
301 WaitForSingleObject (prci
.hProcess
, INFINITE
);
302 GetExitCodeProcess (prci
.hProcess
, &dwExitCode
);
303 nErrorLevel
= (INT
)dwExitCode
;
305 CloseHandle (prci
.hProcess
);
306 /* Get New code page if it has change */
307 InputCodePage
= GetConsoleCP();
308 OutputCodePage
= GetConsoleOutputCP();
312 ErrorMessage(GetLastError (),
313 _T("Error executing CreateProcess()!!\n"));