Skip to content

Commit

Permalink
Added registry flag IPCEnabled to disable IPC until production-ready (
Browse files Browse the repository at this point in the history
#389)

* Update IPC.c

* Added random event name generation

* Added IPCEnabled registry flag

* Implemented use of IsEnabled in the entire project

* Fixed handle leak

* Update appveyor.yml

* Bumped minor version

* Update appveyor.yml

* Update dshidmini.vcxproj

* Fixed System.IO.FileNotFoundException: Could not load file or assembly 'Nefarius.Utilities.WixSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
  • Loading branch information
nefarius authored Nov 4, 2024
1 parent 98a1ecd commit 1494d75
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 43 deletions.
5 changes: 3 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: 3.2.{build}.0
version: 3.3.{build}.0
build_cloud: WIN-LKR467JS4GL
image: Windows
test: off
Expand All @@ -16,6 +16,7 @@ configuration:
branches:
only:
- master
- /v\d+\.\d+\.\d+\.\d+/
skip_commits:
files:
- '**/*.md'
Expand All @@ -41,7 +42,7 @@ dotnet_csproj:
informational_version: '{version}'
before_build:
- cmd: nuget restore
- cmd: dotnet tool install --global Nefarius.Tools.Vpatch
#- cmd: dotnet tool install --global Nefarius.Tools.Vpatch
- cmd: vpatch --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\sys\dshidmini.vcxproj" --vcxproj.inf-time-stamp
- cmd: vpatch --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\sys\dshidmini.rc" --resource.file-version --resource.product-version
- cmd: vpatch --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\XInputBridge\XInputBridge.rc" --resource.file-version --resource.product-version
Expand Down
2 changes: 2 additions & 0 deletions setup/InstallScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ private static void Main()
project.DefaultRefAssemblies.Add(typeof(WebClient).Assembly.Location);
project.DefaultRefAssemblies.Add(typeof(JsonSerializer).Assembly.Location);
project.DefaultRefAssemblies.Add(typeof(Binder).Assembly.Location);
// Nefarius.Utilities.WixSharp
project.DefaultRefAssemblies.Add(typeof(WixExt).Assembly.Location);

project.AfterInstall += ProjectOnAfterInstall;

Expand Down
53 changes: 44 additions & 9 deletions sys/Device.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,22 @@ void DsHidMini_DeviceCleanup(
WdfWaitLockAcquire(driverContext->SlotsLock, NULL);
{
CLEAR_SLOT(driverContext, deviceContext->SlotIndex);
driverContext->IPC.DeviceDispatchers.Callbacks[deviceContext->SlotIndex] = NULL;
driverContext->IPC.DeviceDispatchers.Contexts[deviceContext->SlotIndex] = NULL;
if (driverContext->IPC.IsEnabled)
{
driverContext->IPC.DeviceDispatchers.Callbacks[deviceContext->SlotIndex] = NULL;
driverContext->IPC.DeviceDispatchers.Contexts[deviceContext->SlotIndex] = NULL;
}
}
WdfWaitLockRelease(driverContext->SlotsLock);

const size_t offset = (sizeof(IPC_HID_INPUT_REPORT_MESSAGE) * (deviceContext->SlotIndex - 1));
const PUCHAR pHIDBuffer = (driverContext->IPC.SharedRegions.HID.Buffer + offset);
if (driverContext->IPC.IsEnabled)
{
const size_t offset = (sizeof(IPC_HID_INPUT_REPORT_MESSAGE) * (deviceContext->SlotIndex - 1));
const PUCHAR pHIDBuffer = (driverContext->IPC.SharedRegions.HID.Buffer + offset);

// zero out the slot so potential readers get notified we're gone
RtlZeroMemory(pHIDBuffer, sizeof(IPC_HID_INPUT_REPORT_MESSAGE));
// zero out the slot so potential readers get notified we're gone
RtlZeroMemory(pHIDBuffer, sizeof(IPC_HID_INPUT_REPORT_MESSAGE));
}

EventWriteUnloadEvent(Object);

Expand Down Expand Up @@ -450,8 +456,11 @@ DsDevice_InitContext(
);

pDevCtx->SlotIndex = slotIndex;
pDrvCtx->IPC.DeviceDispatchers.Callbacks[slotIndex] = DSHM_EvtDispatchDeviceMessage;
pDrvCtx->IPC.DeviceDispatchers.Contexts[slotIndex] = pDevCtx;
if (pDrvCtx->IPC.IsEnabled)
{
pDrvCtx->IPC.DeviceDispatchers.Callbacks[slotIndex] = DSHM_EvtDispatchDeviceMessage;
pDrvCtx->IPC.DeviceDispatchers.Contexts[slotIndex] = pDevCtx;
}
break;
}
}
Expand Down Expand Up @@ -742,7 +751,33 @@ DsDevice_InitContext(
break;
}

pDevCtx->IPC.InputReportWaitHandle = CreateEventA(&sa, FALSE, FALSE, NULL);
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = Device;

PUCHAR hidEventNameBuffer = NULL;

if (!NT_SUCCESS(status = WdfMemoryCreate(
&attributes,
NonPagedPoolNx,
DS3_POOL_TAG,
DSHM_HID_EVENT_NAME_LEN,
&pDevCtx->IPC.InputReportWaitEventName,
(PVOID*)&hidEventNameBuffer
)))
{
TraceError(
TRACE_DEVICE,
"WdfMemoryCreate failed with status %!STATUS!",
status
);
EventWriteFailedWithNTStatus(__FUNCTION__, L"WdfMemoryCreate", status);
break;
}

RtlZeroMemory(hidEventNameBuffer, DSHM_HID_EVENT_NAME_LEN);
GenerateRandomEventName(hidEventNameBuffer, DSHM_HID_EVENT_NAME_RND_LEN);

pDevCtx->IPC.InputReportWaitHandle = CreateEventA(&sa, FALSE, FALSE, (LPCSTR)hidEventNameBuffer);

if (pDevCtx->IPC.InputReportWaitHandle == NULL)
{
Expand Down
5 changes: 5 additions & 0 deletions sys/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
EXTERN_C_START

#define DSHM_NAMED_EVENT_DISCONNECT L"Global\\DsHidMiniDisconnectEvent%ls"
#define DSHM_HID_EVENT_NAME_PREFIX "Global\\DsHidMiniHidInputReportEvent_"
#define DSHM_HID_EVENT_NAME_RND_LEN 16
#define DSHM_HID_EVENT_NAME_LEN (sizeof(DSHM_HID_EVENT_NAME_PREFIX) + DSHM_HID_EVENT_NAME_RND_LEN)

struct USB_DEVICE_CONTEXT
{
Expand Down Expand Up @@ -361,6 +364,8 @@ typedef struct _DEVICE_CONTEXT

struct
{
WDFMEMORY InputReportWaitEventName;

HANDLE InputReportWaitHandle;
} IPC;

Expand Down
6 changes: 6 additions & 0 deletions sys/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ typedef struct _DSHM_DRIVER_CONTEXT
//
struct
{
//
// Whether the IPC module is enabled or not
//
ULONG IsEnabled;

//
// Handle of the memory-mapped file
//
Expand Down Expand Up @@ -190,5 +195,6 @@ EVT_WDF_DRIVER_DEVICE_ADD dshidminiEvtDeviceAdd;
EVT_WDF_OBJECT_CONTEXT_CLEANUP dshidminiEvtDriverContextCleanup;

VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength);
void GenerateRandomEventName(PUCHAR buffer, size_t length);

EXTERN_C_END
88 changes: 75 additions & 13 deletions sys/IPC.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,74 @@ static DWORD WINAPI DSHM_IPC_ClientDispatchProc(
_In_ LPVOID lpParameter
);

//
// Sets up direct driver process IPC for sideband communication
//
NTSTATUS InitIPC(void)
{
FuncEntry(TRACE_IPC);

DECLARE_CONST_UNICODE_STRING(valNameIPCEnaabled, L"IPCEnabled");

const WDFDRIVER driver = WdfGetDriver();
const PDSHM_DRIVER_CONTEXT context = DriverGetContext(driver);
WDFKEY hKeyParameters = NULL;
NTSTATUS status;

PUCHAR pCmdBuf = NULL;
PUCHAR pHIDBuf = NULL;
HANDLE hReadEvent = NULL;
HANDLE hWriteEvent = NULL;
HANDLE hMapFile = NULL;
HANDLE hMutex = NULL;
HANDLE hThread = NULL;
HANDLE hThreadTermination = NULL;

if (!NT_SUCCESS(status = WdfDriverOpenParametersRegistryKey(
driver,
KEY_READ,
WDF_NO_OBJECT_ATTRIBUTES,
&hKeyParameters
)))
{
TraceError(
TRACE_IPC,
"WdfDriverOpenParametersRegistryKey failed with status %!STATUS!",
status
);
goto exitFailure;
}

if (!NT_SUCCESS(status = WdfRegistryQueryULong(
hKeyParameters,
&valNameIPCEnaabled,
&context->IPC.IsEnabled
)))
{
TraceError(
TRACE_IPC,
"WdfRegistryQueryULong failed with status %!STATUS!",
status
);
goto exitFailure;
}

//
// Feature disabled in registry
//
if (!context->IPC.IsEnabled)
{
TraceInformation(
TRACE_IPC,
"IPC feature disabled, aborting initialization"
);
status = STATUS_DEVICE_FEATURE_NOT_SUPPORTED;
goto exitFailure;
}

SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
DWORD pageSize = sysInfo.dwAllocationGranularity; // Usually 4096 bytes (4KB)
DWORD pageSize = sysInfo.dwAllocationGranularity;

DWORD cmdRegionSize = pageSize;
DWORD hidRegionSize = pageSize;
Expand All @@ -25,16 +83,7 @@ NTSTATUS InitIPC(void)
TRACE_IPC,
"pageSize = %d, cmdRegionSize = %d, hidRegionSize = %d, totalRegionSize = %d",
pageSize, cmdRegionSize, hidRegionSize, totalRegionSize
);

PUCHAR pCmdBuf = NULL;
PUCHAR pHIDBuf = NULL;
HANDLE hReadEvent = NULL;
HANDLE hWriteEvent = NULL;
HANDLE hMapFile = NULL;
HANDLE hMutex = NULL;
HANDLE hThread = NULL;
HANDLE hThreadTermination = NULL;
);

SECURITY_DESCRIPTOR sd = { 0 };

Expand Down Expand Up @@ -85,7 +134,6 @@ NTSTATUS InitIPC(void)
goto exitFailure;
}

// Create a named event for signaling
hReadEvent = CreateEventA(&sa, FALSE, FALSE, DSHM_IPC_READ_EVENT_NAME);
if (hReadEvent == NULL)
{
Expand Down Expand Up @@ -216,11 +264,17 @@ NTSTATUS InitIPC(void)

context->IPC.DispatchThread = hThread;

if (hKeyParameters)
WdfRegistryClose(hKeyParameters);

FuncExitNoReturn(TRACE_IPC);

return STATUS_SUCCESS;

exitFailure:
if (hKeyParameters)
WdfRegistryClose(hKeyParameters);

if (pCmdBuf)
UnmapViewOfFile(pCmdBuf);

Expand All @@ -245,13 +299,16 @@ NTSTATUS InitIPC(void)
if (hThreadTermination)
CloseHandle(hThreadTermination);

const NTSTATUS status = NTSTATUS_FROM_WIN32(GetLastError());
status = NT_SUCCESS(status) ? status : NTSTATUS_FROM_WIN32(GetLastError());

FuncExit(TRACE_IPC, "status=%!STATUS!", status);

return status;
}

//
// Frees IPC resources
//
void DestroyIPC(void)
{
FuncEntry(TRACE_IPC);
Expand Down Expand Up @@ -291,6 +348,9 @@ void DestroyIPC(void)
FuncExitNoReturn(TRACE_IPC);
}

//
// Processes incoming IPC commands
//
static NTSTATUS DSHM_IPC_DispatchIncomingCommandMessage(
_In_ const PDSHM_DRIVER_CONTEXT Context,
_In_ const PDSHM_IPC_MSG_HEADER Message
Expand Down Expand Up @@ -445,6 +505,8 @@ static DWORD WINAPI DSHM_IPC_ClientDispatchProc(
"DSHM_IPC_DispatchIncomingCommandMessage reported non-success status %!STATUS!",
status
);

// TODO: can we do anything else with a failure status?
}
}

Expand Down
41 changes: 23 additions & 18 deletions sys/InputReport.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,29 @@ DSHM_ParseInputReport(

const WDFDRIVER driver = WdfGetDriver();
const PDSHM_DRIVER_CONTEXT pDrvCtx = DriverGetContext(driver);
/*
* Offset calculation puts each devices' input report copy
* in their respective position in the memory region, like:
* 1st device: ((4 + 49) * (1 - 1)) = 0
* 2nd device: ((4 + 49) * (2 - 1)) = 53
* 3rd device: ((4 + 49) * (3 - 1)) = 106
* and so on
*/
const size_t offset = (sizeof(IPC_HID_INPUT_REPORT_MESSAGE) * (DeviceContext->SlotIndex - 1));
const PIPC_HID_INPUT_REPORT_MESSAGE pHIDBuffer = (PIPC_HID_INPUT_REPORT_MESSAGE)(pDrvCtx->IPC.SharedRegions.HID.Buffer + offset);

// prefix each report with associated device index
pHIDBuffer->SlotIndex = DeviceContext->SlotIndex;
// skip index and copy unmodified raw report to the section
RtlCopyMemory(&pHIDBuffer->InputReport, Report, sizeof(DS3_RAW_INPUT_REPORT));

// signal any reader that there is new data available
SetEvent(DeviceContext->IPC.InputReportWaitHandle);

if (pDrvCtx->IPC.IsEnabled)
{
/*
* Offset calculation puts each devices' input report copy
* in their respective position in the memory region, like:
* 1st device: ((4 + 49) * (1 - 1)) = 0
* 2nd device: ((4 + 49) * (2 - 1)) = 53
* 3rd device: ((4 + 49) * (3 - 1)) = 106
* and so on
*/
const size_t offset = (sizeof(IPC_HID_INPUT_REPORT_MESSAGE) * (DeviceContext->SlotIndex - 1));
const PIPC_HID_INPUT_REPORT_MESSAGE pHIDBuffer = (PIPC_HID_INPUT_REPORT_MESSAGE)(pDrvCtx->IPC.SharedRegions.HID.Buffer +
offset);

// prefix each report with associated device index
pHIDBuffer->SlotIndex = DeviceContext->SlotIndex;
// skip index and copy unmodified raw report to the section
RtlCopyMemory(&pHIDBuffer->InputReport, Report, sizeof(DS3_RAW_INPUT_REPORT));

// signal any reader that there is new data available
SetEvent(DeviceContext->IPC.InputReportWaitHandle);
}

#pragma endregion

Expand Down
28 changes: 28 additions & 0 deletions sys/Util.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "Driver.h"
#include "Util.tmh"

#include <time.h>


VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength)
{
Expand Down Expand Up @@ -34,3 +36,29 @@ VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength)
UNREFERENCED_PARAMETER(BufferLength);
#endif
}

void GenerateRandomEventName(PUCHAR buffer, size_t length)
{
srand((unsigned int)time(NULL)); // Seed the random number generator

const char charset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
size_t prefix_len = strlen(DSHM_HID_EVENT_NAME_PREFIX);

// Ensure that the length is greater than the prefix length
if (length <= prefix_len)
{
buffer[0] = '\0'; // Set the buffer to an empty string
return;
}

strcpy_s((char*)buffer, length, DSHM_HID_EVENT_NAME_PREFIX);
size_t random_part_len = length - prefix_len - 1; // Leave space for the null terminator

for (size_t i = 0; i < random_part_len; ++i)
{
int key = rand() % (int)(sizeof(charset) - 1);
buffer[prefix_len + i] = charset[key];
}

buffer[length - 1] = '\0'; // Null-terminate the string
}
1 change: 0 additions & 1 deletion sys/dshidmini.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;BluetoothApis.lib</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);kernel32.lib;user32.lib</IgnoreSpecificDefaultLibraries>
</Link>
<Inf />
<Inf>
<TimeStamp>1.0.0.0</TimeStamp>
</Inf>
Expand Down

0 comments on commit 1494d75

Please sign in to comment.