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
== _T('/'))
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 WARN("Cannot allocate memory for start comspec!\n");
184 error_out_of_memory();
188 size
= GetEnvironmentVariable (_T("COMSPEC"), comspec
, MAX_PATH
);
189 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND
)
191 _tcscpy(comspec
, _T("cmd"));
197 LPTSTR Oldcomspec
= comspec
;
198 comspec
= cmd_realloc(comspec
,size
* sizeof(TCHAR
) );
201 cmd_free(Oldcomspec
);
204 size
= GetEnvironmentVariable (_T("COMSPEC"), comspec
, size
);
212 Rest
= _T("cmd.exe");
215 /* Parsing the command that gets called by start, and it's parameters */
217 BOOL bInside
= FALSE
;
219 /* find the end of the command and put the arguments in param */
220 for (i
= 0; Rest
[i
]; i
++)
222 if (Rest
[i
] == _T('\"'))
224 if (_istspace(Rest
[i
]) && !bInside
)
233 _tcscpy(szUnquotedName
, Rest
);
234 StripQuotes(szUnquotedName
);
236 /* get the PATH environment variable and parse it */
237 /* search the PATH environment variable for the binary */
238 if (SearchForExecutable(szUnquotedName
, szFullName
))
240 /* check if this is a .BAT or .CMD file */
241 dot
= _tcsrchr(szFullName
, _T('.'));
242 if (dot
&& (!_tcsicmp(dot
, _T(".bat")) || !_tcsicmp(dot
, _T(".cmd"))))
245 _stprintf(szFullCmdLine
, _T("\"%s\" /K %s"), comspec
, Rest
);
246 TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName
), debugstr_aw(Rest
));
250 TRACE ("[EXEC: %s %s]\n", debugstr_aw(szFullName
), debugstr_aw(Rest
));
251 _tcscpy(szFullCmdLine
, szFullName
);
254 /* build command line for CreateProcess() */
257 _tcsncat(szFullCmdLine
, _T(" "), CMDLINE_LENGTH
- _tcslen(szFullCmdLine
));
258 _tcsncat(szFullCmdLine
, param
, CMDLINE_LENGTH
- _tcslen(szFullCmdLine
));
261 /* fill startup info */
262 memset (&stui
, 0, sizeof (STARTUPINFO
));
263 stui
.cb
= sizeof (STARTUPINFO
);
264 stui
.dwFlags
= STARTF_USESHOWWINDOW
;
265 stui
.lpTitle
= lpTitle
;
266 stui
.wShowWindow
= wShowWindow
;
268 bCreate
= CreateProcess(bBat
? comspec
: szFullName
,
269 szFullCmdLine
, NULL
, NULL
, TRUE
, dwCreationFlags
,
270 lpEnvironment
, lpDirectory
, &stui
, &prci
);
275 SetProcessAffinityMask(prci
.hProcess
, dwAffinityMask
);
276 ResumeThread(prci
.hThread
);
278 CloseHandle(prci
.hThread
);
283 /* The file name did not seem to be valid, but maybe it's actually a
284 * directory or URL, so we still want to pass it to ShellExecute. */
285 _tcscpy(szFullName
, szUnquotedName
);
290 /* CreateProcess didn't work; try ShellExecute */
291 DWORD flags
= SEE_MASK_NOCLOSEPROCESS
;
292 if (!(dwCreationFlags
& CREATE_NEW_CONSOLE
))
293 flags
|= SEE_MASK_NO_CONSOLE
;
294 prci
.hProcess
= RunFile(flags
, szFullName
, param
, lpDirectory
, wShowWindow
);
297 if (prci
.hProcess
!= NULL
)
302 WaitForSingleObject (prci
.hProcess
, INFINITE
);
303 GetExitCodeProcess (prci
.hProcess
, &dwExitCode
);
304 nErrorLevel
= (INT
)dwExitCode
;
306 CloseHandle (prci
.hProcess
);
308 /* Update our local codepage cache */
310 UINT uNewInputCodePage
= GetConsoleCP();
311 UINT uNewOutputCodePage
= GetConsoleOutputCP();
313 if ((InputCodePage
!= uNewInputCodePage
) ||
314 (OutputCodePage
!= uNewOutputCodePage
))
316 /* Update the locale as well */
320 InputCodePage
= uNewInputCodePage
;
321 OutputCodePage
= uNewOutputCodePage
;
323 /* Update the streams codepage cache as well */
324 ConStreamSetCacheCodePage(StdIn
, InputCodePage
);
325 ConStreamSetCacheCodePage(StdOut
, OutputCodePage
);
326 ConStreamSetCacheCodePage(StdErr
, OutputCodePage
);
331 ErrorMessage(GetLastError (),
332 _T("Error executing CreateProcess()!!\n"));