Apache Mesos
error.hpp
Go to the documentation of this file.
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef __STOUT_WINDOWS_ERROR_HPP__
18 #define __STOUT_WINDOWS_ERROR_HPP__
19 
20 #include <stout/error.hpp>
21 #include <stout/windows.hpp>
22 #include <stout/stringify.hpp>
23 
24 
25 // A useful type that can be used to represent a Try that has failed. This is a
26 // lot like `ErrnoError`, except instead of wrapping an error coming from the C
27 // standard libraries, it wraps an error coming from the Windows APIs.
28 class WindowsErrorBase : public Error
29 {
30 public:
31  const DWORD code;
32 
33 protected:
34  explicit WindowsErrorBase(DWORD _code)
35  : Error(get_last_error_as_string(_code)), code(_code) {}
36 
37  WindowsErrorBase(DWORD _code, const std::string& message)
38  : Error(message + ": " + get_last_error_as_string(_code)), code(_code) {}
39 
40 private:
41  static std::string get_last_error_as_string(DWORD errorCode)
42  {
43  // Default if no error.
44  if (errorCode == 0) {
45  return std::string();
46  }
47 
48  DWORD allocate_message_buffer =
49  FORMAT_MESSAGE_ALLOCATE_BUFFER |
50  FORMAT_MESSAGE_FROM_SYSTEM |
51  FORMAT_MESSAGE_IGNORE_INSERTS;
52 
53  DWORD default_language = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
54 
55  // This following function `FormatMessage` is a lot like `strerror`, except
56  // it pretty-prints errors from the Windows API instead of from the C
57  // standard library. Basically, the semantics are: we pass in `errorCode`,
58  // and it allocates room for a pretty-printed error message at
59  // `message_buffer`, and then dumps said pretty-printed error message at
60  // that address, in our `default_language`.
61  //
62  // The 5th actual parameter (namely `(LPWSTR)&message_buffer`), may look
63  // strange to readers of this code. It is copied directly out of the
64  // documentation[1], and is unfortunately required to get the
65  // pretty-printed error message. The short story is:
66  //
67  // * The flag `FORMAT_MESSAGE_ALLOCATE_BUFFER` tells `FormatMessage` to
68  // point `message_buffer` (which is an `LPWSTR` a.k.a. `char*`) at a
69  // string error message. But, `message_buffer` to point a `char*` at a
70  // different place, `FormatMessage` would need the address
71  // `&message_buffer` so that it could change where it is pointing.
72  // * So, to solve this problem, the API writers decided that when you
73  // pass that flag in, `FormatMessage` will treat the 5th parameter not
74  // as `LPWSTR` (which is what the type is in the function signagure),
75  // but as `LPWSTR*` a.k.a. `char**`, which (assuming you've casted the
76  // parameter correctly) allows it to allocate the message on your
77  // behalf, and change `message_buffer` to point at this new error
78  // string.
79  // * This is why we need this strange cast that you see below.
80  //
81  // Finally, and this is important: it is up to the user to free the memory
82  // with `LocalFree`! The line below where we do this comes directly from
83  // the documentation as well.
84  //
85  // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx
86  wchar_t *message_buffer = nullptr;
87  size_t size = ::FormatMessageW(
88  allocate_message_buffer,
89  nullptr, // Ignored.
90  errorCode,
91  default_language,
92  (LPWSTR)&message_buffer, // See comment above about quirky cast.
93  0, // Ignored.
94  nullptr); // Ignored.
95 
96  std::wstring message(message_buffer, size);
97 
98  // Required per documentation above.
99  ::LocalFree(message_buffer);
100 
101  return stringify(message);
102  }
103 };
104 
105 
107 public:
108  WindowsError() : WindowsErrorBase(::GetLastError()) {}
109 
110  explicit WindowsError(DWORD _code) : WindowsErrorBase(_code) {}
111 
112  WindowsError(const std::string& message)
113  : WindowsErrorBase(::GetLastError(), message) {}
114 
115  WindowsError(DWORD _code, const std::string& message)
116  : WindowsErrorBase(_code, message) {}
117 };
118 
119 
121 public:
122  WindowsSocketError() : WindowsErrorBase(::WSAGetLastError()) {}
123 
124  explicit WindowsSocketError(DWORD _code) : WindowsErrorBase(_code) {}
125 
126  WindowsSocketError(const std::string& message)
127  : WindowsErrorBase(::WSAGetLastError(), message) {}
128 
129  WindowsSocketError(DWORD _code, const std::string& message)
130  : WindowsErrorBase(_code, message) {}
131 };
132 
133 #endif // __STOUT_WINDOWS_ERROR_HPP__
Definition: errorbase.hpp:35
Try< Bytes > size(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:100
WindowsErrorBase(DWORD _code, const std::string &message)
Definition: error.hpp:37
WindowsError(DWORD _code, const std::string &message)
Definition: error.hpp:115
WindowsSocketError()
Definition: error.hpp:122
Definition: error.hpp:120
Definition: error.hpp:106
WindowsError(DWORD _code)
Definition: error.hpp:110
const DWORD code
Definition: error.hpp:31
WindowsSocketError(DWORD _code)
Definition: error.hpp:124
WindowsSocketError(DWORD _code, const std::string &message)
Definition: error.hpp:129
Definition: error.hpp:28
WindowsSocketError(const std::string &message)
Definition: error.hpp:126
WindowsError()
Definition: error.hpp:108
const std::string message
Definition: errorbase.hpp:45
WindowsError(const std::string &message)
Definition: error.hpp:112
WindowsErrorBase(DWORD _code)
Definition: error.hpp:34
std::string stringify(int flags)