Skip to content

Commit 346dcbf

Browse files
authored
Merge pull request #3 from nefarius/wil-modernization
Introduced Windows Implementation Library
2 parents 012805e + 3cda2fc commit 346dcbf

11 files changed

Lines changed: 115 additions & 204 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(CMAKE_CXX_STANDARD 23)
55
set(CMAKE_CXX_STANDARD_REQUIRED ON)
66

77
find_package(imgui CONFIG REQUIRED)
8+
find_package(WIL CONFIG REQUIRED)
89

910
file(GLOB_RECURSE SOURCE_FILES src/*.cpp)
1011
file(GLOB_RECURSE HEADER_FILES src/*.h)
@@ -22,6 +23,7 @@ target_include_directories(MultiPadTester PRIVATE src res)
2223

2324
target_link_libraries(MultiPadTester PRIVATE
2425
imgui::imgui
26+
WIL::WIL
2527
d3d11.lib
2628
d3dcompiler.lib
2729
dxgi.lib

src/d3d_helpers.cpp

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ bool D3DContext::Create(const HWND hwnd, const int refreshRatePreferred)
4444
if (D3D11CreateDeviceAndSwapChain(
4545
nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0,
4646
levels.data(), levels.size(), D3D11_SDK_VERSION,
47-
&sd, &swapChain, &device, &obtained, &deviceCtx) != S_OK)
47+
&sd, swapChain.put(), device.put(), &obtained, deviceCtx.put()) != S_OK)
4848
return false;
4949

5050
CreateRTV();
@@ -53,39 +53,22 @@ bool D3DContext::Create(const HWND hwnd, const int refreshRatePreferred)
5353

5454
void D3DContext::CreateRTV()
5555
{
56-
ID3D11Texture2D* back = nullptr;
57-
swapChain->GetBuffer(0, IID_PPV_ARGS(&back));
58-
device->CreateRenderTargetView(back, nullptr, &rtv);
59-
back->Release();
56+
wil::com_ptr<ID3D11Texture2D> back;
57+
swapChain->GetBuffer(0, IID_PPV_ARGS(back.put()));
58+
device->CreateRenderTargetView(back.get(), nullptr, rtv.put());
6059
}
6160

6261
void D3DContext::CleanupRTV()
6362
{
64-
if (rtv)
65-
{
66-
rtv->Release();
67-
rtv = nullptr;
68-
}
63+
rtv.reset();
6964
}
7065

7166
void D3DContext::Cleanup()
7267
{
7368
CleanupRTV();
74-
if (swapChain)
75-
{
76-
swapChain->Release();
77-
swapChain = nullptr;
78-
}
79-
if (deviceCtx)
80-
{
81-
deviceCtx->Release();
82-
deviceCtx = nullptr;
83-
}
84-
if (device)
85-
{
86-
device->Release();
87-
device = nullptr;
88-
}
69+
swapChain.reset();
70+
deviceCtx.reset();
71+
device.reset();
8972
}
9073

9174
void D3DContext::Resize(LPARAM lParam)

src/d3d_helpers.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
#pragma once
22
#include <d3d11.h>
33
#include <dxgi.h>
4+
#include <wil/com.h>
45

56
struct D3DContext
67
{
7-
ID3D11Device* device = nullptr;
8-
ID3D11DeviceContext* deviceCtx = nullptr;
9-
IDXGISwapChain* swapChain = nullptr;
10-
ID3D11RenderTargetView* rtv = nullptr;
8+
wil::com_ptr<ID3D11Device> device;
9+
wil::com_ptr<ID3D11DeviceContext> deviceCtx;
10+
wil::com_ptr<IDXGISwapChain> swapChain;
11+
wil::com_ptr<ID3D11RenderTargetView> rtv;
1112

1213
[[nodiscard]] bool Create(HWND hwnd, int refreshRatePreferred = 60);
1314
void CreateRTV();

src/dinput_backend.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@
1010
DInputBackend::~DInputBackend()
1111
{
1212
ReleaseDevices();
13-
if (di_)
14-
{
15-
di_->Release();
16-
di_ = nullptr;
17-
}
13+
di_.reset();
1814
}
1915

2016
void DInputBackend::Init(const HWND hwnd)
@@ -25,7 +21,7 @@ void DInputBackend::Init(const HWND hwnd)
2521
GetWindowLongPtr(hwnd, GWLP_HINSTANCE));
2622

2723
if (FAILED(DirectInput8Create(hInst, DIRECTINPUT_VERSION,
28-
IID_IDirectInput8W, reinterpret_cast<void**>(&di_), nullptr)))
24+
IID_IDirectInput8W, reinterpret_cast<void**>(di_.put()), nullptr)))
2925
return;
3026

3127
EnumerateDevices();
@@ -38,7 +34,7 @@ void DInputBackend::ReleaseDevices()
3834
if (d.device)
3935
{
4036
d.device->Unacquire();
41-
d.device->Release();
37+
d.device.reset();
4238
}
4339
if (d.slot >= 0 && d.slot < kMaxDevices)
4440
states_[d.slot] = GamepadState{};
@@ -197,7 +193,7 @@ void DInputBackend::EnumerateDevices()
197193
if (d.device)
198194
{
199195
d.device->Unacquire();
200-
d.device->Release();
196+
d.device.reset();
201197
}
202198
return true;
203199
});
@@ -211,21 +207,19 @@ bool DInputBackend::SetupDevice(
211207
info.productId = static_cast<uint16_t>(HIWORD(inst.guidProduct.Data1));
212208
info.productName = inst.tszProductName;
213209

214-
if (FAILED(di_->CreateDevice(inst.guidInstance, &info.device, nullptr)))
210+
if (FAILED(di_->CreateDevice(inst.guidInstance, info.device.put(), nullptr)))
215211
return false;
216212

217213
if (FAILED(info.device->SetDataFormat(&c_dfDIJoystick2)))
218214
{
219-
info.device->Release();
220-
info.device = nullptr;
215+
info.device.reset();
221216
return false;
222217
}
223218

224219
if (FAILED(info.device->SetCooperativeLevel(
225220
hwnd_, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
226221
{
227-
info.device->Release();
228-
info.device = nullptr;
222+
info.device.reset();
229223
return false;
230224
}
231225

@@ -241,8 +235,7 @@ bool DInputBackend::SetupDevice(
241235
int s = AllocateSlot();
242236
if (s < 0)
243237
{
244-
info.device->Release();
245-
info.device = nullptr;
238+
info.device.reset();
246239
return false;
247240
}
248241
info.slot = s;

src/dinput_backend.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#endif
99
#include <dinput.h>
1010
#include <vector>
11+
#include <wil/com.h>
1112

1213
class DInputBackend final : public IInputBackend
1314
{
@@ -49,11 +50,11 @@ class DInputBackend final : public IInputBackend
4950
[[nodiscard]] const char* GetName() const override;
5051
[[nodiscard]] const char* GetSlotDisplayName(int slot) const override;
5152

52-
private:
53+
private:
5354
struct DeviceInfo
5455
{
5556
GUID instanceGuid{};
56-
IDirectInputDevice8W* device = nullptr;
57+
wil::com_ptr<IDirectInputDevice8W> device;
5758
int slot = -1;
5859
bool found = false;
5960
uint16_t vendorId = 0;
@@ -62,7 +63,7 @@ class DInputBackend final : public IInputBackend
6263
};
6364

6465
HWND hwnd_ = nullptr;
65-
IDirectInput8W* di_ = nullptr;
66+
wil::com_ptr<IDirectInput8W> di_;
6667
std::vector<DeviceInfo> devices_;
6768
GamepadState states_[kMaxDevices]{};
6869
int pollCounter_ = 0;

src/hidapi_backend.cpp

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,16 @@ HidApiBackend::~HidApiBackend()
2020

2121
void HidApiBackend::CloseDevice(DeviceInfo& dev)
2222
{
23-
if (dev.handle != INVALID_HANDLE_VALUE)
23+
if (dev.handle.is_valid())
2424
{
2525
if (dev.readPending)
26-
CancelIo(dev.handle);
27-
CloseHandle(dev.handle);
28-
dev.handle = INVALID_HANDLE_VALUE;
29-
}
30-
if (dev.overlapped.hEvent)
31-
{
32-
CloseHandle(dev.overlapped.hEvent);
33-
dev.overlapped.hEvent = nullptr;
26+
CancelIo(dev.handle.get());
27+
dev.handle.reset();
3428
}
29+
dev.readEvent.reset();
30+
dev.overlapped.hEvent = nullptr;
3531
dev.readPending = false;
36-
if (dev.preparsed)
37-
{
38-
HidD_FreePreparsedData(dev.preparsed);
39-
dev.preparsed = nullptr;
40-
}
32+
dev.preparsed.reset();
4133
dev.readBuf.clear();
4234
if (dev.slot >= 0 && dev.slot < kMaxDevices)
4335
states_[dev.slot] = GamepadState{};
@@ -62,7 +54,7 @@ void HidApiBackend::Poll()
6254
for (auto it = devices_.begin(); it != devices_.end();)
6355
{
6456
auto& dev = **it;
65-
if (dev.handle == INVALID_HANDLE_VALUE)
57+
if (!dev.handle.is_valid())
6658
{
6759
++it;
6860
continue;
@@ -76,7 +68,7 @@ void HidApiBackend::Poll()
7668
}
7769

7870
DWORD bytesRead = 0;
79-
BOOL ok = GetOverlappedResult(dev.handle, &dev.overlapped,
71+
BOOL ok = GetOverlappedResult(dev.handle.get(), &dev.overlapped,
8072
&bytesRead, FALSE);
8173
if (ok)
8274
{
@@ -228,40 +220,35 @@ bool HidApiBackend::OpenAndSetup(const wchar_t* path, DeviceInfo& info)
228220
if (h == INVALID_HANDLE_VALUE)
229221
return false;
230222

231-
info.handle = h;
223+
info.handle.reset(h);
232224

233225
HIDD_ATTRIBUTES attrs{};
234226
attrs.Size = sizeof(attrs);
235-
if (HidD_GetAttributes(h, &attrs))
227+
if (HidD_GetAttributes(info.handle.get(), &attrs))
236228
{
237229
info.vendorId = attrs.VendorID;
238230
info.productId = attrs.ProductID;
239231
}
240232

241233
PHIDP_PREPARSED_DATA pp = nullptr;
242-
if (!HidD_GetPreparsedData(h, &pp))
234+
if (!HidD_GetPreparsedData(info.handle.get(), &pp))
243235
{
244-
CloseHandle(h);
245-
info.handle = INVALID_HANDLE_VALUE;
236+
info.handle.reset();
246237
return false;
247238
}
248-
info.preparsed = pp;
239+
info.preparsed.reset(pp);
249240

250241
if (HidP_GetCaps(pp, &info.caps) != HIDP_STATUS_SUCCESS)
251242
{
252-
HidD_FreePreparsedData(pp);
253-
info.preparsed = nullptr;
254-
CloseHandle(h);
255-
info.handle = INVALID_HANDLE_VALUE;
243+
info.preparsed.reset();
244+
info.handle.reset();
256245
return false;
257246
}
258247

259248
if (!IsGamepadOrJoystick(info.caps))
260249
{
261-
HidD_FreePreparsedData(pp);
262-
info.preparsed = nullptr;
263-
CloseHandle(h);
264-
info.handle = INVALID_HANDLE_VALUE;
250+
info.preparsed.reset();
251+
info.handle.reset();
265252
return false;
266253
}
267254

@@ -279,10 +266,8 @@ bool HidApiBackend::OpenAndSetup(const wchar_t* path, DeviceInfo& info)
279266
int s = AllocateSlot();
280267
if (s < 0)
281268
{
282-
HidD_FreePreparsedData(pp);
283-
info.preparsed = nullptr;
284-
CloseHandle(h);
285-
info.handle = INVALID_HANDLE_VALUE;
269+
info.preparsed.reset();
270+
info.handle.reset();
286271
return false;
287272
}
288273

@@ -293,7 +278,8 @@ bool HidApiBackend::OpenAndSetup(const wchar_t* path, DeviceInfo& info)
293278
info.readBuf.resize(info.caps.InputReportByteLength);
294279

295280
info.overlapped = {};
296-
info.overlapped.hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
281+
info.readEvent.reset(CreateEventW(nullptr, TRUE, FALSE, nullptr));
282+
info.overlapped.hEvent = info.readEvent.get();
297283

298284
StartRead(info);
299285
return true;
@@ -303,14 +289,14 @@ bool HidApiBackend::OpenAndSetup(const wchar_t* path, DeviceInfo& info)
303289

304290
void HidApiBackend::StartRead(DeviceInfo& dev)
305291
{
306-
if (dev.handle == INVALID_HANDLE_VALUE) return;
292+
if (!dev.handle.is_valid()) return;
307293

308294
constexpr int kMaxSyncReads = 16;
309295
for (int attempt = 0; attempt < kMaxSyncReads; ++attempt)
310296
{
311297
ResetEvent(dev.overlapped.hEvent);
312298
DWORD bytesRead = 0;
313-
BOOL ok = ReadFile(dev.handle, dev.readBuf.data(),
299+
BOOL ok = ReadFile(dev.handle.get(), dev.readBuf.data(),
314300
static_cast<DWORD>(dev.readBuf.size()),
315301
&bytesRead, &dev.overlapped);
316302
if (ok)
@@ -353,7 +339,7 @@ void HidApiBackend::ParseReport(DeviceInfo& dev, DWORD bytesRead)
353339
if (bytesRead == 0) return;
354340
if (dev.slot < 0 || dev.slot >= kMaxDevices) return;
355341

356-
PHIDP_PREPARSED_DATA pp = dev.preparsed;
342+
PHIDP_PREPARSED_DATA pp = dev.preparsed.get();
357343
if (!pp) return;
358344

359345
auto& gs = states_[dev.slot];

src/hidapi_backend.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <memory>
1111
#include <vector>
1212
#include <string>
13+
#include <wil/resource.h>
1314

1415
class HidApiBackend final : public IInputBackend
1516
{
@@ -61,10 +62,22 @@ class HidApiBackend final : public IInputBackend
6162
struct DeviceInfo
6263
{
6364
std::wstring path;
64-
HANDLE handle = INVALID_HANDLE_VALUE;
65+
wil::unique_hfile handle;
66+
wil::unique_handle readEvent;
6567
OVERLAPPED overlapped{};
6668
std::vector<BYTE> readBuf;
67-
PHIDP_PREPARSED_DATA preparsed = nullptr;
69+
struct UniquePreparsed
70+
{
71+
PHIDP_PREPARSED_DATA p = nullptr;
72+
UniquePreparsed() = default;
73+
explicit UniquePreparsed(PHIDP_PREPARSED_DATA q) : p(q) {}
74+
~UniquePreparsed() { reset(); }
75+
UniquePreparsed(UniquePreparsed&& other) noexcept : p(other.p) { other.p = nullptr; }
76+
UniquePreparsed& operator=(UniquePreparsed&& other) noexcept { reset(other.p); other.p = nullptr; return *this; }
77+
void reset(PHIDP_PREPARSED_DATA q = nullptr) { if (p) HidD_FreePreparsedData(p); p = q; }
78+
PHIDP_PREPARSED_DATA get() const { return p; }
79+
explicit operator bool() const { return p != nullptr; }
80+
} preparsed;
6881
HIDP_CAPS caps{};
6982
std::vector<HIDP_VALUE_CAPS> valueCaps;
7083
int slot = -1;

0 commit comments

Comments
 (0)