[vm/ffi] Improve error messages on Windows

Use `FormatMessageA` to allocate an English description of an error code.
Previously, only the error code itself was shown.

Closes https://github.com/dart-lang/sdk/issues/52790

TEST=tests/ffi/dylib_open_test.dart
Cq-Include-Trybots: luci.dart.try:vm-win-debug-x64-try,vm-win-debug-x64c-try,vm-aot-win-debug-x64c-try,vm-aot-asan-linux-release-x64-try,vm-asan-linux-release-x64-try
Change-Id: Iccae6c763fb16d4bb999b9c260fcfea9c5de276b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/328420
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
Simon Binder 2023-12-20 13:24:16 +00:00 committed by Commit Queue
parent 669060f8c7
commit ada6b81761
2 changed files with 49 additions and 1 deletions

View file

@ -267,7 +267,24 @@ static void GetLastErrorAsString(char** error) {
*error = status != nullptr ? strdup(status) : nullptr;
#elif defined(DART_HOST_OS_WINDOWS)
const int status = GetLastError();
*error = status != 0 ? Utils::SCreate("error code %i", status) : nullptr;
if (status != 0) {
char* description = nullptr;
int length = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, status, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
reinterpret_cast<char*>(&description), 0, nullptr);
if (length == 0) {
// Seems like there is no message for this error code.
*error = Utils::SCreate("error code %i", status);
} else {
*error = Utils::SCreate("%s (error code: %i)", description, status);
}
LocalFree(description);
} else {
*error = nullptr;
}
#else
*error = Utils::StrDup("loading dynamic libraries is not supported");
#endif

View file

@ -0,0 +1,31 @@
// Copyright (c) 2023, 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.
import 'dart:ffi';
import 'dart:io';
import 'package:expect/expect.dart';
import 'dylib_utils.dart';
void main() {
testDoesNotExist();
}
void testDoesNotExist() {
final exception = Expect.throws<ArgumentError>(
() => DynamicLibrary.open(dylibName('doesnotexist1234')));
if (Platform.isWindows) {
Expect.contains(
'The specified module could not be found.', exception.message);
Expect.contains('(error code: 126)', exception.message);
} else if (Platform.isLinux) {
Expect.contains('cannot open shared object file: No such file or directory',
exception.message);
} else if (Platform.isMacOS) {
Expect.contains('libdoesnotexist1234.dylib', exception.message);
Expect.contains('no such file', exception.message);
}
}