diff --git a/src/elevator_init.cpp b/src/elevator_init.cpp index 4ced3f69..b16ed356 100644 --- a/src/elevator_init.cpp +++ b/src/elevator_init.cpp @@ -29,13 +29,13 @@ NAN_METHOD(Elevate) { return Nan::ThrowError("Callback must be a function"); } - std::vector arguments = + std::vector arguments = etcher::v8utils::GetArguments(info[0].As()); v8::Local callback = info[1].As(); etcher::ELEVATE_RESULT result = etcher::Elevate( arguments.front(), - std::vector(arguments.begin() + 1, arguments.end())); + std::vector(arguments.begin() + 1, arguments.end())); // Create results object v8::Isolate *isolate = v8::Isolate::GetCurrent(); @@ -51,8 +51,7 @@ NAN_METHOD(Elevate) { YIELD_OBJECT(callback, results); break; default: - std::string details = etcher::ElevateResultToString(result); - YIELD_ERROR(callback, details.c_str()); + YIELD_ERROR(callback, etcher::ElevateResultToString(result)); } } diff --git a/src/os/elevate.h b/src/os/elevate.h index abe79b57..fb7fd3ee 100644 --- a/src/os/elevate.h +++ b/src/os/elevate.h @@ -53,10 +53,10 @@ enum class ELEVATE_RESULT { ELEVATE_UNKNOWN_ERROR }; -ELEVATE_RESULT Elevate(const std::string &command, - std::vector arguments); +ELEVATE_RESULT Elevate(const std::wstring &command, + std::vector arguments); -std::string ElevateResultToString(const ELEVATE_RESULT &result); +std::wstring ElevateResultToString(const ELEVATE_RESULT &result); } // namespace etcher diff --git a/src/os/win32/elevate.cpp b/src/os/win32/elevate.cpp index b7af2764..1a7483aa 100644 --- a/src/os/win32/elevate.cpp +++ b/src/os/win32/elevate.cpp @@ -16,11 +16,11 @@ #include "os/elevate.h" -static std::string JoinArguments(std::vector arguments) { - std::ostringstream result; +static std::wstring JoinArguments(std::vector arguments) { + std::wostringstream result; std::copy(arguments.begin(), arguments.end(), - std::ostream_iterator(result, " ")); + std::ostream_iterator(result, L" ")); return result.str(); } @@ -28,22 +28,22 @@ static std::string JoinArguments(std::vector arguments) { // Make sure to delete the result after you're done // with it by calling `delete[] result;`. // See http://stackoverflow.com/a/1201471 -static LPCTSTR ConvertStringToLPCTSTR(const std::string &string) { - char *result = new char[string.size() + 1]; +static LPCWSTR ConvertStringToLPCWSTR(const std::wstring &string) { + wchar_t *result = new wchar_t[string.size() + 1]; std::copy(string.begin(), string.end(), result); result[string.size()] = 0; return result; } -etcher::ELEVATE_RESULT etcher::Elevate(const std::string &command, - std::vector arguments) { +etcher::ELEVATE_RESULT etcher::Elevate(const std::wstring &command, + std::vector arguments) { // Initialize the SHELLEXECUTEINFO structure. We zero it out // in order to be on the safe side, and set cbSize to the size // of the structure as recommend by MSDN // See: https://msdn.microsoft.com/en-us/library/windows/desktop/bb759784(v=vs.85).aspx - SHELLEXECUTEINFO shellExecuteInfo; + SHELLEXECUTEINFOW shellExecuteInfo; ZeroMemory(&shellExecuteInfo, sizeof(shellExecuteInfo)); - shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO); + shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFOW); // Flags that indicate the content and validity of the other structure member. shellExecuteInfo.fMask = @@ -60,7 +60,7 @@ etcher::ELEVATE_RESULT etcher::Elevate(const std::string &command, SEE_MASK_FLAG_NO_UI; // The action to be performed. - shellExecuteInfo.lpVerb = TEXT("runas"); + shellExecuteInfo.lpVerb = L"runas"; // Run the file in the background shellExecuteInfo.nShow = SW_HIDE; @@ -70,14 +70,14 @@ etcher::ELEVATE_RESULT etcher::Elevate(const std::string &command, // Set file and parameters // We can't just assign the result of `.c_str()`, since - // that pointer is owned by the `std::string` instance, + // that pointer is owned by the `std::wstring` instance, // and will not be safe after the instance is destroyed. - LPCTSTR file = ConvertStringToLPCTSTR(command); - LPCTSTR argv = ConvertStringToLPCTSTR(JoinArguments(arguments)); + LPCWSTR file = ConvertStringToLPCWSTR(command); + LPCWSTR argv = ConvertStringToLPCWSTR(JoinArguments(arguments)); shellExecuteInfo.lpFile = file; shellExecuteInfo.lpParameters = argv; - BOOL executeResult = ShellExecuteEx(&shellExecuteInfo); + BOOL executeResult = ShellExecuteExW(&shellExecuteInfo); delete[] file; delete[] argv; @@ -127,32 +127,32 @@ etcher::ELEVATE_RESULT etcher::Elevate(const std::string &command, return etcher::ELEVATE_RESULT::ELEVATE_SUCCESS; } -std::string +std::wstring etcher::ElevateResultToString(const etcher::ELEVATE_RESULT &result) { switch (result) { case etcher::ELEVATE_RESULT::ELEVATE_SUCCESS: - return "Success"; + return L"Success"; case etcher::ELEVATE_RESULT::ELEVATE_CANCELLED: - return "The user cancelled the elevation request"; + return L"The user cancelled the elevation request"; case etcher::ELEVATE_RESULT::ELEVATE_FILE_NOT_FOUND: - return "The specified file was not found"; + return L"The specified file was not found"; case etcher::ELEVATE_RESULT::ELEVATE_PATH_NOT_FOUND: - return "The specified path was not found"; + return L"The specified path was not found"; case etcher::ELEVATE_RESULT::ELEVATE_DDE_FAIL: - return "The Dynamic Data Exchange (DDE) transaction failed"; + return L"The Dynamic Data Exchange (DDE) transaction failed"; case etcher::ELEVATE_RESULT::ELEVATE_NO_ASSOCIATION: - return "There is no application associated with the " - "specified file name extension"; + return L"There is no application associated with the " + "specified file name extension"; case etcher::ELEVATE_RESULT::ELEVATE_ACCESS_DENIED: - return "Access to the specified file is denied"; + return L"Access to the specified file is denied"; case etcher::ELEVATE_RESULT::ELEVATE_DLL_NOT_FOUND: - return "One of the library files necessary to run the " - "application can't be found"; + return L"One of the library files necessary to run the " + "application can't be found"; case etcher::ELEVATE_RESULT::ELEVATE_NOT_ENOUGH_MEMORY: - return "There is not enough memory to perform the specified action"; + return L"There is not enough memory to perform the specified action"; case etcher::ELEVATE_RESULT::ELEVATE_SHARING_VIOLATION: - return "A sharing violation occurred"; + return L"A sharing violation occurred"; default: - return "Unknown error"; + return L"Unknown error"; } } diff --git a/src/utils/v8utils.cpp b/src/utils/v8utils.cpp index 78774895..6bca61b7 100644 --- a/src/utils/v8utils.cpp +++ b/src/utils/v8utils.cpp @@ -16,14 +16,17 @@ #include "utils/v8utils.h" -std::vector +std::vector etcher::v8utils::GetArguments(v8::Local arguments) { - std::vector result(0); + std::vector result(0); for (uint32_t index = 0; index < arguments->Length(); index++) { - std::string argument( + // See https://stackoverflow.com/q/15615136/1641422 + std::string stringArgument( *v8::String::Utf8Value(arguments->Get(index)->ToString())); - result.push_back(argument); + std::wstring_convert> conversion; + + result.push_back(conversion.from_bytes(stringArgument)); } return result; diff --git a/src/utils/v8utils.h b/src/utils/v8utils.h index 0cc2091f..6807a1c7 100644 --- a/src/utils/v8utils.h +++ b/src/utils/v8utils.h @@ -20,18 +20,23 @@ #include #include #include +#include namespace etcher { namespace v8utils { -std::vector GetArguments(v8::Local arguments); +std::vector GetArguments(v8::Local arguments); } // namespace v8utils } // namespace etcher #define YIELD_ERROR(CALLBACK, ERROR) \ { \ - v8::Local argv[1] = {Nan::Error((ERROR))}; \ - Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (CALLBACK), 1, \ - argv); \ + const wchar_t *message = (ERROR).c_str(); \ + v8::Local argv[1] = { \ + Nan::Error(v8::String::NewFromTwoByte(isolate, \ + (const uint16_t *)message)) \ + }; \ + Nan::MakeCallback(Nan::GetCurrentContext()->Global(), (CALLBACK), \ + 1, argv); \ } \ return;