Intellisense, the Musical part 3
Year 2038 problem
This is a short blog aimed at bringing together a lot of great content already published by many individuals. The issue is the year 2038 issue, also known as Unix Millennium bug, "Y2K38" and many others.
The issue is encountered when a user sets their system date to a year past 2038 (actually it seems the date has to be past January 19, 2038) weird things happen as a result of the date calculation that is performed by the OS. You see, most Unix-like computers calculate system time as the number of seconds since the very beginning of January 1, 1970 (excluding leap years). Since a lot of applications were written in "C" or other variations of it, the date data was stored as a 32 bit signed integer. At one point in time (the year 2038), the number will overflow the 32 bit space assigned to it and will start calculating as a negative number, which when translated back to friendly time format, it looks like the year 2039 is actually the year 1939, and so on. Where there are system date dependencies, as the application encounters a date too far in the past it may fail to function. OS may suffer in terms of activation, validation, Service Packs, Hot Fixes, etc.
Most of these problems were detected and ironed out by the use of KBs or service packs in the past dozen years, but anything that has not been fixed and is still using C/C++ time in 32 bit format will basically break in the year 2038.
You can review the following links for more information:
https://blogs.msdn.com/mthree/archive/2008/04/21/year-2038-042108.aspx
https://en.wikipedia.org/wiki/Year_2038_problem
You can also search for "KB 2038" in MSDN (or follow the link below)
https://social.msdn.microsoft.com/Search/en-US?query=KB%202038&ac=8
0 and 1 are not just numbers, they're spaces!
Again, thanks to our intrepid explorer Ilia S. for helping uncover some more traps in the UMDF HID Collection Filter journey.
Two things to keep in mind as you're creating your driver:
1. UMDF drivers are hosted in a Session 0 based executable on Vista and above -
- and -
2. A lot of Win32 APIs for controlling desktop and user interactions on the desktop are exclusive to user sessions (anything 1 and above) because Session 0 technically doesn't have a desktop and is intended to be a protected space.
So those of you who are wanting / trying to get HID Collection Filter drivers running in UMDF so you can do some magic on the desktop, you will need to do some of the following:
A Session 0 overview for you with some tips, hints and tricks on how to "exit out" to user desktop sessions.
https://msdn.microsoft.com/en-us/library/bb756986.aspx
But focus more on this portion;
Leverage Windows 7, Windows Vista and Windows Server 2008 capability:
- Use client or server mechanisms such as remote procedure call (RPC) or named pipes to communicate between services and applications.
- Use the WTSSendMessage function to create a simple message box on the user's desktop. This allows the service to give the user a notification and request a simple response.
- For more complex UI, use the CreateProcessAsUser function to create a process in the user's session.
- Explicitly choose either the Local\ or Global\ namespace for any named objects, such as events or mapped memory that the service makes available.
And a good tutorial on how to make an application using those patterns (this does require the Platform SDK)
https://msdn.microsoft.com/en-us/library/aa379010(VS.85).aspx
And finally for today, I am still working on getting you some sample code for a UMDF HID Collection Filter driver, but life decided it needed some attention last week so I'm a tad behind on that. :)
And a thank you to one of our developers, Kumar for pointing me to those Session 0 links and tips!
Now playing – Transatlantic The Whirlwind (yes, I do love my prog rock)
And here you thought I had a cloaking device
Got a good one to share with the group;
Q: Can I make a kernel mode driver that opens a handle and talks to a UMDF based driver in another device stack?
A: Why yes you can! Quite simply done provide you follow all the rules. This is a variant of the UMDF initiated cross stack communication we talked about a while ago, but KMDF, being a DF (driver framework) supports essentially the same IoTarget model that UMDF does.
Now Playing – Rush Far Cry
And Or what?
From the, "it's funny because it happened to me" file, I did it again. While debugging a recent issue in the test lab, I had pushed the root cause out as an attempt to free an invalid handle. I cracked open the code to find the line and looked at it in passing, "yup, simple logic error, if ((deviceHandle != NULL) && (deviceHandle != INVALID_HANDLE_VALUE))" What I saw was really not what I thought I saw. Yup, I saw the reverse of this where it was checking if they were equal so I suggested the fix that state the && be changed to || and it should be if (! (deviceHandle == NULL) || (deviceHandle == INVALID_HANDLE_VALUE)). Then Bob pointed out the obvious. :)
On the testing side, we had a meeting recently to discuss some new test tools and there the continual theme Bob started and I picked up on came to pass; Testers should be the most paranoid people in the world. Over the years I've had my concepts of design and coding altered greatly. I went from the simple error handling should the odd API / DDI fail to the belief that they will always fail. As a result, my error handling routines have become exponentially more robust and adaptive. So during this meeting Bob and I were always thinking negative, "how are you going to handle when this fails, because it will fail. Believe it or not, at some point, it will fail." Yessir, I'm just a negative guy.
And finally, so long and thanks for all the fish Bill. Yes, I'm feeling terribly melancholy today.
*Currently playing - Sloan All Used Up
Apr(grave)es Post, les Deluge**
I would like to make one small clarification to Ilias' post here, I don't have the local WDK integrated in to Visual Studio 200n Help environment. It's merely using the online WDK as I press F1 or do a relevant search. As Visual Studio 2005 and 2008 default to using online MSDN for all help references, I haven't really bothered to find a way to integrate a local WDK into the new help schema. I know a few of us internally as well as some of you have contacted the WDK and Visual Studio Teams about enabling this functionality and didn't get an encouraging response. Rest assured, we'll keep working on it from our end.
And also after my post, and Ilias' subsequent post, I was literally inundated with one email (okay, it was two) asking how I got Intellisense for WDF / WDM working in Visual Studio. Fear not, I will write up a post in the next few days describing how I managed to accomplish such a feat. Really, it's just smoke and mirrors. If you want to get a head start and try to figure it out on your own, be my guest. My walkthrough post will probably have to wait until the weekend, but I'll get it done.
Editorial time - As a musician (bass player, pedestrian drummer, plunky keyboards) for well over 20 years, I find Guitar Hero and Rock Band the most disconcerting games ever. First off, 5 fret inputs? I only have 5 inputs? This forced my frustration levels to 11 the other night as I attempted to actually PLAY the bass line from Stone Temple Pilots Interstate Love Song in Rock Band using only 5 buttons and the strummy bar thing-a-majig. This ended up providing untold amounts of schadenfreude to my wife as she sat watching my hands struggle to find the other 3 strings I've grown so accustom to over the years. And never have I been punished in such a sinister manner for attempting to actually play the correct bass or drum line either. Seriously, on expert mode they still drop plucks, strums and beats which results in me losing consecutive note streaks. I have still only managed to play one song on either game at any difficulty level at 100%. The end result is after a few moments of rather off color verbage being thrown at the TV / Console area, I often just wander back to Nerdvana, adorn my beloved '83 Fender Jazz and proceed to play the REAL song. Oh, don't ask what I think about the Rush covers in Rock Band...please.
*Currently playing - Rush, Subdivisions
**Nice, I try to add a è (even via HTML code) to the title and it chokes...so to my French speaking friends, please forgive me.
Because inquiring minds want to know
A follow up question was posed from my last post about the WDF book no longer being in print and I thought it would be better to do a post so it will show up in RSS feeds;
Q: Any idea what triggered this? I realize that our technology area doesn't sell as much as others, but seems strange to pull the only book on the topic.
Inquiring minds...
-scott
A: We're digging around to find an answer for you all. The digital versions are still available though so all hope is not lost.
Blue Moon, you saw me standing alone.....
I love sharing simple mistakes for some reason. I think it's because we're all prone to searching for how to do something simple, like handle METHOD_NEITHER requests in our KMDF driver, and only read the documentation on how to initialize that ability, but not remembering all the little rules that govern the surrounding APIs. Oft leaving us with a series of bug checks, driver load failures or head scratching "huh" scenarios.
This not so good -
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } <...some other code went here...> WdfDeviceInitSetIoInCallerContextCallback ( DeviceInit, SomeEvtInContextCallBack);
This good -
WdfDeviceInitSetIoInCallerContextCallback ( DeviceInit, SomeEvtInContextCallBack); status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; }
See, at some point in history, I had paged out of my grey matter memory module that tidbit in the MSDN documentation for WdfDeviceCreate which says; After the driver calls WdfDeviceCreate, it can no longer access the WDFDEVICE_INIT structure.
Boy oh boy you sure can't access it afterwards, that bad boy is a glorious, awe inspiring, blue screening NULL after WdfDeviceCreate is through!
Born free, as free as the bits will flow...
The RTM of the WDK will be available to download today (crosses fingers).
Act 2 of the Visual Studio Musical will be available later this week.
Cross stack communications
The subject of how to talk to another device stack has come up again, and since I only briefly touched on it a year ago, I thought it would be good provide some code snippets and a little more background on how to accomplish such a feat. The gist of what we are trying to do here is load a UMDF based driver for one device, open a handle to a different device stack and submit I/O to that stack. To do that in UMDF we need to establish a UMDF I/O target and the foundation of that I/O target object is a file handle.
So the basic building blocks are as follows;
// // Add these to your base class // IWDFIoTarget m_ExternalTarget; HANDLE m_ExternalHandle;
You can add these to any of your existing classes, but it probably serves best to house these elements in your Device or Queue classes. They are tied to the lifetime of the I/O you are sending to the external target, so where you house them is really down to your design and implementation.
Based on your needs and how you design your driver, you will need to determine when you proceed with the following sections. For simplicity, I'll establish the connection to the remote stack in the Device Initialization routine, but the same can be done at just about any other point of initialization or even during a later phase of driver operations.
IWDFFileHandleTargetFactory * pFileHandleTargetFactory = NULL; // ....... // abstracted device init code for brevity // ........ if (SUCCEEDED (hr)) { m_FxDevice = fxDevice; // // We can release the reference as the lifespan is tied to the // framework object. // fxDevice->Release(); } // Open the device and get the handle. m_ExternalHandle = CreateFile ( DeviceStack, // path device stack to open GENERIC_READ | GENERIC_WRITE, // these flags are driven more by the target stack. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, // You must open the handle with this flag NULL); if (INVALID_HANDLE_VALUE == m_ExternalHandle) { DWORD err = GetLastError(); TraceEvents( TRACE_LEVEL_ERROR, TEST_TRACE_DEVICE, "%!FUNC! Cannot open handle to device %!winerr!", err); hr = HRESULT_FROM_WIN32(err); } if (SUCCEEDED(hr)) { hr = m_FxDevice->QueryInterface(IID_PPV_ARGS(&pFileHandleTargetFactory)); if (FAILED(hr)) { TraceEvents( TRACE_LEVEL_ERROR, TEST_TRACE_DEVICE, L"ERROR: Unable to obtain target factory for creating FileHandle based I/O target %!hresult!", hr); } } if (SUCCEEDED(hr)) { hr = pFileHandleTargetFactory->CreateFileHandleTarget(m_ExternalHandle, &m_ExternalTarget); }
You'll need to release the reference to the pFileHandleTargetFactory object, either by a SAFE_RELEASE macro, direct call to the Release(); method, or by using a CComPtr /CComQIPtr class wrapper on the object on declaration. You'll also need to clean up the Windows file handle when it is no longer needed. And IF the IWDFIoTarget object's lifetime scope is narrower than the device object's lifetime, you will need to call DeleteWdfObject method on m_ExternalTarget.
At this point, you have your remote target object to use in sending I/O to that secondary device stack.
What I'll cover next is going to be some hefty theory on when you should and don't need to use queue objects and how to send I/O to an external stack based on whether you have a queue or not. Fun! ;)
d'OH-nuts
As promised here is the correction to the hybrid INF file you'll need to make.
[SourceDisksFiles]
kmdf1394vdev.sys=1
umdf1394vdev.dll=1
WudfUpdate_01007.dll=1
WdfCoInstaller01005.dll=1 WdfCoInstaller01007.dll=1
....
[CoInstaller_CopyFiles]
wdfcoinstaller01007.dll wdfcoinstaller01007.dll
WudfUpdate_01007.dll
...
[CoInstaller_AddReg]
HKR,,CoInstallers32,0x00010000,"wdfcoinstaller01005.dll,WdfCoInstaller","WUDFUpdate_01007.dll" wdfcoinstaller01007.dll
...
[KMDF1394VDEV_wdfsect]
KmdfLibraryVersion = 1.5 1.7
Apologies for letting that get out in the wild. :)
Double filtered for added UMDF flavor.
UPDATED: 9-March-2010 Astute readers noted that I had the incorrect driver load order when talking about the UmdfServiceOrder directive. :) It IS left to right reading and the LEFT most driver is the lowest driver.
In my previous post about Filter Drivers, I mentioned that this time I would focus on a more UMDF centric stack. This one is pretty simple.
For UMDF only based driver stacks, the single most important directive is the UmdfServiceOrder INF directvie. As I mentioned last post, that directive is a left to right list determining load order for the drivers contained in the device stack. With the left most element in that list being the the lowest driver loaded.
Here are two examples – First a UMDF two driver stack with an upper filter;
[<mydriver>_Install.NT.Wdf] UmdfService=UMDFFunction,WUDFFuncDriver_Install UmdfService=UMDFFilter,UMDFFilter_Install UmdfServiceOrder=UMDFFilter, UMDFFunction
Now to install a lower filter, simply flip the order in that directive;
[<mydriver>_Install.NT.Wdf] UmdfService=UMDFFunction,WUDFFuncDriver_Install UmdfService=UMDFFilter,UMDFFilter_Install UmdfServiceOrder=UMDFFunction, UMDFFilter
The last tidbits here are; for a device stack that only contains UMDF drivers, there is no need to add any of these settings in the INF;
[<mydriver>_Device_AddReg] ; Load the redirector as an upperfilter on this specific device. ; 0x00010008 - FLG_ADDREG_TYPE_MULTI_SZ | FLG_ADDREG_APPEND HKR,,"UpperFilters",0x00010008,"WUDFRd"
And also as before, the filter driver needs to be a good citizen on the stack, pass on requests it does not own to the next driver and don't touch anything unless you must. The previous code samples I've posted all still apply, but the basics are; GetDefaultIoTarget, FormatUsingCurrentType and Send.
There's no need to change any code for a basic filter driver based on its load order (upper or lower filter). As you get in to more advanced driver functionality you may find a need to change default behaviors. For those cases, you can always send us mail. :)
There was also some questions about why would you want or need to be an upper or lower filter driver. That one gets in to a bit more of a "it's up to you" but the core logic that applies to WDM / KMDF drivers applies to UMDF drivers (save the parts about bus drivers *g*).
Heads up!
Sharing a cross post that is of interest to you WDF users;
House cleaning
The fourth part of Abhishek's online UMDF debugging tutorials is up now. :)
https://www.microsoft.com/whdc/devtools/debugging/umdftraining.mspx
Next up, those of you playing with Windows 7 may have noticed that the "Found New Hardware" wizard is gone! This in itself is not that big a deal, but it does mean that some of the WDK sample installation instructions are no longer valid.
Simple fix at the end of the day, the device will come up as an "Unknown Device" within Device Manager, choose "Update Driver" from the right click context menu for that device and then follow the directions to point it to the driver(s) you need!
That's all for today, those of you in the U.S. enjoy your 4th of July weekend. And just remember, light fuse then run away.
*Currently Playing - Dream Theater Light Fuse and Get Away
How active are you?
Was pondering a few questions the last few days.
- How many of you UMDF writers use ATL in your drivers?
- If you do, do you have more of a kernel driver background or a user mode background?
Since UMDF works on an object model very similar to COM, the ATL does provide a lot of useful object lifetime management functions and interface implementation (BEGIN_COM_MAP / COM_INTERFACE_ENTRY).
Like I said, just some curious questions for the group. Post comments or send me an email if you feel like chiming in. I'm thinking if enough people are interested in using ATL, I could do a series of how to migrate non-ATL drivers to ATL drivers.
Currently playing: nothing
How to avoid getting a HID to the head (a guide to making a UMDF - HID collection filter)
First of all, HUGE thanks to Ilia S. for helping to track down this little trap. I'm glad we finally got your driver up and running! Nothing like having an 8 hour time difference to slow things down. :)
For those of you who like the 30 second version;
If you need to use Impersonation in a UMDF driver, regardless of being a filter or a function driver, you cannot have AutoForwardCreateCleanupClose set to WdfTrue. For filter drivers this means you must invoke AutoForwardCreateCleanupClose with WdfFalse AFTER you call SetFilter and BEFORE you call CreateDevice and then follow all the rules for balancing Create and Close and handling Impersonation (same link as above for impersonation). Easy enough? :)
For those of you who like long winded technical posts, I am going to do a write up on how to get a UMDF driver to sit on top of a HID collection.
And for those of you who like to work ahead and start digging around on your own, you first need to match your INF section for HWID to HID\VID_<nnnn>&PID_<nnnn>&XX_xx&&ColNN. Second install WUDFRd as an upper filter to that HWID. Now, if your collection has enforced secure read, you're going to need that little tip above.
I'll work on getting the first part of the write up done this week and posted by early next week. I need to do a little code work on a sample for you faithful readers. *thumbs up*
As always, fire off any questions you have!
Now Playing – Stone Temple Pilots Trippin' on a hole in a paper heart
How to jiggle the handle(s) and get your 1.7 to work in Vista
As people who write drivers are something of a rare breed, I know we probably share a lot of common readers between our Driver blogs and via the OSR boards, but just in case the three or four of you who read my blog haven't seen this, I wanted to make sure it got out there.
We had a bit of a stumble with the 1.7 coinstaller package that went out with the WDK recently.
We're pretty close to being done with a fix as Bob said, so fret not. I'd like to thank those who pestered me about the issue for helping narrow it down, and also those who pestered the external boards and email alias.
Now, if we could all join hands around the camp fire and sing "row, row, row your boat" to complete this little moment of community unity.
Still working on the Visual Studio stuff, but those of you with free time are more than welcome to skip ahead.
*Currently playing - Not a single thing...
I never promised you a rose garden, but I did promise Act 2 of a Musical
And I'm sad to say that I won't have it ready this weekend. I'll work on it next week I promise.
In the mean time, how about we write a kernel in a Managed Language eh? So cool to see they have some proof of concepts going.
*Currently playing - Living Colour, Open Letter (to a Landlord)
I owe you all a large, humongous apology
Work and home work have prevented me from completing the 2nd part of the Intellisense Musical. I had asked my wife if I could have Saturday to work on it, and of course after the trip to Lowes for paint supplies and spending hours with her setting things up and answering questions, it was time for me to make dinner.
I won't promise that I'll have it ready any time soon, but that I am working on it as I get the chance to. The primary stumbling block from me just releasing what I have built internally is, well, it's got a lot of internal stuff in there and I'll guarantee you that won't go over well with superiors and the like. So I'm trying to make a generic enough version that you can all use (should you choose to) but something that also won't result in a cavalcade of "HELP" mails. :)
So, in deference to that, I've been pinged a couple of times and asked how to make it work when you're using a MAKE project file. And in that case it's even easier than a C/C++ project.
*Currently playing - Not a single thing...
Intellisense-ational!
After reading Ilias' post about Intellisense lacking for driver projects, I first thought about running upstairs and throwing a few more quarters at him. Then I thought about making a snarky response in his blog post. But in the end, I just decided to show him up;
That looks a lot like Intellisense to me no? And he just accused me of photoshopping these....sheesh ;)
Forgive the borders, I am just in a very goofy mood today.
Anyways, onward and upward, I promised a post regarding some cross stack communications. Well it turns out my loyal reader was suffering a bit of Patrick-itous. In this case, they were releasing a file handle after initial usage, so there wasn't anything really wrong with the UMDF process code.
But for completion sake a 60 second overview of what was going on - Suppose you wish to communicate with a WDM / KMDF driver in another stack. Simply done in UMDF land; Open a handle to the target (make sure you use the OVERLAPPED flag), then call CreateFileHandleTarget. Don't forget to store the target object returned, and don't close the file handle...especially you Anil *g*. After that it's simply a matter of determining how and what you want to send to that driver. Provided the driver recognizes the IOCTL you're sending, you're all set for communication with a driver outside the current stack.
Keep in mind that all requests submitted from the UMDF driver will fall under IRP_MJ_DEVICE_CONTROL.
Should somebody decide to email me and say they would like to see some sample code, I will churn some up for general consumption. Suffice it to say, what comes after this point isn't much different than what I posted in the OnDeviceIoControl section here. Save you don't really need to make the call to GetDefaultTarget. And if you aren't touching the request at all on pass through you can forgo the infrastructure and just follow the SubmitAsyncRequestToLower code here.
*Currently playing - Peter Gabriel, Digging in the Dirt
Intellisense, the Musical part 3
Like all good stories, sometimes the 2nd act is the hardest to follow. In this case it was simply a matter of other things coming up rather than writers block. :)
What kicked me in the rump to get this next part up was a few more questions about driver writing, WDK integration into Visual Studio and Intellisense. One of the very cool features of Visual Studio 2008 is the ability to make a project from existing code.
The end result can look something like this (warning, this is a 1920x1200 resolution PNG *g*)
I'll walk you through this using the "a picture is worth a thousand words" mentality;
Select "Next"
Then point it to the root of the WDK installation. Pointing it to the root rather than right at the src folder will save you some intellsense headaches later on, sure you'll get inclusion of all the WDK folders, but it's actually not a bad thing in the end;
Select "Next"
Then;
Select "Finish" from here. We're still not going to use Visual Studio to do any building for now, partly because I refuse to give up all command windows in my life and also because I'm still tinkering with all the settings required to use the WDK build environments under Visual Studio.
Now your Solution Explorer will probably look like a mess of files listed alphabetically. Simply hover over the "Show All Files" button at the top and toggle it until you get an Explorer like layout of the samples sources structure.
Now you have pointer to the first picture in the blog post. :)
As a side note to any Microsoft Employees who may actually read my blog – Yes, you can do the same thing with our Source Control Enlistments (I have a VS project for each branch I work out of). And if you have one of the Source Control plugs in for Visual Studio, you can also have all the check in / check out / history that our source control provides.
Comments
Post a Comment