/*****************************************************************************\ * * * 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 /* MsvcLibX library extensions */ #include "msvcDebugm.h" #include "msvclibx.h" #include "msvcLimits.h" #ifdef _WIN32 #include #include /*---------------------------------------------------------------------------*\ * * | 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) */