move explorer and cmd. Add a few .rbuild files
[reactos.git] / reactos / base / shell / cmd / start.c
1 /*
2 * START.C - start internal command.
3 *
4 *
5 * History:
6 *
7 * 24-Jul-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
8 * Started.
9 *
10 * 30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
11 * Remove all hardcode string to En.rc
12 */
13
14 #include <precomp.h>
15 #include "resource.h"
16
17 #ifdef INCLUDE_CMD_START
18
19
20 INT cmd_start (LPTSTR First, LPTSTR Rest)
21 {
22 TCHAR szFullName[CMDLINE_LENGTH];
23 TCHAR first[CMDLINE_LENGTH];
24 TCHAR *rest = NULL;
25 TCHAR *param = NULL;
26 INT size;
27 LPTSTR comspec;
28 BOOL bWait = FALSE;
29 BOOL bBat = FALSE;
30 BOOL bCreate = FALSE;
31 TCHAR szFullCmdLine [CMDLINE_LENGTH];
32 PROCESS_INFORMATION prci;
33 STARTUPINFO stui;
34
35
36
37 if (_tcsncmp (Rest, _T("/?"), 2) == 0)
38 {
39 ConOutResPaging(TRUE,STRING_START_HELP1);
40 return 0;
41 }
42
43 /* get comspec */
44 comspec = malloc ( MAX_PATH * sizeof(TCHAR));
45 if (comspec == NULL)
46 {
47 error_out_of_memory();
48 return 1;
49 }
50 SetLastError(0);
51 size = GetEnvironmentVariable (_T("COMSPEC"), comspec, 512);
52 if(GetLastError() == ERROR_ENVVAR_NOT_FOUND)
53 {
54 Rest = _T("cmd");
55 }
56 else
57 {
58 if (size > MAX_PATH)
59 {
60 comspec = realloc(comspec,size * sizeof(TCHAR) );
61 if (comspec==NULL)
62 {
63 return 1;
64 }
65 size = GetEnvironmentVariable (_T("COMSPEC"), comspec, size);
66 }
67 }
68
69 nErrorLevel = 0;
70
71 if( !*Rest )
72 {
73 _tcscpy(Rest,_T("\""));
74 _tcscat(Rest,comspec);
75 _tcscat(Rest,_T("\""));
76 }
77
78 rest = malloc ( _tcslen(Rest) + 1 * sizeof(TCHAR));
79 if (rest == NULL)
80 {
81 if(comspec != NULL)
82 free(comspec);
83 error_out_of_memory();
84 return 1;
85 }
86
87 param =malloc ( _tcslen(Rest) + 1 * sizeof(TCHAR));
88 if (rest == NULL)
89 {
90 if(comspec != NULL)
91 free(comspec);
92 free(rest);
93 error_out_of_memory();
94 return 1;
95 }
96
97 param[0] = _T('\0');
98
99
100 _tcscpy(rest,Rest);
101
102 /* Parsing the command that gets called by start, and it's parameters */
103 if(!_tcschr(rest,_T('\"')))
104 {
105 INT i = 0;
106 INT count = _tcslen(rest);
107
108 /* find the end of the command and start of the args */
109 for(i = 0; i < count; i++)
110 {
111 if(rest[i] == _T(' '))
112 {
113
114 _tcscpy(param,&rest[i]);
115 rest[i] = _T('\0');
116 break;
117 }
118 }
119 }
120 else
121 {
122 INT i = 0;
123 INT count = _tcslen(rest);
124 BOOL bInside = FALSE;
125
126 /* find the end of the command and put the arguments in param */
127 for(i = 0; i < count; i++)
128 {
129 if(rest[i] == _T('\"'))
130 bInside = !bInside;
131 if((rest[i] == _T(' ')) && !bInside)
132 {
133 _tcscpy(param,&rest[i]);
134 rest[i] = _T('\0');
135 break;
136 }
137 }
138 i = 0;
139 /* remove any slashes */
140 while(i < count)
141 {
142 if(rest[i] == _T('\"'))
143 memmove(&rest[i],&rest[i + 1], _tcslen(&rest[i]) * sizeof(TCHAR));
144 else
145 i++;
146 }
147 }
148
149 /* check for a drive change */
150
151 if (!_tcscmp (first + 1, _T(":")) && _istalpha (*first))
152 {
153 TCHAR szPath[CMDLINE_LENGTH];
154
155 _tcscpy (szPath, _T("A:"));
156 szPath[0] = _totupper (*first);
157 SetCurrentDirectory (szPath);
158 GetCurrentDirectory (CMDLINE_LENGTH, szPath);
159 if (szPath[0] != (TCHAR)_totupper (*first))
160 ConErrResPuts (STRING_FREE_ERROR1);
161
162 if (rest != NULL)
163 free(rest);
164
165 if (param != NULL)
166 free(param);
167 if (comspec != NULL)
168 free(comspec);
169 return 0;
170 }
171
172 /* get the PATH environment variable and parse it */
173 /* search the PATH environment variable for the binary */
174 if (!SearchForExecutable (rest, szFullName))
175 {
176 error_bad_command ();
177
178 if (rest != NULL)
179 free(rest);
180
181 if (param != NULL)
182 free(param);
183
184 if (comspec != NULL)
185 free(comspec);
186 return 1;
187 }
188
189
190 /* check if this is a .BAT or .CMD file */
191 if (!_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".bat")) ||
192 !_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".cmd")))
193 {
194 bBat = TRUE;
195 memset(szFullCmdLine,0,CMDLINE_LENGTH * sizeof(TCHAR));
196
197
198 _tcscpy(szFullCmdLine,comspec);
199
200 memcpy(&szFullCmdLine[_tcslen(szFullCmdLine)],_T("\" /K \""), 6 * sizeof(TCHAR));
201 memcpy(&szFullCmdLine[_tcslen(szFullCmdLine)], szFullName, _tcslen(szFullName) * sizeof(TCHAR));
202 memcpy(&szFullCmdLine[1], &szFullCmdLine[0], _tcslen(szFullCmdLine) * sizeof(TCHAR));
203 szFullCmdLine[0] = _T('\"');
204 szFullCmdLine[_tcslen(szFullCmdLine)] = _T('\"');
205 }
206
207 #ifdef _DEBUG
208 DebugPrintf (_T("[BATCH: %s %s]\n"), szFullName, rest);
209 #endif
210
211
212 #ifdef _DEBUG
213 DebugPrintf (_T("[EXEC: %s %s]\n"), szFullName, rest);
214 #endif
215 /* build command line for CreateProcess() */
216 if (bBat == FALSE)
217 {
218 _tcscpy (szFullCmdLine, first);
219 if( param != NULL )
220 {
221
222 _tcscat(szFullCmdLine, _T(" ") );
223 _tcscat (szFullCmdLine, param);
224 }
225 }
226
227 /* fill startup info */
228 memset (&stui, 0, sizeof (STARTUPINFO));
229 stui.cb = sizeof (STARTUPINFO);
230 stui.dwFlags = STARTF_USESHOWWINDOW;
231 stui.wShowWindow = SW_SHOWDEFAULT;
232
233 if (bBat == TRUE)
234 {
235 bCreate = CreateProcess (NULL, szFullCmdLine, NULL, NULL, FALSE,
236 CREATE_NEW_CONSOLE, NULL, NULL, &stui, &prci);
237 }
238 else
239 {
240 bCreate = CreateProcess (szFullName, szFullCmdLine, NULL, NULL, FALSE,
241 CREATE_NEW_CONSOLE, NULL, NULL, &stui, &prci);
242 }
243
244 if (bCreate)
245 {
246 if (bWait)
247 {
248 DWORD dwExitCode;
249 WaitForSingleObject (prci.hProcess, INFINITE);
250 GetExitCodeProcess (prci.hProcess, &dwExitCode);
251 nErrorLevel = (INT)dwExitCode;
252 }
253 CloseHandle (prci.hThread);
254 CloseHandle (prci.hProcess);
255 /* Get New code page if it has change */
256 InputCodePage= GetConsoleCP();
257 OutputCodePage = GetConsoleOutputCP();
258 }
259 else
260 {
261 ErrorMessage(GetLastError (),
262 _T("Error executing CreateProcess()!!\n"));
263 }
264
265
266 if (rest != NULL)
267 free(rest);
268
269 if (param != NULL)
270 free(param);
271
272 if (comspec != NULL)
273 free(comspec);
274 return 0;
275 }
276
277 #endif
278
279 /* EOF */