Skip to content
Browse files

windows: make spawn with custom environment work again

  • Loading branch information...
1 parent 5c674b2 commit abc945bc04bcd84ecb980988264949013ca35198 @piscisaureus piscisaureus committed Aug 28, 2012
Showing with 44 additions and 18 deletions.
  1. +44 −18 src/win/process.c
View
62 src/win/process.c
@@ -37,9 +37,9 @@
typedef struct env_var {
const char* narrow;
const WCHAR* wide;
- int len; /* including null or '=' */
+ size_t len; /* including null or '=' */
+ DWORD value_len;
int supplied;
- int value_len;
} env_var_t;
#define E_V(str) { str "=", L##str, sizeof(str), 0, 0 }
@@ -549,10 +549,10 @@ uv_err_t make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr)
* issues associated with that solution; this is the caller's
* char**, and modifying it is rude.
*/
-static void check_required_vars_contains_var(env_var_t* required, int size,
+static void check_required_vars_contains_var(env_var_t* required, int count,
const char* var) {
int i;
- for (i = 0; i < size; ++i) {
+ for (i = 0; i < count; ++i) {
if (_strnicmp(required[i].narrow, var, required[i].len) == 0) {
required[i].supplied = 1;
return;
@@ -572,11 +572,11 @@ static void check_required_vars_contains_var(env_var_t* required, int size,
* these get defined if the input environment block does not contain any
* values for them.
*/
-WCHAR* make_program_env(char** env_block) {
+uv_err_t make_program_env(char* env_block[], WCHAR** dst_ptr) {
WCHAR* dst;
WCHAR* ptr;
char** env;
- int env_len = 1 * sizeof(WCHAR); /* room for closing null */
+ size_t env_len = 1; /* room for closing null */
int len;
int i;
DWORD var_size;
@@ -588,36 +588,53 @@ WCHAR* make_program_env(char** env_block) {
};
for (env = env_block; *env; env++) {
+ int len;
check_required_vars_contains_var(required_vars,
ARRAY_SIZE(required_vars),
*env);
- env_len += (uv_utf8_to_utf16(*env, NULL, 0) * sizeof(WCHAR));
+
+ len = MultiByteToWideChar(CP_UTF8,
+ 0,
+ *env,
+ -1,
+ NULL,
+ 0);
+ if (len <= 0) {
+ return uv__new_sys_error(GetLastError());
+ }
+
+ env_len += len;
}
for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
if (!required_vars[i].supplied) {
- env_len += required_vars[i].len * sizeof(WCHAR);
+ env_len += required_vars[i].len;
var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);
if (var_size == 0) {
- uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
+ return uv__new_sys_error(GetLastError());
}
- required_vars[i].value_len = (int)var_size;
- env_len += (int)var_size * sizeof(WCHAR);
+ required_vars[i].value_len = var_size;
+ env_len += var_size;
}
}
- dst = malloc(env_len);
+ dst = malloc(env_len * sizeof(WCHAR));
if (!dst) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ return uv__new_artificial_error(UV_ENOMEM);
}
ptr = dst;
for (env = env_block; *env; env++, ptr += len) {
- len = uv_utf8_to_utf16(*env, ptr, (size_t)(env_len - (ptr - dst)));
- if (!len) {
+ len = MultiByteToWideChar(CP_UTF8,
+ 0,
+ *env,
+ -1,
+ ptr,
+ (int) (env_len - (ptr - dst)));
@bnoordhuis
bnoordhuis added a note Aug 28, 2012

An int? The win32 API is so daft...

@piscisaureus
Joyent member
piscisaureus added a note Aug 28, 2012

yup

I considered writing my own, but the benefit isn't very obvious :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ if (len <= 0) {
free(dst);
- return NULL;
+ return uv__new_sys_error(GetLastError());
}
}
@@ -636,8 +653,11 @@ WCHAR* make_program_env(char** env_block) {
}
}
+ /* Terminate with an extra NULL. */
*ptr = L'\0';
- return dst;
+
+ *dst_ptr = dst;
+ return uv_ok_;
}
@@ -740,7 +760,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
WCHAR* path = NULL;
BOOL result;
WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
- *env = NULL, *cwd = NULL;
+ *env = NULL, *cwd = NULL;
STARTUPINFOW startup;
PROCESS_INFORMATION info;
DWORD process_flags;
@@ -775,6 +795,12 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
if (err.code != UV_OK)
goto done;
+ if (options.env) {
+ err = make_program_env(options.env, &env);
+ if (err.code != UV_OK)
+ goto done;
+ }
+
if (options.cwd) {
/* Explicit cwd */
err = uv_utf8_to_utf16_alloc(options.cwd, &cwd);

1 comment on commit abc945b

@bnoordhuis

LGTM

Please sign in to comment.
Something went wrong with that request. Please try again.