Flutter Engine
The Flutter Engine
utils_win.cc
Go to the documentation of this file.
1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "platform/globals.h"
6#if defined(DART_HOST_OS_WINDOWS)
7
8#include <errno.h> // NOLINT
9#include <time.h> // NOLINT
10#include <memory>
11
12#include "bin/utils.h"
13#include "bin/utils_win.h"
14#include "platform/assert.h"
15#include "platform/syslog.h"
16
17namespace dart {
18namespace bin {
19
20// The offset between a `FILETIME` epoch (January 1, 1601 UTC) and a Unix
21// epoch (January 1, 1970 UTC) measured in 100ns intervals.
22//
23// See https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
24static constexpr int64_t kFileTimeEpoch = 116444736000000000LL;
25
26// Although win32 uses 64-bit integers for representing timestamps,
27// these are packed into a FILETIME structure. The FILETIME
28// structure is just a struct representing a 64-bit integer. The
29// TimeStamp union allows access to both a FILETIME and an integer
30// representation of the timestamp. The Windows timestamp is in
31// 100-nanosecond intervals since January 1, 1601.
32union TimeStamp {
33 FILETIME ft_;
34 int64_t t_;
35};
36
37void FormatMessageIntoBuffer(DWORD code, wchar_t* buffer, int buffer_length) {
38 DWORD message_size =
39 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
40 nullptr, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
41 buffer, buffer_length, nullptr);
42 if (message_size == 0) {
43 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
44 Syslog::PrintErr("FormatMessage failed for error code %d (error %d)\n",
46 }
47 _snwprintf(buffer, buffer_length, L"OS Error %d", code);
48 }
49 // Ensure string termination.
50 buffer[buffer_length - 1] = 0;
51}
52
53FILETIME GetFiletimeFromMillis(int64_t millis) {
54 const int64_t kTimeScaler = 10000; // 100 ns to ms.
55 TimeStamp t;
56 t.t_ = millis * kTimeScaler + kFileTimeEpoch;
57 return t.ft_;
58}
59
60OSError::OSError() : sub_system_(kSystem), code_(0), message_(nullptr) {
61 Reload();
62}
63
64void OSError::Reload() {
65 SetCodeAndMessage(kSystem, GetLastError());
66}
67
68void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
69 set_sub_system(sub_system);
70 set_code(code);
71
72 const int kMaxMessageLength = 256;
73 wchar_t message[kMaxMessageLength];
74 FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
75 char* utf8 = StringUtilsWin::WideToUtf8(message);
76 SetMessage(utf8);
77}
78
79char* StringUtils::ConsoleStringToUtf8(char* str,
80 intptr_t len,
81 intptr_t* result_len) {
82 int wide_len = MultiByteToWideChar(CP_ACP, 0, str, len, nullptr, 0);
83 wchar_t* wide;
84 wide =
85 reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(wide_len * sizeof(*wide)));
86 MultiByteToWideChar(CP_ACP, 0, str, len, wide, wide_len);
87 char* utf8 = StringUtilsWin::WideToUtf8(wide, wide_len, result_len);
88 return utf8;
89}
90
91char* StringUtils::Utf8ToConsoleString(char* utf8,
92 intptr_t len,
93 intptr_t* result_len) {
94 intptr_t wide_len;
95 wchar_t* wide = StringUtilsWin::Utf8ToWide(utf8, len, &wide_len);
96 int system_len = WideCharToMultiByte(CP_ACP, 0, wide, wide_len, nullptr, 0,
97 nullptr, nullptr);
98 char* ansi;
99 ansi =
100 reinterpret_cast<char*>(Dart_ScopeAllocate(system_len * sizeof(*ansi)));
101 if (ansi == nullptr) {
102 return nullptr;
103 }
104 WideCharToMultiByte(CP_ACP, 0, wide, wide_len, ansi, system_len, nullptr,
105 nullptr);
106 if (result_len != nullptr) {
107 *result_len = system_len;
108 }
109 return ansi;
110}
111
112char* StringUtilsWin::WideToUtf8(wchar_t* wide,
113 intptr_t len,
114 intptr_t* result_len) {
115 // If len is -1 then WideCharToMultiByte will include the terminating
116 // NUL byte in the length.
117 int utf8_len =
118 WideCharToMultiByte(CP_UTF8, 0, wide, len, nullptr, 0, nullptr, nullptr);
119 char* utf8;
120 utf8 = reinterpret_cast<char*>(Dart_ScopeAllocate(utf8_len * sizeof(*utf8)));
121 WideCharToMultiByte(CP_UTF8, 0, wide, len, utf8, utf8_len, nullptr, nullptr);
122 if (result_len != nullptr) {
123 *result_len = utf8_len;
124 }
125 return utf8;
126}
127
128wchar_t* StringUtilsWin::Utf8ToWide(char* utf8,
129 intptr_t len,
130 intptr_t* result_len) {
131 // If len is -1 then MultiByteToWideChar will include the terminating
132 // NUL byte in the length.
133 int wide_len = MultiByteToWideChar(CP_UTF8, 0, utf8, len, nullptr, 0);
134 wchar_t* wide;
135 wide =
136 reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(wide_len * sizeof(*wide)));
137 MultiByteToWideChar(CP_UTF8, 0, utf8, len, wide, wide_len);
138 if (result_len != nullptr) {
139 *result_len = wide_len;
140 }
141 return wide;
142}
143
144const char* StringUtils::Utf8ToConsoleString(const char* utf8,
145 intptr_t len,
146 intptr_t* result_len) {
147 return const_cast<const char*>(StringUtils::Utf8ToConsoleString(
148 const_cast<char*>(utf8), len, result_len));
149}
150
151const char* StringUtils::ConsoleStringToUtf8(const char* str,
152 intptr_t len,
153 intptr_t* result_len) {
154 return const_cast<const char*>(StringUtils::ConsoleStringToUtf8(
155 const_cast<char*>(str), len, result_len));
156}
157
158const char* StringUtilsWin::WideToUtf8(const wchar_t* wide,
159 intptr_t len,
160 intptr_t* result_len) {
161 return const_cast<const char*>(
162 StringUtilsWin::WideToUtf8(const_cast<wchar_t*>(wide), len, result_len));
163}
164
165const wchar_t* StringUtilsWin::Utf8ToWide(const char* utf8,
166 intptr_t len,
167 intptr_t* result_len) {
168 return const_cast<const wchar_t*>(
169 StringUtilsWin::Utf8ToWide(const_cast<char*>(utf8), len, result_len));
170}
171
172bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
173 wchar_t* command_line = GetCommandLineW();
174 int unicode_argc;
175 wchar_t** unicode_argv = CommandLineToArgvW(command_line, &unicode_argc);
176 if (unicode_argv == nullptr) {
177 return false;
178 }
179 // The argc passed to main should have the same argc as we get here.
180 ASSERT(argc == unicode_argc);
181 if (argc < unicode_argc) {
182 unicode_argc = argc;
183 }
184 for (int i = 0; i < unicode_argc; i++) {
185 wchar_t* arg = unicode_argv[i];
186 int arg_len =
187 WideCharToMultiByte(CP_UTF8, 0, arg, -1, nullptr, 0, nullptr, nullptr);
188 char* utf8_arg = reinterpret_cast<char*>(malloc(arg_len));
189 WideCharToMultiByte(CP_UTF8, 0, arg, -1, utf8_arg, arg_len, nullptr,
190 nullptr);
191 argv[i] = utf8_arg;
192 }
193 LocalFree(unicode_argv);
194 return true;
195}
196
197static int64_t GetCurrentTimeMicros() {
198 const int64_t kTimeScaler = 10; // 100 ns to us.
199
200 TimeStamp time;
201 GetSystemTimeAsFileTime(&time.ft_);
202 return (time.t_ - kFileTimeEpoch) / kTimeScaler;
203}
204
205static int64_t qpc_ticks_per_second = 0;
206
208 LARGE_INTEGER ticks_per_sec;
209 if (!QueryPerformanceFrequency(&ticks_per_sec)) {
210 qpc_ticks_per_second = 0;
211 } else {
212 qpc_ticks_per_second = static_cast<int64_t>(ticks_per_sec.QuadPart);
213 }
214}
215
216int64_t TimerUtils::GetCurrentMonotonicMillis() {
217 return GetCurrentMonotonicMicros() / 1000;
218}
219
220int64_t TimerUtils::GetCurrentMonotonicMicros() {
221 if (qpc_ticks_per_second == 0) {
222 // QueryPerformanceCounter not supported, fallback.
223 return GetCurrentTimeMicros();
224 }
225 // Grab performance counter value.
226 LARGE_INTEGER now;
227 QueryPerformanceCounter(&now);
228 int64_t qpc_value = static_cast<int64_t>(now.QuadPart);
229 // Convert to microseconds.
230 int64_t seconds = qpc_value / qpc_ticks_per_second;
231 int64_t leftover_ticks = qpc_value - (seconds * qpc_ticks_per_second);
232 int64_t result = seconds * kMicrosecondsPerSecond;
233 result += ((leftover_ticks * kMicrosecondsPerSecond) / qpc_ticks_per_second);
234 return result;
235}
236
237void TimerUtils::Sleep(int64_t millis) {
238 ::Sleep(millis);
239}
240
241std::unique_ptr<wchar_t[]> Utf8ToWideChar(const char* path) {
242 int wide_len = MultiByteToWideChar(CP_UTF8, 0, path, -1, nullptr, 0);
243 auto result = std::make_unique<wchar_t[]>(wide_len);
244 MultiByteToWideChar(CP_UTF8, 0, path, -1, result.get(), wide_len);
245 return result;
246}
247
248} // namespace bin
249} // namespace dart
250
251#endif // defined(DART_HOST_OS_WINDOWS)
static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
DART_EXPORT uint8_t * Dart_ScopeAllocate(intptr_t size)
#define ASSERT(E)
GAsyncResult * result
static constexpr int kMicrosecondsPerSecond
Win32Message message
char ** argv
Definition: library.h:9
std::unique_ptr< wchar_t[]> Utf8ToWideChar(const char *path)
FILETIME GetFiletimeFromMillis(int64_t millis)
void FormatMessageIntoBuffer(DWORD code, wchar_t *buffer, int buffer_length)
bool InitOnce(char **error)
Definition: dart_vm.cc:33
void * malloc(size_t size)
Definition: allocation.cc:19
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
static double time(int loops, Benchmark *bench, Target *target)
Definition: nanobench.cpp:394
struct _FILETIME FILETIME
WINBASEAPI _Check_return_ _Post_equals_last_error_ DWORD WINAPI GetLastError(VOID)
unsigned long DWORD
Definition: windows_types.h:22