18
18
#endif
19
19
20
20
namespace ntl {
21
- class device {
22
- friend class device_dispatch_invoker;
21
+ namespace device_control {
22
+ struct code {
23
+ code(ULONG code) : value(code) {}
24
+
25
+ auto device_type() const { return DEVICE_TYPE_FROM_CTL_CODE(value); }
26
+ auto method() const { return METHOD_FROM_CTL_CODE(value); }
27
+ auto function() const { return IoGetFunctionCodeFromCtlCode(value); }
28
+ bool operator==(const code &rhs) const { return value == rhs.value; }
29
+ bool operator==(ULONG rhs) const { return value == rhs; }
30
+ bool operator==(int rhs) const { return value == static_cast<ULONG>(rhs); }
31
+
32
+ ULONG value;
33
+ };
34
+
35
+ struct in_buffer {
36
+ in_buffer(const void *ptr, size_t size) : ptr(ptr), size(size) {}
37
+ const void *ptr;
38
+ size_t size;
39
+ };
40
+
41
+ struct out_buffer {
42
+ out_buffer(void *ptr, size_t size) : ptr(ptr), size(size) {}
43
+ void *ptr;
44
+ size_t size;
45
+ };
46
+
47
+ using dispatch_fn = std::function<void(const device_control::code &,
48
+ const device_control::in_buffer &,
49
+ device_control::out_buffer &)>;
50
+ } // namespace device_control
51
+ } // namespace ntl
52
+
53
+ namespace ntl {
54
+ namespace detail {
55
+ namespace device {
56
+ struct dispatchers_t {
57
+ device_control::dispatch_fn on_device_control;
58
+ };
59
+
60
+ template <typename Extension> struct extension_data_t;
61
+
62
+ template <> struct extension_data_t<void> { dispatchers_t dispatchers; };
23
63
64
+ template <typename Extension> struct extension_data_t {
65
+ dispatchers_t dispatchers;
66
+ Extension data;
67
+ };
68
+
69
+ template <typename T> class extension_t;
70
+
71
+ template <> class extension_t<void> {
24
72
public:
25
- using on_device_control_fn = std::function<void(uint32_t, const uint8_t *,
26
- size_t, uint8_t *, size_t *)>;
73
+ extension_t() : device_(nullptr) {}
74
+ extension_t(PDEVICE_OBJECT device) : device_(device) {}
75
+
76
+ extension_data_t<void> *get_context() {
77
+ return reinterpret_cast<extension_data_t<void> *>(device_->DeviceExtension);
78
+ }
27
79
28
80
private:
29
- friend class driver;
81
+ PDEVICE_OBJECT device_;
82
+ };
30
83
31
- struct context_base {
32
- context_base(const std::type_info &type) : type(type) {}
33
- const std::type_info &type;
34
- on_device_control_fn on_device_control;
35
- };
84
+ template <typename Extension> class extension_t {
85
+ public:
86
+ extension_t() : device_(nullptr) {}
87
+ extension_t(PDEVICE_OBJECT device) : device_(device) {}
36
88
37
- template <typename T> class context;
89
+ extension_data_t<Extension> *get_context() {
90
+ return reinterpret_cast<extension_data_t<Extension> *>(
91
+ device_->DeviceExtension);
92
+ }
38
93
39
- template <> struct context<void> : public context_base {
40
- context() : context_base(typeid(void)) {}
41
- };
94
+ Extension &extension() { return get_context()->data; }
42
95
43
- template <typename T> struct context : public context_base {
44
- context() : context_base(typeid(T)) {}
45
- T data;
46
- };
96
+ private:
97
+ PDEVICE_OBJECT device_;
98
+ };
99
+ } // namespace device
100
+ } // namespace detail
101
+
102
+ using device_type = DEVICE_TYPE;
103
+
104
+ class device_options {
105
+ friend class driver;
47
106
48
107
public:
49
- using type_t = DEVICE_TYPE;
108
+ device_options() : type_(FILE_DEVICE_UNKNOWN), exclusive_(false) {}
50
109
51
- class options {
52
- friend class driver;
53
- friend class device;
110
+ device_options &name(const std::wstring &name) {
111
+ name_ = name;
112
+ return *this;
113
+ }
114
+ device_options &type(device_type type) {
115
+ type_ = type;
116
+ return *this;
117
+ }
118
+ device_options &exclusive(bool exclusive = true) {
119
+ exclusive_ = exclusive;
120
+ return *this;
121
+ }
54
122
55
- public:
56
- options() : type_(FILE_DEVICE_UNKNOWN), exclusive_(false) {}
123
+ const std::wstring &name() const { return name_; }
124
+ device_type type() const { return type_; }
125
+ bool is_exclusive() const { return exclusive_; }
57
126
58
- options &name(const std::wstring &name) {
59
- name_ = name;
60
- return *this;
61
- }
62
- options &type(type_t type) {
63
- type_ = type;
64
- return *this;
65
- }
66
- options &exclusive(bool exclusive = true) {
67
- exclusive_ = exclusive;
68
- return *this;
69
- }
127
+ private:
128
+ std::wstring name_;
129
+ device_type type_;
130
+ bool exclusive_;
131
+ };
70
132
71
- private:
72
- bool exclusive_;
73
- std::wstring name_;
74
- type_t type_;
75
- };
133
+ template <typename Extension>
134
+ class device : public detail::device::extension_t<Extension> {
135
+ friend class device_dispatch_invoker;
136
+ friend class driver;
76
137
77
138
protected:
78
- device(PDEVICE_OBJECT device, const options &opts,
79
- std::function<void()> finalizer)
80
- : object_(device), name_(opts.name_), finalizer_(finalizer ) {}
139
+ device(PDEVICE_OBJECT device, const device_options &opts)
140
+ : detail::device::extension_t<Extension>(device), object_(device),
141
+ name_(opts.name() ) {}
81
142
82
143
private:
83
144
device(const device &) = delete;
84
145
85
146
public:
86
147
device() : object_(nullptr) {}
87
148
88
- device(device &&other) { *this = std::move(other); }
149
+ device(device &&other)
150
+ : detail::device::extension_t<Extension>(other.object_) {
151
+ *this = std::move(other);
152
+ }
89
153
90
154
device &operator=(device &&rhs) {
91
155
object_ = rhs.detach();
92
156
name_.swap(rhs.name_);
93
- finalizer_ = std::move(rhs.finalizer_);
94
157
return *this;
95
158
}
96
159
97
160
~device() {
98
161
auto obj = detach();
99
162
if (obj) {
100
- if (finalizer_)
101
- finalizer_();
163
+ if (obj->DeviceExtension)
164
+ detail::device::extension_t<Extension>::get_context()
165
+ ->~extension_data_t();
102
166
IoDeleteDevice(obj);
103
167
}
104
168
}
105
169
106
- private :
107
- template <typename Extension> context<Extension> *get_context () {
108
- return reinterpret_cast<context< Extension> *>(object_->DeviceExtension) ;
170
+ protected :
171
+ detail::device::dispatchers_t &dispatchers () {
172
+ return detail::device::extension_t< Extension>::get_context()->dispatchers ;
109
173
}
110
174
111
175
public:
112
- template <typename Extension> Extension &extension() {
113
- auto ext = get_context<Extension>();
114
- if (ext->type != typeid(Extension))
115
- throw std::runtime_error("bad type");
116
- return ext->data;
117
- }
118
-
119
- device &on_device_control(on_device_control_fn &&f) {
120
- get_context<void>()->on_device_control = f;
176
+ device &on_device_control(device_control::dispatch_fn &&f) {
177
+ dispatchers().on_device_control = f;
121
178
return *this;
122
179
}
123
180
@@ -127,7 +184,7 @@ public:
127
184
return name_;
128
185
}
129
186
130
- type_t type() const {
187
+ device_type type() const {
131
188
if (!object_)
132
189
throw std::runtime_error("invalid device object.");
133
190
return object_->DeviceType;
@@ -141,6 +198,5 @@ public:
141
198
private:
142
199
PDEVICE_OBJECT object_;
143
200
std::wstring name_;
144
- std::function<void()> finalizer_;
145
201
};
146
202
} // namespace ntl
0 commit comments