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