Skip to content

Commit

Permalink
-Went to creating IO targets from enumerated symlinks.
Browse files Browse the repository at this point in the history
-The targets device ID's are then compared against taillights (our) device ID.
-If there is a match, then the IO target is sent down the stack.

Tested on two computers.
  • Loading branch information
ManOnTheMountainTech committed Mar 6, 2024
1 parent d65962c commit 06e7b02
Show file tree
Hide file tree
Showing 7 changed files with 488 additions and 64 deletions.
11 changes: 11 additions & 0 deletions TailLight/SetBlack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

typedef struct _SET_BLACK_WORKITEM_CONTEXT {
UNICODE_STRING symLink;
} SET_BLACK_WORKITEM_CONTEXT, * PSET_BLACK_WORKITEM_CONTEXT;

WDF_DECLARE_CONTEXT_TYPE(SET_BLACK_WORKITEM_CONTEXT);

NTSTATUS CreateWorkItemForIoTargetOpenDevice(WDFDEVICE device, CONST UNICODE_STRING& symLink);
NTSTATUS SetBlackAsync(WDFDEVICE device,
CONST UNICODE_STRING& symLink);
260 changes: 260 additions & 0 deletions TailLight/SetTaillightBlack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
#include "driver.h"
#include <Hidport.h>

#include "SetBlack.h"

EVT_WDF_REQUEST_COMPLETION_ROUTINE SetBlackCompletionRoutine;
EVT_WDF_WORKITEM SetBlackWorkItem;

NTSTATUS CreateWorkItemForIoTargetOpenDevice(WDFDEVICE device,
CONST UNICODE_STRING& symLink)
/*++
Routine Description:
Creates a WDF workitem to do the SetBlack() call after the driver
stack has initialized.
Arguments:
Device - Handle to a pre-allocated WDF work item.
Requirements:
Must be synchronized to the device.
--*/
{
WDFWORKITEM hWorkItem = 0;
NTSTATUS status = STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE;
{
WDF_WORKITEM_CONFIG workItemConfig;
WDF_OBJECT_ATTRIBUTES workItemAttributes;
WDF_OBJECT_ATTRIBUTES_INIT(&workItemAttributes);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workItemAttributes,
SET_BLACK_WORKITEM_CONTEXT);
workItemAttributes.ParentObject = device;

DEVICE_CONTEXT* pDeviceContext = WdfObjectGet_DEVICE_CONTEXT(device);

// It's possible to get called twice. Been there, done that?
if ((!pDeviceContext) || pDeviceContext->fSetBlackSuccess) {
return STATUS_SUCCESS;
}

WDF_WORKITEM_CONFIG_INIT(&workItemConfig, SetBlackWorkItem);

status = WdfWorkItemCreate(&workItemConfig,
&workItemAttributes,
&hWorkItem);

if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID,
DPFLTR_ERROR_LEVEL,
"TailLight: Workitem creation failure 0x%x\n",
status));
return status; // Maybe better luck next time.
}

auto workItemContext = WdfObjectGet_SET_BLACK_WORKITEM_CONTEXT(hWorkItem);
workItemContext->symLink = symLink;
}

WdfWorkItemEnqueue(hWorkItem);

return status;
}

static NTSTATUS TryToOpenIoTarget(WDFIOTARGET target,
CONST UNICODE_STRING symLink) {

PAGED_CODE();

WDF_IO_TARGET_OPEN_PARAMS openParams = {};
WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
&openParams,
&symLink,
STANDARD_RIGHTS_ALL);

openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ;

NTSTATUS status = STATUS_UNSUCCESSFUL;

// Ensure freed if fails.
status = WdfIoTargetOpen(target, &openParams);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID,
DPFLTR_ERROR_LEVEL,
"TailLight: 0x%x while opening the I/O target from worker thread\n",
status));
}

return status;
}

void SetBlackCompletionRoutine(
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS Params,
_In_ WDFCONTEXT Context)
{
UNREFERENCED_PARAMETER(Target);
UNREFERENCED_PARAMETER(Params);
UNREFERENCED_PARAMETER(Context);

NTSTATUS status = STATUS_UNSUCCESSFUL;
status = WdfRequestGetStatus(Request);
KdPrint(("TailLight: %s WdfRequestSend status: 0x%x\n", __func__, status));

// One-shot and top of stack, so delete and pray.
WdfObjectDelete(Request);
}

VOID SetBlackWorkItem(
WDFWORKITEM workItem)
/*++
Routine Description:
Creates a WDF workitem to do the SetBlack() call after the driver
stack has initialized.
Arguments:
workItem - Handle to a pre-allocated WDF work item.
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
WDFDEVICE device = static_cast<WDFDEVICE>(WdfWorkItemGetParentObject(workItem));
auto workItemContext = WdfObjectGet_SET_BLACK_WORKITEM_CONTEXT(workItem);

status = SetBlackAsync(device, workItemContext->symLink);

if (NT_SUCCESS(status)) {
DEVICE_CONTEXT* pDeviceContext = WdfObjectGet_DEVICE_CONTEXT(device);
InterlockedIncrement((PLONG)(&pDeviceContext->fSetBlackSuccess));
}

NukeWdfHandle<WDFWORKITEM>(workItem);
}

NTSTATUS SetBlackAsync(WDFDEVICE device,
CONST UNICODE_STRING& symLink) {

PAGED_CODE();

NTSTATUS status = STATUS_UNSUCCESSFUL;
WDFIOTARGET hidTarget = NULL;

DEVICE_CONTEXT* pDeviceContext = NULL;

pDeviceContext =
WdfObjectGet_DEVICE_CONTEXT(device);

if (pDeviceContext == NULL) {
return STATUS_DEVICE_NOT_READY;
}
{
WDF_OBJECT_ATTRIBUTES attributes;
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);

// Ensure freed if fails.
status = WdfIoTargetCreate(
device,
&attributes,
&hidTarget);

if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID,
DPFLTR_ERROR_LEVEL,
"TailLight: 0x%x while creating I/O target from worker thread\n",
status));
return status;
}

status = TryToOpenIoTarget(hidTarget, symLink);
}

if (NT_SUCCESS(status)) {

UNICODE_STRING theirHwId = {};

status = AllocateHwIdString(hidTarget, theirHwId);
if (NT_SUCCESS(status)) {
if (!RtlEqualUnicodeString(&pDeviceContext->OurHardwareId,
&theirHwId,
TRUE)) {
status = STATUS_NOT_FOUND;
goto ExitAndFree;
}
}

WDFREQUEST request = NULL;

status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES,
hidTarget,
&request);

if (!NT_SUCCESS(status)) {
KdPrint(("TailLight: WdfRequestCreate failed 0x%x\n", status));
goto ExitAndFree;
}

WdfRequestSetCompletionRoutine(
request,
SetBlackCompletionRoutine,
WDF_NO_CONTEXT);

TailLightReport report = {};
report.Blue = 0x0;
report.Green = 0x0;
report.Red = 0x0;

// Set up a WDF memory object for the IOCTL request
WDF_OBJECT_ATTRIBUTES mem_attrib = {};
WDF_OBJECT_ATTRIBUTES_INIT(&mem_attrib);
mem_attrib.ParentObject = request; // auto-delete with request*/

WDFMEMORY InBuffer = 0;
BYTE* pInBuffer = nullptr;

status = WdfMemoryCreate(&mem_attrib,
NonPagedPoolNx,
POOL_TAG,
sizeof(TailLightReport),
&InBuffer,
(void**)&pInBuffer);

if (!NT_SUCCESS(status)) {
KdPrint(("TailLight: WdfMemoryCreate failed: 0x%x\n", status));
goto ExitAndFree;
}

// TODO: Wondering if we just cant cast pInBuffr as a TailLightReport
RtlCopyMemory(pInBuffer, &report, sizeof(TailLightReport));

// Format the request as write operation
status = WdfIoTargetFormatRequestForIoctl(hidTarget,
request,
IOCTL_HID_SET_FEATURE,
InBuffer,
NULL,
0,
0);

if (!NT_SUCCESS(status)) {
KdPrint(("TailLight: WdfIoTargetFormatRequestForIoctl failed: 0x%x\n", status));
goto ExitAndFree;
}

if (!WdfRequestSend(request, hidTarget, WDF_NO_SEND_OPTIONS)) {
WdfObjectDelete(request);
request = NULL;
status = STATUS_UNSUCCESSFUL;
}
}

ExitAndFree:
NukeWdfHandle<WDFIOTARGET>(hidTarget);

return status;
}
6 changes: 5 additions & 1 deletion TailLight/TailLight.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<DriverType>KMDF</DriverType>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
Expand Down Expand Up @@ -82,12 +83,13 @@ copy "$(WDKBinRoot_x64)\certmgr.exe" $(PackageDir)</Command>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib</AdditionalDependencies>
<AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\hidparse.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
</Link>
<ClCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<ShowIncludes>false</ShowIncludes>
</ClCompile>
<Midl>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
Expand All @@ -109,6 +111,7 @@ copy "$(WDKBinRoot_x64)\certmgr.exe" $(PackageDir)</Command>
<ClCompile Include="device.cpp" />
<ClCompile Include="driver.cpp" />
<ClCompile Include="eventlog.cpp" />
<ClCompile Include="SetTaillightBlack.cpp" />
<ClCompile Include="vfeature.cpp" />
<ClCompile Include="wmi.cpp" />
<ResourceCompile Include="module.rc" />
Expand All @@ -122,6 +125,7 @@ copy "$(WDKBinRoot_x64)\certmgr.exe" $(PackageDir)</Command>
<ClInclude Include="device.h" />
<ClInclude Include="driver.h" />
<ClInclude Include="eventlog.h" />
<ClInclude Include="SetBlack.h" />
<ClInclude Include="TailLight.h" />
<ClInclude Include="vfeature.h" />
<ClInclude Include="wmi.h" />
Expand Down
Loading

0 comments on commit 06e7b02

Please sign in to comment.