Skip to content

Commit

Permalink
win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
Browse files Browse the repository at this point in the history
uv_spawn() on Windows will fail with ERROR_ELEVATION_REQUIRED (740) if
attempting to run an application that requires elevation.

Add a Windows test that calls uv_spawn() with a helper .exe that
requires elevated permissions. Test should either run successfully if
run with Administrator privileges or fail with the mapped error.

Refs: nodejs/node#9464
  • Loading branch information
richardlau committed Nov 30, 2016
1 parent c2f0e4f commit 9004498
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/win/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ int uv_translate_sys_error(int sys_errno) {
switch (sys_errno) {
case ERROR_NOACCESS: return UV_EACCES;
case WSAEACCES: return UV_EACCES;
case ERROR_ELEVATION_REQUIRED: return UV_EACCES;
case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
case WSAEADDRINUSE: return UV_EADDRINUSE;
case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
Expand Down
3 changes: 3 additions & 0 deletions test/elevation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int main(int argc, char **argv) {
return 0;
}
1 change: 1 addition & 0 deletions test/test-error.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ TEST_IMPL(error_message) {
TEST_IMPL(sys_error) {
#if defined(_WIN32)
ASSERT(uv_translate_sys_error(ERROR_NOACCESS) == UV_EACCES);
ASSERT(uv_translate_sys_error(ERROR_ELEVATION_REQUIRED) == UV_EACCES);
ASSERT(uv_translate_sys_error(WSAEADDRINUSE) == UV_EADDRINUSE);
ASSERT(uv_translate_sys_error(ERROR_BAD_PIPE) == UV_EPIPE);
#else
Expand Down
6 changes: 6 additions & 0 deletions test/test-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ TEST_DECLARE (spawn_fails)
#ifndef _WIN32
TEST_DECLARE (spawn_fails_check_for_waitpid_cleanup)
#endif
#ifdef _WIN32
TEST_DECLARE (spawn_requires_elevation)
#endif
TEST_DECLARE (spawn_exit_code)
TEST_DECLARE (spawn_stdout)
TEST_DECLARE (spawn_stdin)
Expand Down Expand Up @@ -656,6 +659,9 @@ TASK_LIST_START
TEST_ENTRY (spawn_fails)
#ifndef _WIN32
TEST_ENTRY (spawn_fails_check_for_waitpid_cleanup)
#endif
#ifdef _WIN32
TEST_ENTRY (spawn_requires_elevation)
#endif
TEST_ENTRY (spawn_exit_code)
TEST_ENTRY (spawn_stdout)
Expand Down
46 changes: 46 additions & 0 deletions test/test-spawn.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,52 @@ TEST_IMPL(spawn_fails_check_for_waitpid_cleanup) {
#endif


#ifdef _WIN32
TEST_IMPL(spawn_requires_elevation) {
int r;
uv_fs_t req;
char path[1024];
size_t path_size = 1024;

/* Find helper elevation.exe -- Assumed in same location as test runner */
r = uv_exepath(exepath, &exepath_size);
ASSERT(r == 0);
exepath[exepath_size] = '\0';
snprintf(path, path_size, "%s\\..\\elevation.exe", exepath);
uv_loop_t* loop = uv_default_loop();
ASSERT(0 == uv_fs_realpath(loop, &req, path, NULL));

/*
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
*/
if (req.result == UV_ENOSYS) {
uv_fs_req_cleanup(&req);
RETURN_SKIP("realpath is not supported on Windows XP");
}

ASSERT(req.ptr != NULL);

init_process_options("", fail_cb);
options.file = options.args[0] = req.ptr;

printf("Launching %s\n", (char*) req.ptr);
r = uv_spawn(uv_default_loop(), &process, &options);
printf("r = %d, %s - %s\n", r, uv_err_name(r), uv_strerror(r));

/*
* Will either succeed or fail depending on whether test is being run with
* elevated permissions
*/
ASSERT(r == 0 || r == UV_EACCES);
uv_close((uv_handle_t*) &process, NULL);
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));

MAKE_VALGRIND_HAPPY();
return 0;
}
#endif


TEST_IMPL(spawn_exit_code) {
int r;

Expand Down
25 changes: 23 additions & 2 deletions uv.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@
}],
]
},

{
'target_name': 'run-tests',
'type': 'executable',
Expand Down Expand Up @@ -569,5 +568,27 @@
},
},
},
]
],
'conditions': [
['OS=="win"', {
'targets': [
{
'target_name': 'elevation',
'type': 'executable',
'sources': [
'test/elevation.c'
],
'msvs_settings': {
'VCLinkerTool': {
'UACExecutionLevel': 2, # requireAdministrator
'UACUIAccess': 'false',
},
'VCManifestTool': {
'EmbedManifest': 'true',
}
},
}
],
}],
],
}

0 comments on commit 9004498

Please sign in to comment.