]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentracing-cpp/src/dynamic_load_windows.cpp
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / opentracing-cpp / src / dynamic_load_windows.cpp
1 #include <opentracing/dynamic_load.h>
2 #include <opentracing/version.h>
3
4 #include <windows.h>
5
6 namespace opentracing {
7 BEGIN_OPENTRACING_ABI_NAMESPACE
8 // Returns the last Win32 error, in string format. Returns an empty string if
9 // there is no error.
10 //
11 // Taken from https://stackoverflow.com/a/17387176/4447365
12 static std::string GetLastErrorAsString() {
13 // Get the error message, if any.
14 DWORD errorMessageID = ::GetLastError();
15 if (errorMessageID == 0)
16 return std::string(); // No error message has been recorded
17
18 LPSTR messageBuffer = nullptr;
19 size_t size = FormatMessageA(
20 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
21 FORMAT_MESSAGE_IGNORE_INSERTS,
22 NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
23 (LPSTR)&messageBuffer, 0, NULL);
24
25 std::string message(messageBuffer, size);
26
27 // Free the buffer.
28 LocalFree(messageBuffer);
29
30 return message;
31 }
32
33 namespace {
34 class DynamicLibraryHandleWindows : public DynamicLibraryHandle {
35 public:
36 explicit DynamicLibraryHandleWindows(HINSTANCE handle) : handle_{handle} {}
37
38 ~DynamicLibraryHandleWindows() override { FreeLibrary(handle_); }
39
40 private:
41 HINSTANCE handle_;
42 };
43 } // namespace
44
45 expected<DynamicTracingLibraryHandle> DynamicallyLoadTracingLibrary(
46 const char* shared_library, std::string& error_message) noexcept try {
47 const auto handle = LoadLibrary(shared_library);
48 if (handle == nullptr) {
49 error_message = "An error occurred: " + GetLastErrorAsString();
50 return make_unexpected(dynamic_load_failure_error);
51 }
52
53 std::unique_ptr<DynamicLibraryHandle> dynamic_library_handle{
54 new DynamicLibraryHandleWindows{handle}};
55
56 const auto make_tracer_factory =
57 reinterpret_cast<OpenTracingMakeTracerFactoryType**>(
58 GetProcAddress(handle, "OpenTracingMakeTracerFactory"));
59
60 if (make_tracer_factory == nullptr) {
61 error_message =
62 "An error occurred while looking up for OpenTracingMakeTracerFactory "
63 ": " +
64 GetLastErrorAsString();
65 return make_unexpected(dynamic_load_failure_error);
66 }
67
68 if (*make_tracer_factory == nullptr) {
69 error_message =
70 "An error occurred while looking up for OpenTracingMakeTracerFactory. "
71 "It seems that it was set to nullptr.";
72 return make_unexpected(dynamic_load_failure_error);
73 }
74
75 const void* error_category = nullptr;
76 void* tracer_factory = nullptr;
77 const auto rcode = (*make_tracer_factory)(
78 OPENTRACING_VERSION, OPENTRACING_ABI_VERSION, &error_category,
79 static_cast<void*>(&error_message), &tracer_factory);
80 if (rcode != 0) {
81 if (error_category == nullptr) {
82 error_message = "failed to construct a TracerFactory: unknown error code";
83 return make_unexpected(dynamic_load_failure_error);
84 }
85 const auto error_code = std::error_code{
86 rcode, *static_cast<const std::error_category*>(error_category)};
87 if (error_message.empty()) {
88 error_message = error_code.message();
89 }
90 return make_unexpected(error_code);
91 }
92
93 if (tracer_factory == nullptr) {
94 error_message =
95 "failed to construct a TracerFactory: `tracer_factory` is null";
96 return make_unexpected(dynamic_load_failure_error);
97 }
98
99 return DynamicTracingLibraryHandle{
100 std::unique_ptr<const TracerFactory>{
101 static_cast<TracerFactory*>(tracer_factory)},
102 std::move(dynamic_library_handle)};
103 } catch (const std::bad_alloc&) {
104 return make_unexpected(std::make_error_code(std::errc::not_enough_memory));
105 }
106 END_OPENTRACING_ABI_NAMESPACE
107 } // namespace opentracing