summaryrefslogtreecommitdiff
path: root/common/rawaccel-io.hpp
blob: 7f553925d3cb7cbbe9f99e0aa41188b4bdacd67c (plain) (blame)
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
#pragma once

#include <system_error>

#define NOMINMAX
#include <Windows.h>

#include "rawaccel.hpp"

#define RA_READ CTL_CODE(0x8888, 0x888, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define RA_WRITE CTL_CODE(0x8888, 0x889, METHOD_BUFFERED, FILE_ANY_ACCESS)

#pragma warning(push)
#pragma warning(disable:4245) // int -> DWORD conversion while passing CTL_CODE

namespace rawaccel {

	mouse_modifier read() {
		HANDLE ra_handle = INVALID_HANDLE_VALUE;

		ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0);

		if (ra_handle == INVALID_HANDLE_VALUE) {
			throw install_error();
		}

		mouse_modifier mod;
		DWORD dummy;

		BOOL success = DeviceIoControl(
			ra_handle,
			RA_READ,
			NULL,					  // input buffer
			0,                        // input buffer size
			&mod,                     // output buffer
			sizeof(mouse_modifier),   // output buffer size
			&dummy,                   // bytes returned
			NULL                      // overlapped structure
		);

		CloseHandle(ra_handle);

		if (!success) {
			throw std::system_error(GetLastError(), std::system_category(), "DeviceIoControl failed");
		}

		return mod;
	}


	void write(mouse_modifier mod) {
		HANDLE ra_handle = INVALID_HANDLE_VALUE;

		ra_handle = CreateFileW(L"\\\\.\\rawaccel", 0, 0, 0, OPEN_EXISTING, 0, 0);

		if (ra_handle == INVALID_HANDLE_VALUE) {
			throw install_error();
		}

		DWORD dummy;

		BOOL success = DeviceIoControl(
			ra_handle,
			RA_WRITE,
			&mod,                     // input buffer
			sizeof(mouse_modifier),   // input buffer size
			NULL,                     // output buffer
			0,                        // output buffer size
			&dummy,                   // bytes returned
			NULL                      // overlapped structure
		);

		CloseHandle(ra_handle);

		if (!success) {
			if (auto err = GetLastError(); err != ERROR_BUSY) {
				throw std::system_error(err, std::system_category(), "DeviceIoControl failed");
			}
			throw cooldown_error();
		}
	}

}

#pragma warning(pop)