Update crt headers and mingw lib from mingw64. Update crt a bit. 4 msvcrt time tests...
[reactos.git] / reactos / lib / sdk / crt / process / process.c
1 /*
2 * PROJECT: ReactOS CRT library
3 * LICENSE: GPL (?) - See COPYING in the top level directory
4 * FILE: lib/sdk/crt/process/process.c
5 * PURPOSE: Process management functions
6 * PROGRAMMERS: ???
7 */
8
9 #include <precomp.h>
10 #include <process.h>
11 #include <tchar.h>
12 #include <internal/wine/msvcrt.h>
13
14 #ifdef _UNICODE
15 #define sT "S"
16 #define find_execT find_execW
17 #define argvtosT argvtosW
18 #define do_spawnT do_spawnW
19 #define valisttosT valisttosW
20 #define extT extW
21 #else
22 #define sT "s"
23 #define find_execT find_execA
24 #define argvtosT argvtosA
25 #define do_spawnT do_spawnA
26 #define valisttosT valisttosA
27 #define extT extA
28 #endif
29
30 #define MK_STR(s) #s
31
32 _TCHAR const* extT[] =
33 {
34 _T(""),
35 _T(".bat"),
36 _T(".cmd"),
37 _T(".com"),
38 _T(".exe")
39 };
40
41 const _TCHAR* find_execT(const _TCHAR* path, _TCHAR* rpath)
42 {
43 _TCHAR *rp;
44 const _TCHAR *rd;
45 unsigned int i, found = 0;
46
47 TRACE(MK_STR(find_execT)"('%"sT"', %x)\n", path, rpath);
48
49 if (path == NULL)
50 {
51 return NULL;
52 }
53 if (_tcslen(path) > FILENAME_MAX - 1)
54 {
55 return path;
56 }
57 /* copy path in rpath */
58 for (rd = path, rp = rpath; *rd; *rp++ = *rd++)
59 ;
60 *rp = 0;
61 /* try first with the name as is */
62 for (i = 0; i < sizeof(extT) / sizeof(*extT); i++)
63 {
64 _tcscpy(rp, extT[i]);
65
66 TRACE("trying '%"sT"'\n", rpath);
67
68 if (_taccess(rpath, F_OK) == 0 && access_dirT(rpath) != 0)
69 {
70 found = 1;
71 break;
72 }
73 }
74 if (!found)
75 {
76 _TCHAR* env = _tgetenv(_T("PATH"));
77 if (env)
78 {
79 _TCHAR* ep = env;
80 while (*ep && !found)
81 {
82 if (*ep == ';')
83 ep++;
84 rp=rpath;
85 for (; *ep && (*ep != ';'); *rp++ = *ep++)
86 ;
87 if (rp > rpath)
88 {
89 rp--;
90 if (*rp != '/' && *rp != '\\')
91 {
92 *++rp = '\\';
93 }
94 rp++;
95 }
96 for (rd=path; *rd; *rp++ = *rd++)
97 ;
98 for (i = 0; i < sizeof(extT) / sizeof(*extT); i++)
99 {
100 _tcscpy(rp, extT[i]);
101
102 TRACE("trying '%"sT"'\n", rpath);
103
104 if (_taccess(rpath, F_OK) == 0 && access_dirT(rpath) != 0)
105 {
106 found = 1;
107 break;
108 }
109 }
110 }
111 }
112 }
113
114 return found ? rpath : path;
115 }
116
117 static _TCHAR*
118 argvtosT(const _TCHAR* const* argv, _TCHAR delim)
119 {
120 int i, len;
121 _TCHAR *ptr, *str;
122
123 if (argv == NULL)
124 return NULL;
125
126 for (i = 0, len = 0; argv[i]; i++)
127 {
128 len += _tcslen(argv[i]) + 1;
129 }
130
131 str = ptr = (_TCHAR*) malloc(len + 1);
132 if (str == NULL)
133 return NULL;
134
135 for(i = 0; argv[i]; i++)
136 {
137 len = _tcslen(argv[i]);
138 memcpy(ptr, argv[i], len * sizeof(_TCHAR));
139 ptr += len;
140 *ptr++ = delim;
141 }
142 *ptr = 0;
143
144 return str;
145 }
146
147 static _TCHAR*
148 valisttosT(const _TCHAR* arg0, va_list alist, _TCHAR delim)
149 {
150 va_list alist2 = alist;
151 _TCHAR *ptr, *str;
152 int len;
153
154 if (arg0 == NULL)
155 return NULL;
156
157 ptr = (_TCHAR*)arg0;
158 len = 0;
159 do
160 {
161 len += _tcslen(ptr) + 1;
162 ptr = va_arg(alist, _TCHAR*);
163 }
164 while(ptr != NULL);
165
166 str = (_TCHAR*) malloc(len + 1);
167 if (str == NULL)
168 return NULL;
169
170 ptr = str;
171 do
172 {
173 len = _tcslen(arg0);
174 memcpy(ptr, arg0, len * sizeof(_TCHAR));
175 ptr += len;
176 *ptr++ = delim;
177 arg0 = va_arg(alist2, _TCHAR*);
178 }
179 while(arg0 != NULL);
180 *ptr = 0;
181
182 return str;
183 }
184
185 static intptr_t
186 do_spawnT(int mode, const _TCHAR* cmdname, const _TCHAR* args, const _TCHAR* envp)
187 {
188 STARTUPINFO StartupInfo = {0};
189 PROCESS_INFORMATION ProcessInformation;
190 // char* fmode;
191 // HANDLE* hFile;
192 // int i, last;
193 BOOL bResult;
194 DWORD dwExitCode;
195 DWORD dwError;
196
197 TRACE(MK_STR(do_spawnT)"(%i,'%"sT"','%"sT"','%"sT"')",mode,cmdname,args,envp);
198
199
200 if (mode != _P_NOWAIT && mode != _P_NOWAITO && mode != _P_WAIT && mode != _P_DETACH && mode != _P_OVERLAY)
201 {
202 __set_errno ( EINVAL );
203 return( -1);
204 }
205
206 if (0 != _taccess(cmdname, F_OK))
207 {
208 __set_errno ( ENOENT );
209 return(-1);
210 }
211 if (0 == access_dirT(cmdname))
212 {
213 __set_errno ( EISDIR );
214 return(-1);
215 }
216
217 memset (&StartupInfo, 0, sizeof(StartupInfo));
218 StartupInfo.cb = sizeof(StartupInfo);
219
220 #if 0
221
222 for (last = i = 0; i < FDINFO_FD_MAX; i++)
223 {
224 if ((void*)-1 != _get_osfhandle(i))
225 {
226 last = i + 1;
227 }
228 }
229
230 if (last)
231 {
232 StartupInfo.cbReserved2 = sizeof(ULONG) + last * (sizeof(char) + sizeof(HANDLE));
233 StartupInfo.lpReserved2 = malloc(StartupInfo.cbReserved2);
234 if (StartupInfo.lpReserved2 == NULL)
235 {
236 __set_errno ( ENOMEM );
237 return -1;
238 }
239
240 *(DWORD*)StartupInfo.lpReserved2 = last;
241 fmode = (char*)(StartupInfo.lpReserved2 + sizeof(ULONG));
242 hFile = (HANDLE*)(StartupInfo.lpReserved2 + sizeof(ULONG) + last * sizeof(char));
243 for (i = 0; i < last; i++)
244 {
245 int _mode = __fileno_getmode(i);
246 HANDLE h = _get_osfhandle(i);
247 /* FIXME: The test of console handles (((ULONG)Handle) & 0x10000003) == 0x3)
248 * is possible wrong
249 */
250 if ((((ULONG)h) & 0x10000003) == 0x3 || _mode & _O_NOINHERIT || (i < 3 && mode == _P_DETACH))
251 {
252 *hFile = INVALID_HANDLE_VALUE;
253 *fmode = 0;
254 }
255 else
256 {
257 DWORD dwFlags;
258 BOOL bFlag;
259 bFlag = GetHandleInformation(h, &dwFlags);
260 if (bFlag && (dwFlags & HANDLE_FLAG_INHERIT))
261 {
262 *hFile = h;
263 *fmode = (_O_ACCMODE & _mode) | (((_O_TEXT | _O_BINARY) & _mode) >> 8);
264 }
265 else
266 {
267 *hFile = INVALID_HANDLE_VALUE;
268 *fmode = 0;
269 }
270 }
271 fmode++;
272 hFile++;
273 }
274 }
275 #endif
276
277 create_io_inherit_block(&StartupInfo.cbReserved2, &StartupInfo.lpReserved2);
278
279 bResult = CreateProcess((_TCHAR *)cmdname,
280 (_TCHAR *)args,
281 NULL,
282 NULL,
283 TRUE,
284 mode == _P_DETACH ? DETACHED_PROCESS : 0,
285 (LPVOID)envp,
286 NULL,
287 &StartupInfo,
288 &ProcessInformation);
289
290 if (StartupInfo.lpReserved2)
291 {
292 free(StartupInfo.lpReserved2);
293 }
294
295 if (!bResult)
296 {
297 dwError = GetLastError();
298 ERR("%x\n", dwError);
299 __set_errno(dwError);
300 return(-1);
301 }
302 CloseHandle(ProcessInformation.hThread);
303 switch(mode)
304 {
305 case _P_NOWAIT:
306 case _P_NOWAITO:
307 return((intptr_t)ProcessInformation.hProcess);
308 case _P_OVERLAY:
309 CloseHandle(ProcessInformation.hProcess);
310 _exit(0);
311 case _P_WAIT:
312 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
313 GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
314 CloseHandle(ProcessInformation.hProcess);
315 return( (int)dwExitCode); //CORRECT?
316 case _P_DETACH:
317 CloseHandle(ProcessInformation.hProcess);
318 return( 0);
319 }
320 return( (intptr_t)ProcessInformation.hProcess);
321 }
322
323 /*
324 * @implemented
325 */
326 intptr_t _tspawnl(int mode, const _TCHAR *cmdname, const _TCHAR* arg0, ...)
327 {
328 va_list argp;
329 _TCHAR* args;
330 int ret = -1;
331
332 TRACE(MK_STR(_tspawnl)"('%"sT"')\n", cmdname);
333
334 va_start(argp, arg0);
335 args = valisttosT(arg0, argp, ' ');
336
337 if (args)
338 {
339 ret = do_spawnT(mode, cmdname, args, NULL);
340 free(args);
341 }
342 return ret;
343 }
344
345 /*
346 * @implemented
347 */
348 intptr_t _tspawnv(int mode, const _TCHAR *cmdname, const _TCHAR* const* argv)
349 {
350 _TCHAR* args;
351 int ret = -1;
352
353 TRACE(MK_STR(_tspawnv)"('%"sT"')\n", cmdname);
354
355 args = argvtosT(argv, ' ');
356
357 if (args)
358 {
359 ret = do_spawnT(mode, cmdname, args, NULL);
360 free(args);
361 }
362 return ret;
363 }
364
365 /*
366 * @implemented
367 */
368 intptr_t _tspawnle(int mode, const _TCHAR *cmdname, const _TCHAR* arg0, ... /*, NULL, const char* const* envp*/)
369 {
370 va_list argp;
371 _TCHAR* args;
372 _TCHAR* envs;
373 _TCHAR const * const* ptr;
374 int ret = -1;
375
376 TRACE(MK_STR(_tspawnle)"('%"sT"')\n", cmdname);
377
378 va_start(argp, arg0);
379 args = valisttosT(arg0, argp, ' ');
380 do
381 {
382 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
383 }
384 while (ptr != NULL);
385 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
386 envs = argvtosT(ptr, 0);
387 if (args)
388 {
389 ret = do_spawnT(mode, cmdname, args, envs);
390 free(args);
391 }
392 if (envs)
393 {
394 free(envs);
395 }
396 return ret;
397
398 }
399
400 /*
401 * @implemented
402 */
403 intptr_t _tspawnve(int mode, const _TCHAR *cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
404 {
405 _TCHAR *args;
406 _TCHAR *envs;
407 int ret = -1;
408
409 TRACE(MK_STR(_tspawnve)"('%"sT"')\n", cmdname);
410
411 args = argvtosT(argv, ' ');
412 envs = argvtosT(envp, 0);
413
414 if (args)
415 {
416 ret = do_spawnT(mode, cmdname, args, envs);
417 free(args);
418 }
419 if (envs)
420 {
421 free(envs);
422 }
423 return ret;
424 }
425
426 /*
427 * @implemented
428 */
429 intptr_t _tspawnvp(int mode, const _TCHAR* cmdname, const _TCHAR* const* argv)
430 {
431 _TCHAR pathname[FILENAME_MAX];
432
433 TRACE(MK_STR(_tspawnvp)"('%"sT"')\n", cmdname);
434
435 return _tspawnv(mode, find_execT(cmdname, pathname), argv);
436 }
437
438 /*
439 * @implemented
440 */
441 intptr_t _tspawnlp(int mode, const _TCHAR* cmdname, const _TCHAR* arg0, .../*, NULL*/)
442 {
443 va_list argp;
444 _TCHAR* args;
445 int ret = -1;
446 _TCHAR pathname[FILENAME_MAX];
447
448 TRACE(MK_STR(_tspawnlp)"('%"sT"')\n", cmdname);
449
450 va_start(argp, arg0);
451 args = valisttosT(arg0, argp, ' ');
452 if (args)
453 {
454 ret = do_spawnT(mode, find_execT(cmdname, pathname), args, NULL);
455 free(args);
456 }
457 return ret;
458 }
459
460
461 /*
462 * @implemented
463 */
464 intptr_t _tspawnlpe(int mode, const _TCHAR* cmdname, const _TCHAR* arg0, .../*, NULL, const char* const* envp*/)
465 {
466 va_list argp;
467 _TCHAR* args;
468 _TCHAR* envs;
469 _TCHAR const* const * ptr;
470 int ret = -1;
471 _TCHAR pathname[FILENAME_MAX];
472
473 TRACE(MK_STR(_tspawnlpe)"('%"sT"')\n", cmdname);
474
475 va_start(argp, arg0);
476 args = valisttosT(arg0, argp, ' ');
477 do
478 {
479 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
480 }
481 while (ptr != NULL);
482 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
483 envs = argvtosT(ptr, 0);
484 if (args)
485 {
486 ret = do_spawnT(mode, find_execT(cmdname, pathname), args, envs);
487 free(args);
488 }
489 if (envs)
490 {
491 free(envs);
492 }
493 return ret;
494 }
495
496 /*
497 * @implemented
498 */
499 intptr_t _tspawnvpe(int mode, const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
500 {
501 _TCHAR pathname[FILENAME_MAX];
502
503 TRACE(MK_STR(_tspawnvpe)"('%"sT"')\n", cmdname);
504
505 return _tspawnve(mode, find_execT(cmdname, pathname), argv, envp);
506 }
507
508 /*
509 * @implemented
510 */
511 intptr_t _texecl(const _TCHAR* cmdname, const _TCHAR* arg0, ...)
512 {
513 _TCHAR* args;
514 va_list argp;
515 int ret = -1;
516
517 TRACE(MK_STR(_texecl)"('%"sT"')\n", cmdname);
518
519 va_start(argp, arg0);
520 args = valisttosT(arg0, argp, ' ');
521
522 if (args)
523 {
524 ret = do_spawnT(P_OVERLAY, cmdname, args, NULL);
525 free(args);
526 }
527 return ret;
528 }
529
530 /*
531 * @implemented
532 */
533 intptr_t _texecv(const _TCHAR* cmdname, const _TCHAR* const* argv)
534 {
535 TRACE(MK_STR(_texecv)"('%"sT"')\n", cmdname);
536 return _tspawnv(P_OVERLAY, cmdname, argv);
537 }
538
539 /*
540 * @implemented
541 */
542 intptr_t _texecle(const _TCHAR* cmdname, const _TCHAR* arg0, ... /*, NULL, char* const* envp */)
543 {
544 va_list argp;
545 _TCHAR* args;
546 _TCHAR* envs;
547 _TCHAR const* const* ptr;
548 int ret = -1;
549
550 TRACE(MK_STR(_texecle)"('%"sT"')\n", cmdname);
551
552 va_start(argp, arg0);
553 args = valisttosT(arg0, argp, ' ');
554 do
555 {
556 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
557 }
558 while (ptr != NULL);
559 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
560 envs = argvtosT(ptr, 0);
561 if (args)
562 {
563 ret = do_spawnT(P_OVERLAY, cmdname, args, envs);
564 free(args);
565 }
566 if (envs)
567 {
568 free(envs);
569 }
570 return ret;
571 }
572
573 /*
574 * @implemented
575 */
576 intptr_t _texecve(const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
577 {
578 TRACE(MK_STR(_texecve)"('%"sT"')\n", cmdname);
579 return _tspawnve(P_OVERLAY, cmdname, argv, envp);
580 }
581
582 /*
583 * @implemented
584 */
585 intptr_t _texeclp(const _TCHAR* cmdname, const _TCHAR* arg0, ...)
586 {
587 _TCHAR* args;
588 va_list argp;
589 int ret = -1;
590 _TCHAR pathname[FILENAME_MAX];
591
592 TRACE(MK_STR(_texeclp)"('%"sT"')\n", cmdname);
593
594 va_start(argp, arg0);
595 args = valisttosT(arg0, argp, ' ');
596
597 if (args)
598 {
599 ret = do_spawnT(P_OVERLAY, find_execT(cmdname, pathname), args, NULL);
600 free(args);
601 }
602 return ret;
603 }
604
605 /*
606 * @implemented
607 */
608 intptr_t _texecvp(const _TCHAR* cmdname, const _TCHAR* const* argv)
609 {
610 TRACE(MK_STR(_texecvp)"('%"sT"')\n", cmdname);
611 return _tspawnvp(P_OVERLAY, cmdname, argv);
612 }
613
614 /*
615 * @implemented
616 */
617 intptr_t _texeclpe(const _TCHAR* cmdname, const _TCHAR* arg0, ... /*, NULL, char* const* envp */)
618 {
619 va_list argp;
620 _TCHAR* args;
621 _TCHAR* envs;
622 _TCHAR const* const* ptr;
623 int ret = -1;
624 _TCHAR pathname[FILENAME_MAX];
625
626 TRACE(MK_STR(_texeclpe)"('%"sT"')\n", cmdname);
627
628 va_start(argp, arg0);
629 args = valisttosT(arg0, argp, ' ');
630 do
631 {
632 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
633 }
634 while (ptr != NULL);
635 ptr = (_TCHAR const* const*)va_arg(argp, _TCHAR*);
636 envs = argvtosT(ptr, 0);
637 if (args)
638 {
639 ret = do_spawnT(P_OVERLAY, find_execT(cmdname, pathname), args, envs);
640 free(args);
641 }
642 if (envs)
643 {
644 free(envs);
645 }
646 return ret;
647 }
648
649 /*
650 * @implemented
651 */
652 intptr_t _texecvpe(const _TCHAR* cmdname, const _TCHAR* const* argv, const _TCHAR* const* envp)
653 {
654 TRACE(MK_STR(_texecvpe)"('%"sT"')\n", cmdname);
655 return _tspawnvpe(P_OVERLAY, cmdname, argv, envp);
656 }
657
658