119 lines
4.6 KiB
C
119 lines
4.6 KiB
C
/*****************************************************************************\
|
|
* *
|
|
* Filename spawn.c *
|
|
* *
|
|
* Description: WIN32 UTF-8 version of spawn *
|
|
* *
|
|
* Notes: *
|
|
* *
|
|
* History: *
|
|
* 2014-03-27 JFL Created this module. *
|
|
* 2014-07-03 JFL Added support for pathnames >= 260 characters. *
|
|
* *
|
|
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
|
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
|
\*****************************************************************************/
|
|
|
|
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
|
|
|
/* Microsoft C libraries include files */
|
|
#include <stdio.h>
|
|
/* MsvcLibX library extensions */
|
|
#include "msvcDebugm.h"
|
|
#include "msvclibx.h"
|
|
#include "msvcLimits.h"
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <windows.h>
|
|
#include <process.h>
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
* *
|
|
| Function _spawnvpU |
|
|
| |
|
|
| Description UTF-8 version of Microsoft's _spawnvp |
|
|
| |
|
|
| Parameters: int iMode Spawning mode. P_WAIT or P_NOWAIT |
|
|
| char *pszCommand Program to start |
|
|
| char **argv List of arguments, terminated by NULL |
|
|
| |
|
|
| Returns: The exit code (if P_WAIT) or the process ID (if P_NOWAIT) |
|
|
| |
|
|
| Notes |
|
|
| |
|
|
| History |
|
|
| 2014-03-04 JFL Created this routine. |
|
|
* *
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
intptr_t _spawnvpU(int iMode, const char *pszCommand, char *const *argv) {
|
|
WCHAR wszCommand[PATH_MAX];
|
|
WCHAR **wszArgv;
|
|
int n;
|
|
int nArgs;
|
|
int iArg;
|
|
intptr_t iRet;
|
|
|
|
DEBUG_CODE({
|
|
int i;
|
|
DEBUG_PRINTF(("_spawnvpU(%d, \"%s\", {", iMode, pszCommand));
|
|
if (DEBUG_IS_ON()) {
|
|
for (i=0; argv[i]; i++) {
|
|
if (i) printf(", ");
|
|
printf("\"%s\"", argv[i]);
|
|
}
|
|
printf("});\n");
|
|
}
|
|
})
|
|
|
|
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
|
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
|
pszCommand, /* lpMultiByteStr, */
|
|
wszCommand, /* lpWideCharStr, */
|
|
COUNTOF(wszCommand) /* cchWideChar, */
|
|
);
|
|
if (!n) {
|
|
errno = Win32ErrorToErrno();
|
|
return -1;
|
|
}
|
|
|
|
for (nArgs=0; argv[nArgs]; nArgs++) ; /* Count the number of arguments */
|
|
wszArgv = (WCHAR **)malloc((nArgs+1) * sizeof(WCHAR *));
|
|
if (!wszArgv) return -1; /* errno already set by malloc */
|
|
|
|
for (iArg=0; argv[iArg]; iArg++) { /* Convert every argument */
|
|
int iArgBufSize = lstrlen(argv[iArg]) + 1;
|
|
wszArgv[iArg] = malloc(sizeof(WCHAR)*iArgBufSize);
|
|
if (!wszArgv[iArg]) {
|
|
while (iArg) free(wszArgv[--iArg]); /* Free the partial arg list */
|
|
free(wszArgv);
|
|
return -1; /* errno already set by malloc */
|
|
}
|
|
/* Convert the argument to a unicode string. This is not a pathname, so just do a plain conversion */
|
|
n = MultiByteToWideChar(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
|
0, /* dwFlags, */
|
|
argv[iArg], /* lpMultiByteStr, */
|
|
iArgBufSize, /* cbMultiByte, */
|
|
wszArgv[iArg], /* lpWideCharStr, */
|
|
iArgBufSize /* cchWideChar, */
|
|
);
|
|
if (!n) {
|
|
errno = Win32ErrorToErrno();
|
|
while (iArg >= 0) free(wszArgv[iArg--]); /* Free the partial arg list */
|
|
free(wszArgv);
|
|
return -1;
|
|
}
|
|
}
|
|
wszArgv[nArgs] = NULL;
|
|
|
|
iRet = _wspawnvp(iMode, wszCommand, wszArgv);
|
|
|
|
while (nArgs) free(wszArgv[--nArgs]); /* Free the full arg list */
|
|
free(wszArgv);
|
|
return iRet;
|
|
}
|
|
|
|
#endif /* defined(_WIN32) */
|
|
|