Coder Social home page Coder Social logo

dmf's Introduction

Driver Module Framework (DMF)

DMF is an extension to WDF that enables extra functionality for a WDF driver developer. It helps developers write any type of WDF driver better and faster.

DMF as a framework allows creation of WDF objects called DMF Modules. The code for these DMF Modules can be shared between different drivers. In addition, DMF bundles a library of DMF Modules that we have developed for our drivers and feel would provide value to other driver developers.

DMF does not replace WDF. DMF is a second framework that is used with WDF. The developer leveraging DMF still uses WDF and all its primitives to write device drivers.

The source code for both the framework and Modules written using the framework are released.

Introduction Video from 2018 WinHEC:
www.WinHEC.com (See the video titled, "Introduction to Driver Module Framework".)

This blog post provides more information: https://blogs.windows.com/buildingapps/2018/08/15/introducing-driver-module-framework/

The Documentation\ folder has detailed information about the framework and how to use it.

DMF Documentation:

To learn how to build and use DMF in a driver, please look here: https://github.com/Microsoft/DMF/blob/master/Dmf/Documentation/Driver%20Module%20Framework.md

Module Documentation:

Detailed documentation about each Module is available on the wiki: https://github.com/Microsoft/DMF/wiki/DMF-Overview

Samples:

DmfSamples has all the sample drivers that show in incremental steps how to use DMF in a driver.

Questions/Feedback

Please send email to: [email protected]

To build DMF and the sample drivers, follow the steps here.

Contributing:

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

dmf's People

Contributors

ankurung avatar domars avatar girib avatar girishpattabiraman avatar gotham13 avatar harishsk avatar joncamp avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar mr-yamraj01 avatar msftgits avatar nefarius avatar rajeshbg avatar samtertzakian avatar surfacedmfuser1 avatar williambernardet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dmf's Issues

Unused inc folder

A lot of the samples add the ..\inc folder as additional includes folder, while for most samples this folder does not exist.

Examples:

<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.</AdditionalIncludeDirectories>

<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc;.;..\..\DMF\Modules.Library</AdditionalIncludeDirectories>

Latest code generates following linker errors in my project

I pulled the latest DMF code and now I am getting the following linker errors in my driver project...

1>user_code.obj : error LNK2019: unresolved external symbol _invalid_parameter_noinfo referenced in function memcpy_s
1>user_code.obj : error LNK2019: unresolved external symbol _errno referenced in function memcpy_s
1>DmfK.lib(DmfUtility.obj) : error LNK2019: unresolved external symbol __stdio_common_vswprintf referenced in function _vsnwprintf_l
1>DmfK.lib(DmfCore.obj) : error LNK2019: unresolved external symbol __stdio_common_vsprintf referenced in function _vsnprintf_l
1>DmfK.lib(Dmf_CrashDump.obj) : error LNK2019: unresolved external symbol __stdio_common_vsprintf_s referenced in function _vsprintf_s_l

Duplicated lines

Remove duplicated lines at:

#define HID_UNIT_EXPONENT_BYTE(val) (HID_GLOBAL_UNIT_EXPONENT | HID_SIZE_BYTE), val
#define HID_UNIT_EXPONENT_BYTE(val) (HID_GLOBAL_UNIT_EXPONENT | HID_SIZE_BYTE), val
#define HID_UNIT_EXPONENT_WORD(val) (HID_GLOBAL_UNIT_EXPONENT | HID_SIZE_WORD), (val & 0xFF), ((val >> 8) & 0xFF)
#define HID_UNIT_EXPONENT_WORD(val) (HID_GLOBAL_UNIT_EXPONENT | HID_SIZE_WORD), (val & 0xFF), ((val >> 8) & 0xFF)
#define HID_UNIT_EXPONENT_DWORD(val) (HID_GLOBAL_UNIT_EXPONENT | HID_SIZE_DWORD), (val & 0xFF), ((val >> 8) & 0xFF), ((val >> 16) & 0xFF), ((val >> 24) & 0xFF)
#define HID_UNIT_EXPONENT_DWORD(val) (HID_GLOBAL_UNIT_EXPONENT | HID_SIZE_DWORD), (val & 0xFF), ((val >> 8) & 0xFF), ((val >> 16) & 0xFF), ((val >> 24) & 0xFF)
#define HID_UNIT_BYTE(val) (HID_GLOBAL_UNIT | HID_SIZE_BYTE), val
#define HID_UNIT_BYTE(val) (HID_GLOBAL_UNIT | HID_SIZE_BYTE), val
#define HID_UNIT_WORD(val) (HID_GLOBAL_UNIT | HID_SIZE_WORD), (val & 0xFF), ((val >> 8) & 0xFF)
#define HID_UNIT_WORD(val) (HID_GLOBAL_UNIT | HID_SIZE_WORD), (val & 0xFF), ((val >> 8) & 0xFF)
#define HID_UNIT_DWORD(val) (HID_GLOBAL_UNIT | HID_SIZE_DWORD), (val & 0xFF), ((val >> 8) & 0xFF), ((val >> 16) & 0xFF), ((val >> 24) & 0xFF)
#define HID_UNIT_DWORD(val) (HID_GLOBAL_UNIT | HID_SIZE_DWORD), (val & 0xFF), ((val >> 8) & 0xFF), ((val >> 16) & 0xFF), ((val >> 24) & 0xFF)

Why are lib files added to linker manually?

In the Dmf projects I see that the includes and libraries are added manually in the project settings using "Additional Include directories" and "Additional dependencies".

Coming from the C# world, I'm used to the "Add reference" feature for linking projects together which makes Visual Studio manage the references between projects (it automatically includes the necessary DLLs files without you worrying about the paths). Also, this lets Visual Studio understand the dependencies between projects, so that Visual Studio will (re)build the required projects in the correct order. Also to the developers it helps to keep track of the dependencies between projects.

Say, e.g. that you would change something in DmfUModules.Library, which would be referenced by DmfUModules.Template, and you recompile DmfUModules.Template, then I believe it will see that it also needs to build DmfUModules.Library for the changes to come through.

According to https://stackoverflow.com/a/29579275/1114918 this is also possible for C/C++ (both static libraries and DLLs). Is there a reason for which, in DMF, adding the dependencies manually is more practical? Or could this make the project setup easier?

WDF Verifier (Handle Tracking) trips over FILEOJECT de-reference without using the right tag

As per our e-mail conversation, a reminder that a bug check is triggered when WDF Verifier and Handle Tracking is turned on when the module Dmf_NotifyUserWithRequestMultiple is used. Fix as below:

 Dmf/Modules.Library/Dmf_NotifyUserWithRequestMultiple.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Dmf/Modules.Library/Dmf_NotifyUserWithRequestMultiple.c b/Dmf/Modules.Library/Dmf_NotifyUserWithRequestMultiple.c
index dc7dd75..32a8f9e 100644
--- a/Dmf/Modules.Library/Dmf_NotifyUserWithRequestMultiple.c
+++ b/Dmf/Modules.Library/Dmf_NotifyUserWithRequestMultiple.c
@@ -690,7 +690,8 @@ Return Value:
 
         // Dereference FileObject.
         //
-        WdfObjectDereference(fileObjectForDereference);
+        WdfObjectDereferenceWithTag(fileObjectForDereference, 
+									(VOID*)dmfModuleNotifyUserWithRequestMultiple);
     }
 
     // 3. Broadcast data to the Clients in the ListHead list.

Cheers!

Suggestion: move Modules.Template to samples

The code in Modules.Template seems to be used for the samples mostly (besides serving as a template for new modules).

Currently, the code in DmfSamples / in DmfSamples.sln seems to contain a lot of wrapper code, which seems not to be needed for the lib code that is generated by Dmf.sln. Also, when looking through the samples, you need to look into two solutions to have an overview of the complete driver (because the samples rely on their modules in Modules.Template).

Would it be an idea to move this code to the DmfSamples folder and solution, so that the Dmf folder & solution only contain the "library code" and so that there is a better separation between library & samples?

DMF_CONTEXT_GET and DMF_CONFIG_GET issue

So I have written and declared 2 modules: Dmf_HostController and Dmf_UsbDevice

Each Module is based on the Dmf_Template.h/c

I noticed that whenever Dmf_UsbDevice called its DMF_CONTEXT_GET, it would call the DMF_CONTEXT_GET of the Dmf_HostController instead. If I remove the Dmf_HostController from the project the Dmf_UsbDevice calls the correct DMF_CONTEXT_GET.

I looked through DmfModule.h and found DMF_MODULE_DECLARE_CONTEXT. If I append the static keyword like this:

static __forceinline
DMF_CONTEXT_##ModuleName##* 
DMF_CONTEXT_GET(          ... 

Then Dmf_UsbDevice calls the correct DMF_CONTEXT_GET.
The same issue arises when calling DMF_CONFIG_GET.

So it seems the compiler inserts the wrong function when calling DMF_CONTEXT_GET and DMF_CONFIG_GET

Kind regards

Do not use Visual Studio 16.10.0 or 16.10.1 or 16.10.2 with DMF due to link regressions

We have received many reports of various linker errors when people use Visual Studio 16.10.0 or 16.10.1.

The Visual Studio Team has been correcting the issues. Please try 16.10.2 and above to see if it corrects the issues. If not, please use Visual Studio 16.9.x.

These are not DMF specific issues...even people not using DMF have reported these issues.

To get older Visual Studio, please visit:
https://docs.microsoft.com/en-us/visualstudio/releases/2019/history

To see more information about this issue, please visit:
#166

This week, I have been addressing various versions of these issues and 100% of the issues have been resolved by people installing Visual Studio 16.9.8.

One of the issues is that when people have received these errors, they have tried to "fix" them by adding libraries and making other changes. But, these changes have made things worse...drivers link but then during runtime weird errors happen which prevent driver images from loading.

DMF makes heavy use of the C runtime library in the DDK. That is why it is so sensitive the regression. Drivers that do not use the runtime library may not see the issue.

EyeGazeIoctl sample fails ApiValidator

I'm trying to test the Eye gaze driver from the samples. I've taken the sample as is, compiled it on Windows 10 64bit.

It failed the first test of ApiValidator with
EyeGazeIoctl.sys has unsupported API call to "ntoskrnl.exe!KeGetCurrentIrql"

I've looked at the Gaze HID sample project and the provided sample driver from here, and running the tests on this driver passes the ApiValidator
However this file was updated 2 weeks ago.

Why is `EnableLookAside` a `ULONG` and not a `BOOLEAN`?

See:

ULONG EnableLookAside;

It confused me that EnableLookAside is a ULONG. I thought it was meant to specify the count of something, but apparently not, looking at how it is used. Any reason why it is not a BOOLEAN?

Same goes for other config structs that use the same field, like:

ULONG EnableLookAsideOutput;

DMF in Visual Studio WDK templates?

This is not a bug - I just wanted to say that it would be great if the WDK templates in Visual Studio would make use of DMF.

Not sure whether this issue is the right place to share this feedback though.

Code analyzer produces warning on DMF_MODULE_DECLARE_CONTEXT

Hi
When i running the code analyzer with Minimum Driver Rules. I get a C6031 warning. The warning is related to DMF_MODULE_LIVEKERNELDUMP_POINTER_STORE.

#define DMF_MODULE_DECLARE_CONTEXT(ModuleName)                                                           \
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DMF_CONTEXT_##ModuleName##,                                           \
                                   ##ModuleName##ContextGet);                                            \
VOID                                                                                                     \
DMF_##ModuleName##_LiveKernelDumpInitialize(_In_ DMFMODULE DmfModule)                                    \
{                                                                                                        \
    DMF_CONTEXT_##ModuleName##* moduleContext;                                                           \
                                                                                                         \
    moduleContext = ##ModuleName##ContextGet(DmfModule);                                                 \
    DMF_MODULE_LIVEKERNELDUMP_POINTER_STORE(DmfModule,moduleContext,sizeof(DMF_CONTEXT_##ModuleName##)); \
}                                                                                                        \

I see that the #define evaulates to DMF_LiveKernelDump_DataBufferSourceAdd which have the _Must_inspect_result_ annotation. DMF_##ModuleName##_LiveKernelDumpInitialize does not inspect the return value. So I would expect that either DMF_LiveKernelDump_DataBufferSourceAdd should have the _Must_inspect_result_ removed or DMF_##ModuleName##_LiveKernelDumpInitialize should inspect the return value.
Any thoughts on this ?

Building with Windows 11, version 22H2 WDK (10.0.22621.0) supported?

I prepared a fresh Windows 11 machine with latest Visual Studio 2022 and SDK/WDK Windows 11, version 22H2 WDK (10.0.22621.0) but attempting to build DMF fails with the following errors:

Build started...
1>------ Build started: Project: DmfUModules.Library, Configuration: Debug x64 ------
2>------ Build started: Project: DmfUFramework, Configuration: Debug x64 ------
3>------ Build started: Project: DmfKFramework, Configuration: Debug x64 ------
4>------ Build started: Project: DmfKModules.Library, Configuration: Debug x64 ------
2>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
2>Done building project "DmfUFramework.vcxproj" -- FAILED.
1>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
1>Done building project "DmfUModules.Library.vcxproj" -- FAILED.
5>------ Build started: Project: DmfUModules.Library.Tests, Configuration: Debug x64 ------
6>------ Build started: Project: DmfUModules.Template, Configuration: Debug x64 ------
5>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
5>Done building project "DmfUModules.Library.Tests.vcxproj" -- FAILED.
6>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
6>Done building project "DmfUModules.Template.vcxproj" -- FAILED.
7>------ Build started: Project: DmfU, Configuration: Debug x64 ------
7>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
7>Done building project "DmfU.vcxproj" -- FAILED.
3>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
3>Done building project "DmfKFramework.vcxproj" -- FAILED.
4>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
4>Done building project "DmfKModules.Library.vcxproj" -- FAILED.
8>------ Build started: Project: DmfKModules.Library.Tests, Configuration: Debug x64 ------
9>------ Build started: Project: DmfKModules.Template, Configuration: Debug x64 ------
8>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
8>Done building project "DmfKModules.Library.Tests.vcxproj" -- FAILED.
9>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
9>Done building project "DmfKModules.Template.vcxproj" -- FAILED.
10>------ Build started: Project: DmfK, Configuration: Debug x64 ------
10>C:\Program Files (x86)\Windows Kits\10\build\10.0.22621.0\WindowsDriver.common.targets(314,5): error MSB4044: The "ValidateNTTargetVersion" task was not given a value for the required parameter "ValidNTTargetVersions".
10>Done building project "DmfK.vcxproj" -- FAILED.
========== Build: 0 succeeded, 10 failed, 0 up-to-date, 0 skipped ==========

As an experiment I tried to set the Target OS Version to Windows 10 or newer but that blew up even more:

image

Unused config param in DMF_VirtualHidKeyboard module

These config param in DMF_VirtualHidKeyboard module are not been used:

  • HidDescriptorLength
  • HidDescriptor

Related file:
https://github.com/microsoft/DMF/blob/v1.1.108/Dmf/Modules.Library/Dmf_VirtualHidDeviceVhf.h
https://github.com/microsoft/DMF/blob/v1.1.108/Dmf/Modules.Library/Dmf_VirtualHidDeviceVhf.c
https://github.com/microsoft/DMF/blob/v1.1.108/Dmf/Modules.Library/Dmf_VirtualHidDeviceVhf.md

Is there any purpose for keeping it or just placeholder for deprecated config?
I can help to submit a pull request for cleaning the code (including the related sample) if it is really unused code.

manual made project files for a software driver?

Is there any way to manually create a project file for a software driver I want to write when my device does not have internet to make the wdf installer work?

What do I need to do you ask? Well for my program it is a need to filter the threads by a list of handles I pass in (std::vector<HANDLE>) to a function I want exported and then imported to a function to filter if it is a system made or user made thread. Then if they are then return the # of user made threads in that list. I would also like in that driver also be able to detect when (if the application asks) whenever some other process calls CreateRemoteThread using the handle to the process for means of deploying an registered callback from within the driver to the application.

Edit: Why does kernel32 not have a function for that system / user thread distinction for user mode applications in case they want to do that so they can avoid all this software driver hackery or even a way for applications to see if they even want the thread from a call to CreateRemoteThread from another process too then if not have the application tell the function no; and make it error with an unauthorized error code from the caller (the other process in this case)?

And yes; I get you need backwards compat then; but then you can do an api call to turn on the new stuff for the process wide only then am I right and have it check some sort of list to see if the process subscribed to it. no?
So maybe something to list that needs done:

  1. Ways to filter between system (kernel made) threads / user (application made) threads without needing any sort of drivers.
  2. A way to update CreateRemoteThread that can allow the application to decide if it wants the thread if the handle from GetCurrentProcess() != input handle on the call. If not make the function return an error code that represents "unauthorized".
  3. A way to subscribe to (2.) on this list by introducing another function that adds the current process to a list then CreateRemoteThread looks to see if it is before doing the updated behavior to prevent breaking existing applications. Maybe in that function it could just be some sort of callback registration function that uses the handle to the process (returned from an internal GetCurrentProcess() call) to add the callback to the list.

I know this might seem a bit much; but any improvement to even the windows threadig API that allows something like this done is a win for me and my projects.

HID minidriver module?

This issue is a follow-up to #13.

Currently there is a Virtual HID Framework module but it does not support UMDF since VHF only supports KMDF.

@samtertzakian could you please comment on these two questions:

  • are there any plans to add a HID minidriver (not VHF based) module to provide a solution that supports UMDF?
  • if not, would you be interested in collaborating on a PR that adds such a module? I have not written one yet, but I have written a driver based on the vhidmini2 sample that I would like to refactor so that it makes use of DMF. Part of that refactoring would be the creation of a HID minidriver module that could become part of DMF.

I am not a professional driver developer (I am a C# developer), so some best practices that are used in the DMF codebase might be missing from my code.

Debugging assertion in DMF\Dmf\Modules.Library\Dmf_ScheduledTask.c

Don't know what the issue is as of yet, still debugging. So far found...


DMF\Dmf\Modules.Library\Dmf_ScheduledTask.md
will execute neither in during PrepareHardware nor D0Exntry. (Is this Exit or Entry, or Both)

DMF\Dmf\Modules.Library\Dmf_ScheduledTask.c
if (moduleConfig->ExecuteWhen == ScheduledTask_ExecuteWhen_Other)
{
TraceEvents(TRACE_LEVEL_INFORMATION, DMF_TRACE, "Set ModuleClosing");
moduleContext->ModuleClosing = TRUE;
}
DMF\Dmf\Modules.Library\Dmf_ScheduledTask.c
// Stop the timer and wait for any pending call to finish.
//
DmfAssert(moduleContext->ModuleClosing); (Hitting this assertion)
WdfTimerStop(moduleContext->Timer,
TRUE);

DMF\Dmf\Modules.Library\Dmf_QueuedWorkItem.c
scheduledTaskConfig.ExecuteWhen = ScheduledTask_ExecuteWhen_Other;

DMF\Dmf\Modules.Library.Tests\Dmf_Tests_ScheduledTask.c
if (taskDescription->ExecuteWhen != ScheduledTask_ExecuteWhen_Other)
{
continue;
}

[UMDF] DMF_VirtualHidMini fails WriteReport requests on descriptors without Report IDs

Greetings,

just stumbled upon an interesting issue with the DMF_VirtualHidMini module. I have a device which (for compatibility reasons) doesn't utilize Report IDs in its HID Report Descriptor. It exposes one input, feature and output report. Snippet of Output Report definition in descriptor:

	0x06, 0x00, 0xFF,  //     Usage Page (Vendor Defined 0xFF00)
	0x09, 0x01,        //     Usage (0x01)
	0x75, 0x08,        //     Report Size (8)
	0x95, 0x30,        //     Report Count (48)
	0x91, 0x02,        //     Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)

Everything works fine except writing an output report, WriteFile / GetOverlappedResult failed with ERROR_INSUFFICIENT_BUFFER despite the same code working perfectly with the legacy kernel-driver equivalent of my new UMDF-only code, which got me curious.

[2021-02-24 13:11:28.502] [WriteFile] [info] ret=0, lastError=997 (0049) ->  00 02 00 00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2021-02-24 13:11:28.502] [GetOverlappedResult] [info] ret=0, lastError=122, bytesWritten=0

I am aware of the trickery necessary to get the Report ID delivered from mshidumdf.sys to the reflector and my driver so I examined the VirtualHidMini_RequestGetHidXferPacket_ToWriteToDevice implementation of DmfU and I think I found a bug:

Accessing the output buffer fails with STATUS_BUFFER_TOO_SMALL and my own callback isn't even invoked, the module answers this request with an error. Assuming that a zero-length buffer is the result of an absence of a Report ID (being effectively 0) I introduced this experimental hack and sure enough, my code works now, I receive the buffer content and the user-land API completes with success:

    // Get report Id from output buffer length.
    //
    ntStatus = WdfRequestRetrieveOutputMemory(Request,
                                              &outputMemory);
    if ( !NT_SUCCESS(ntStatus) && ntStatus != STATUS_BUFFER_TOO_SMALL )
    {
        TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE, "WdfRequestRetrieveOutputMemory fails: ntStatus=%!STATUS!", ntStatus);
        goto Exit;
    }

    // React to this specific case by assuming 0
    //
    if (ntStatus == STATUS_BUFFER_TOO_SMALL)
    {
        Packet->reportId = 0;
    }
    else
    {
        WdfMemoryGetBuffer(outputMemory,
            &outputBufferLength);
        Packet->reportId = (UCHAR)outputBufferLength;
    }

If my assumptions are correct I'd gladly provide a PR and see this change merged so the framework can handle this edge-case properly as well 😁

Thank you!

#include <initguid.h> note

Depending on what Modules are used, it may be necessary to include initguid.h before including DMF in the Client driver. Thus, this sequence is necessary in some drivers. NOTE: Only include this file in a single file of the Client driver otherwise it is possible that multiple defintion errors may occur during linking.

#include <initguid.h>
#include <Modules.Library.h>

Where best to ask for help?

(Sorry if this is the wrong place)

I saw the [email protected] mail address, there is the Issues section of this Github repository and there is the driver development & WDK section in the MSDN forums.

When I search for "DMF" in the driver development / WDK forums, I get zero hits. That suggests that there are few people with DMF knowledge in the forums, and I do not want to make a mess of the Issues section of this repository.

What would be the best place to ask for help / troubleshooting regarding DMF driver development?

Unexpected behaviour of ScheduledTask module

Greetings!

First of all; this might be on me for misconfiguring or misusing this module so let me quickly summarize what I try to achieve. I have a device which requires a buffer sent to periodically while it's powered on, for example like every 10ms and/or sooner on demand.

Therefore I chose the ScheduledTask module which offers a deferred and "retry on success" pattern. This is unfortunately not working for me (the callback as seen below is only fired once after invoked), here's my setup:

DMF_MODULE_ATTRIBUTES moduleAttributes;
DMF_CONFIG_ScheduledTask dmfSchedulerCfg;

// ... other logic ...

DMF_CONFIG_ScheduledTask_AND_ATTRIBUTES_INIT(
&dmfSchedulerCfg,
&moduleAttributes
);

dmfSchedulerCfg.EvtScheduledTaskCallback = DMF_OutputReportScheduledTaskCallback;
dmfSchedulerCfg.CallbackContext = deviceContext;
dmfSchedulerCfg.PersistenceType = ScheduledTask_Persistence_NotPersistentAcrossReboots;
dmfSchedulerCfg.ExecutionMode = ScheduledTask_ExecutionMode_Deferred;
dmfSchedulerCfg.ExecuteWhen = ScheduledTask_ExecuteWhen_Other;
dmfSchedulerCfg.TimerPeriodMsOnSuccess = 10;
dmfSchedulerCfg.TimerPeriodMsOnFail = 10;

DMF_DmfModuleAdd(
DmfModuleInit,
&moduleAttributes,
WDF_NO_OBJECT_ATTRIBUTES,
&deviceContext->OutputReportScheduler
);

Here's my callback:

ScheduledTask_Result_Type
DMF_OutputReportScheduledTaskCallback(
	_In_ DMFMODULE DmfModule,
	_In_ VOID* CallbackContext,
	_In_ WDF_POWER_DEVICE_STATE PreviousState)
{
	// ... send buffer to device ...
	
	return ScheduledTask_WorkResult_SuccessButTryAgain;
}

I invoke it like so (which works, but only once until called again):

DMF_ScheduledTask_ExecuteNowDeferred(
		Context->OutputReportScheduler,
		Context
	);

Before I do a deep-dive into dissecting the module; any obvious error here in my thinking of what the module can do for me or the configuration I posted? Thanks!

Trying to use Dmf_IoctlHandler with Control Device Object, supported?

I replaced a lot of verbose code with Dmf_IoctlHandler on my control device but I found multiple issues in doing so. While it seems to "work" the way I want, Driver Verifier has several complaints:

DMF_DmfControlDeviceInitAllocate

DMF_DmfControlDeviceInitAllocate behaves slightly differently depending on supplying a PWDFDEVICE_INIT or NULL, but both logic branches set dmfDeviceInit->FileObjectConfigHooked to TRUE, which triggers the assert in DMF_DmfDeviceInitHookFileObjectConfig because it thinks the hooks have been set already. Is this intentional? Am I using it wrong?

DMF_DmfDeviceInitHookFileObjectConfig

If I omit calling DMF_DmfDeviceInitHookFileObjectConfig my IOCTL handlers get fired but now ofc. the module won't get its file object hooks called so depending on the use case it's only partially operable. E.g. checking administrative access will not work.

I hope I could explain my setup well enough, am wondering if it's working as intended or an oversight.

Cheers

Framework package to link against?

(Coming from .Net background, not sure if this is common for driver development)

Seeing that C++/WinRT is distributed as a NuGet package now, I'm wondering whether DMF could be released as a (NuGet) package as well?

Meaning - a packaged version of a compiled version together with the required headers?

Advantages for developers would be a easier consumption, a cleaner project repository and clear dependency management.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.