process.c 33.7 KB
Newer Older
1 2 3 4 5 6 7
/*
 * msvcrt.dll spawn/exec functions
 *
 * Copyright 1996,1998 Marcus Meissner
 * Copyright 1996 Jukka Iivonen
 * Copyright 1997,2000 Uwe Bonnes
 * Copyright 2000 Jon Griffiths
8
 * Copyright 2007 Hans Leidekker
9
 *
10 11 12 13 14 15 16 17 18 19 20 21
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23
 *
24 25 26 27 28
 * FIXME:
 * -File handles need some special handling. Sometimes children get
 *  open file handles, sometimes not. The docs are confusing
 * -No check for maximum path/argument/environment size is done
 */
29 30 31

#include <stdarg.h>

32
#include "msvcrt.h"
33
#include <winnls.h>
34
#include "mtdll.h"
35 36 37
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
38

39 40 41 42 43 44 45
static void msvcrt_search_executable(const MSVCRT_wchar_t *name, MSVCRT_wchar_t *fullname, int use_path)
{
  static const MSVCRT_wchar_t path[] = {'P','A','T','H',0};
  static const MSVCRT_wchar_t suffix[][5] =
    {{'.','c','o','m',0}, {'.','e','x','e',0}, {'.','b','a','t',0}, {'.','c','m','d',0}};

  MSVCRT_wchar_t buffer[MAX_PATH];
46
  const MSVCRT_wchar_t *env, *p, *end;
47 48 49 50 51 52
  unsigned int i, name_len, path_len;
  int extension = 1;

  *fullname = '\0';
  msvcrt_set_errno(ERROR_FILE_NOT_FOUND);

53 54 55
  end = name + MAX_PATH - 1;
  for(p = name; p < end; p++)
      if(!*p) break;
56 57 58 59 60 61 62 63 64
  name_len = p - name;

  /* FIXME extra-long names are silently truncated */
  memcpy(buffer, name, name_len * sizeof(MSVCRT_wchar_t));
  buffer[name_len] = '\0';

  /* try current dir first */
  if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
  {
65
    MSVCRT_wcscpy(fullname, buffer);
66 67 68 69 70 71 72 73 74 75 76 77 78 79
    return;
  }

  for (p--; p >= name; p--)
    if (*p == '\\' || *p == '/' || *p == ':' || *p == '.') break;

  /* if there's no extension, try some well-known extensions */
  if ((p < name || *p != '.') && name_len <= MAX_PATH - 5)
  {
    for (i = 0; i < 4; i++)
    {
      memcpy(buffer + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
      if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
      {
80
        MSVCRT_wcscpy(fullname, buffer);
81 82 83 84 85 86
        return;
      }
    }
    extension = 0;
  }

87
  if (!use_path || !(env = MSVCRT__wgetenv(path))) return;
88 89 90 91 92 93 94 95 96 97 98 99

  /* now try search path */
  do
  {
    p = env;
    while (*p && *p != ';') p++;
    if (p == env) return;

    path_len = p - env;
    if (path_len + name_len <= MAX_PATH - 2)
    {
      memcpy(buffer, env, path_len * sizeof(MSVCRT_wchar_t));
100
      if (buffer[path_len] != '/' && buffer[path_len] != '\\')
101 102 103 104 105 106
      {
        buffer[path_len++] = '\\';
        buffer[path_len] = '\0';
      }
      else buffer[path_len] = '\0';

107
      MSVCRT_wcscat(buffer, name);
108 109
      if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
      {
110
        MSVCRT_wcscpy(fullname, buffer);
111 112 113 114 115 116 117 118 119 120 121
        return;
      }
    }
    /* again, if there's no extension, try some well-known extensions */
    if (!extension && path_len + name_len <= MAX_PATH - 5)
    {
      for (i = 0; i < 4; i++)
      {
        memcpy(buffer + path_len + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t));
        if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES)
        {
122
          MSVCRT_wcscpy(fullname, buffer);
123 124 125 126 127 128 129 130 131 132
          return;
        }
      }
    }
    env = *p ? p + 1 : p;
  } while(1);
}

static MSVCRT_intptr_t msvcrt_spawn(int flags, const MSVCRT_wchar_t* exe, MSVCRT_wchar_t* cmdline,
                                    MSVCRT_wchar_t* env, int use_path)
133 134 135
{
  STARTUPINFOW si;
  PROCESS_INFORMATION pi;
136
  MSVCRT_wchar_t fullname[MAX_PATH];
137
  DWORD create_flags = CREATE_UNICODE_ENVIRONMENT;
138 139

  TRACE("%x %s %s %s %d\n", flags, debugstr_w(exe), debugstr_w(cmdline), debugstr_w(env), use_path);
140 141 142 143 144 145 146

  if ((unsigned)flags > MSVCRT__P_DETACH)
  {
    *MSVCRT__errno() = MSVCRT_EINVAL;
    return -1;
  }

147 148
  msvcrt_search_executable(exe, fullname, use_path);

149 150 151
  memset(&si, 0, sizeof(si));
  si.cb = sizeof(si);
  msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2);
152
  if (flags == MSVCRT__P_DETACH) create_flags |= DETACHED_PROCESS;
153
  if (!CreateProcessW(fullname, cmdline, NULL, NULL, TRUE,
154
                      create_flags, env, NULL, &si, &pi))
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
  {
    msvcrt_set_errno(GetLastError());
    MSVCRT_free(si.lpReserved2);
    return -1;
  }

  MSVCRT_free(si.lpReserved2);
  switch(flags)
  {
  case MSVCRT__P_WAIT:
    WaitForSingleObject(pi.hProcess, INFINITE);
    GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return pi.dwProcessId;
  case MSVCRT__P_DETACH:
    CloseHandle(pi.hProcess);
    pi.hProcess = 0;
    /* fall through */
  case MSVCRT__P_NOWAIT:
  case MSVCRT__P_NOWAITO:
    CloseHandle(pi.hThread);
    return (MSVCRT_intptr_t)pi.hProcess;
  case  MSVCRT__P_OVERLAY:
    MSVCRT__exit(0);
  }
  return -1; /* can't reach here */
}

184 185 186
/* INTERNAL: Convert wide argv list to a single 'delim'-separated wide string, with an
 * extra '\0' to terminate it.
 */
187
static MSVCRT_wchar_t* msvcrt_argvtos(const MSVCRT_wchar_t* const* arg, MSVCRT_wchar_t delim)
188 189
{
  const MSVCRT_wchar_t* const* a;
190
  int size;
191 192 193
  MSVCRT_wchar_t* p;
  MSVCRT_wchar_t* ret;

194
  if (!arg)
195 196 197 198 199 200 201 202 203 204
  {
      /* Return NULL for an empty environment list */
      return NULL;
  }

  /* get length */
  a = arg;
  size = 0;
  while (*a)
  {
205
    size += MSVCRT_wcslen(*a) + 1;
206 207 208 209 210 211 212 213 214 215 216 217
    a++;
  }

  ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t));
  if (!ret)
    return NULL;

  /* fill string */
  a = arg;
  p = ret;
  while (*a)
  {
218
    int len = MSVCRT_wcslen(*a);
219 220 221 222 223 224 225 226 227 228
    memcpy(p,*a,len * sizeof(MSVCRT_wchar_t));
    p += len;
    *p++ = delim;
    a++;
  }
  if (delim && p > ret) p[-1] = 0;
  else *p = 0;
  return ret;
}

229 230
/* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an
 * extra '\0' to terminate it.
231
 */
232 233 234
static MSVCRT_wchar_t *msvcrt_argvtos_aw(const char * const *arg, MSVCRT_wchar_t delim)
{
  const char * const *a;
235
  unsigned int len;
236 237
  MSVCRT_wchar_t *p, *ret;

238
  if (!arg)
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
  {
      /* Return NULL for an empty environment list */
      return NULL;
  }

  /* get length */
  a = arg;
  len = 0;
  while (*a)
  {
    len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0);
    a++;
  }

  ret = MSVCRT_malloc((len + 1) * sizeof(MSVCRT_wchar_t));
  if (!ret)
    return NULL;

  /* fill string */
  a = arg;
  p = ret;
  while (*a)
  {
    p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret));
    *p++ = delim;
    a++;
  }
  if (delim && p > ret) p[-1] = 0;
  else *p = 0;
  return ret;
}

271 272 273
/* INTERNAL: Convert wide va_list to a single 'delim'-separated wide string, with an
 * extra '\0' to terminate it.
 */
274
static MSVCRT_wchar_t *msvcrt_valisttos(const MSVCRT_wchar_t *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
275
{
276 277 278
    unsigned int size = 0, pos = 0;
    const MSVCRT_wchar_t *arg;
    MSVCRT_wchar_t *new, *ret = NULL;
279

280 281
    for (arg = arg0; arg; arg = va_arg( alist, MSVCRT_wchar_t * ))
    {
282
        unsigned int len = MSVCRT_wcslen( arg ) + 1;
283 284 285 286 287 288 289 290 291 292 293
        if (pos + len >= size)
        {
            size = max( 256, size * 2 );
            size = max( size, pos + len + 1 );
            if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
            {
                MSVCRT_free( ret );
                return NULL;
            }
            ret = new;
        }
294
        MSVCRT_wcscpy( ret + pos, arg );
295 296 297 298 299 300 301 302 303
        pos += len;
        ret[pos - 1] = delim;
    }
    if (pos)
    {
        if (delim) ret[pos - 1] = 0;
        else ret[pos] = 0;
    }
    return ret;
304 305
}

306 307 308
/* INTERNAL: Convert ansi va_list to a single 'delim'-separated wide string, with an
 * extra '\0' to terminate it.
 */
309
static MSVCRT_wchar_t *msvcrt_valisttos_aw(const char *arg0, __ms_va_list alist, MSVCRT_wchar_t delim)
310
{
311 312 313
    unsigned int size = 0, pos = 0;
    const char *arg;
    MSVCRT_wchar_t *new, *ret = NULL;
314

315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    for (arg = arg0; arg; arg = va_arg( alist, char * ))
    {
        unsigned int len = MultiByteToWideChar( CP_ACP, 0, arg, -1, NULL, 0 );
        if (pos + len >= size)
        {
            size = max( 256, size * 2 );
            size = max( size, pos + len + 1 );
            if (!(new = MSVCRT_realloc( ret, size * sizeof(MSVCRT_wchar_t) )))
            {
                MSVCRT_free( ret );
                return NULL;
            }
            ret = new;
        }
        pos += MultiByteToWideChar( CP_ACP, 0, arg, -1, ret + pos, size - pos );
        ret[pos - 1] = delim;
    }
    if (pos)
    {
        if (delim) ret[pos - 1] = 0;
        else ret[pos] = 0;
    }
    return ret;
338 339
}

340 341 342 343 344 345 346 347
/* INTERNAL: retrieve COMSPEC environment variable */
static MSVCRT_wchar_t *msvcrt_get_comspec(void)
{
  static const MSVCRT_wchar_t cmd[] = {'c','m','d',0};
  static const MSVCRT_wchar_t comspec[] = {'C','O','M','S','P','E','C',0};
  MSVCRT_wchar_t *ret;
  unsigned int len;

348
  if (!(len = GetEnvironmentVariableW(comspec, NULL, 0))) len = ARRAY_SIZE(cmd);
349 350
  if ((ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
  {
351
    if (!GetEnvironmentVariableW(comspec, ret, len)) MSVCRT_wcscpy(ret, cmd);
352 353 354 355
  }
  return ret;
}

356 357 358
/*********************************************************************
 *		_cwait (MSVCRT.@)
 */
359
MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action)
360 361 362 363
{
  HANDLE hPid = (HANDLE)pid;
  int doserrno;

364
  if (!WaitForSingleObject(hPid, INFINITE))
365 366 367 368 369 370 371
  {
    if (status)
    {
      DWORD stat;
      GetExitCodeProcess(hPid, &stat);
      *status = (int)stat;
    }
372
    return pid;
373 374 375 376 377
  }
  doserrno = GetLastError();

  if (doserrno == ERROR_INVALID_HANDLE)
  {
378
    *MSVCRT__errno() =  MSVCRT_ECHILD;
379
    *MSVCRT___doserrno() = doserrno;
380 381
  }
  else
382
    msvcrt_set_errno(doserrno);
383 384 385 386

  return status ? *status = -1 : -1;
}

387 388 389 390 391
/*********************************************************************
 *      _wexecl (MSVCRT.@)
 *
 * Unicode version of _execl
 */
392
MSVCRT_intptr_t WINAPIV _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
393
{
394
  __ms_va_list ap;
395 396 397
  MSVCRT_wchar_t *args;
  MSVCRT_intptr_t ret;

398
  __ms_va_start(ap, arg0);
399
  args = msvcrt_valisttos(arg0, ap, ' ');
400
  __ms_va_end(ap);
401

402
  ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0);
403 404 405 406 407

  MSVCRT_free(args);
  return ret;
}

408 409
/*********************************************************************
 *		_execl (MSVCRT.@)
410
 *
411
 * Like on Windows, this function does not handle arguments with spaces
412
 * or double-quotes.
413
 */
414
MSVCRT_intptr_t WINAPIV _execl(const char* name, const char* arg0, ...)
415
{
416
  __ms_va_list ap;
417
  MSVCRT_wchar_t *nameW, *args;
418
  MSVCRT_intptr_t ret;
419 420

  if (!(nameW = msvcrt_wstrdupa(name))) return -1;
421

422
  __ms_va_start(ap, arg0);
423
  args = msvcrt_valisttos_aw(arg0, ap, ' ');
424
  __ms_va_end(ap);
425

426
  ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 0);
427

428 429
  MSVCRT_free(nameW);
  MSVCRT_free(args);
430 431 432
  return ret;
}

433 434 435 436 437
/*********************************************************************
 *      _wexecle (MSVCRT.@)
 *
 * Unicode version of _execle
 */
438
MSVCRT_intptr_t WINAPIV _wexecle(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
439
{
440
  __ms_va_list ap;
441 442 443 444
  MSVCRT_wchar_t *args, *envs = NULL;
  const MSVCRT_wchar_t * const *envp;
  MSVCRT_intptr_t ret;

445
  __ms_va_start(ap, arg0);
446
  args = msvcrt_valisttos(arg0, ap, ' ');
447
  __ms_va_end(ap);
448

449
  __ms_va_start(ap, arg0);
450 451 452
  while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
  envp = va_arg( ap, const MSVCRT_wchar_t * const * );
  if (envp) envs = msvcrt_argvtos(envp, 0);
453
  __ms_va_end(ap);
454

455
  ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 0);
456 457 458 459 460 461

  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
}

462 463 464
/*********************************************************************
 *		_execle (MSVCRT.@)
 */
465
MSVCRT_intptr_t WINAPIV _execle(const char* name, const char* arg0, ...)
466
{
467
  __ms_va_list ap;
468 469 470 471 472 473
  MSVCRT_wchar_t *nameW, *args, *envs = NULL;
  const char * const *envp;
  MSVCRT_intptr_t ret;

  if (!(nameW = msvcrt_wstrdupa(name))) return -1;

474
  __ms_va_start(ap, arg0);
475
  args = msvcrt_valisttos_aw(arg0, ap, ' ');
476
  __ms_va_end(ap);
477

478
  __ms_va_start(ap, arg0);
479 480 481
  while (va_arg( ap, char * ) != NULL) /*nothing*/;
  envp = va_arg( ap, const char * const * );
  if (envp) envs = msvcrt_argvtos_aw(envp, 0);
482
  __ms_va_end(ap);
483

484
  ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 0);
485 486 487 488 489

  MSVCRT_free(nameW);
  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
490 491
}

492 493 494 495 496
/*********************************************************************
 *      _wexeclp (MSVCRT.@)
 *
 * Unicode version of _execlp
 */
497
MSVCRT_intptr_t WINAPIV _wexeclp(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
498
{
499
  __ms_va_list ap;
500
  MSVCRT_wchar_t *args;
501 502
  MSVCRT_intptr_t ret;

503
  __ms_va_start(ap, arg0);
504
  args = msvcrt_valisttos(arg0, ap, ' ');
505
  __ms_va_end(ap);
506

507
  ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 1);
508 509 510 511 512

  MSVCRT_free(args);
  return ret;
}

513 514
/*********************************************************************
 *		_execlp (MSVCRT.@)
515
 *
516
 * Like on Windows, this function does not handle arguments with spaces
517
 * or double-quotes.
518
 */
519
MSVCRT_intptr_t WINAPIV _execlp(const char* name, const char* arg0, ...)
520
{
521
  __ms_va_list ap;
522
  MSVCRT_wchar_t *nameW, *args;
523
  MSVCRT_intptr_t ret;
524

525
  if (!(nameW = msvcrt_wstrdupa(name))) return -1;
526

527
  __ms_va_start(ap, arg0);
528
  args = msvcrt_valisttos_aw(arg0, ap, ' ');
529
  __ms_va_end(ap);
530

531
  ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, NULL, 1);
532

533 534
  MSVCRT_free(nameW);
  MSVCRT_free(args);
535 536 537
  return ret;
}

538 539 540 541 542
/*********************************************************************
 *      _wexeclpe (MSVCRT.@)
 *
 * Unicode version of _execlpe
 */
543
MSVCRT_intptr_t WINAPIV _wexeclpe(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
544
{
545
  __ms_va_list ap;
546
  MSVCRT_wchar_t *args, *envs = NULL;
547 548 549
  const MSVCRT_wchar_t * const *envp;
  MSVCRT_intptr_t ret;

550
  __ms_va_start(ap, arg0);
551
  args = msvcrt_valisttos(arg0, ap, ' ');
552
  __ms_va_end(ap);
553

554
  __ms_va_start(ap, arg0);
555 556 557
  while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
  envp = va_arg( ap, const MSVCRT_wchar_t * const * );
  if (envp) envs = msvcrt_argvtos(envp, 0);
558
  __ms_va_end(ap);
559

560
  ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, envs, 1);
561 562 563 564 565 566

  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
}

567 568 569
/*********************************************************************
 *		_execlpe (MSVCRT.@)
 */
570
MSVCRT_intptr_t WINAPIV _execlpe(const char* name, const char* arg0, ...)
571
{
572
  __ms_va_list ap;
573
  MSVCRT_wchar_t *nameW, *args, *envs = NULL;
574 575 576 577 578
  const char * const *envp;
  MSVCRT_intptr_t ret;

  if (!(nameW = msvcrt_wstrdupa(name))) return -1;

579
  __ms_va_start(ap, arg0);
580
  args = msvcrt_valisttos_aw(arg0, ap, ' ');
581
  __ms_va_end(ap);
582

583
  __ms_va_start(ap, arg0);
584 585 586
  while (va_arg( ap, char * ) != NULL) /*nothing*/;
  envp = va_arg( ap, const char * const * );
  if (envp) envs = msvcrt_argvtos_aw(envp, 0);
587
  __ms_va_end(ap);
588

589
  ret = msvcrt_spawn(MSVCRT__P_OVERLAY, nameW, args, envs, 1);
590 591 592 593 594

  MSVCRT_free(nameW);
  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
595 596
}

597 598 599 600 601
/*********************************************************************
 *      _wexecv (MSVCRT.@)
 *
 * Unicode version of _execv
 */
602
MSVCRT_intptr_t CDECL _wexecv(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
603
{
604
  return MSVCRT__wspawnve(MSVCRT__P_OVERLAY, name, argv, NULL);
605 606
}

607 608
/*********************************************************************
 *		_execv (MSVCRT.@)
609
 *
610
 * Like on Windows, this function does not handle arguments with spaces
611
 * or double-quotes.
612
 */
613
MSVCRT_intptr_t CDECL _execv(const char* name, const char* const* argv)
614
{
615
  return MSVCRT__spawnve(MSVCRT__P_OVERLAY, name, argv, NULL);
616 617
}

618 619 620 621 622
/*********************************************************************
 *      _wexecve (MSVCRT.@)
 *
 * Unicode version of _execve
 */
623
MSVCRT_intptr_t CDECL _wexecve(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
624
{
625
  return MSVCRT__wspawnve(MSVCRT__P_OVERLAY, name, argv, envv);
626 627
}

628 629
/*********************************************************************
 *		_execve (MSVCRT.@)
630
 *
631
 * Like on Windows, this function does not handle arguments with spaces
632
 * or double-quotes.
633
 */
634
MSVCRT_intptr_t CDECL MSVCRT__execve(const char* name, const char* const* argv, const char* const* envv)
635
{
636
  return MSVCRT__spawnve(MSVCRT__P_OVERLAY, name, argv, envv);
637 638
}

639 640 641 642 643
/*********************************************************************
 *      _wexecvpe (MSVCRT.@)
 *
 * Unicode version of _execvpe
 */
644
MSVCRT_intptr_t CDECL _wexecvpe(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv)
645
{
646
  return MSVCRT__wspawnvpe(MSVCRT__P_OVERLAY, name, argv, envv);
647 648
}

649 650
/*********************************************************************
 *		_execvpe (MSVCRT.@)
651
 *
652
 * Like on Windows, this function does not handle arguments with spaces
653
 * or double-quotes.
654
 */
655
MSVCRT_intptr_t CDECL _execvpe(const char* name, const char* const* argv, const char* const* envv)
656
{
657
  return MSVCRT__spawnvpe(MSVCRT__P_OVERLAY, name, argv, envv);
658 659
}

660 661 662 663 664
/*********************************************************************
 *      _wexecvp (MSVCRT.@)
 *
 * Unicode version of _execvp
 */
665
MSVCRT_intptr_t CDECL _wexecvp(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
666 667 668 669
{
  return _wexecvpe(name, argv, NULL);
}

670 671
/*********************************************************************
 *		_execvp (MSVCRT.@)
672
 *
673
 * Like on Windows, this function does not handle arguments with spaces
674
 * or double-quotes.
675
 */
676
MSVCRT_intptr_t CDECL _execvp(const char* name, const char* const* argv)
677 678 679 680
{
  return _execvpe(name, argv, NULL);
}

681 682 683 684 685
/*********************************************************************
 *      _wspawnl (MSVCRT.@)
 *
 * Unicode version of _spawnl
 */
686
MSVCRT_intptr_t WINAPIV MSVCRT__wspawnl(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
687
{
688
  __ms_va_list ap;
689 690 691
  MSVCRT_wchar_t *args;
  MSVCRT_intptr_t ret;

692
  __ms_va_start(ap, arg0);
693
  args = msvcrt_valisttos(arg0, ap, ' ');
694
  __ms_va_end(ap);
695

696
  ret = msvcrt_spawn(flags, name, args, NULL, 0);
697 698 699 700 701

  MSVCRT_free(args);
  return ret;
}

702 703
/*********************************************************************
 *		_spawnl (MSVCRT.@)
704
 *
705
 * Like on Windows, this function does not handle arguments with spaces
706
 * or double-quotes.
707
 */
708
MSVCRT_intptr_t WINAPIV MSVCRT__spawnl(int flags, const char* name, const char* arg0, ...)
709
{
710
  __ms_va_list ap;
711
  MSVCRT_wchar_t *nameW, *args;
712
  MSVCRT_intptr_t ret;
713

714 715
  if (!(nameW = msvcrt_wstrdupa(name))) return -1;

716
  __ms_va_start(ap, arg0);
717
  args = msvcrt_valisttos_aw(arg0, ap, ' ');
718
  __ms_va_end(ap);
719

720
  ret = msvcrt_spawn(flags, nameW, args, NULL, 0);
721

722 723
  MSVCRT_free(nameW);
  MSVCRT_free(args);
724 725 726
  return ret;
}

727 728 729 730 731
/*********************************************************************
 *      _wspawnle (MSVCRT.@)
 *
 * Unicode version of _spawnle
 */
732
MSVCRT_intptr_t WINAPIV MSVCRT__wspawnle(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
733
{
734
  __ms_va_list ap;
735 736 737 738
  MSVCRT_wchar_t *args, *envs = NULL;
  const MSVCRT_wchar_t * const *envp;
  MSVCRT_intptr_t ret;

739
  __ms_va_start(ap, arg0);
740
  args = msvcrt_valisttos(arg0, ap, ' ');
741
  __ms_va_end(ap);
742

743
  __ms_va_start(ap, arg0);
744 745 746
  while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
  envp = va_arg( ap, const MSVCRT_wchar_t * const * );
  if (envp) envs = msvcrt_argvtos(envp, 0);
747
  __ms_va_end(ap);
748

749
  ret = msvcrt_spawn(flags, name, args, envs, 0);
750 751 752 753 754 755

  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
}

756 757 758
/*********************************************************************
 *		_spawnle (MSVCRT.@)
 */
759
MSVCRT_intptr_t WINAPIV MSVCRT__spawnle(int flags, const char* name, const char* arg0, ...)
760
{
761
  __ms_va_list ap;
762 763 764 765 766 767
  MSVCRT_wchar_t *nameW, *args, *envs = NULL;
  const char * const *envp;
  MSVCRT_intptr_t ret;

  if (!(nameW = msvcrt_wstrdupa(name))) return -1;

768
  __ms_va_start(ap, arg0);
769
  args = msvcrt_valisttos_aw(arg0, ap, ' ');
770
  __ms_va_end(ap);
771

772
  __ms_va_start(ap, arg0);
773 774 775
  while (va_arg( ap, char * ) != NULL) /*nothing*/;
  envp = va_arg( ap, const char * const * );
  if (envp) envs = msvcrt_argvtos_aw(envp, 0);
776
  __ms_va_end(ap);
777

778
  ret = msvcrt_spawn(flags, nameW, args, envs, 0);
779 780 781 782 783

  MSVCRT_free(nameW);
  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
784 785
}

786 787 788 789 790
/*********************************************************************
 *      _wspawnlp (MSVCRT.@)
 *
 * Unicode version of _spawnlp
 */
791
MSVCRT_intptr_t WINAPIV MSVCRT__wspawnlp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
792
{
793
  __ms_va_list ap;
794
  MSVCRT_wchar_t *args;
795 796
  MSVCRT_intptr_t ret;

797
  __ms_va_start(ap, arg0);
798
  args = msvcrt_valisttos(arg0, ap, ' ');
799
  __ms_va_end(ap);
800

801
  ret = msvcrt_spawn(flags, name, args, NULL, 1);
802 803 804 805

  MSVCRT_free(args);
  return ret;
}
806

807
/*********************************************************************
808
 *		_spawnlp (MSVCRT.@)
809
 *
810
 * Like on Windows, this function does not handle arguments with spaces
811
 * or double-quotes.
812
 */
813
MSVCRT_intptr_t WINAPIV MSVCRT__spawnlp(int flags, const char* name, const char* arg0, ...)
814
{
815
  __ms_va_list ap;
816
  MSVCRT_wchar_t *nameW, *args;
817
  MSVCRT_intptr_t ret;
818

819
  if (!(nameW = msvcrt_wstrdupa(name))) return -1;
820

821
  __ms_va_start(ap, arg0);
822
  args = msvcrt_valisttos_aw(arg0, ap, ' ');
823
  __ms_va_end(ap);
824

825
  ret = msvcrt_spawn(flags, nameW, args, NULL, 1);
826

827 828
  MSVCRT_free(nameW);
  MSVCRT_free(args);
829 830 831
  return ret;
}

832 833 834 835 836
/*********************************************************************
 *      _wspawnlpe (MSVCRT.@)
 *
 * Unicode version of _spawnlpe
 */
837
MSVCRT_intptr_t WINAPIV MSVCRT__wspawnlpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...)
838
{
839
  __ms_va_list ap;
840
  MSVCRT_wchar_t *args, *envs = NULL;
841 842 843
  const MSVCRT_wchar_t * const *envp;
  MSVCRT_intptr_t ret;

844
  __ms_va_start(ap, arg0);
845
  args = msvcrt_valisttos(arg0, ap, ' ');
846
  __ms_va_end(ap);
847

848
  __ms_va_start(ap, arg0);
849 850 851
  while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/;
  envp = va_arg( ap, const MSVCRT_wchar_t * const * );
  if (envp) envs = msvcrt_argvtos(envp, 0);
852
  __ms_va_end(ap);
853

854
  ret = msvcrt_spawn(flags, name, args, envs, 1);
855 856 857 858 859 860

  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
}

861 862 863
/*********************************************************************
 *		_spawnlpe (MSVCRT.@)
 */
864
MSVCRT_intptr_t WINAPIV MSVCRT__spawnlpe(int flags, const char* name, const char* arg0, ...)
865
{
866
  __ms_va_list ap;
867
  MSVCRT_wchar_t *nameW, *args, *envs = NULL;
868 869
  const char * const *envp;
  MSVCRT_intptr_t ret;
870

871
  if (!(nameW = msvcrt_wstrdupa(name))) return -1;
872

873
  __ms_va_start(ap, arg0);
874
  args = msvcrt_valisttos_aw(arg0, ap, ' ');
875
  __ms_va_end(ap);
876

877
  __ms_va_start(ap, arg0);
878 879 880
  while (va_arg( ap, char * ) != NULL) /*nothing*/;
  envp = va_arg( ap, const char * const * );
  if (envp) envs = msvcrt_argvtos_aw(envp, 0);
881
  __ms_va_end(ap);
882

883
  ret = msvcrt_spawn(flags, nameW, args, envs, 1);
884

885 886 887 888
  MSVCRT_free(nameW);
  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
889 890
}

891 892
/*********************************************************************
 *		_spawnve (MSVCRT.@)
893
 *
894
 * Like on Windows, this function does not handle arguments with spaces
895
 * or double-quotes.
896
 */
897
MSVCRT_intptr_t CDECL MSVCRT__spawnve(int flags, const char* name, const char* const* argv,
898
                               const char* const* envv)
899
{
900 901
  MSVCRT_wchar_t *nameW, *args, *envs;
  MSVCRT_intptr_t ret;
902

903
  if (!(nameW = msvcrt_wstrdupa(name))) return -1;
904

905 906
  args = msvcrt_argvtos_aw(argv, ' ');
  envs = msvcrt_argvtos_aw(envv, 0);
907

908
  ret = msvcrt_spawn(flags, nameW, args, envs, 0);
909

910 911
  MSVCRT_free(nameW);
  MSVCRT_free(args);
912
  MSVCRT_free(envs);
913 914 915
  return ret;
}

916 917 918 919 920
/*********************************************************************
 *      _wspawnve (MSVCRT.@)
 *
 * Unicode version of _spawnve
 */
921
MSVCRT_intptr_t CDECL MSVCRT__wspawnve(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
922 923
                                const MSVCRT_wchar_t* const* envv)
{
924 925
  MSVCRT_wchar_t *args, *envs;
  MSVCRT_intptr_t ret;
926

927 928
  args = msvcrt_argvtos(argv, ' ');
  envs = msvcrt_argvtos(envv, 0);
929

930
  ret = msvcrt_spawn(flags, name, args, envs, 0);
931

932
  MSVCRT_free(args);
933 934 935 936
  MSVCRT_free(envs);
  return ret;
}

937 938
/*********************************************************************
 *		_spawnv (MSVCRT.@)
939
 *
940
 * Like on Windows, this function does not handle arguments with spaces
941
 * or double-quotes.
942
 */
943
MSVCRT_intptr_t CDECL MSVCRT__spawnv(int flags, const char* name, const char* const* argv)
944
{
945
  return MSVCRT__spawnve(flags, name, argv, NULL);
946 947
}

948 949 950 951 952
/*********************************************************************
 *      _wspawnv (MSVCRT.@)
 *
 * Unicode version of _spawnv
 */
953
MSVCRT_intptr_t CDECL MSVCRT__wspawnv(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
954
{
955
  return MSVCRT__wspawnve(flags, name, argv, NULL);
956 957
}

958 959
/*********************************************************************
 *		_spawnvpe (MSVCRT.@)
960
 *
961
 * Like on Windows, this function does not handle arguments with spaces
962
 * or double-quotes.
963
 */
964
MSVCRT_intptr_t CDECL MSVCRT__spawnvpe(int flags, const char* name, const char* const* argv,
965
                                const char* const* envv)
966
{
967 968 969 970 971 972 973 974 975 976 977 978 979 980
  MSVCRT_wchar_t *nameW, *args, *envs;
  MSVCRT_intptr_t ret;

  if (!(nameW = msvcrt_wstrdupa(name))) return -1;

  args = msvcrt_argvtos_aw(argv, ' ');
  envs = msvcrt_argvtos_aw(envv, 0);

  ret = msvcrt_spawn(flags, nameW, args, envs, 1);

  MSVCRT_free(nameW);
  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
981 982
}

983 984 985 986 987
/*********************************************************************
 *      _wspawnvpe (MSVCRT.@)
 *
 * Unicode version of _spawnvpe
 */
988
MSVCRT_intptr_t CDECL MSVCRT__wspawnvpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv,
989 990
                                 const MSVCRT_wchar_t* const* envv)
{
991 992
  MSVCRT_wchar_t *args, *envs;
  MSVCRT_intptr_t ret;
993

994 995 996 997 998 999 1000 1001
  args = msvcrt_argvtos(argv, ' ');
  envs = msvcrt_argvtos(envv, 0);

  ret = msvcrt_spawn(flags, name, args, envs, 1);

  MSVCRT_free(args);
  MSVCRT_free(envs);
  return ret;
1002 1003
}

1004 1005
/*********************************************************************
 *		_spawnvp (MSVCRT.@)
1006
 *
1007
 * Like on Windows, this function does not handle arguments with spaces
1008
 * or double-quotes.
1009
 */
1010
MSVCRT_intptr_t CDECL MSVCRT__spawnvp(int flags, const char* name, const char* const* argv)
1011
{
1012
  return MSVCRT__spawnvpe(flags, name, argv, NULL);
1013 1014
}

1015 1016 1017 1018 1019
/*********************************************************************
 *      _wspawnvp (MSVCRT.@)
 *
 * Unicode version of _spawnvp
 */
1020
MSVCRT_intptr_t CDECL MSVCRT__wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv)
1021
{
1022
  return MSVCRT__wspawnvpe(flags, name, argv, NULL);
1023 1024
}

1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
static struct popen_handle {
    MSVCRT_FILE *f;
    HANDLE proc;
} *popen_handles;
static DWORD popen_handles_size;

void msvcrt_free_popen_data(void)
{
    MSVCRT_free(popen_handles);
}

1036
/*********************************************************************
1037 1038 1039
 *		_wpopen (MSVCRT.@)
 *
 * Unicode version of _popen
1040
 */
1041
MSVCRT_FILE* CDECL MSVCRT__wpopen(const MSVCRT_wchar_t* command, const MSVCRT_wchar_t* mode)
1042
{
1043 1044
  MSVCRT_FILE *ret;
  BOOL readPipe = TRUE;
1045
  int textmode, fds[2], fdToDup, fdToOpen, fdStdHandle = -1;
1046 1047 1048 1049
  const MSVCRT_wchar_t *p;
  MSVCRT_wchar_t *comspec, *fullcmd;
  unsigned int len;
  static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};
1050 1051
  struct popen_handle *container;
  DWORD i;
1052

1053
  TRACE("(command=%s, mode=%s)\n", debugstr_w(command), debugstr_w(mode));
1054 1055 1056 1057

  if (!command || !mode)
    return NULL;

1058
  textmode = *MSVCRT___p__fmode() & (MSVCRT__O_BINARY | MSVCRT__O_TEXT);
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
  for (p = mode; *p; p++)
  {
    switch (*p)
    {
      case 'W':
      case 'w':
        readPipe = FALSE;
        break;
      case 'B':
      case 'b':
        textmode |= MSVCRT__O_BINARY;
        textmode &= ~MSVCRT__O_TEXT;
        break;
      case 'T':
      case 't':
        textmode |= MSVCRT__O_TEXT;
        textmode &= ~MSVCRT__O_BINARY;
        break;
    }
  }
1079
  if (MSVCRT__pipe(fds, 0, textmode) == -1)
1080 1081 1082 1083 1084
    return NULL;

  fdToDup = readPipe ? 1 : 0;
  fdToOpen = readPipe ? 0 : 1;

1085
  _lock(_POPEN_LOCK);
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
  for(i=0; i<popen_handles_size; i++)
  {
    if (!popen_handles[i].f)
      break;
  }
  if (i==popen_handles_size)
  {
    i = (popen_handles_size ? popen_handles_size*2 : 8);
    container = MSVCRT_realloc(popen_handles, i*sizeof(*container));
    if (!container) goto error;

    popen_handles = container;
    container = popen_handles+popen_handles_size;
    memset(container, 0, (i-popen_handles_size)*sizeof(*container));
    popen_handles_size = i;
  }
  else container = popen_handles+i;

1104
  if ((fdStdHandle = MSVCRT__dup(fdToDup)) == -1)
1105
    goto error;
1106
  if (MSVCRT__dup2(fds[fdToDup], fdToDup) != 0)
1107 1108
    goto error;

1109
  MSVCRT__close(fds[fdToDup]);
1110

1111
  if (!(comspec = msvcrt_get_comspec())) goto error;
1112
  len = MSVCRT_wcslen(comspec) + MSVCRT_wcslen(flag) + MSVCRT_wcslen(command) + 1;
1113

1114 1115 1116 1117 1118 1119
  if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
  {
    HeapFree(GetProcessHeap(), 0, comspec);
    goto error;
  }

1120 1121 1122
  MSVCRT_wcscpy(fullcmd, comspec);
  MSVCRT_wcscat(fullcmd, flag);
  MSVCRT_wcscat(fullcmd, command);
1123

1124 1125
  if ((container->proc = (HANDLE)msvcrt_spawn(MSVCRT__P_NOWAIT, comspec, fullcmd, NULL, 1))
          == INVALID_HANDLE_VALUE)
1126
  {
1127
    MSVCRT__close(fds[fdToOpen]);
1128 1129 1130 1131
    ret = NULL;
  }
  else
  {
1132
    ret = MSVCRT__wfdopen(fds[fdToOpen], mode);
1133
    if (!ret)
1134
      MSVCRT__close(fds[fdToOpen]);
1135
    container->f = ret;
1136
  }
1137
  _unlock(_POPEN_LOCK);
1138
  HeapFree(GetProcessHeap(), 0, comspec);
1139
  HeapFree(GetProcessHeap(), 0, fullcmd);
1140 1141
  MSVCRT__dup2(fdStdHandle, fdToDup);
  MSVCRT__close(fdStdHandle);
1142 1143 1144
  return ret;

error:
1145
  _unlock(_POPEN_LOCK);
1146 1147 1148
  if (fdStdHandle != -1) MSVCRT__close(fdStdHandle);
  MSVCRT__close(fds[0]);
  MSVCRT__close(fds[1]);
1149 1150 1151 1152
  return NULL;
}

/*********************************************************************
1153
 *      _popen (MSVCRT.@)
1154
 */
1155
MSVCRT_FILE* CDECL MSVCRT__popen(const char* command, const char* mode)
1156
{
1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
  MSVCRT_FILE *ret;
  MSVCRT_wchar_t *cmdW, *modeW;

  TRACE("(command=%s, mode=%s)\n", debugstr_a(command), debugstr_a(mode));

  if (!command || !mode)
    return NULL;

  if (!(cmdW = msvcrt_wstrdupa(command))) return NULL;
  if (!(modeW = msvcrt_wstrdupa(mode)))
  {
    HeapFree(GetProcessHeap(), 0, cmdW);
    return NULL;
  }

  ret = MSVCRT__wpopen(cmdW, modeW);

  HeapFree(GetProcessHeap(), 0, cmdW);
  HeapFree(GetProcessHeap(), 0, modeW);
  return ret;
1177 1178 1179 1180 1181
}

/*********************************************************************
 *		_pclose (MSVCRT.@)
 */
1182
int CDECL MSVCRT__pclose(MSVCRT_FILE* file)
1183
{
1184 1185 1186 1187 1188
  HANDLE h;
  DWORD i;

  if (!MSVCRT_CHECK_PMT(file != NULL)) return -1;

1189
  _lock(_POPEN_LOCK);
1190 1191 1192 1193 1194 1195 1196
  for(i=0; i<popen_handles_size; i++)
  {
    if (popen_handles[i].f == file)
      break;
  }
  if(i == popen_handles_size)
  {
1197
    _unlock(_POPEN_LOCK);
1198 1199 1200 1201 1202 1203
    *MSVCRT__errno() = MSVCRT_EBADF;
    return -1;
  }

  h = popen_handles[i].proc;
  popen_handles[i].f = NULL;
1204
  _unlock(_POPEN_LOCK);
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215

  MSVCRT_fclose(file);
  if(WaitForSingleObject(h, INFINITE)==WAIT_FAILED || !GetExitCodeProcess(h, &i))
  {
    msvcrt_set_errno(GetLastError());
    CloseHandle(h);
    return -1;
  }

  CloseHandle(h);
  return i;
1216 1217
}

1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
/*********************************************************************
 *      _wsystem (MSVCRT.@)
 *
 * Unicode version of system
 */
int CDECL _wsystem(const MSVCRT_wchar_t* cmd)
{
  int res;
  MSVCRT_wchar_t *comspec, *fullcmd;
  unsigned int len;
  static const MSVCRT_wchar_t flag[] = {' ','/','c',' ',0};

1230 1231 1232 1233 1234 1235 1236 1237 1238
  comspec = msvcrt_get_comspec();

  if (cmd == NULL)
  {
    if (comspec == NULL)
    {
        *MSVCRT__errno() = MSVCRT_ENOENT;
        return 0;
    }
1239
    HeapFree(GetProcessHeap(), 0, comspec);
1240 1241 1242 1243 1244 1245
    return 1;
  }

  if ( comspec == NULL)
    return -1;

1246
  len = MSVCRT_wcslen(comspec) + MSVCRT_wcslen(flag) + MSVCRT_wcslen(cmd) + 1;
1247 1248 1249 1250 1251 1252

  if (!(fullcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(MSVCRT_wchar_t))))
  {
    HeapFree(GetProcessHeap(), 0, comspec);
    return -1;
  }
1253 1254 1255
  MSVCRT_wcscpy(fullcmd, comspec);
  MSVCRT_wcscat(fullcmd, flag);
  MSVCRT_wcscat(fullcmd, cmd);
1256

1257
  res = msvcrt_spawn(MSVCRT__P_WAIT, comspec, fullcmd, NULL, 1);
1258 1259 1260 1261 1262 1263

  HeapFree(GetProcessHeap(), 0, comspec);
  HeapFree(GetProcessHeap(), 0, fullcmd);
  return res;
}

1264 1265 1266
/*********************************************************************
 *		system (MSVCRT.@)
 */
1267
int CDECL MSVCRT_system(const char* cmd)
1268
{
1269 1270
  int res = -1;
  MSVCRT_wchar_t *cmdW;
1271

1272 1273 1274
  if (cmd == NULL)
    return _wsystem(NULL);

1275 1276 1277 1278 1279 1280
  if ((cmdW = msvcrt_wstrdupa(cmd)))
  {
    res = _wsystem(cmdW);
    HeapFree(GetProcessHeap(), 0, cmdW);
  }
  return res;
1281 1282 1283 1284 1285
}

/*********************************************************************
 *		_loaddll (MSVCRT.@)
 */
1286
MSVCRT_intptr_t CDECL _loaddll(const char* dllname)
1287
{
1288
  return (MSVCRT_intptr_t)LoadLibraryA(dllname);
1289 1290 1291 1292 1293
}

/*********************************************************************
 *		_unloaddll (MSVCRT.@)
 */
1294
int CDECL _unloaddll(MSVCRT_intptr_t dll)
1295
{
1296
  if (FreeLibrary((HMODULE)dll))
1297 1298 1299 1300
    return 0;
  else
  {
    int err = GetLastError();
1301
    msvcrt_set_errno(err);
1302 1303 1304
    return err;
  }
}
1305 1306 1307 1308

/*********************************************************************
 *		_getdllprocaddr (MSVCRT.@)
 */
1309
void * CDECL _getdllprocaddr(MSVCRT_intptr_t dll, const char *name, int ordinal)
1310 1311 1312 1313 1314 1315 1316 1317 1318
{
    if (name)
    {
        if (ordinal != -1) return NULL;
        return GetProcAddress( (HMODULE)dll, name );
    }
    if (HIWORD(ordinal)) return NULL;
    return GetProcAddress( (HMODULE)dll, (LPCSTR)(ULONG_PTR)ordinal );
}
1319 1320 1321 1322 1323 1324 1325 1326

/*********************************************************************
 *              _getpid (MSVCRT.@)
 */
int CDECL _getpid(void)
{
    return GetCurrentProcessId();
}
1327

1328
#if _MSVCR_VER>=110
1329 1330 1331 1332 1333 1334 1335
/*********************************************************************
 *  __crtTerminateProcess (MSVCR110.@)
 */
int CDECL MSVCR110__crtTerminateProcess(UINT exit_code)
{
    return TerminateProcess(GetCurrentProcess(), exit_code);
}
1336
#endif