Driver Problems? Questions? Issues?
Put OSR's experience to work for you! Contact us for assistance with:
  • Creating the right design for your requirements
  • Reviewing your existing driver code
  • Analyzing driver reliability/performance issues
  • Custom training mixed with consulting and focused directly on your specific areas of interest/concern.
Check us out. OSR, the Windows driver experts.

OSR Seminars


Go Back   OSR Online Lists > ntdev
Welcome, Guest
You must login to post to this list
  Message 1 of 17  
16 Apr 18 07:45
Paul Jackson
xxxxxx@gmail.com
Join Date: 15 Apr 2018
Posts To This List: 19
Help converting a WDM KS (camera) filter driver to KMDF

Hi guys, After the latest thread, I decided to convert the WDM driver I have to KMDF. I have a filter driver which captures the IOCTL_KS_READ_STREAM control code, and sets a completion routine with `WdfRequestSetCompletionRoutine` to post-process a camera's image. I try to access the image structure and the frame in the callback, but unfortunately I weren't able to do this using KMDF API. In the WDM API, I accessed the following: (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) In the KMDF callback, I tried using these APIs: WdfRequestRetrieveUnsafeUserInputBuffer WdfRequestProbeAndLockUserBufferForRead But that doesn't work for me. Could you suggest a way to access and modify the frame data? Thanks.
  Message 2 of 17  
16 Apr 18 12:04
Tim Roberts
xxxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11997
Help converting a WDM KS (camera) filter driver to KMDF

xxxxx@gmail.com wrote: > After the latest thread, I decided to convert the WDM driver I have to KMDF. I have a filter driver which captures the IOCTL_KS_READ_STREAM control code, and sets a completion routine with `WdfRequestSetCompletionRoutine` to post-process a camera's image. > > I try to access the image structure and the frame in the callback, but unfortunately I weren't able to do this using KMDF API. In the WDM API, I accessed the following: > (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer > MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) > > In the KMDF callback, I tried using these APIs: > WdfRequestRetrieveUnsafeUserInputBuffer > WdfRequestProbeAndLockUserBufferForRead > <...excess quoted lines suppressed...> You have embarked on a non-trivial task.  The issue is that all of the IOCTL_KS_* ioctls were designed for kernel-to-kernel communication.  They are METHOD_NEITHER, and they don't follow any of the defined IRP rules, which means you can't really use the KMDF APIs to access the data.  The rules they do follow are undocumented.  What I know, I know from reverse engineering. In IOCTL_KS_READ_STREAM, the Type3InputBuffer and SystemBuffer are not used.  The address of the KSSTREAM_HEADER is in UserBuffer, and the MdlAddress points to the actual frame buffer (not the KSSTREAM_HEADER). However, some of this is set up by ksthunk.sys, which sits in between 64-bit KS drivers and 32-bit apps.  The setup may be slightly different on a 32-bit system, where ksthunk doesn't apply. -- Tim Roberts, xxxxx@probo.com Providenza & Boekelheide, Inc.
  Message 3 of 17  
17 Apr 18 06:46
Paul Jackson
xxxxxx@gmail.com
Join Date: 15 Apr 2018
Posts To This List: 19
Help converting a WDM KS (camera) filter driver to KMDF

Thank you for the reply Tim, and for the various posts in the forums with information about KS. Your posts gave me some insight about what's going on. Your information helped me understand the following code on GitHub, which seems to work: https://github.com/flowerinthenight/windows-camera-class-filter-driver/blob/maste r/ccfltr/ccfltr.c#L395 Now I'm trying to upgrade the WDM example to KMDF. I started with the toaster KMDF example, and tried to use `WdfRequestSetCompletionRoutine` for post-processing: https://github.com/Microsoft/Windows-driver-samples/blob/master/general/toaster/t oastDrv/kmdf/filter/generic/filter.c#L328 Your comment, "you can't really use the KMDF APIs to access the data", made me notice that I can use the `WdfRequestWdmGetIrp` function to get the raw IRP pointer in the completion routine, and use a code which is similar to the WDM example. So far, looks like it works. Are the any other details that I need to be aware of? Also, you mentioned WdfSynchronizationScopeNone in one of the threads: https://www.osronline.com/showthread.cfm?link=212301 Can you please say whether and why it's needed in my case? Thank you so much for the help!
  Message 4 of 17  
17 Apr 18 10:38
Peter Viscarola
xxxxxx@osr.com
Join Date:
Posts To This List: 6237
List Moderator
Help converting a WDM KS (camera) filter driver to KMDF

Hmmmm... In reference to the (almost 7 year old) thread you linked: If you're processing METHOD_NEITHER IOCTLs, and you want to be in the context of the current process, relying on Sync Scope None is a poor practice. It works by way of implementation, not by way of architectural correctness. If you want to be called in the context of the requesting process, you should use the InCallerContext Event Processing Callback. Are you RECEIVING MTHOD_NEITHER IOCTLs or are you SENDING them? Sorry... I'm not a Ks guy, so I can only be of limited help with that end of things. But I'm reasonably familiar with WDF. Peter OSR @OSRDrivers
  Message 5 of 17  
17 Apr 18 14:05
Tim Roberts
xxxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11997
Help converting a WDM KS (camera) filter driver to KMDF

xxxxx@osr.com wrote: > Hmmmm... In reference to the (almost 7 year old) thread you linked: If you're processing METHOD_NEITHER IOCTLs, and you want to be in the context of the current process, relying on Sync Scope None is a poor practice. It works by way of implementation, not by way of architectural correctness. > > If you want to be called in the context of the requesting process, you should use the InCallerContext Event Processing Callback. > > Are you RECEIVING MTHOD_NEITHER IOCTLs or are you SENDING them? Sorry... I'm not a Ks guy, so I can only be of limited help with that end of things. But I'm reasonably familiar with WDF. Receiving.  It is the KS subsystem that sends these ioctls to streaming drivers. The fact that these ioctls don't follow the rules makes the usual "in caller context" advice somewhat squishy.  Although these are METHOD_NEITHER ioctls, they originate in kernel mode, and they do not follow the rules of a METHOD_NEITHER ioctl that you would get from user mode.  The address fields in the IRP are used in a way that is specific to KS, and all the addresses have already been converted to kernel addresses. There is some truly weird voodoo magic in the KS interface.  They open a file handle to the filter, and a file handle to each pin.  When you get the IRP_MJ_CREATE call for the pin, the file name in the request not only includes the device interface reference string, but also the desired video format, as a binary structure, including embedded zeros.  That works just fine, as long as the driver knows what it is going to receive, but it's certainly odd. -- Tim Roberts, xxxxx@probo.com Providenza & Boekelheide, Inc.
  Message 6 of 17  
17 Apr 18 14:16
Tim Roberts
xxxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11997
Help converting a WDM KS (camera) filter driver to KMDF

xxxxx@gmail.com wrote: > Your information helped me understand the following code on GitHub, which seems to work: > https://github.com/flowerinthenight/windows-camera-class-filter-driver/blob/maste r/ccfltr/ccfltr.c#L395 Maybe, but I'm suspicious of anyone who writes code like this: InterlockedAnd(&pDeviceExtension->IsVideoInfoHeader2, 0); InterlockedAnd(&pDeviceExtension->KsStateRun, 0); InterlockedAnd(&pDeviceExtension->StreamerPid, 0); That shows a misunderstanding on several levels.  A DeviceExtension is automatically zeroed on creation, and a write of a 32-bit value is already atomic, so this would have had the same effect: pDeviceExtension->IsVideoInfoHeader2 = 0; pDeviceExtension->KsStateRun = 0; pDeviceExtension->StreamerPid = 0; > Your comment, "you can't really use the KMDF APIs to access the data", made me notice that I can use the `WdfRequestWdmGetIrp` function to get the raw IRP pointer in the completion routine, and use a code which is similar to the WDM example. So far, looks like it works. Yep, that's the right way to do it.   > Are the any other details that I need to be aware of? I'm sure there are lots, but it depends on what you need to do.  If you need to know the format of the video stream as it was negotiated, that turns out to be complicated.  Are you able to assume a format? > Also, you mentioned WdfSynchronizationScopeNone in one of the threads: > https://www.osronline.com/showthread.cfm?link=212301 > Can you please say whether and why it's needed in my case? It's difficult to come up with general rules.  You need to know what parts of your shared state are vulnerable and need locking.  If you access a lot of shared data, then a sync scope can make that easier, but it's also easy to overdo it. -- Tim Roberts, xxxxx@probo.com Providenza & Boekelheide, Inc.
  Message 7 of 17  
18 Apr 18 04:14
Paul Jackson
xxxxxx@gmail.com
Join Date: 15 Apr 2018
Posts To This List: 19
Help converting a WDM KS (camera) filter driver to KMDF

> I'm suspicious of anyone who writes code like this Maybe it's not perfect, but that's literally the only relevant example that I found in the internet. > a write of a 32-bit value is already atomic That's probably true in practice for all relevant processors, but isn't it true that in theory some processor (e.g. some esoteric ARM) can lack such guarantees? > If you need to know the format of the video stream as it was negotiated, that turns out to be complicated. The author of the example does this by checking the GUID at VideoInfoHeader.DataFormat.SubFormat. Is there more to it? My task is to replace the webcam image if a condition is met, as a security measure. I can have a replacement image for common formats (say MJPG and a couple of more), and just have a zero-sized buffer returned for less known formats, which is acceptable as long as the streaming is blocked.
  Message 8 of 17  
19 Apr 18 08:40
Peter Viscarola
xxxxxx@osr.com
Join Date:
Posts To This List: 6237
List Moderator
Help converting a WDM KS (camera) filter driver to KMDF

<quote> The fact that these ioctls don't follow the rules makes the usual "in caller context" advice somewhat squishy. Although these are METHOD_NEITHER ioctls, they originate in kernel mode, and they do not follow the rules of a METHOD_NEITHER ioctl that you would get from user mode. The address fields in the IRP are used in a way that is specific to KS, and all the addresses have already been converted to kernel addresses. </quote> That makes sense. You definitely know KS. The only other thing I'll throw in here in CASE it's useful, is that KMDF "knows about" kernel-mode to kernel-mode METHOD_NEITHER IOCTLs. And, IIRC, actually supports the use of the typical WdfRequestRetrieveOutputBuffer/WdfRequestRetrieveInputBuffer functions in this case. Assuming the buffer pointers are KVAs, of course, and the lengths are... proper. <quote> Maybe it's not perfect, but that's literally the only relevant example that I found in the internet. </quote> Confucius once wrote: "Posting a sample on the Internet doesn't make the author wise or the sample good." I think he wrote this in Autumn Annals, just after The September That Never Ended. <quote> That's probably true in practice for all relevant processors, but isn't it true that in theory some processor (e.g. some esoteric ARM) can lack such guarantees? </quote> Seriously? Allow me to put your fears to rest: No system on which Windows will run will violate this constraint. (This reminds me of the arguments people used to give me about assuming endian-ness in my network driver code: "Suppose you're running on a big endian system," they would say. My answer was always "Then my driver isn't running at all, because Windows isn't going to run on a big endian system anytime soon.") Peter OSR @OSRDrivers
  Message 9 of 17  
19 Apr 18 12:50
Tim Roberts
xxxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11997
Help converting a WDM KS (camera) filter driver to KMDF

xxxxx@osr.com wrote: > (This reminds me of the arguments people used to give me about assuming endian-ness in my network driver code: "Suppose you're running on a big endian system," they would say. My answer was always "Then my driver isn't running at all, because Windows isn't going to run on a big endian system anytime soon.") Exactly, and this applies across the board -- even to Windows CE.  Although CE runs on many strange processors that are traditionally big-endian, the operating system requires them to run in little-endian mode. -- Tim Roberts, xxxxx@probo.com Providenza & Boekelheide, Inc.
  Message 10 of 17  
22 Apr 18 13:45
Paul Jackson
xxxxxx@gmail.com
Join Date: 15 Apr 2018
Posts To This List: 19
Help converting a WDM KS (camera) filter driver to KMDF

OK, good to know. Another question about cameras: can IRP_MJ_CREATE be called for the same camera device object more than once, before the previous handle gets IRP_MJ_CLEANUP? Also, is there any significance to IRP_MJ_CLOSE, or does it always happen right after IRP_MJ_CLEANUP? Which one is better to consider the camera activity to be stopped?
  Message 11 of 17  
22 Apr 18 17:46
Tim Roberts
xxxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11997
Help converting a WDM KS (camera) filter driver to KMDF

On Apr 22, 2018, at 10:44 AM, xxxxx@gmail.com <xxxxx@lists.osr.com> wrote: > > OK, good to know. > > Another question about cameras: can IRP_MJ_CREATE be called for the same camera device object more than once, before the previous handle gets IRP_MJ_CLEANUP? Certainly. A single camera can be opened by multiple processes, or multiple times by a single process. In the KS world, for example, you'll get separate file opens for the filter and for each of the pins. > Also, is there any significance to IRP_MJ_CLOSE, or does it always happen right after IRP_MJ_CLEANUP? Which one is better to consider the camera activity to be stopped? For a KS driver, neither one. Camera activity begins when the pin transitions to the run state (KSSTATE_RUN), and stops when the pin transitions out of run state. A KS driver's streaming state is controlled by the KSPROPERTY_CONNECTION_STATE property within KSPROPSETID_Connection. IRP_MJ_CLEANUP happens while the process is still accessible. IRP_MJ_CLOSE can arrive after the process memory is gone. The OSR web site has an extensive article on why it's better to handle IRP_MJ_CLOSE. ??? Tim Roberts, xxxxx@probo.com Providenza & Boekelheide, Inc.
  Message 12 of 17  
23 Apr 18 07:51
Paul Jackson
xxxxxx@gmail.com
Join Date: 15 Apr 2018
Posts To This List: 19
Help converting a WDM KS (camera) filter driver to KMDF

I don't quite understand how it works. > A single camera can be opened by multiple processes, or multiple times by a single process. I know that only one process at a time can use a given camera. How is this enforced? Where does the second connection fail? I tried debugging the filter driver, but didn't find clues. I see that a regular communication for a single process looks like this: ===================================== IRP_MJ_CREATE (filename = "\global") IRP_MJ_CREATE (filename = "{146F1A80-4791-11D0-A5D6-28DB04C10000}\<binary_data>") KSSTATE_ACQUIRE KSSTATE_PAUSE KSSTATE_RUN IOCTL_KS_READ_STREAM IOCTL_KS_READ_STREAM ... KSSTATE_PAUSE KSSTATE_STOP IRP_MJ_CLEANUP IRP_MJ_CLOSE IRP_MJ_CLEANUP IRP_MJ_CLOSE ===================================== Now, if I open another app while already using the camera, it looks like this: ===================================== IRP_MJ_CREATE(1) (filename = "\global") IRP_MJ_CREATE(1) (filename = "{146F1A80-4791-11D0-A5D6-28DB04C10000}\<binary_data>") KSSTATE_ACQUIRE(1) KSSTATE_PAUSE(1) KSSTATE_RUN(1) IOCTL_KS_READ_STREAM(1) IOCTL_KS_READ_STREAM(1) ... IRP_MJ_CREATE(2) (filename = "\global") IRP_MJ_CREATE(2) (filename = "{146F1A80-4791-11D0-A5D6-28DB04C10000}\<binary_data>") KSSTATE_ACQUIRE(2) KSSTATE_PAUSE(2) KSSTATE_RUN(2) IOCTL_KS_READ_STREAM(1) ... KSSTATE_PAUSE(1) KSSTATE_STOP(1) IRP_MJ_CLEANUP(1) IRP_MJ_CLOSE(1) IRP_MJ_CLEANUP(1) IRP_MJ_CLOSE(1) ===================================== I'd like to be able to connect the video format in <binary_data> to IOCTL_KS_READ_STREAM, to be able to know what to expect in the frame buffer. But in order for this to work correctly, I need to know to discard the "IRP_MJ_CREATE(2)" IRP.
  Message 13 of 17  
23 Apr 18 11:57
Tim Roberts
xxxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11997
Help converting a WDM KS (camera) filter driver to KMDF

xxxxx@gmail.com wrote: > I don't quite understand how it works. > >> A single camera can be opened by multiple processes, or multiple times by a single process. > I know that only one process at a time can use a given camera. How is this enforced? Where does the second connection fail? I tried debugging the filter driver, but didn't find clues. At the transition to KSSTATE_ACQUIRE, the driver is supposed to fail that if the hardware resources are already committed.  This convention was invented during the days of Windows Media Center, because it opened an instance in a service at boot time, even if it wasn't recording anything.  If drivers failed during Create, no other devices could use the camera. > I see that a regular communication for a single process looks like this: > ===================================== > IRP_MJ_CREATE (filename = "\global") That's the filter.   > IRP_MJ_CREATE (filename = "{146F1A80-4791-11D0-A5D6-28DB04C10000}\<binary_data>") That's the pin.  The <binary data> is the selected video format. > Now, if I open another app while already using the camera, it looks like this: > ===================================== > IRP_MJ_CREATE(1) (filename = "\global") > IRP_MJ_CREATE(1) (filename = "{146F1A80-4791-11D0-A5D6-28DB04C10000}\<binary_data>") > KSSTATE_ACQUIRE(1) > KSSTATE_PAUSE(1) > KSSTATE_RUN(1) > IOCTL_KS_READ_STREAM(1) > IOCTL_KS_READ_STREAM(1) <...excess quoted lines suppressed...> That should have failed. > I'd like to be able to connect the video format in <binary_data> to IOCTL_KS_READ_STREAM, to be able to know what to expect in the frame buffer. But in order for this to work correctly, I need to know to discard the "IRP_MJ_CREATE(2)" IRP. You get a file handle in the IOCTL_KS_READ_STREAM call.  You can connect that to the corresponding IRP_MJ_CREATE. -- Tim Roberts, xxxxx@probo.com Providenza & Boekelheide, Inc.
  Message 14 of 17  
25 Apr 18 08:17
Paul Jackson
xxxxxx@gmail.com
Join Date: 15 Apr 2018
Posts To This List: 19
Help converting a WDM KS (camera) filter driver to KMDF

You are right, KSSTATE_ACQUIRE fails with 0xc000009a (STATUS_INSUFFICIENT_RESOURCES). Here's why I didn't see it: https://github.com/flowerinthenight/windows-camera-class-filter-driver/issues/2 Another question: In the completion routine for IOCTL_KS_READ_STREAM, the example uses ProbeForRead on KSSTREAM_HEADER's Data pointer. That doesn't look correct to me, but I'm not sure. Driver Verifier says: Error String ProbeForRead should only be called at IRQL <= APC_LEVEL. I think that there are two issues here: first the IRQL mismatch, and second the fact that the Data pointer can be irrelevant since the completion routine is likely to run in the context of a different process. Am I right? And if that's so, can this check be just removed? I mean, can I trust Irp->MdlAddress without additional checks? Or can it be invalid, and if so what's the proper way to check this? Thanks again for your help!
  Message 15 of 17  
25 Apr 18 15:58
Tim Roberts
xxxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11997
Help converting a WDM KS (camera) filter driver to KMDF

xxxxx@gmail.com wrote: > Another question: > In the completion routine for IOCTL_KS_READ_STREAM, the example uses ProbeForRead on KSSTREAM_HEADER's Data pointer. That doesn't look correct to me, but I'm not sure. Driver Verifier says: > Error String ProbeForRead should only be called at IRQL <= APC_LEVEL. That shouldn't be necessary.  Maybe this was an issue in Windows 98, but these days all the addresses in the IRP should be kernel-mode addresses by the time they get to you.  There's a filter called "ksthunk" that sits on top of the main driver and provides a nice, clean IRP to the drivers below it.  That way, lower drivers don't have to deal with the 32/64 issues. How far back do you need to support?  Are you worried about XP?   > I think that there are two issues here: first the IRQL mismatch, and second the fact that the Data pointer can be irrelevant since the completion routine is likely to run in the context of a different process. Am I right? And if that's so, can this check be just removed? I mean, can I trust Irp->MdlAddress without additional checks? Or can it be invalid, and if so what's the proper way to check this? The Irp->MdlAddress buffer should already be locked by the time you see it. -- Tim Roberts, xxxxx@probo.com Providenza & Boekelheide, Inc.
  Message 16 of 17  
26 Apr 18 04:48
Paul Jackson
xxxxxx@gmail.com
Join Date: 15 Apr 2018
Posts To This List: 19
Help converting a WDM KS (camera) filter driver to KMDF

Great, thanks. > How far back do you need to support? Are you worried about XP? Windows 7 and up should be supported. Windows XP is nice to have if I can get the support for free or almost for free. What's the difference regarding Windows XP?
  Message 17 of 17  
26 Apr 18 12:38
Tim Roberts
xxxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11997
Help converting a WDM KS (camera) filter driver to KMDF

xxxxx@gmail.com wrote: > >> How far back do you need to support? Are you worried about XP? > Windows 7 and up should be supported. Windows XP is nice to have if I can get the support for free or almost for free. > What's the difference regarding Windows XP? The "ksthunk" helper I mentioned came into being when the 64-bit systems arrived.  In the XP days, it's quite possible you WILL have to worry about locking and mapping user-mode pointers.  That's ugly. -- Tim Roberts, xxxxx@probo.com Providenza & Boekelheide, Inc.
Posting Rules  
You may not post new threads
You may not post replies
You may not post attachments
You must login to OSR Online AND be a member of the ntdev list to be able to post.

All times are GMT -5. The time now is 17:04.


Copyright ©2015, OSR Open Systems Resources, Inc.
Based on vBulletin Copyright ©2000 - 2005, Jelsoft Enterprises Ltd.
Modified under license