mirror of
https://github.com/RawAccelOfficial/rawaccel.git
synced 2025-05-11 18:36:46 +02:00
Add project files.
This commit is contained in:
parent
916f28087f
commit
78156f3416
19 changed files with 10729 additions and 0 deletions
19
common-install/common-install.vcxitems
Normal file
19
common-install/common-install.vcxitems
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<ItemsProjectGuid>{058d66c6-d88b-4fdb-b0e4-0a6fe7483b95}</ItemsProjectGuid>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectCapability Include="SourceItemsFromImports" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)utility-install.hpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
2000
common-install/external/WinReg.hpp
vendored
Normal file
2000
common-install/external/WinReg.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
46
common-install/utility-install.hpp
Normal file
46
common-install/utility-install.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <Windows.h>
|
||||
|
||||
#include "external/WinReg.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
namespace wr = winreg;
|
||||
|
||||
inline const std::wstring DRIVER_NAME = L"rawaccel";
|
||||
inline const std::wstring DRIVER_FILE_NAME = DRIVER_NAME + L".sys";
|
||||
|
||||
fs::path get_sys_path() {
|
||||
std::wstring path;
|
||||
path.resize(MAX_PATH);
|
||||
|
||||
UINT chars_copied = GetSystemDirectoryW(path.data(), MAX_PATH);
|
||||
if (chars_copied == 0) throw std::runtime_error("GetSystemDirectory failed");
|
||||
|
||||
path.resize(chars_copied);
|
||||
return path;
|
||||
}
|
||||
|
||||
fs::path get_target_path() {
|
||||
return get_sys_path() / L"drivers" / DRIVER_FILE_NAME;
|
||||
}
|
||||
|
||||
fs::path make_temp_path(const fs::path& p) {
|
||||
auto tmp_path = p;
|
||||
tmp_path.concat(".tmp");
|
||||
return tmp_path;
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
void modify_upper_filters(Func fn) {
|
||||
const std::wstring FILTERS_NAME = L"UpperFilters";
|
||||
wr::RegKey key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e96f-e325-11ce-bfc1-08002be10318}"
|
||||
);
|
||||
|
||||
std::vector<std::wstring> filters = key.GetMultiStringValue(FILTERS_NAME);
|
||||
fn(filters);
|
||||
key.SetMultiStringValue(FILTERS_NAME, filters);
|
||||
}
|
22
common/common.vcxitems
Normal file
22
common/common.vcxitems
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<ItemsProjectGuid>{24b4226f-1461-408f-a1a4-1371c97153ea}</ItemsProjectGuid>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectCapability Include="SourceItemsFromImports" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel-userspace.hpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)rawaccel.hpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)x64-util.hpp" />
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)vec2.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
7027
common/external/clipp.h
vendored
Normal file
7027
common/external/clipp.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
113
common/rawaccel-userspace.hpp
Normal file
113
common/rawaccel-userspace.hpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "external/clipp.h"
|
||||
|
||||
#include "rawaccel.hpp"
|
||||
|
||||
namespace rawaccel {
|
||||
|
||||
inline constexpr int SYSTEM_ERROR = -1;
|
||||
inline constexpr int PARSE_ERROR = 1;
|
||||
inline constexpr int INVALID_ARGUMENT = 2;
|
||||
|
||||
void error(const char* s) {
|
||||
throw std::domain_error(s);
|
||||
}
|
||||
|
||||
variables parse(int argc, char** argv) {
|
||||
double degrees = 0;
|
||||
vec2d sens = { 1, 1 };
|
||||
accel_function::args_t accel_args{};
|
||||
|
||||
// default options
|
||||
auto opt_sens = "sensitivity, <y> defaults to <x> (default = 1)" % (
|
||||
clipp::option("sens") &
|
||||
clipp::number("x", sens.x, sens.y) &
|
||||
clipp::opt_number("y", sens.y)
|
||||
);
|
||||
auto opt_rot = "counter-clockwise rotation (default = 0)" % (
|
||||
clipp::option("rotate") &
|
||||
clipp::number("degrees", degrees)
|
||||
);
|
||||
|
||||
// mode-independent accel options
|
||||
auto opt_weight = "accel multiplier, <y> defaults to <x> (default = 1)" % (
|
||||
clipp::option("weight") &
|
||||
clipp::number("x", accel_args.weight.x, accel_args.weight.y) &
|
||||
clipp::opt_number("y", accel_args.weight.y)
|
||||
);
|
||||
auto opt_offset = "speed (dots/ms) where accel kicks in (default = 0)" % (
|
||||
clipp::option("offset") & clipp::number("speed", accel_args.offset)
|
||||
);
|
||||
auto opt_cap = "accel scale cap, <y> defaults to <x> (default = 9)" % (
|
||||
clipp::option("cap") &
|
||||
clipp::number("x", accel_args.cap.x, accel_args.cap.y) &
|
||||
clipp::opt_number("y", accel_args.cap.y)
|
||||
);
|
||||
auto opt_tmin = "minimum time between polls (default = 0.4)" % (
|
||||
clipp::option("tmin") &
|
||||
clipp::number("ms", accel_args.time_min)
|
||||
);
|
||||
|
||||
auto accel_var = (clipp::required("accel") & clipp::number("num", accel_args.accel)) % "ramp rate";
|
||||
auto limit_var = (clipp::required("limit") & clipp::number("scale", accel_args.lim_exp)) % "limit";
|
||||
|
||||
// modes
|
||||
auto noaccel_mode = "no-accel mode" % (
|
||||
clipp::command("off", "noaccel").set(accel_args.accel_mode, mode::noaccel)
|
||||
);
|
||||
auto lin_mode = "linear accel mode:" % (
|
||||
clipp::command("linear").set(accel_args.accel_mode, mode::linear),
|
||||
accel_var
|
||||
);
|
||||
auto classic_mode = "classic accel mode:" % (
|
||||
clipp::command("classic").set(accel_args.accel_mode, mode::classic),
|
||||
accel_var,
|
||||
(clipp::required("exponent") & clipp::number("num", accel_args.lim_exp)) % "exponent"
|
||||
);
|
||||
auto nat_mode = "natural accel mode:" % (
|
||||
clipp::command("natural").set(accel_args.accel_mode, mode::natural),
|
||||
accel_var,
|
||||
limit_var
|
||||
);
|
||||
auto log_mode = "logarithmic accel mode:" % (
|
||||
clipp::command("logarithmic").set(accel_args.accel_mode, mode::logarithmic),
|
||||
accel_var
|
||||
);
|
||||
auto sig_mode = "sigmoid accel mode:" % (
|
||||
clipp::command("sigmoid").set(accel_args.accel_mode, mode::sigmoid),
|
||||
accel_var,
|
||||
limit_var,
|
||||
(clipp::required("midpoint") & clipp::number("speed", accel_args.midpoint)) % "midpoint"
|
||||
);
|
||||
|
||||
auto accel_mode_exclusive = (lin_mode | classic_mode | nat_mode | log_mode | sig_mode);
|
||||
auto accel_opts = "mode-independent accel options:" % (opt_offset, opt_cap, opt_weight, opt_tmin);
|
||||
|
||||
bool help = false;
|
||||
|
||||
auto cli = clipp::group(clipp::command("help").set(help)) | (
|
||||
noaccel_mode | (accel_mode_exclusive, accel_opts),
|
||||
opt_sens,
|
||||
opt_rot
|
||||
);
|
||||
|
||||
if (!clipp::parse(argc, argv, cli)) {
|
||||
std::cout << clipp::usage_lines(cli, "rawaccel");
|
||||
std::exit(PARSE_ERROR);
|
||||
}
|
||||
|
||||
if (help) {
|
||||
auto fmt = clipp::doc_formatting{}.first_column(4)
|
||||
.doc_column(28)
|
||||
.last_column(80);
|
||||
std::cout << clipp::make_man_page(cli, "rawaccel", fmt);
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
return variables(-degrees, sens, accel_args);
|
||||
}
|
||||
|
||||
} // rawaccel
|
176
common/rawaccel.hpp
Normal file
176
common/rawaccel.hpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
#pragma once
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
#include "vec2.h"
|
||||
#include "x64-util.hpp"
|
||||
|
||||
namespace rawaccel {
|
||||
|
||||
enum class mode { noaccel, linear, classic, natural, logarithmic, sigmoid };
|
||||
|
||||
struct rotator {
|
||||
vec2d rot_vec = { 1, 0 };
|
||||
|
||||
inline vec2d operator()(const vec2d& input) const {
|
||||
return {
|
||||
input.x * rot_vec.x - input.y * rot_vec.y,
|
||||
input.x * rot_vec.y + input.y * rot_vec.x
|
||||
};
|
||||
}
|
||||
|
||||
rotator(double degrees) {
|
||||
double rads = degrees * M_PI / 180;
|
||||
rot_vec = { cos(rads), sin(rads) };
|
||||
}
|
||||
|
||||
rotator() = default;
|
||||
};
|
||||
|
||||
struct accel_scale_clamp {
|
||||
double lo = 0;
|
||||
double hi = 9;
|
||||
|
||||
inline double operator()(double scale) const {
|
||||
return clampsd(scale, lo, hi);
|
||||
}
|
||||
|
||||
accel_scale_clamp(double cap) : accel_scale_clamp() {
|
||||
if (cap <= 0) {
|
||||
// use default, effectively uncapped accel
|
||||
return;
|
||||
}
|
||||
|
||||
if (cap < 1) {
|
||||
// assume negative accel
|
||||
lo = cap;
|
||||
hi = 1;
|
||||
}
|
||||
else hi = cap;
|
||||
}
|
||||
|
||||
accel_scale_clamp() = default;
|
||||
};
|
||||
|
||||
void error(const char*);
|
||||
|
||||
struct accel_function {
|
||||
using milliseconds = double;
|
||||
|
||||
/*
|
||||
This value is ideally a few microseconds lower than
|
||||
the user's mouse polling interval, though it should
|
||||
not matter if the system is stable.
|
||||
*/
|
||||
milliseconds time_min = 0.4;
|
||||
|
||||
double speed_offset = 0;
|
||||
|
||||
// speed midpoint in sigmoid mode
|
||||
double m = 0;
|
||||
|
||||
// accel ramp rate
|
||||
double b = 0;
|
||||
|
||||
// the limit for natural and sigmoid modes,
|
||||
// or the exponent for classic mode
|
||||
double k = 1;
|
||||
|
||||
vec2d weight = { 1, 1 };
|
||||
vec2<accel_scale_clamp> clamp;
|
||||
|
||||
inline vec2d operator()(const vec2d& input, milliseconds time, mode accel_mode) const {
|
||||
double mag = sqrtsd(input.x * input.x + input.y * input.y);
|
||||
double time_clamped = clampsd(time, time_min, 100);
|
||||
double speed = maxsd(mag / time_clamped - speed_offset, 0);
|
||||
|
||||
double accel_val = 0;
|
||||
|
||||
switch (accel_mode) {
|
||||
case mode::linear: accel_val = b * speed;
|
||||
break;
|
||||
case mode::classic: accel_val = pow(b * speed, k);
|
||||
break;
|
||||
case mode::natural: accel_val = k - (k * exp(-b * speed));
|
||||
break;
|
||||
case mode::logarithmic: accel_val = log(speed * b + 1);
|
||||
break;
|
||||
case mode::sigmoid: accel_val = k / (exp(-b * (speed - m)) + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
double scale_x = weight.x * accel_val + 1;
|
||||
double scale_y = weight.y * accel_val + 1;
|
||||
|
||||
return {
|
||||
input.x * clamp.x(scale_x),
|
||||
input.y * clamp.y(scale_y)
|
||||
};
|
||||
}
|
||||
|
||||
struct args_t {
|
||||
mode accel_mode = mode::noaccel;
|
||||
milliseconds time_min = 0.4;
|
||||
double offset = 0;
|
||||
double accel = 0;
|
||||
double lim_exp = 2;
|
||||
double midpoint = 0;
|
||||
vec2d weight = { 1, 1 };
|
||||
vec2d cap = { 0, 0 };
|
||||
};
|
||||
|
||||
accel_function(args_t args) {
|
||||
// Preconditions to guard against division by zero and
|
||||
// ensure the C math functions can not return NaN or -Inf.
|
||||
if (args.accel < 0) error("accel can not be negative, use a negative weight to compensate");
|
||||
if (args.time_min <= 0) error("min time must be positive");
|
||||
if (args.lim_exp <= 1) {
|
||||
if (args.accel_mode == mode::classic) error("exponent must be greater than 1");
|
||||
else error("limit must be greater than 1");
|
||||
}
|
||||
|
||||
time_min = args.time_min;
|
||||
m = args.midpoint;
|
||||
b = args.accel;
|
||||
k = args.lim_exp - 1;
|
||||
if (args.accel_mode == mode::natural) b /= k;
|
||||
|
||||
speed_offset = args.offset;
|
||||
weight = args.weight;
|
||||
clamp.x = accel_scale_clamp(args.cap.x);
|
||||
clamp.y = accel_scale_clamp(args.cap.y);
|
||||
}
|
||||
|
||||
accel_function() = default;
|
||||
};
|
||||
|
||||
struct variables {
|
||||
bool apply_rotate = false;
|
||||
bool apply_accel = false;
|
||||
mode accel_mode = mode::noaccel;
|
||||
rotator rotate;
|
||||
accel_function accel_fn;
|
||||
vec2d sensitivity = { 1, 1 };
|
||||
|
||||
variables(double degrees, vec2d sens, accel_function::args_t accel_args)
|
||||
: accel_fn(accel_args)
|
||||
{
|
||||
apply_rotate = degrees != 0;
|
||||
if (apply_rotate) rotate = rotator(degrees);
|
||||
else rotate = rotator();
|
||||
|
||||
apply_accel = accel_args.accel_mode != mode::noaccel;
|
||||
accel_mode = accel_args.accel_mode;
|
||||
|
||||
if (sens.x == 0) sens.x = 1;
|
||||
if (sens.y == 0) sens.y = 1;
|
||||
sensitivity = sens;
|
||||
}
|
||||
|
||||
variables() = default;
|
||||
};
|
||||
|
||||
} // rawaccel
|
9
common/vec2.h
Normal file
9
common/vec2.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
template <typename T>
|
||||
struct vec2 {
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
|
||||
using vec2d = vec2<double>;
|
22
common/x64-util.hpp
Normal file
22
common/x64-util.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <emmintrin.h>
|
||||
|
||||
inline double sqrtsd(double val) {
|
||||
__m128d src = _mm_load_sd(&val);
|
||||
__m128d dst = _mm_sqrt_sd(src, src);
|
||||
_mm_store_sd(&val, dst);
|
||||
return val;
|
||||
}
|
||||
|
||||
inline constexpr double minsd(double a, double b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
inline constexpr double maxsd(double a, double b) {
|
||||
return (b < a) ? a : b;
|
||||
}
|
||||
|
||||
inline constexpr double clampsd(double v, double lo, double hi) {
|
||||
return minsd(maxsd(v, lo), hi);
|
||||
}
|
53
console/console.cpp
Normal file
53
console/console.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include <iostream>
|
||||
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
|
||||
#include <rawaccel-userspace.hpp>
|
||||
|
||||
#define RA_WRITE CTL_CODE(0x8888, 0x888, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
namespace ra = rawaccel;
|
||||
|
||||
void write(ra::variables vars) {
|
||||
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 std::system_error(GetLastError(), std::system_category(), "CreateFile failed");
|
||||
}
|
||||
|
||||
DWORD dummy;
|
||||
|
||||
BOOL success = DeviceIoControl(
|
||||
ra_handle,
|
||||
RA_WRITE,
|
||||
&vars,
|
||||
sizeof(ra::variables),
|
||||
NULL, // output buffer
|
||||
0, // output buffer size
|
||||
&dummy, // bytes returned
|
||||
NULL // overlapped structure
|
||||
);
|
||||
|
||||
CloseHandle(ra_handle);
|
||||
|
||||
if (!success) {
|
||||
throw std::system_error(GetLastError(), std::system_category(), "DeviceIoControl failed");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
try {
|
||||
write(ra::parse(argc, argv));
|
||||
}
|
||||
catch (std::domain_error e) {
|
||||
std::cerr << e.what() << '\n';
|
||||
return ra::INVALID_ARGUMENT;
|
||||
}
|
||||
catch (std::system_error e) {
|
||||
std::cerr << "Error: " << e.what() << " (" << e.code() << ")\n";
|
||||
return ra::SYSTEM_ERROR;
|
||||
}
|
||||
}
|
97
console/console.vcxproj
Normal file
97
console/console.vcxproj
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{AB7B3759-B85F-4067-8935-FB4539B41869}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>console</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
<Import Project="..\common\common.vcxitems" Label="Shared" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>rawaccel</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>rawaccel</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(SolutionDir)\external</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(SolutionDir)\external</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="console.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
611
driver/driver.cpp
Normal file
611
driver/driver.cpp
Normal file
|
@ -0,0 +1,611 @@
|
|||
#include <rawaccel.hpp>
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text (INIT, DriverEntry)
|
||||
#pragma alloc_text (PAGE, EvtDeviceAdd)
|
||||
#pragma alloc_text (PAGE, EvtIoInternalDeviceControl)
|
||||
#pragma alloc_text (PAGE, RawaccelControl)
|
||||
#endif
|
||||
|
||||
namespace ra = rawaccel;
|
||||
|
||||
using milliseconds = double;
|
||||
|
||||
struct {
|
||||
milliseconds tick_interval = 0; // set in DriverEntry
|
||||
ra::variables vars;
|
||||
} global;
|
||||
|
||||
VOID
|
||||
RawaccelCallback(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PMOUSE_INPUT_DATA InputDataStart,
|
||||
IN PMOUSE_INPUT_DATA InputDataEnd,
|
||||
IN OUT PULONG InputDataConsumed
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Called when there are mouse packets to report to the RIT.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - Context passed during the connect IOCTL
|
||||
|
||||
InputDataStart - First packet to be reported
|
||||
|
||||
InputDataEnd - One past the last packet to be reported. Total number of
|
||||
packets is equal to InputDataEnd - InputDataStart
|
||||
|
||||
InputDataConsumed - Set to the total number of packets consumed by the RIT
|
||||
(via the function pointer we replaced in the connect
|
||||
IOCTL)
|
||||
|
||||
--*/
|
||||
{
|
||||
WDFDEVICE hDevice = WdfWdmDeviceGetWdfDeviceHandle(DeviceObject);
|
||||
PDEVICE_EXTENSION devExt = FilterGetData(hDevice);
|
||||
|
||||
if (!(InputDataStart->Flags & MOUSE_MOVE_ABSOLUTE)) {
|
||||
auto num_packets = InputDataEnd - InputDataStart;
|
||||
|
||||
// if IO is backed up to the point where we get more than 1 packet here
|
||||
// then applying accel is pointless as we can't get an accurate timing
|
||||
|
||||
bool local_apply_accel = num_packets == 1;
|
||||
if (num_packets != 1) {
|
||||
DebugPrint(("RA received %d packets\n", num_packets));
|
||||
}
|
||||
|
||||
vec2d local_carry = devExt->carry;
|
||||
|
||||
auto it = InputDataStart;
|
||||
do {
|
||||
vec2d input = {
|
||||
static_cast<double>(it->LastX),
|
||||
static_cast<double>(it->LastY)
|
||||
};
|
||||
|
||||
if (global.vars.apply_rotate) {
|
||||
input = global.vars.rotate(input);
|
||||
}
|
||||
|
||||
if (global.vars.apply_accel && local_apply_accel) {
|
||||
auto now = KeQueryPerformanceCounter(NULL).QuadPart;
|
||||
auto ticks = now - devExt->counter.QuadPart;
|
||||
devExt->counter.QuadPart = now;
|
||||
|
||||
milliseconds time = ticks * global.tick_interval;
|
||||
if (time < global.vars.accel_fn.time_min) {
|
||||
DebugPrint(("RA time < min with %d ticks\n", ticks));
|
||||
}
|
||||
|
||||
input = global.vars.accel_fn(input, time, global.vars.accel_mode);
|
||||
}
|
||||
|
||||
double result_x = input.x * global.vars.sensitivity.x + local_carry.x;
|
||||
double result_y = input.y * global.vars.sensitivity.y + local_carry.y;
|
||||
|
||||
LONG out_x = static_cast<LONG>(result_x);
|
||||
LONG out_y = static_cast<LONG>(result_y);
|
||||
|
||||
local_carry.x = result_x - out_x;
|
||||
local_carry.y = result_y - out_y;
|
||||
|
||||
it->LastX = out_x;
|
||||
it->LastY = out_y;
|
||||
|
||||
++it;
|
||||
} while (it < InputDataEnd);
|
||||
|
||||
devExt->carry = local_carry;
|
||||
}
|
||||
|
||||
(*(PSERVICE_CALLBACK_ROUTINE)devExt->UpperConnectData.ClassService)(
|
||||
devExt->UpperConnectData.ClassDeviceObject,
|
||||
InputDataStart,
|
||||
InputDataEnd,
|
||||
InputDataConsumed
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:28118) // this callback will run at IRQL=PASSIVE_LEVEL
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
RawaccelControl(
|
||||
WDFQUEUE Queue,
|
||||
WDFREQUEST Request,
|
||||
size_t OutputBufferLength,
|
||||
size_t InputBufferLength,
|
||||
ULONG IoControlCode
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
|
||||
requests from the system.
|
||||
Arguments:
|
||||
Queue - Handle to the framework queue object that is associated
|
||||
with the I/O request.
|
||||
Request - Handle to a framework request object.
|
||||
OutputBufferLength - length of the request's output buffer,
|
||||
if an output buffer is available.
|
||||
InputBufferLength - length of the request's input buffer,
|
||||
if an input buffer is available.
|
||||
IoControlCode - the driver-defined or system-defined I/O control code
|
||||
(IOCTL) that is associated with the request.
|
||||
Return Value:
|
||||
VOID
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
void* input_buffer;
|
||||
size_t input_size;
|
||||
|
||||
UNREFERENCED_PARAMETER(Queue);
|
||||
UNREFERENCED_PARAMETER(OutputBufferLength);
|
||||
UNREFERENCED_PARAMETER(IoControlCode);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DebugPrint(("Ioctl received into filter control object.\n"));
|
||||
|
||||
if (InputBufferLength != sizeof(ra::variables)) {
|
||||
DebugPrint(("Received unknown request of %u bytes\n", InputBufferLength));
|
||||
// status maps to win32 error code 1784: ERROR_INVALID_USER_BUFFER
|
||||
WdfRequestComplete(Request, STATUS_INVALID_BUFFER_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
sizeof(ra::variables),
|
||||
&input_buffer,
|
||||
&input_size
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DebugPrint(("RetrieveInputBuffer failed: 0x%x\n", status));
|
||||
// status maps to win32 error code 1359: ERROR_INTERNAL_ERROR
|
||||
WdfRequestComplete(Request, STATUS_MESSAGE_LOST);
|
||||
return;
|
||||
}
|
||||
|
||||
global.vars = *reinterpret_cast<ra::variables*>(input_buffer);
|
||||
|
||||
WdfRequestComplete(Request, STATUS_SUCCESS);
|
||||
}
|
||||
#pragma warning(pop) // enable 28118 again
|
||||
|
||||
|
||||
NTSTATUS
|
||||
DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
Installable driver initialization entry point.
|
||||
This entry point is called directly by the I/O system.
|
||||
|
||||
--*/
|
||||
{
|
||||
|
||||
WDF_DRIVER_CONFIG config;
|
||||
NTSTATUS status;
|
||||
WDFDRIVER driver;
|
||||
|
||||
DebugPrint(("km accel filter.\n"));
|
||||
DebugPrint(("Built %s %s\n", __DATE__, __TIME__));
|
||||
|
||||
// Initialize driver config to control the attributes that
|
||||
// are global to the driver. Note that framework by default
|
||||
// provides a driver unload routine. If you create any resources
|
||||
// in the DriverEntry and want to be cleaned in driver unload,
|
||||
// you can override that by manually setting the EvtDriverUnload in the
|
||||
// config structure. In general xxx_CONFIG_INIT macros are provided to
|
||||
// initialize most commonly used members.
|
||||
|
||||
WDF_DRIVER_CONFIG_INIT(
|
||||
&config,
|
||||
EvtDeviceAdd
|
||||
);
|
||||
|
||||
//
|
||||
// Create a framework driver object to represent our driver.
|
||||
//
|
||||
status = WdfDriverCreate(DriverObject,
|
||||
RegistryPath,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&config,
|
||||
&driver);
|
||||
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
LARGE_INTEGER freq;
|
||||
KeQueryPerformanceCounter(&freq);
|
||||
global.tick_interval = 1e3 / freq.QuadPart;
|
||||
|
||||
CreateControlDevice(driver);
|
||||
}
|
||||
else {
|
||||
DebugPrint(("WdfDriverCreate failed with status 0x%x\n", status));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
VOID
|
||||
CreateControlDevice(WDFDRIVER Driver)
|
||||
/*++
|
||||
Routine Description:
|
||||
This routine is called to create a control device object so that application
|
||||
can talk to the filter driver directly instead of going through the entire
|
||||
device stack. This kind of control device object is useful if the filter
|
||||
driver is underneath another driver which prevents ioctls not known to it
|
||||
or if the driver's dispatch routine is owned by some other (port/class)
|
||||
driver and it doesn't allow any custom ioctls.
|
||||
Arguments:
|
||||
Driver - Handle to wdf driver object.
|
||||
Return Value:
|
||||
WDF status code
|
||||
--*/
|
||||
{
|
||||
PWDFDEVICE_INIT pInit = NULL;
|
||||
WDFDEVICE controlDevice = NULL;
|
||||
WDF_IO_QUEUE_CONFIG ioQueueConfig;
|
||||
NTSTATUS status;
|
||||
WDFQUEUE queue;
|
||||
DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME);
|
||||
DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING);
|
||||
|
||||
DebugPrint(("Creating Control Device\n"));
|
||||
|
||||
//
|
||||
//
|
||||
// In order to create a control device, we first need to allocate a
|
||||
// WDFDEVICE_INIT structure and set all properties.
|
||||
//
|
||||
pInit = WdfControlDeviceInitAllocate(
|
||||
Driver,
|
||||
&SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R
|
||||
);
|
||||
|
||||
if (pInit == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
//
|
||||
// Set exclusive to false so that more than one app can talk to the
|
||||
// control device simultaneously.
|
||||
//
|
||||
WdfDeviceInitSetExclusive(pInit, FALSE);
|
||||
|
||||
status = WdfDeviceInitAssignName(pInit, &ntDeviceName);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
status = WdfDeviceCreate(&pInit,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&controlDevice);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a symbolic link for the control object so that usermode can open
|
||||
// the device.
|
||||
//
|
||||
|
||||
status = WdfDeviceCreateSymbolicLink(controlDevice, &symbolicLinkName);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the default queue associated with the control device object
|
||||
// to be Serial so that request passed to RawaccelControl are serialized.
|
||||
//
|
||||
|
||||
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
|
||||
WdfIoQueueDispatchSequential);
|
||||
|
||||
ioQueueConfig.EvtIoDeviceControl = RawaccelControl;
|
||||
|
||||
//
|
||||
// Framework by default creates non-power managed queues for
|
||||
// filter drivers.
|
||||
//
|
||||
status = WdfIoQueueCreate(controlDevice,
|
||||
&ioQueueConfig,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
&queue // pointer to default queue
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
//
|
||||
// Control devices must notify WDF when they are done initializing. I/O is
|
||||
// rejected until this call is made.
|
||||
//
|
||||
WdfControlFinishInitializing(controlDevice);
|
||||
|
||||
return;
|
||||
|
||||
Error:
|
||||
|
||||
if (pInit != NULL) WdfDeviceInitFree(pInit);
|
||||
|
||||
if (controlDevice != NULL) {
|
||||
//
|
||||
// Release the reference on the newly created object, since
|
||||
// we couldn't initialize it.
|
||||
//
|
||||
WdfObjectDelete(controlDevice);
|
||||
}
|
||||
|
||||
DebugPrint(("CreateControlDevice failed\n", status));
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
EvtDeviceAdd(
|
||||
IN WDFDRIVER Driver,
|
||||
IN PWDFDEVICE_INIT DeviceInit
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
EvtDeviceAdd is called by the framework in response to AddDevice
|
||||
call from the PnP manager. Here you can query the device properties
|
||||
using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based
|
||||
on that, decide to create a filter device object and attach to the
|
||||
function stack.
|
||||
|
||||
If you are not interested in filtering this particular instance of the
|
||||
device, you can just return STATUS_SUCCESS without creating a framework
|
||||
device.
|
||||
|
||||
Arguments:
|
||||
|
||||
Driver - Handle to a framework driver object created in DriverEntry
|
||||
|
||||
DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
|
||||
|
||||
Return Value:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
WDF_OBJECT_ATTRIBUTES deviceAttributes;
|
||||
NTSTATUS status;
|
||||
WDFDEVICE hDevice;
|
||||
WDF_IO_QUEUE_CONFIG ioQueueConfig;
|
||||
|
||||
UNREFERENCED_PARAMETER(Driver);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DebugPrint(("Enter FilterEvtDeviceAdd \n"));
|
||||
|
||||
//
|
||||
// Tell the framework that you are filter driver. Framework
|
||||
// takes care of inherting all the device flags & characterstics
|
||||
// from the lower device you are attaching to.
|
||||
//
|
||||
WdfFdoInitSetFilter(DeviceInit);
|
||||
|
||||
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_MOUSE);
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes,
|
||||
DEVICE_EXTENSION);
|
||||
|
||||
|
||||
//
|
||||
// Create a framework device object. This call will in turn create
|
||||
// a WDM deviceobject, attach to the lower stack and set the
|
||||
// appropriate flags and attributes.
|
||||
//
|
||||
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DebugPrint(("WdfDeviceCreate failed with status code 0x%x\n", status));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Configure the default queue to be Parallel. Do not use sequential queue
|
||||
// if this driver is going to be filtering PS2 ports because it can lead to
|
||||
// deadlock. The PS2 port driver sends a request to the top of the stack when it
|
||||
// receives an ioctl request and waits for it to be completed. If you use a
|
||||
// a sequential queue, this request will be stuck in the queue because of the
|
||||
// outstanding ioctl request sent earlier to the port driver.
|
||||
//
|
||||
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
|
||||
WdfIoQueueDispatchParallel);
|
||||
|
||||
//
|
||||
// Framework by default creates non-power managed queues for
|
||||
// filter drivers.
|
||||
//
|
||||
ioQueueConfig.EvtIoInternalDeviceControl = EvtIoInternalDeviceControl;
|
||||
|
||||
status = WdfIoQueueCreate(hDevice,
|
||||
&ioQueueConfig,
|
||||
WDF_NO_OBJECT_ATTRIBUTES,
|
||||
WDF_NO_HANDLE // pointer to default queue
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status));
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
EvtIoInternalDeviceControl(
|
||||
IN WDFQUEUE Queue,
|
||||
IN WDFREQUEST Request,
|
||||
IN size_t OutputBufferLength,
|
||||
IN size_t InputBufferLength,
|
||||
IN ULONG IoControlCode
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine is the dispatch routine for internal device control requests.
|
||||
There are two specific control codes that are of interest:
|
||||
|
||||
IOCTL_INTERNAL_MOUSE_CONNECT:
|
||||
Store the old context and function pointer and replace it with our own.
|
||||
This makes life much simpler than intercepting IRPs sent by the RIT and
|
||||
modifying them on the way back up.
|
||||
|
||||
IOCTL_INTERNAL_I8042_HOOK_MOUSE:
|
||||
Add in the necessary function pointers and context values so that we can
|
||||
alter how the ps/2 mouse is initialized.
|
||||
|
||||
NOTE: Handling IOCTL_INTERNAL_I8042_HOOK_MOUSE is *NOT* necessary if
|
||||
all you want to do is filter MOUSE_INPUT_DATAs. You can remove
|
||||
the handling code and all related device extension fields and
|
||||
functions to conserve space.
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
|
||||
PDEVICE_EXTENSION devExt;
|
||||
PCONNECT_DATA connectData;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
WDFDEVICE hDevice;
|
||||
size_t length;
|
||||
|
||||
UNREFERENCED_PARAMETER(OutputBufferLength);
|
||||
UNREFERENCED_PARAMETER(InputBufferLength);
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
hDevice = WdfIoQueueGetDevice(Queue);
|
||||
devExt = FilterGetData(hDevice);
|
||||
|
||||
switch (IoControlCode) {
|
||||
|
||||
//
|
||||
// Connect a mouse class device driver to the port driver.
|
||||
//
|
||||
case IOCTL_INTERNAL_MOUSE_CONNECT:
|
||||
//
|
||||
// Only allow one connection.
|
||||
//
|
||||
if (devExt->UpperConnectData.ClassService != NULL) {
|
||||
status = STATUS_SHARING_VIOLATION;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy the connection parameters to the device extension.
|
||||
//
|
||||
status = WdfRequestRetrieveInputBuffer(Request,
|
||||
sizeof(CONNECT_DATA),
|
||||
reinterpret_cast<PVOID*>(&connectData),
|
||||
&length);
|
||||
if(!NT_SUCCESS(status)){
|
||||
DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status));
|
||||
break;
|
||||
}
|
||||
|
||||
devExt->counter = KeQueryPerformanceCounter(NULL);
|
||||
devExt->carry = {};
|
||||
devExt->UpperConnectData = *connectData;
|
||||
|
||||
//
|
||||
// Hook into the report chain. Everytime a mouse packet is reported to
|
||||
// the system, RawaccelCallback will be called
|
||||
//
|
||||
|
||||
connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice);
|
||||
connectData->ClassService = RawaccelCallback;
|
||||
|
||||
break;
|
||||
|
||||
//
|
||||
// Disconnect a mouse class device driver from the port driver.
|
||||
//
|
||||
case IOCTL_INTERNAL_MOUSE_DISCONNECT:
|
||||
//
|
||||
// Clear the connection parameters in the device extension.
|
||||
//
|
||||
// devExt->UpperConnectData.ClassDeviceObject = NULL;
|
||||
// devExt->UpperConnectData.ClassService = NULL;
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
case IOCTL_MOUSE_QUERY_ATTRIBUTES:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
WdfRequestComplete(Request, status);
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchPassThrough(Request, WdfDeviceGetIoTarget(hDevice));
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
VOID
|
||||
DispatchPassThrough(
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ WDFIOTARGET Target
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
Passes a request on to the lower driver.
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Pass the IRP to the target
|
||||
//
|
||||
|
||||
WDF_REQUEST_SEND_OPTIONS options;
|
||||
BOOLEAN ret;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
//
|
||||
// We are not interested in post processing the IRP so
|
||||
// fire and forget.
|
||||
//
|
||||
WDF_REQUEST_SEND_OPTIONS_INIT(&options,
|
||||
WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);
|
||||
|
||||
ret = WdfRequestSend(Request, Target, &options);
|
||||
|
||||
if (ret == FALSE) {
|
||||
status = WdfRequestGetStatus(Request);
|
||||
DebugPrint(("WdfRequestSend failed: 0x%x\n", status));
|
||||
WdfRequestComplete(Request, status);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
47
driver/driver.h
Normal file
47
driver/driver.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <kbdmou.h>
|
||||
#include <wdf.h>
|
||||
|
||||
#include "vec2.h"
|
||||
|
||||
#if DBG
|
||||
#define DebugPrint(_x_) DbgPrint _x_
|
||||
#else
|
||||
#define DebugPrint(_x_)
|
||||
#endif
|
||||
|
||||
#define NTDEVICE_NAME L"\\Device\\rawaccel"
|
||||
#define SYMBOLIC_NAME_STRING L"\\DosDevices\\rawaccel"
|
||||
|
||||
typedef struct _DEVICE_EXTENSION {
|
||||
LARGE_INTEGER counter;
|
||||
vec2d carry;
|
||||
CONNECT_DATA UpperConnectData;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, FilterGetData)
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
EVT_WDF_DRIVER_DEVICE_ADD EvtDeviceAdd;
|
||||
EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtIoInternalDeviceControl;
|
||||
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL RawaccelControl;
|
||||
|
||||
VOID RawaccelCallback(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PMOUSE_INPUT_DATA InputDataStart,
|
||||
IN PMOUSE_INPUT_DATA InputDataEnd,
|
||||
IN OUT PULONG InputDataConsumed
|
||||
);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
VOID CreateControlDevice(WDFDRIVER Driver);
|
||||
|
||||
VOID DispatchPassThrough(
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ WDFIOTARGET Target
|
||||
);
|
133
driver/driver.vcxproj
Normal file
133
driver/driver.vcxproj
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{60D6C942-AC20-4C05-A2BE-54B5C966534D}</ProjectGuid>
|
||||
<RootNamespace>$(MSBuildProjectName)</RootNamespace>
|
||||
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
|
||||
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<SampleGuid>{C3E0B8D8-9BDC-4A02-9E56-773CB59546DB}</SampleGuid>
|
||||
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||
<ProjectName>driver</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>False</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<OverrideDefaultRuntimeLibrary>true</OverrideDefaultRuntimeLibrary>
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetVersion>Windows10</TargetVersion>
|
||||
<UseDebugLibraries>True</UseDebugLibraries>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
<Import Project="..\common\common.vcxitems" Label="Shared" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetName>rawaccel</TargetName>
|
||||
<EnableInf2cat>false</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>rawaccel</TargetName>
|
||||
<EnableInf2cat>false</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories);$(SolutionDir)\external;$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>
|
||||
</RuntimeLibrary>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
|
||||
<ExpandAttributedSource>false</ExpandAttributedSource>
|
||||
<UseUnicodeForAssemblerListing>false</UseUnicodeForAssemblerListing>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<ControlFlowGuard>Guard</ControlFlowGuard>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LinkTimeCodeGeneration>
|
||||
</LinkTimeCodeGeneration>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>
|
||||
</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib;$(DDK_LIB_PATH)wdmsec.lib;$(DDK_LIB_PATH)libcntpr.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
<AdditionalOptions>/Kernel %(AdditionalOptions)</AdditionalOptions>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories);$(SolutionDir)\external;$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>
|
||||
</RuntimeLibrary>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>
|
||||
</IgnoreAllDefaultLibraries>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib;$(DDK_LIB_PATH)wdmsec.lib;$(DDK_LIB_PATH)libcntpr.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="driver.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
|
||||
<None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="driver.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
80
installer/installer.cpp
Normal file
80
installer/installer.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <utility-install.hpp>
|
||||
|
||||
void add_service(const fs::path& target) {
|
||||
SC_HANDLE schSCManager = OpenSCManager(
|
||||
NULL, // local computer
|
||||
NULL, // ServicesActive database
|
||||
SC_MANAGER_ALL_ACCESS // full access rights
|
||||
);
|
||||
|
||||
if (schSCManager == NULL) throw std::runtime_error("OpenSCManager failed");
|
||||
|
||||
SC_HANDLE schService = CreateService(
|
||||
schSCManager, // SCM database
|
||||
DRIVER_NAME.c_str(), // name of service
|
||||
DRIVER_NAME.c_str(), // service name to display
|
||||
SERVICE_ALL_ACCESS, // desired access
|
||||
SERVICE_KERNEL_DRIVER, // service type
|
||||
SERVICE_DEMAND_START, // start type
|
||||
SERVICE_ERROR_NORMAL, // error control type
|
||||
target.c_str(), // path to service's binary
|
||||
NULL, // no load ordering group
|
||||
NULL, // no tag identifier
|
||||
NULL, // no dependencies
|
||||
NULL, // LocalSystem account
|
||||
NULL // no password
|
||||
);
|
||||
|
||||
if (schService) {
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto err = GetLastError(); err != ERROR_SERVICE_EXISTS) {
|
||||
CloseServiceHandle(schSCManager);
|
||||
throw std::runtime_error("CreateService failed");
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
fs::path source = fs::path(L"driver") / DRIVER_FILE_NAME;
|
||||
|
||||
if (!fs::exists(source)) {
|
||||
throw std::runtime_error(source.generic_string() + " does not exist");
|
||||
}
|
||||
|
||||
fs::path target = get_target_path();
|
||||
|
||||
add_service(target);
|
||||
|
||||
fs::path tmp = make_temp_path(target);
|
||||
|
||||
// schedule tmp to be deleted if rename target -> tmp is successful
|
||||
if (MoveFileExW(target.c_str(), tmp.c_str(), MOVEFILE_REPLACE_EXISTING)) {
|
||||
MoveFileExW(tmp.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
|
||||
}
|
||||
|
||||
fs::copy_file(source, target, fs::copy_options::overwrite_existing);
|
||||
|
||||
modify_upper_filters([](std::vector<std::wstring>& filters) {
|
||||
auto driver_pos = std::find(filters.begin(), filters.end(), DRIVER_NAME);
|
||||
|
||||
if (driver_pos != filters.end()) return;
|
||||
|
||||
auto mouclass_pos = std::find(filters.begin(), filters.end(), L"mouclass");
|
||||
filters.insert(mouclass_pos, DRIVER_NAME);
|
||||
});
|
||||
|
||||
std::cout << "Install complete, change will take effect after restart.\n";
|
||||
}
|
||||
catch (std::exception e) {
|
||||
std::cerr << "Error: " << e.what() << '\n';
|
||||
}
|
||||
|
||||
std::cout << "Press any key to close this window . . .\n";
|
||||
_getwch();
|
||||
}
|
98
installer/installer.vcxproj
Normal file
98
installer/installer.vcxproj
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{896950D1-520A-420A-B6B1-73014B92A68C}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>installer</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
<Import Project="..\common-install\common-install.vcxitems" Label="Shared" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="installer.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
56
rawaccel.sln
Normal file
56
rawaccel.sln
Normal file
|
@ -0,0 +1,56 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30104.148
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "driver\driver.vcxproj", "{60D6C942-AC20-4C05-A2BE-54B5C966534D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxitems", "{24B4226F-1461-408F-A1A4-1371C97153EA}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer", "installer\installer.vcxproj", "{896950D1-520A-420A-B6B1-73014B92A68C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console", "console\console.vcxproj", "{AB7B3759-B85F-4067-8935-FB4539B41869}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common-install", "common-install\common-install.vcxitems", "{058D66C6-D88B-4FDB-B0E4-0A6FE7483B95}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uninstaller", "uninstaller\uninstaller.vcxproj", "{A4097FF6-A6F0-44E8-B8D0-538D0FB75936}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
common-install\common-install.vcxitems*{058d66c6-d88b-4fdb-b0e4-0a6fe7483b95}*SharedItemsImports = 9
|
||||
common\common.vcxitems*{24b4226f-1461-408f-a1a4-1371c97153ea}*SharedItemsImports = 9
|
||||
common\common.vcxitems*{60d6c942-ac20-4c05-a2be-54b5c966534d}*SharedItemsImports = 4
|
||||
common-install\common-install.vcxitems*{896950d1-520a-420a-b6b1-73014b92a68c}*SharedItemsImports = 4
|
||||
common-install\common-install.vcxitems*{a4097ff6-a6f0-44e8-b8d0-538d0fb75936}*SharedItemsImports = 4
|
||||
common\common.vcxitems*{ab7b3759-b85f-4067-8935-fb4539b41869}*SharedItemsImports = 4
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{60D6C942-AC20-4C05-A2BE-54B5C966534D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{60D6C942-AC20-4C05-A2BE-54B5C966534D}.Debug|x64.Build.0 = Debug|x64
|
||||
{60D6C942-AC20-4C05-A2BE-54B5C966534D}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{60D6C942-AC20-4C05-A2BE-54B5C966534D}.Release|x64.ActiveCfg = Release|x64
|
||||
{60D6C942-AC20-4C05-A2BE-54B5C966534D}.Release|x64.Build.0 = Release|x64
|
||||
{896950D1-520A-420A-B6B1-73014B92A68C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{896950D1-520A-420A-B6B1-73014B92A68C}.Debug|x64.Build.0 = Debug|x64
|
||||
{896950D1-520A-420A-B6B1-73014B92A68C}.Release|x64.ActiveCfg = Release|x64
|
||||
{896950D1-520A-420A-B6B1-73014B92A68C}.Release|x64.Build.0 = Release|x64
|
||||
{AB7B3759-B85F-4067-8935-FB4539B41869}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AB7B3759-B85F-4067-8935-FB4539B41869}.Debug|x64.Build.0 = Debug|x64
|
||||
{AB7B3759-B85F-4067-8935-FB4539B41869}.Release|x64.ActiveCfg = Release|x64
|
||||
{AB7B3759-B85F-4067-8935-FB4539B41869}.Release|x64.Build.0 = Release|x64
|
||||
{A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Debug|x64.Build.0 = Debug|x64
|
||||
{A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Release|x64.ActiveCfg = Release|x64
|
||||
{A4097FF6-A6F0-44E8-B8D0-538D0FB75936}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {A3B5EC34-5340-4301-8BE9-33096EFEF77E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
29
uninstaller/uninstaller.cpp
Normal file
29
uninstaller/uninstaller.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <utility-install.hpp>
|
||||
|
||||
int main() {
|
||||
try {
|
||||
modify_upper_filters([](std::vector<std::wstring>& filters) {
|
||||
std::erase(filters, DRIVER_NAME);
|
||||
});
|
||||
|
||||
fs::path target = get_target_path();
|
||||
fs::path tmp = make_temp_path(target);
|
||||
|
||||
// schedule tmp to be deleted if rename target -> tmp is successful
|
||||
if (MoveFileExW(target.c_str(), tmp.c_str(), MOVEFILE_REPLACE_EXISTING)) {
|
||||
MoveFileExW(tmp.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
|
||||
}
|
||||
else { // tmp is in use and delete is already scheduled
|
||||
if (fs::exists(target)) fs::remove(target);
|
||||
}
|
||||
std::cout << "Removal complete, change will take effect after restart.\n";
|
||||
}
|
||||
catch (std::exception e) {
|
||||
std::cerr << "Error: " << e.what() << '\n';
|
||||
}
|
||||
|
||||
std::cout << "Press any key to close this window . . .\n";
|
||||
_getwch();
|
||||
}
|
91
uninstaller/uninstaller.vcxproj
Normal file
91
uninstaller/uninstaller.vcxproj
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{a4097ff6-a6f0-44e8-b8d0-538d0fb75936}</ProjectGuid>
|
||||
<RootNamespace>uninstaller</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
<Import Project="..\common-install\common-install.vcxitems" Label="Shared" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="uninstaller.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
Loading…
Add table
Add a link
Reference in a new issue