Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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",
45 code, GetLastError());
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
207void TimerUtils::InitOnce() {
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)
static const uint8_t buffer[]
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)
void * malloc(size_t size)
Definition allocation.cc:19
struct _FILETIME FILETIME
WINBASEAPI _Check_return_ _Post_equals_last_error_ DWORD WINAPI GetLastError(VOID)
unsigned long DWORD