Files
sdk/runtime/bin/utils_win.cc
T
Zachary Anderson b990bc3794 Fix native extension lookup
This CL allows native extension lookup to defer to the platform's
library lookup (e.g. dlopen) when the library cannot be found next to
the importing Dart library. It also allows dart-ext: to accept an
absolute path to the native library.

R=asiva@google.com

Review URL: https://codereview.chromium.org/2285223003 .
2016-08-30 09:31:47 -07:00

269 lines
7.9 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/globals.h"
#if defined(TARGET_OS_WINDOWS)
#include <errno.h> // NOLINT
#include <time.h> // NOLINT
#include "bin/log.h"
#include "bin/utils.h"
#include "bin/utils_win.h"
#include "platform/assert.h"
namespace dart {
namespace bin {
void FormatMessageIntoBuffer(DWORD code, wchar_t* buffer, int buffer_length) {
DWORD message_size =
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buffer,
buffer_length,
NULL);
if (message_size == 0) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
Log::PrintErr("FormatMessage failed for error code %d (error %d)\n",
code,
GetLastError());
}
_snwprintf(buffer, buffer_length, L"OS Error %d", code);
}
// Ensure string termination.
buffer[buffer_length - 1] = 0;
}
OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
set_code(GetLastError());
static const int kMaxMessageLength = 256;
wchar_t message[kMaxMessageLength];
FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
char* utf8 = StringUtilsWin::WideToUtf8(message);
SetMessage(utf8);
}
void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
set_sub_system(sub_system);
set_code(code);
static const int kMaxMessageLength = 256;
wchar_t message[kMaxMessageLength];
FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
char* utf8 = StringUtilsWin::WideToUtf8(message);
SetMessage(utf8);
}
char* StringUtils::ConsoleStringToUtf8(char* str,
intptr_t len,
intptr_t* result_len) {
int wide_len = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0);
wchar_t* wide;
wide =
reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(wide_len * sizeof(*wide)));
MultiByteToWideChar(CP_ACP, 0, str, len, wide, wide_len);
char* utf8 = StringUtilsWin::WideToUtf8(wide, wide_len, result_len);
return utf8;
}
char* StringUtils::Utf8ToConsoleString(char* utf8,
intptr_t len,
intptr_t* result_len) {
intptr_t wide_len;
wchar_t* wide = StringUtilsWin::Utf8ToWide(utf8, len, &wide_len);
int system_len = WideCharToMultiByte(
CP_ACP, 0, wide, wide_len, NULL, 0, NULL, NULL);
char* ansi;
ansi =
reinterpret_cast<char*>(Dart_ScopeAllocate(system_len * sizeof(*ansi)));
if (ansi == NULL) {
return NULL;
}
WideCharToMultiByte(CP_ACP, 0, wide, wide_len, ansi, system_len, NULL, NULL);
if (result_len != NULL) {
*result_len = system_len;
}
return ansi;
}
char* StringUtilsWin::WideToUtf8(wchar_t* wide,
intptr_t len,
intptr_t* result_len) {
// If len is -1 then WideCharToMultiByte will include the terminating
// NUL byte in the length.
int utf8_len = WideCharToMultiByte(
CP_UTF8, 0, wide, len, NULL, 0, NULL, NULL);
char* utf8;
utf8 = reinterpret_cast<char*>(Dart_ScopeAllocate(utf8_len * sizeof(*utf8)));
WideCharToMultiByte(CP_UTF8, 0, wide, len, utf8, utf8_len, NULL, NULL);
if (result_len != NULL) {
*result_len = utf8_len;
}
return utf8;
}
wchar_t* StringUtilsWin::Utf8ToWide(char* utf8,
intptr_t len,
intptr_t* result_len) {
// If len is -1 then MultiByteToWideChar will include the terminating
// NUL byte in the length.
int wide_len = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
wchar_t* wide;
wide =
reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(wide_len * sizeof(*wide)));
MultiByteToWideChar(CP_UTF8, 0, utf8, len, wide, wide_len);
if (result_len != NULL) {
*result_len = wide_len;
}
return wide;
}
const char* StringUtils::Utf8ToConsoleString(
const char* utf8, intptr_t len, intptr_t* result_len) {
return const_cast<const char*>(
StringUtils::Utf8ToConsoleString(
const_cast<char*>(utf8), len, result_len));
}
const char* StringUtils::ConsoleStringToUtf8(
const char* str, intptr_t len, intptr_t* result_len) {
return const_cast<const char*>(
StringUtils::ConsoleStringToUtf8(
const_cast<char*>(str), len, result_len));
}
const char* StringUtilsWin::WideToUtf8(
const wchar_t* wide, intptr_t len, intptr_t* result_len) {
return const_cast<const char*>(
StringUtilsWin::WideToUtf8(const_cast<wchar_t*>(wide), len, result_len));
}
const wchar_t* StringUtilsWin::Utf8ToWide(
const char* utf8, intptr_t len, intptr_t* result_len) {
return const_cast<const wchar_t*>(
StringUtilsWin::Utf8ToWide(const_cast<char*>(utf8), len, result_len));
}
char* StringUtils::StrNDup(const char* s, intptr_t n) {
intptr_t len = strlen(s);
if ((n < 0) || (len < 0)) {
return NULL;
}
if (n < len) {
len = n;
}
char* result = reinterpret_cast<char*>(malloc(len + 1));
if (result == NULL) {
return NULL;
}
result[len] = '\0';
return reinterpret_cast<char*>(memmove(result, s, len));
}
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
wchar_t* command_line = GetCommandLineW();
int unicode_argc;
wchar_t** unicode_argv = CommandLineToArgvW(command_line, &unicode_argc);
if (unicode_argv == NULL) {
return false;
}
// The argc passed to main should have the same argc as we get here.
ASSERT(argc == unicode_argc);
if (argc < unicode_argc) {
unicode_argc = argc;
}
for (int i = 0; i < unicode_argc; i++) {
wchar_t* arg = unicode_argv[i];
int arg_len =
WideCharToMultiByte(CP_UTF8, 0, arg, -1, NULL, 0, NULL, NULL);
char* utf8_arg = reinterpret_cast<char*>(malloc(arg_len));
WideCharToMultiByte(CP_UTF8, 0, arg, -1, utf8_arg, arg_len, NULL, NULL);
argv[i] = utf8_arg;
}
LocalFree(unicode_argv);
return true;
}
// Although win32 uses 64-bit integers for representing timestamps,
// these are packed into a FILETIME structure. The FILETIME
// structure is just a struct representing a 64-bit integer. The
// TimeStamp union allows access to both a FILETIME and an integer
// representation of the timestamp. The Windows timestamp is in
// 100-nanosecond intervals since January 1, 1601.
union TimeStamp {
FILETIME ft_;
int64_t t_;
};
static int64_t GetCurrentTimeMicros() {
static const int64_t kTimeEpoc = 116444736000000000LL;
static const int64_t kTimeScaler = 10; // 100 ns to us.
TimeStamp time;
GetSystemTimeAsFileTime(&time.ft_);
return (time.t_ - kTimeEpoc) / kTimeScaler;
}
static int64_t qpc_ticks_per_second = 0;
void TimerUtils::InitOnce() {
LARGE_INTEGER ticks_per_sec;
if (!QueryPerformanceFrequency(&ticks_per_sec)) {
qpc_ticks_per_second = 0;
} else {
qpc_ticks_per_second = static_cast<int64_t>(ticks_per_sec.QuadPart);
}
}
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
int64_t TimerUtils::GetCurrentMonotonicMicros() {
if (qpc_ticks_per_second == 0) {
// QueryPerformanceCounter not supported, fallback.
return GetCurrentTimeMicros();
}
// Grab performance counter value.
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
int64_t qpc_value = static_cast<int64_t>(now.QuadPart);
// Convert to microseconds.
int64_t seconds = qpc_value / qpc_ticks_per_second;
int64_t leftover_ticks = qpc_value - (seconds * qpc_ticks_per_second);
int64_t result = seconds * kMicrosecondsPerSecond;
result += ((leftover_ticks * kMicrosecondsPerSecond) / qpc_ticks_per_second);
return result;
}
void TimerUtils::Sleep(int64_t millis) {
::Sleep(millis);
}
} // namespace bin
} // namespace dart
#endif // defined(TARGET_OS_WINDOWS)