diff --git a/appveyor.yml b/appveyor.yml index 1c990008..8151f4b0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 3.2.{build}.0 +version: 3.3.{build}.0 build_cloud: WIN-LKR467JS4GL image: Windows test: off @@ -16,6 +16,7 @@ configuration: branches: only: - master + - /v\d+\.\d+\.\d+\.\d+/ skip_commits: files: - '**/*.md' @@ -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 diff --git a/setup/InstallScript.cs b/setup/InstallScript.cs index 85c5427b..d8e1819a 100644 --- a/setup/InstallScript.cs +++ b/setup/InstallScript.cs @@ -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; diff --git a/sys/Device.c b/sys/Device.c index cf28f5ee..1fc1e7e5 100644 --- a/sys/Device.c +++ b/sys/Device.c @@ -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); @@ -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; } } @@ -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) { diff --git a/sys/Device.h b/sys/Device.h index 4e14aea4..f934b78b 100644 --- a/sys/Device.h +++ b/sys/Device.h @@ -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 { @@ -361,6 +364,8 @@ typedef struct _DEVICE_CONTEXT struct { + WDFMEMORY InputReportWaitEventName; + HANDLE InputReportWaitHandle; } IPC; diff --git a/sys/Driver.h b/sys/Driver.h index 08d9a0ca..0c6237f8 100644 --- a/sys/Driver.h +++ b/sys/Driver.h @@ -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 // @@ -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 diff --git a/sys/IPC.c b/sys/IPC.c index e51d9199..ebcd9680 100644 --- a/sys/IPC.c +++ b/sys/IPC.c @@ -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; @@ -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 }; @@ -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) { @@ -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); @@ -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); @@ -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 @@ -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? } } diff --git a/sys/InputReport.c b/sys/InputReport.c index 856d241f..074af168 100644 --- a/sys/InputReport.c +++ b/sys/InputReport.c @@ -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 diff --git a/sys/Util.c b/sys/Util.c index 0e82aa0c..d854f391 100644 --- a/sys/Util.c +++ b/sys/Util.c @@ -1,6 +1,8 @@ #include "Driver.h" #include "Util.tmh" +#include + VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength) { @@ -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 +} diff --git a/sys/dshidmini.vcxproj b/sys/dshidmini.vcxproj index af66d7be..a1af13c0 100644 --- a/sys/dshidmini.vcxproj +++ b/sys/dshidmini.vcxproj @@ -207,7 +207,6 @@ %(AdditionalDependencies);OneCoreUAP.lib;BluetoothApis.lib %(IgnoreSpecificDefaultLibraries);kernel32.lib;user32.lib - 1.0.0.0