37
37
typedef struct env_var {
38
38
const char * narrow ;
39
39
const WCHAR * wide ;
40
- int len ; /* including null or '=' */
40
+ size_t len ; /* including null or '=' */
41
+ DWORD value_len ;
41
42
int supplied ;
42
- int value_len ;
43
43
} env_var_t ;
44
44
45
45
#define E_V (str ) { str "=", L##str, sizeof(str), 0, 0 }
@@ -102,13 +102,13 @@ static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
102
102
* Helper function for search_path
103
103
*/
104
104
static WCHAR * search_path_join_test (const WCHAR * dir ,
105
- int dir_len ,
106
- const WCHAR * name ,
107
- int name_len ,
108
- const WCHAR * ext ,
109
- int ext_len ,
110
- const WCHAR * cwd ,
111
- int cwd_len ) {
105
+ size_t dir_len ,
106
+ const WCHAR * name ,
107
+ size_t name_len ,
108
+ const WCHAR * ext ,
109
+ size_t ext_len ,
110
+ const WCHAR * cwd ,
111
+ size_t cwd_len ) {
112
112
WCHAR * result , * result_pos ;
113
113
DWORD attrs ;
114
114
@@ -193,12 +193,12 @@ static WCHAR* search_path_join_test(const WCHAR* dir,
193
193
* Helper function for search_path
194
194
*/
195
195
static WCHAR * path_search_walk_ext (const WCHAR * dir ,
196
- int dir_len ,
197
- const WCHAR * name ,
198
- int name_len ,
199
- WCHAR * cwd ,
200
- int cwd_len ,
201
- int name_has_ext ) {
196
+ size_t dir_len ,
197
+ const WCHAR * name ,
198
+ size_t name_len ,
199
+ WCHAR * cwd ,
200
+ size_t cwd_len ,
201
+ int name_has_ext ) {
202
202
WCHAR * result ;
203
203
204
204
/* If the name itself has a nonempty extension, try this extension first */
@@ -281,11 +281,11 @@ static WCHAR* search_path(const WCHAR *file,
281
281
WCHAR * file_name_start ;
282
282
WCHAR * dot ;
283
283
const WCHAR * dir_start , * dir_end , * dir_path ;
284
- int dir_len ;
284
+ size_t dir_len ;
285
285
int name_has_ext ;
286
286
287
- int file_len = wcslen (file );
288
- int cwd_len = wcslen (cwd );
287
+ size_t file_len = wcslen (file );
288
+ size_t cwd_len = wcslen (cwd );
289
289
290
290
/* If the caller supplies an empty filename,
291
291
* we're not gonna return c:\windows\.exe -- GFY!
@@ -380,8 +380,9 @@ static WCHAR* search_path(const WCHAR *file,
380
380
* Returns a pointer to the end (next char to be written) of the buffer
381
381
*/
382
382
WCHAR * quote_cmd_arg (const WCHAR * source , WCHAR * target ) {
383
- int len = wcslen (source ),
384
- i , quote_hit ;
383
+ size_t len = wcslen (source );
384
+ size_t i ;
385
+ int quote_hit ;
385
386
WCHAR * start ;
386
387
387
388
/*
@@ -512,7 +513,7 @@ uv_err_t make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr)
512
513
* arg ,
513
514
-1 ,
514
515
temp_buffer ,
515
- dst + dst_len - pos );
516
+ ( int ) ( dst + dst_len - pos ) );
516
517
if (arg_len == 0 ) {
517
518
goto error ;
518
519
}
@@ -548,10 +549,10 @@ uv_err_t make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr)
548
549
* issues associated with that solution; this is the caller's
549
550
* char**, and modifying it is rude.
550
551
*/
551
- static void check_required_vars_contains_var (env_var_t * required , int size ,
552
+ static void check_required_vars_contains_var (env_var_t * required , int count ,
552
553
const char * var ) {
553
554
int i ;
554
- for (i = 0 ; i < size ; ++ i ) {
555
+ for (i = 0 ; i < count ; ++ i ) {
555
556
if (_strnicmp (required [i ].narrow , var , required [i ].len ) == 0 ) {
556
557
required [i ].supplied = 1 ;
557
558
return ;
@@ -571,11 +572,11 @@ static void check_required_vars_contains_var(env_var_t* required, int size,
571
572
* these get defined if the input environment block does not contain any
572
573
* values for them.
573
574
*/
574
- WCHAR * make_program_env (char * * env_block ) {
575
+ uv_err_t make_program_env (char * env_block [], WCHAR * * dst_ptr ) {
575
576
WCHAR * dst ;
576
577
WCHAR * ptr ;
577
578
char * * env ;
578
- int env_len = 1 * sizeof ( WCHAR ) ; /* room for closing null */
579
+ size_t env_len = 1 ; /* room for closing null */
579
580
int len ;
580
581
int i ;
581
582
DWORD var_size ;
@@ -587,36 +588,53 @@ WCHAR* make_program_env(char** env_block) {
587
588
};
588
589
589
590
for (env = env_block ; * env ; env ++ ) {
591
+ int len ;
590
592
check_required_vars_contains_var (required_vars ,
591
593
ARRAY_SIZE (required_vars ),
592
594
* env );
593
- env_len += (uv_utf8_to_utf16 (* env , NULL , 0 ) * sizeof (WCHAR ));
595
+
596
+ len = MultiByteToWideChar (CP_UTF8 ,
597
+ 0 ,
598
+ * env ,
599
+ -1 ,
600
+ NULL ,
601
+ 0 );
602
+ if (len <= 0 ) {
603
+ return uv__new_sys_error (GetLastError ());
604
+ }
605
+
606
+ env_len += len ;
594
607
}
595
608
596
609
for (i = 0 ; i < ARRAY_SIZE (required_vars ); ++ i ) {
597
610
if (!required_vars [i ].supplied ) {
598
- env_len += required_vars [i ].len * sizeof ( WCHAR ) ;
611
+ env_len += required_vars [i ].len ;
599
612
var_size = GetEnvironmentVariableW (required_vars [i ].wide , NULL , 0 );
600
613
if (var_size == 0 ) {
601
- uv_fatal_error (GetLastError (), "GetEnvironmentVariableW" );
614
+ return uv__new_sys_error (GetLastError ());
602
615
}
603
- required_vars [i ].value_len = ( int ) var_size ;
604
- env_len += ( int ) var_size * sizeof ( WCHAR ) ;
616
+ required_vars [i ].value_len = var_size ;
617
+ env_len += var_size ;
605
618
}
606
619
}
607
620
608
- dst = malloc (env_len );
621
+ dst = malloc (env_len * sizeof ( WCHAR ) );
609
622
if (!dst ) {
610
- uv_fatal_error ( ERROR_OUTOFMEMORY , "malloc" );
623
+ return uv__new_artificial_error ( UV_ENOMEM );
611
624
}
612
625
613
626
ptr = dst ;
614
627
615
628
for (env = env_block ; * env ; env ++ , ptr += len ) {
616
- len = uv_utf8_to_utf16 (* env , ptr , (size_t )(env_len - (ptr - dst )));
617
- if (!len ) {
629
+ len = MultiByteToWideChar (CP_UTF8 ,
630
+ 0 ,
631
+ * env ,
632
+ -1 ,
633
+ ptr ,
634
+ (int ) (env_len - (ptr - dst )));
635
+ if (len <= 0 ) {
618
636
free (dst );
619
- return NULL ;
637
+ return uv__new_sys_error ( GetLastError ()) ;
620
638
}
621
639
}
622
640
@@ -635,8 +653,11 @@ WCHAR* make_program_env(char** env_block) {
635
653
}
636
654
}
637
655
656
+ /* Terminate with an extra NULL. */
638
657
* ptr = L'\0' ;
639
- return dst ;
658
+
659
+ * dst_ptr = dst ;
660
+ return uv_ok_ ;
640
661
}
641
662
642
663
@@ -739,7 +760,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
739
760
WCHAR * path = NULL ;
740
761
BOOL result ;
741
762
WCHAR * application_path = NULL , * application = NULL , * arguments = NULL ,
742
- * env = NULL , * cwd = NULL ;
763
+ * env = NULL , * cwd = NULL ;
743
764
STARTUPINFOW startup ;
744
765
PROCESS_INFORMATION info ;
745
766
DWORD process_flags ;
@@ -774,6 +795,12 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
774
795
if (err .code != UV_OK )
775
796
goto done ;
776
797
798
+ if (options .env ) {
799
+ err = make_program_env (options .env , & env );
800
+ if (err .code != UV_OK )
801
+ goto done ;
802
+ }
803
+
777
804
if (options .cwd ) {
778
805
/* Explicit cwd */
779
806
err = uv_utf8_to_utf16_alloc (options .cwd , & cwd );
0 commit comments