aboutsummaryrefslogtreecommitdiff
path: root/libbutl/win32-utility.hxx
blob: b71eb1ad2ab3e0aeeec37a68289c7526a4cfed6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// file      : libbutl/win32-utility.hxx -*- C++ -*-
// license   : MIT; see accompanying LICENSE file

#pragma once

// Use this header to include <windows.h> and a couple of Win32-specific
// utilities.
//

#ifdef _WIN32

// Try to include <windows.h> so that it doesn't mess other things up.
//
#ifndef WIN32_LEAN_AND_MEAN
#  define WIN32_LEAN_AND_MEAN
#  ifndef NOMINMAX // No min and max macros.
#    define NOMINMAX
#    include <windows.h>
#    undef NOMINMAX
#  else
#    include <windows.h>
#  endif
#  undef WIN32_LEAN_AND_MEAN
#else
#  ifndef NOMINMAX
#    define NOMINMAX
#    include <windows.h>
#    undef NOMINMAX
#  else
#    include <windows.h>
#  endif
#endif

#ifndef __cpp_lib_modules_ts
#include <string>
#else
import std.core;
#endif

#include <libbutl/export.hxx>

namespace butl
{
  namespace win32
  {
    // RAII type for handles. Note that failure to close the handle is
    // silently ignored by both the destructor and reset().
    //
    // The handle can be INVALID_HANDLE_VALUE. Such a handle is treated as
    // unopened and is not closed.
    //
    struct nullhandle_t
    {
      constexpr explicit nullhandle_t (HANDLE) {}
      operator HANDLE () const {return INVALID_HANDLE_VALUE;}
    };

    LIBBUTL_SYMEXPORT extern const nullhandle_t nullhandle;

    class LIBBUTL_SYMEXPORT auto_handle
    {
    public:
      auto_handle (nullhandle_t = nullhandle) noexcept
        : handle_ (INVALID_HANDLE_VALUE) {}

      explicit
      auto_handle (HANDLE h) noexcept: handle_ (h) {}

      auto_handle (auto_handle&& h) noexcept: handle_ (h.release ()) {}
      auto_handle& operator= (auto_handle&&) noexcept;

      auto_handle (const auto_handle&) = delete;
      auto_handle& operator= (const auto_handle&) = delete;

      ~auto_handle () noexcept;

      HANDLE
      get () const noexcept {return handle_;}

      void
      reset (HANDLE h = INVALID_HANDLE_VALUE) noexcept;

      HANDLE
      release () noexcept
      {
        HANDLE r (handle_);
        handle_ = INVALID_HANDLE_VALUE;
        return r;
      }

      // Close an open handle. Throw std::system_error on the underlying OS
      // error. Reset the descriptor to INVALID_HANDLE_VALUE whether the
      // exception is thrown or not.
      //
      void
      close ();

    private:
      HANDLE handle_;
    };

    inline bool
    operator== (const auto_handle& x, const auto_handle& y)
    {
      return x.get () == y.get ();
    }

    inline bool
    operator!= (const auto_handle& x, const auto_handle& y)
    {
      return !(x == y);
    }

    inline bool
    operator== (const auto_handle& x, nullhandle_t)
    {
      return x.get () == INVALID_HANDLE_VALUE;
    }

    inline bool
    operator!= (const auto_handle& x, nullhandle_t y)
    {
      return !(x == y);
    }

    LIBBUTL_SYMEXPORT std::string
    error_msg (DWORD code);

    LIBBUTL_SYMEXPORT std::string
    last_error_msg ();
  }
};

#include <libbutl/win32-utility.ixx>
#endif // _WIN32