<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Trouble Ahead- Trouble Behind : test development</title><link>http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx</link><description>Tags: test development</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>2008 DDC slides now available to all!</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/07/22/2008-ddc-slides-now-available-to-all.aspx</link><pubDate>Wed, 22 Jul 2009 14:24:33 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9844701</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9844701.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9844701</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9844701</wfw:comment><description>&lt;p&gt;Got an email late last week stating that the material I and others presented at the 2008 Driver Developers Conference (which Dieter and James want renamed to Driver Development and Test Conference- more power to that idea!) is now available &lt;a href="http://www.microsoft.com/whdc/resources/ddc/default.mspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The sessions I participated in are a &lt;a href="http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DDE-T689_DDC08.pptx" target="_blank"&gt;description of several WDF test technologies&lt;/a&gt; and some hand waving about &lt;a href="http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DDE-T687_DDC08.pptx" target="_blank"&gt;troubleshooting WDF installation problems&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;If you are a tester, you might also want to take a look at James and Dieter’s &lt;a href="http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DDE-T673_DDC08.pptx" target="_blank"&gt;presentation on concurrency testing&lt;/a&gt;, and who wouldn’t want to know about the &lt;a href="http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DDE-T677_DDC08.pptx" target="_blank"&gt;new Driver Verifier features for Win7&lt;/a&gt; (ably presented by Daniel Mihai)?&amp;#160; I also recommend the &lt;a href="http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DDE-C679_DDC08.pptx" target="_blank"&gt;presentation on DSF&lt;/a&gt;, because in many ways I live and die by DSF.&lt;/p&gt;  &lt;p&gt;That would be “Device Simulation Framework” if the acronym is unknown to you.&amp;#160; Sooner or later, having an easily reproduced software simulator for a device trumps going to EBay to buy some long out-of-production hardware your test driver must have…&amp;#160; That’s just one reason I like it, but that’s all I have time for now…&lt;/p&gt;  &lt;p&gt;There’s more- but that’s why it’s called a “browser”, eh?&amp;#160; By all means, browse!&lt;/p&gt;  &lt;p&gt;As for why it took so long to make public- remember this conference occurred under non-disclosure agreements.&amp;#160; Takes some time to unravel things and get all the requisite hoops jumped through.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9844701" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/customer+service/default.aspx">customer service</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/UMDF/default.aspx">UMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/DSF/default.aspx">DSF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Driver+Verifier/default.aspx">Driver Verifier</category></item><item><title>He’s Gone</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/06/25/he-s-gone.aspx</link><pubDate>Fri, 26 Jun 2009 05:15:16 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9804623</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9804623.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9804623</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9804623</wfw:comment><description>&lt;p&gt;It has been a tough week, and a busy one.&amp;#160; I’m getting ready to leave on a vacation, and trying to get all those last-minute things done.&amp;#160; &lt;/p&gt;  &lt;p&gt;While &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2009/06/18/crazy-is-as-crazy-does.aspx"&gt;my last post&lt;/a&gt; discussed the genesis of what I call the Configuration Agent and the WDF QA Universal Setup Job, this week’s focus has been entirely on another of my oddball notions- it started as a desire to build a &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2008/11/12/adaptive-fault-injection.aspx"&gt;more precise fault injection engine&lt;/a&gt; for testing the KMDF loader.&amp;#160; With that California background, the project name was easy- Fault?&amp;#160; Why, San Andreas, of course!&amp;#160; &lt;/p&gt;  &lt;p&gt;At a high level it was a programming model built around IAT filtering of calls from a driver into the kernel.&amp;#160; I wanted precision, so I could specify behavior by thread and IRQL, program each DDI independently, allow a driver to do its own filtering [i.e. get a callback with context for a DDI call under given conditions]- and with enough flexibility and locking behavior that the behavior could be reprogrammed within such a callback. For instance, in one working application of mine a filter on calls to &lt;em&gt;IoCallDriver&lt;/em&gt; from the KMDF runtime were routed on specific threads to a callback in the test driver which then turned off all call logging, as it meant the call was leaving it’s stack location- I was using the logs from calls to various resource allocation DDI to make sure the framework did not allocate resources under conditions in which we contractually would not fail- so I wanted to stop logging before I called IoCallDriver and to restart it after it returned [I knew the driver handling it was synchronous- otherwise I would have to hook the completion side of things, of course].&lt;/p&gt;  &lt;p&gt;So the concept went well beyond fault injection, but it’s always been a side-line.&amp;#160; My initial tests wound up being very white box, and a refactoring of the loader code&amp;#160; meant a similar rewrite of the test was necessary, but there was no time to do that…&amp;#160; But with Windows 7 winding up [since we’ve announced dates, that can’t qualify as a secret anymore], I have time to go back and try to at least do a few new things beyond mere maintenance.&amp;#160; Such time is rare and fleeting, so I’ve been busily making the most of it.&lt;/p&gt;  &lt;p&gt;So today was busy- I worked a bit of overtime on a COM automation server (in process) exposing a scriptable interface to my engine for some of the other team members to use, and got it at least working well enough to demo.&amp;#160; Still have my packing to do, and dinner to make and so forth, so home I headed.&lt;/p&gt;  &lt;p&gt;Then I turned on the television, and immediately heard the news about Michael Jackson.&amp;#160; Whoa…&lt;/p&gt;  &lt;p&gt;On those old tapes I’ve been scraping &lt;a href="http://bobkjelgaard.members.winisp.net/bob-audio.htm"&gt;for my archives&lt;/a&gt; I’ve got many covers of his material from the time I was playing in bar bands: Billie Jean, Thriller, Beat It- and more.&amp;#160; I’ve not posted them because frankly I never thought I did any of them justice- a lot of my material from those days has rough edges [anyone who listens to what I have posted can hear that], but these were just not good enough.&amp;#160; But add me to the billions of fans, then and since, sure…&lt;/p&gt;  &lt;p&gt;The other thought that came early on was that in my previous post I mentioned having learned to keep some of my more controversial opinions to myself- one of those was intense skepticism about the molestation accusations.&amp;#160; I knew I wasn’t likely to sway anyone there- so why bother?&lt;/p&gt;  &lt;p&gt;He’s gone, and he was younger than I am- scary stuff.&amp;#160; Life is fleeting, and it was an unexpected reminder of that.&lt;/p&gt;  &lt;p&gt;But, it’s time to pack my CDs and games and controllers, write those last few checks for bills coming due during the vacation. eat that dinner, and get ready for a night’s rest prior to that final day of work, so another slapdash post, and back to work…&lt;/p&gt;  &lt;p&gt;There was some offsetting good news today- besides finding out I really do still remember enough about COM to roll out an in-process automation server on the QT- without using ATL of course, where would the challenge be in that [answer: in learning something new for a change- you old dog!]?&amp;#160; But of course it falls into that semi-confidential area where I’ll just have to sit on it for a while [not that it’s likely to shatter the world if revealed anyway, but circumspection is worthy of practice even for an old blowhard like myself].&lt;/p&gt;  &lt;p&gt;I’ll try to do something more substantial someday- these days I’ve just not got the time to really write anything too terribly technical.&amp;#160; My apologies to those diehards who still try to read this awful stuff I’m churning out of late…&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9804623" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/UMDF/default.aspx">UMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>Crazy is as crazy does</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/06/18/crazy-is-as-crazy-does.aspx</link><pubDate>Thu, 18 Jun 2009 23:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9777458</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9777458.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9777458</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9777458</wfw:comment><description>&lt;P&gt;When I was an undergraduate at &lt;A href="http://www.caltech.edu/" mce_href="http://www.caltech.edu/"&gt;CalTech&lt;/A&gt;, my &lt;A href="http://ihc.caltech.edu/housesystem.html" mce_href="http://ihc.caltech.edu/housesystem.html"&gt;student residence&lt;/A&gt;- &lt;A href="http://en.wikipedia.org/wiki/Ricketts_House" mce_href="http://en.wikipedia.org/wiki/Ricketts_House"&gt;Ricketts House&lt;/A&gt;- had a tradition where we relieved some of the tedium and stress of the annual election for house officers [President, Vice-President, Social Vice-President, Secretary and Treasurer was the lineup if memory serves me well] by nominating and electing people to “Minor Offices”. [Looking at the Wikipedia link, I see I probably fit the Scurve profile more than I had realized- I’ve had many problems since with holding controversial and unpopular opinions- now that I’m old I just keep them to myself more than I used to].&lt;/P&gt;
&lt;P&gt;This process was largely temporized on the spot, and usually fueled with socializing, various recreational substances and a great deal of levity.&amp;nbsp; Some offices had “duties”- for instance, the RLPL (Resident Lecturer on Pornographic Literature) was in charge of the acquired collection of said “literature”- and in self-defense I’ll add that this had been an all-male school until a year or two before I arrived.&amp;nbsp; Others (such as the “House Christian”) were largely symbolic- often made up and discarded as seemed appropriate to the assembled wits at the time.&amp;nbsp; [To put the RLPL in context, I remember utilizing the service to read a Playboy interview from the mid-60’s, of &lt;A href="http://www.jerrygarcia.com/" mce_href="http://www.jerrygarcia.com/"&gt;Jerry Garcia&lt;/A&gt;, so it wasn’t always the porn that was the draw].&lt;/P&gt;
&lt;P&gt;My purpose for the aside and the title of this post combine.&amp;nbsp; During my tenure, while I never held an elected office, I was elected several times to one particular office- “House Crazy &amp;lt;a word I cannot use on MSDN, or email, or say on public broadcast- I suppose “F-bomb” comes close enough&amp;gt;”.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I’ve always had a quirky sense of humor, and I displayed it a lot during those years, so I suppose I deserved the title- things like taking a philistine swipe at some of the campus art being acquired by building a “sculpture garden” that included discarded urinals I dragged up from the basements [I swear you could find anything down there, if you looked long enough], stacks of chairs, umbrellas, discarded lumber- all tastefully arranged for display of course- and I really liked building things off-the-cuff with precarious and eccentric balance to them, so there was some “art” involved, in at least one sense of the word.&amp;nbsp; The darbs sort of liked it- I doubt the Master of Student Housing liked it, since we titled the display with his name.&amp;nbsp; Never can tell, though- some people actually can take a joke [I usually try to]…&lt;/P&gt;
&lt;P&gt;Another factor was being a pyromaniac- I can remember holding a drinking glass with some burning gasoline in it [not a lot- maybe a few millimeters, before it ignited] at one point [only because I had to find a place to toss it, to avoid injury to myself- with a bunch of people crowded around it took a while to find one- even at that somebody insisted I was throwing it at them- not the case- at that distance I wouldn’t have missed…], and at another being asked to detonate an explosive mixture someone had painted on an exterior window and then decided they didn’t feel safe either leaving or igniting- in normal form, I used a long rolled up piece of newspaper, ignited one end, set the other against the frame, and then ran, barefoot as always, across the roof tiles, which were often littered with shards of gritty nasty stuff, but my feet were long since tougher than that [of course this wasn’t on the ground floor] to get out of range.&amp;nbsp; But it was a bit of a letdown, that time- not sure it even shattered the window- where’s the fun in that?&lt;/P&gt;
&lt;P&gt;I suppose I did earn the title [and I believe I paid for most of the damages, as well, but that would be even more off-topic stories]…&lt;/P&gt;
&lt;P&gt;So today I find other outlets, and wanting to write something before I go on vacation without having posted anything in almost two months, I’ll pick one at random and see if it’s worth talking about.&lt;/P&gt;
&lt;H2&gt;Endless Dogfood&lt;/H2&gt;
&lt;P&gt;“Dog Food” is what we refer to new and unreleased software as, here at Microsoft.&amp;nbsp; Using it means you are helping those who are developing the software as an adjunct tester, and being a helpful sort [as are most of the other ‘softies I know], I participate when I can. But it brings its issues, particularly if you are using it for real work- and if you’re not using it for real work, then just how is it you are helping?&lt;/P&gt;
&lt;P&gt;To test KMDF and UMDF, we use a lot of tools- many of which you know.&amp;nbsp; But to maximize the potential return of our test effort, I want to “dog food” as much of it as possible.&amp;nbsp; That’s not as simple as it sounds- these are just a few of the issues experience has shown me:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;most products under development are built frequently, with multiple versions shared out from their “release shares”.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;The form in which those shares are presented [in terms of paths to specific processor architectures, for instance] has some variations.&lt;/LI&gt;
&lt;LI&gt;Sometimes when a product goes bad, you have to get it from somewhere else, such as a private build.&lt;/LI&gt;
&lt;LI&gt;Or you may have to stick with a previous fixed version for a while.&lt;/LI&gt;
&lt;LI&gt;But most of the time you want to get as much as possible from the same place, because some people won’t even talk to you if they see you doing much mixing and matching.&lt;/LI&gt;
&lt;LI&gt;If that mixing and matching includes things that go into driver packages [and it does for us], then cataloging and signing becomes an issue.&lt;/LI&gt;
&lt;LI&gt;Worse yet, since we do our own servicing, we sometimes have to run signed content used to test our older products whose signatures have expired and are no longer valid.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;We used to make horrid ad-hoc changes to handle these things- breaking paths down into “parameters” banged together in explicit paths to form a full path, for instance.&amp;nbsp; Done differently for each automated test, of course.&amp;nbsp; To get a test run by someone else, you had to communicate a complicated list of these “parameters” to whomever was running it, and they had to get all of them right.&lt;/P&gt;
&lt;P&gt;One day I decided I’d had enough, and out of that was born one of those custom designed solutions that is probably as quirky as the problem it solves.&amp;nbsp; Not the global sort of solution Microsoft sells to people, but the kind of stuff a lot of people in IT or support roles have to build just to survive.&lt;/P&gt;
&lt;P&gt;In the amalgam that is my work life, this became part and parcel of a task I was doing at the same time, which was to bring some commonality to all of our test setups, so it was easier to look at a machine on which a problem had been reported and know what you were actually looking at.&lt;/P&gt;
&lt;H3&gt;Simple Mind, Simple solution&lt;/H3&gt;
&lt;P&gt;So I started with some basic rules:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;One setup job goes out, finds all the tools we use, copies them to the test machine, and sets them up.&lt;/LI&gt;
&lt;LI&gt;Individual tests never go to the network for anything- if someone needs something, we add procurement of that to the setup job.&lt;/LI&gt;
&lt;LI&gt;The setup job will own making sure that everything is signed.&lt;/LI&gt;
&lt;LI&gt;The setup job is going to be very smart- no more complicated instructions.&amp;nbsp; Our most common test requirements should be its defaults, and if we need something run outside our group, all that should be needed is one reasonably mnemonic string value, used as a parameter,&amp;nbsp;to identify the machine configuration we are testing.&lt;/LI&gt;
&lt;LI&gt;The setup job is going to log where everything that is pulled off the network came from in easily accessible form, including a history of such locations from previous runs of that same job if it gets run more than once after a new OS is installed.&lt;/LI&gt;
&lt;LI&gt;It will be easy to tell it to get the most recent version of anything we use- but it will also be possible to tell it to get a specific version.&amp;nbsp; Our team will own making sure that knowledge is there in a fashion that we can meet bullet #4 above.&amp;nbsp; Bet you thought I’d forgotten I’d mentioned dog food earlier, didn’t you?&lt;/LI&gt;
&lt;LI&gt;Everything we use is to come from a supported source- not some file someone stuck on a share somewhere that had no clear ownership [or symbol files, usually…].&lt;/LI&gt;
&lt;LI&gt;Experience says there will always be some need for temporary exceptions to that last one- so put all those eggs in one basket and watch that basket closely.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Well, WTT does provide some facilities aiding in what we wanted, but it was not at all close to everything we needed.&amp;nbsp; So it was time to invent.&lt;/P&gt;
&lt;P&gt;First, I broke the job into phases:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;An Analysis phase where it takes that single parameter, along with some database of recorded setup knowledge, and determines for itself [by checking the appropriate shares] if all the pieces needed are available, and if they are, which specific places to get them from.&amp;nbsp; The results of this phase are “cast in concrete”, and the subsequent phases will use this information and only this information- not go looking again [which causes problems when things change between the analysis and when they get around to looking, for instance].&lt;/LI&gt;
&lt;LI&gt;A “staging” phase where anything that isn’t already on the machine is copied to the machine.&amp;nbsp; The places copied from are determined by the preceding analysis.&amp;nbsp; If it starts out on the network, and you need it on two places on the machine- this phase has to copy it to the machine first, and then from one place on the machine to the other.&amp;nbsp; It is also not a problem if later jobs also do such copying- as long as they never go to the network again.&lt;/LI&gt;
&lt;LI&gt;Finally, a “configuration” phase where tools are installed [from MSI or such already copied in the staging process], registries tweaked, and the machine is made ready for testing.&amp;nbsp; At this point, any of our jobs should be able to be run in any order [and one benefit here was we can now test either KMDF or UMDF where we had previously been one or the other].&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;That done, it was time to make it a reality…&lt;/P&gt;
&lt;H3&gt;Maybe not so simple, after all&lt;/H3&gt;
&lt;P&gt;First of all I needed that way to record values so they were usable both by WTT and by scripts and command line apps and whatever else without too much intervention.&amp;nbsp; Some research and experience aforethought turned up the answer, and it was almost as old as I am- the machine’s global environment is accessible to all of them, it can be updated with simple registry operations, and you can even make the changes immediately recognizable to all the pieces that really count by broadcasting a Windows message when you finish the updating [Wei indirectly clued me in on the last part- he observed that if he used the control panel the changes were immediate, even on open command prompts, but not after using one of the early versions of this code].&lt;/P&gt;
&lt;P&gt;Then there perhaps would have been the signing issue, except that we had been working on that one- we had found that we could catalog and self-sign everything and that seemed to cover everything [eventually this has had some holes, on pre-Vista OS, but I’m working on them when I can].&amp;nbsp; But we were using a copy from some WDK stuck on a share- see rule #7 above!&lt;/P&gt;
&lt;P&gt;So, I now needed some way to encode directions about where to find things how those directions changed under various circumstances, and how they differed under certain test requirements, and something that would take that information and create those environment variables.&amp;nbsp; It also had to meet my logging and reporting requirements.&lt;/P&gt;
&lt;P&gt;I wound up with another ancient solution- Windows private profiles [aka INI files].&amp;nbsp; As I’ve already taken up too much time composing this, I’ll have to continue the story at a later date…&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9777458" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/lifestyle/default.aspx">lifestyle</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>Exceptions rule!</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/04/18/exceptions-rule.aspx</link><pubDate>Sat, 18 Apr 2009 19:24:55 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9555103</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9555103.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9555103</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9555103</wfw:comment><description>&lt;p&gt;I’ve decided to revert to storytelling mode today.&amp;#160; So sit right back and you’ll hear a tale, a tale of my fateful trip (or click something useful- you’re the one deciding, and I’m the one typing to satisfy whatever inner demon has driven me to do this today)…&lt;/p&gt;  &lt;p&gt;It began when someone found a bug in the static version of KMDF- the one almost nobody gets to use and which we have been trying to discontinue any support.&amp;#160; But people were still using it, and we had no clear migration path, and there was a bug.&amp;#160; So we decided to begin testing it.&amp;#160; Poor &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2008/06/28/potential.aspx"&gt;Neslihan&lt;/a&gt; got that task (well at least it wasn’t me, this time).&amp;#160; Soon we had added a static KMDF driver to our list of test drivers used in our daily automated testing.&lt;/p&gt;  &lt;p&gt;Then, of course, we got the bugcheck.&amp;#160; As often happens, I played “Johnny-on-the-spot” and (virtually speaking) leapt onto the remote debug session accompanying the report.&amp;#160; Buffer overflow?&amp;#160; In FxDriverEntry?&amp;#160; But only on Itanium (I checked the other architectures that ran the same test, of course- no problems)?&amp;#160; What in blazes is this about?&lt;/p&gt;  &lt;p&gt;Well, the method is well documented, and not all that hard to understand- a “cookie&amp;quot; gets initialized, it gets stored to the local stack frame in such a way that code overflowing buffers in the stack frame will overwrite the stored copy.&amp;#160; On exit, code gets called that checks that value to see if that happened.&amp;#160; It’s a little more complicated than that, and I’m not going to be precise, because part of that complication is related to securing the method against the sort of people who like to exploit buffer overflows [so I’m not going to make the method clear for them- they can do their own research without my assistance].&amp;#160; The bugcheck analysis will even tell you the two values- expected and actual, making it easy for people who really think overflows are a bad idea to make a quick guess as to where the overflow came from.&lt;/p&gt;  &lt;p&gt;But the circumstances seemed suspicious, so I went and read the source code- H’mm- there’s a default value the cookie is initialized to…&amp;#160; Interesting- that’s the value we have- but it doesn’t match the expected value.&lt;/p&gt;  &lt;p&gt;At which time, something I’ve known for years hit me like the proverbial sledgehammer- our entry code calls GsDriverEntry (which supports the stack probes inserted by the GS compiler switch, hence its name) when it finishes.&amp;#160; GsDriverEntry &lt;em&gt;initializes&lt;/em&gt; the cookie, which means that that was why the values didn’t match.&amp;#160; Like the sword of Damocles, this had been hanging over our heads for years- the first time the compiler decided to do stack probes in our entry code, everything would break.&amp;#160; Ouch…&lt;/p&gt;  &lt;p&gt;I’ll leave a bunch of story out here- things got “interesting” at that point, but the problem eventually got solved, both for us and for other people facing similar issues, as well.&amp;#160; Short answer is that everyone now initializes the cookie right at the start, just as should happen…&lt;/p&gt;  &lt;p&gt;But a while back I had occasion to tweak the build process for the WdfVerifier WDK applet, and afterwards I ran it briefly to make sure I didn’t break anything in the process.&amp;#160; Oh, joy of joys- NONE of the 1.9 client drivers are being properly identified.&amp;#160; They are all identified as “Inbox”, which is what I do when &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2008/11/11/determining-a-kmdf-driver-s-client-version.aspx"&gt;the client identification method I described last year&lt;/a&gt; fails on me.&lt;/p&gt;  &lt;p&gt;Already beginning to panic, I think- did someone change FxDriverEntry, and I didn’t even notice it?&amp;#160; So I go to our source control system, and look at the change history.&amp;#160; The most recent change is the fix for the problem with the stack probes (yes it occurred on static, but what scared me then was it could have happened to any version, because were weren't doing things properly).&amp;#160; But that just calls library routines to initialize said cookie… Oh, blazes, those routines must be calling an import I wasn’t accounting for!!!&amp;#160; Why???&amp;#160; Because I NULL the IAT to force access violations, and I handle the exception by giving up on getting the true version, and fall back to calling it “Inbox”- which is, after all, exactly what I am seeing.&amp;#160; Oh, well- so much for my having thoroughly considered all the test and product consequences of that change when it was made…&lt;/p&gt;  &lt;p&gt;Well, easy enough to find out what that import might be.&amp;#160; One nice trick &lt;a href="http://blogs.msdn.com/iliast"&gt;Ilias&lt;/a&gt; showed me is that you can open any binary in WinDbg as a crash dump, and happily resolve symbols and disassemble code.&amp;#160; So I pick a random driver on my dev box, and do so.&lt;/p&gt;  &lt;p&gt;What, no imports?&amp;#160; But, but--- hmm- it uses a fixed address (load of a 64-bit immediate value into RAX, since my dev box is an X64, thank you- you x86 dinosaurs can keep your wimpy processors).&amp;#160; What’s with this?&lt;/p&gt;  &lt;p&gt;The answer lies in wdm.h, of course- KeQueryTickCount turns out to always be a macro- on x86 and IA64, it accesses KeTickCount [which is an import, and if you followed my earlier tale, it’s clear adding an import to my existing hack-o-matic mechanism is a trivial task]- but on X64, it accesses an essentially hardcoded address in a “SharedUserData” area.&amp;#160; This snippet is from wdm.h, so you can see for yourself…&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="preproc"&gt;#define&lt;/span&gt; KI_USER_SHARED_DATA 0xFFFFF78000000000UI64

&lt;span class="preproc"&gt;#define&lt;/span&gt; SharedUserData ((KUSER_SHARED_DATA * &lt;span class="kwrd"&gt;const&lt;/span&gt;)KI_USER_SHARED_DATA)

&lt;span class="preproc"&gt;#define&lt;/span&gt; SharedInterruptTime (KI_USER_SHARED_DATA + 0x8)
&lt;span class="preproc"&gt;#define&lt;/span&gt; SharedSystemTime (KI_USER_SHARED_DATA + 0x14)
&lt;span class="preproc"&gt;#define&lt;/span&gt; SharedTickCount (KI_USER_SHARED_DATA + 0x320)

&lt;span class="preproc"&gt;#define&lt;/span&gt; KeQueryInterruptTime() *((&lt;span class="kwrd"&gt;volatile&lt;/span&gt; ULONG64 *)(SharedInterruptTime))

&lt;span class="preproc"&gt;#define&lt;/span&gt; KeQuerySystemTime(CurrentCount)                                     \
    *((PULONG64)(CurrentCount)) = *((&lt;span class="kwrd"&gt;volatile&lt;/span&gt; ULONG64 *)(SharedSystemTime))

&lt;span class="preproc"&gt;#define&lt;/span&gt; KeQueryTickCount(CurrentCount)                                      \
    *((PULONG64)(CurrentCount)) = *((&lt;span class="kwrd"&gt;volatile&lt;/span&gt; ULONG64 *)(SharedTickCount))&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;My. my. my- this is a problem- no import I can just tweak to point into my code.&amp;#160; For a plus, at least the value can’t change (if it did, existing drivers would, after all, cease to work)- well, at least not easily, so I’ll save any remaining paranoia about that for another time.&amp;#160; But I’m going to access violate trying to access that address in user mode (not to mention the reams of experimental evidence I had just accumulated by noticing the problem in the first place)…&lt;/p&gt;

&lt;p&gt;So in reading about exception handling, a phrase happens to catch my eye- putting it in my words, it says that when continuing an exception, you can alter the context record supplied to you with the exception (and I know this process well, but that’s perhaps a story for a different time).&amp;#160; Whoa- that must mean I can change the contents of the registers programmatically, and then tell it to repeat the failed instruction!&amp;#160; Now, I can’t find that illustrated in any of the samples the material I’m reading points me to [nor could I find it an an internet search, although the latter was by no means exhaustive].&amp;#160; But that HAS to be what it means, right?&lt;/p&gt;

&lt;p&gt;So I start coding- first the half dozen or so lines needed to handle the KeTickCount import.&amp;#160; Then an exception filter [only for AMD64, of course].&amp;#160; The logic is my usual bit of precise work: If it is an access violation, and if it is a read, and it is a read of that exact address, and one of the integer registers in the context record has that same address, then change that register’s entry in the context record to the address of the proxy I’ve decided to keep in WdfVerifier, and tell the OS to repeat the failed instruction.&amp;#160; I began with RAX, because after all, that’s what I had seen in my investigation, and it seemed the most likely place for a while, but I added the whole set since under the circumstances, it seemed unlikely to do any harm.&amp;#160; Anything that didn’t match that exact pattern, and I gave up- just execute the handler, which does nothing.&amp;#160; The attempt to run the driver entry code to extract the client version will fail, but WdfVerifier keeps running, and the machine itself is still quite safe from my hackery.&lt;/p&gt;

&lt;p&gt;Worked the first time, it did (not counting my usual compiles to get rid of typos).&amp;#160; Problem solved.&amp;#160; Total work time from start to finish- something like 5 or 6 hours- good enough- after all, I did have to do some research…&amp;#160; Of course, there’s always somebody who can do it better, faster, and quicker- and they usually jump out of the woodwork if I start talking about things in that fashion, but it’s my story, so I’ll brag now and regret it later…&lt;/p&gt;

&lt;p&gt;Exceptions do indeed rule!&amp;#160; I love it when a plan comes together…&lt;/p&gt;

&lt;p&gt;A glimpse now at handling the new import…&lt;/p&gt;

&lt;pre class="csharpcode"&gt;
    &lt;span class="rem"&gt;//  The descriptors are an array of entries per module, each terminated with an all-0 entry.&lt;/span&gt;
    &lt;span class="rem"&gt;//  Each entry has an RVA for the module image name, and a second for a 0-terminated list of RVAs to the structures used for&lt;/span&gt;
    &lt;span class="rem"&gt;//  resolving names of exported entries from the module (in loading these get resolved to real addresses and are plugged into&lt;/span&gt;
    &lt;span class="rem"&gt;//  the loaded image's import address table in the same order).  So we now know how to write an image loader if we need to...&lt;/span&gt;

    &lt;span class="rem"&gt;//  First, find the descriptor for the KMDF loader, and quit if it isn't there.&lt;/span&gt;
    DWORD   StringCopy = (DWORD) -1, WdfBind = (DWORD) -1, InitEvent = (DWORD) -1, TickCount = (DWORD) -1; 

    &lt;span class="rem"&gt;//  Then look for the Bind and Unbind entry points.  Case counts!&lt;/span&gt;

    &lt;span class="kwrd"&gt;enum&lt;/span&gt; {OutdatedTechnology, HasBind, HasUnbind, OneCoolDriver};
    
    BYTE        TargetIdentification = OutdatedTechnology;

....

            &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt;  (IsKernel)
            {
                &lt;span class="kwrd"&gt;if&lt;/span&gt;  (0 == strcmp(&lt;span class="str"&gt;&amp;quot;RtlCopyUnicodeString&amp;quot;&lt;/span&gt;, (PSTR) NameDescriptor.Name))
                    StringCopy = ImportsIndex;
                &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt;  (0 == strcmp(&lt;span class="str"&gt;&amp;quot;KeInitializeEvent&amp;quot;&lt;/span&gt;, (PSTR) NameDescriptor.Name))
                    InitEvent = ImportsIndex;
                &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt;  (0 == strcmp(&lt;span class="str"&gt;&amp;quot;KeTickCount&amp;quot;&lt;/span&gt;, (PSTR) NameDescriptor.Name))
                    TickCount = ImportsIndex;
                
                ImportsIndex++;
            }
.....


        DWORD       IATSize, RelocationsSize;
        LONGLONG    OurFakeTickCount = 0x8badf00ddeadbeefI64;   &lt;span class="rem"&gt;//  ersatz Tick count &lt;/span&gt;        
        PVOID*  ImportAddresses = (PVOID*) 
            ImageDirectoryEntryToDataEx(DriverImage, TRUE, IMAGE_DIRECTORY_ENTRY_IAT, &amp;amp;IATSize, &amp;amp;Unused);
        
        PIMAGE_BASE_RELOCATION  Relocations = (PIMAGE_BASE_RELOCATION)
            ImageDirectoryEntryToDataEx(DriverImage, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &amp;amp;RelocationsSize, &amp;amp;Unused);

        &lt;span class="kwrd"&gt;if&lt;/span&gt;  (NULL == ImportAddresses)
        {
            FreeLibrary((HMODULE) DriverImage);
            &lt;span class="kwrd"&gt;return&lt;/span&gt;  &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        }

        &lt;span class="rem"&gt;//  Plug them in here, and we are good to go!&lt;/span&gt;

        DWORD   OldProtect;

        &lt;span class="kwrd"&gt;if&lt;/span&gt;  (!VirtualProtect(ImportAddresses, IATSize, PAGE_READWRITE, &amp;amp;OldProtect))
        {
            FreeLibrary((HMODULE) DriverImage);
            &lt;span class="kwrd"&gt;return&lt;/span&gt;  &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        }

        memset(ImportAddresses, 0, IATSize);

        ImportAddresses[StringCopy] = FakeOutStringCopy;
        ImportAddresses[WdfBind] = CollectVersion;
        &lt;span class="kwrd"&gt;if&lt;/span&gt;  (InitEvent != (DWORD) -1)
            ImportAddresses[InitEvent] = FakeEventInit;
        &lt;span class="kwrd"&gt;if&lt;/span&gt;  (TickCount != (DWORD) -1)
            ImportAddresses[TickCount] = &amp;amp;OurFakeTickCount;

        VirtualProtect(ImportAddresses, IATSize, OldProtect, &amp;amp;OldProtect);&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;So for some other glimpses, this is one part of the other hackery (complete with my elementary-level annotations):&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; AllKMDFDrivers
{
    MachineKey&amp;amp;             Owner;
    KMDFDriverList&amp;amp;         InstalledKMDFDrivers;
    LoadedDrivers&amp;amp;          CurrentlyLoadedDrivers;
    LoaderDiagnosticsFlag   LoaderFlag;
    String                  RuntimeVersion;
    DWORD                   Major, Minor, Build;

    &lt;span class="kwrd"&gt;bool&lt;/span&gt;            ServiceUsesKMDFLoader(__in PCWSTR ServiceName, __in RegistryKey&amp;amp; Service, __out MyBindInfoAlias&amp;amp; Binding);
    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt;     FakeOutStringCopy(__in PVOID, __in PVOID);  &lt;span class="rem"&gt;//  Fake RtlCopyUnicodeString entry&lt;/span&gt;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt;     FakeEventInit(__in PVOID, __in ULONG, __in ULONG);  &lt;span class="rem"&gt;//  Fake KeInitializeEvent entry&lt;/span&gt;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; ULONG    CollectVersion(__out MyBindInfoAlias&amp;amp; BindingOut, __in PVOID, __in MyBindInfoAlias&amp;amp; BindingIn, __in PVOID);
&lt;span class="preproc"&gt;#if&lt;/span&gt; defined(_AMD64_)
    &lt;span class="kwrd"&gt;static&lt;/span&gt; LONG     Filterx64Exception(__in EXCEPTION_POINTERS* ExceptionInfo, __in LONGLONG&amp;amp; FakeTickCount);
&lt;span class="preproc"&gt;#endif&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;While the rest of it looks like this (and again, this is partial)- yes, feel free to hate my stylistic indifference to the herd- perhaps I’ll get fired for this, and all can breathe a vast sigh of relief…&lt;/p&gt;

&lt;p&gt;First, the code that calls the filter&lt;/p&gt;

&lt;pre class="csharpcode"&gt;        MangledDriverEntry  CrashAndBurn = (MangledDriverEntry) ((PBYTE) DriverImage + EntryRva);

        __try
        {
            CrashAndBurn(Binding, &amp;amp;Binding);
        }
&lt;span class="preproc"&gt;#if&lt;/span&gt; !defined(_AMD64_)
        __except(EXCEPTION_EXECUTE_HANDLER)
&lt;span class="preproc"&gt;#else&lt;/span&gt;     
        __except(Filterx64Exception(GetExceptionInformation(), OurFakeTickCount))
&lt;span class="preproc"&gt;#endif&lt;/span&gt;
        {
        }&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;and now our filter:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="preproc"&gt;#if&lt;/span&gt; defined(_AMD64_)
&lt;span class="rem"&gt;/**********************************************************************************************************************************&lt;/span&gt;
&lt;span class="rem"&gt;&lt;/span&gt;
&lt;span class="rem"&gt;LONG    AllKMDFDrivers::Filterx64Exception(__in EXCEPTION_POINTERS* ExceptionInfo, __in LONGLONG&amp;amp; FakeTickCount)&lt;/span&gt;
&lt;span class="rem"&gt;&lt;/span&gt;
&lt;span class="rem"&gt;Ahh, the joys of low-level intervention by the truly incorrigible!  On AMD64, we will get an exception when the code tries to get&lt;/span&gt;
&lt;span class="rem"&gt;the tick count.  This value resides at a known address (which cannot change because if it did, all existing drivers would then fail&lt;/span&gt;
&lt;span class="rem"&gt;to work- although I suppose someone could resort to what I am about to do- bring it on, I'll see if I can keep up with the absurd&lt;/span&gt;
&lt;span class="rem"&gt;arms race).&lt;/span&gt;
&lt;span class="rem"&gt;&lt;/span&gt;
&lt;span class="rem"&gt;So, first, verify from the exception record that we are getting an access violation of some sort reading that known address.  Then&lt;/span&gt;
&lt;span class="rem"&gt;see if one of the integer registers has that address (start with RAX, since that's where it currently is, and I bet it doesn't&lt;/span&gt;
&lt;span class="rem"&gt;change much).  If it does, change it to point to the value given to this function (which resides in WdfVerifier, since I made it&lt;/span&gt;
&lt;span class="rem"&gt;a reference, and will let the compiler play enforcer), and then continue execution.&lt;/span&gt;
&lt;span class="rem"&gt;&lt;/span&gt;
&lt;span class="rem"&gt;In all other cases, execute the handler, which will do nothing (meaning the version will continue to be unknown).&lt;/span&gt;
&lt;span class="rem"&gt;&lt;/span&gt;
&lt;span class="rem"&gt;**********************************************************************************************************************************/&lt;/span&gt;

LONG    AllKMDFDrivers::Filterx64Exception(__in EXCEPTION_POINTERS* ExceptionInfo, __in LONGLONG&amp;amp; FakeTickCount)
{

    &lt;span class="rem"&gt;//  cf definition of SharedTickCount in wdm.h&lt;/span&gt;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; DWORD64    KnownTickCountAddress = 0xFFFFF78000000320UI64;

    &lt;span class="kwrd"&gt;if&lt;/span&gt;  (NULL == ExceptionInfo || NULL == ExceptionInfo-&amp;gt;ExceptionRecord || NULL == ExceptionInfo-&amp;gt;ContextRecord)
        &lt;span class="kwrd"&gt;return&lt;/span&gt;  EXCEPTION_EXECUTE_HANDLER;

    &lt;span class="kwrd"&gt;switch&lt;/span&gt;  (ExceptionInfo-&amp;gt;ExceptionRecord-&amp;gt;ExceptionCode)
    {
    &lt;span class="kwrd"&gt;case&lt;/span&gt;    EXCEPTION_ACCESS_VIOLATION:
    &lt;span class="kwrd"&gt;case&lt;/span&gt;    EXCEPTION_IN_PAGE_ERROR:    &lt;span class="rem"&gt;//  Unlikely, but what the heck...&lt;/span&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt;  (2 &amp;gt; ExceptionInfo-&amp;gt;ExceptionRecord-&amp;gt;NumberParameters)
            &lt;span class="kwrd"&gt;return&lt;/span&gt;  EXCEPTION_EXECUTE_HANDLER;
        &lt;span class="kwrd"&gt;break&lt;/span&gt;;

    &lt;span class="kwrd"&gt;default&lt;/span&gt;:
        &lt;span class="kwrd"&gt;return&lt;/span&gt;  EXCEPTION_EXECUTE_HANDLER;
    }

    &lt;span class="kwrd"&gt;if&lt;/span&gt;  (EXCEPTION_NONCONTINUABLE == ExceptionInfo-&amp;gt;ExceptionRecord-&amp;gt;ExceptionFlags)
        &lt;span class="kwrd"&gt;return&lt;/span&gt;  EXCEPTION_EXECUTE_HANDLER;

    &lt;span class="kwrd"&gt;if&lt;/span&gt;  (EXCEPTION_READ_FAULT != ExceptionInfo-&amp;gt;ExceptionRecord-&amp;gt;ExceptionInformation[0] ||
        KnownTickCountAddress != ExceptionInfo-&amp;gt;ExceptionRecord-&amp;gt;ExceptionInformation[1])
        &lt;span class="kwrd"&gt;return&lt;/span&gt;  EXCEPTION_EXECUTE_HANDLER;

    &lt;span class="kwrd"&gt;if&lt;/span&gt;  (KnownTickCountAddress == ExceptionInfo-&amp;gt;ContextRecord-&amp;gt;Rax)
    {
        ExceptionInfo-&amp;gt;ContextRecord-&amp;gt;Rax = (DWORD64) &amp;amp;FakeTickCount;
            &lt;span class="kwrd"&gt;return&lt;/span&gt;  EXCEPTION_CONTINUE_EXECUTION;
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt;  (KnownTickCountAddress == ExceptionInfo-&amp;gt;ContextRecord-&amp;gt;Rbx)
 &lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The rest I leave as an exercise to the reader, having already put all 0.378 of you through the treadmill today…&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9555103" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/debugging/default.aspx">debugging</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/WdfVerifier/default.aspx">WdfVerifier</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>Using C++ in a KMDF driver part 1- a pattern for using contexts as objects</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/03/12/using-c-in-a-kmdf-driver-part-1-a-pattern-for-using-contexts-as-objects.aspx</link><pubDate>Thu, 12 Mar 2009 16:36:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9471696</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9471696.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9471696</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9471696</wfw:comment><description>&lt;p&gt;This is an article I’ve started probably close to a dozen times since I started this blog, but never published.&amp;#160; In part because of all the heat the topic of using C++ in the kernel generates, and the rest perhaps because of my reaction to that heat.&lt;/p&gt;  &lt;p&gt;So I’ll get one thing off my chest at the start and perhaps that will be enough to let me proceed.&lt;/p&gt;  &lt;p&gt;I’ve been writing drivers with C++ in the kernel (or the Win 3.1/9x/ME VMM) pretty much since I began using the language (in the very early 90’s).&amp;#160; I routinely use paged code (paged data not so much- I’ve never had designs where there seemed to be any benefit to it).&amp;#160; That spans more than a decade- in fact, its close to two decades now.&lt;/p&gt;  &lt;p&gt;I’ve NEVER had a problem with the issues raised in the paper.&amp;#160; I’m not even going to link to it.&amp;#160; If you want to find it- it isn’t hard to find.&amp;#160; On top of that, in a determined effort to find people who had, I didn’t find many- and the one clear case I did find was cured with a #pragma that would have made sense if you were a C programmer and had a basic understanding of where VTABLES and such get emitted to.&amp;#160; So I personally have a sense of mismatch between my own experience and the strongly worded severity there.&lt;/p&gt;  &lt;p&gt;I’ve been told that if I persist, I’ll deserve all the paging problems I get [and that nobody will help me with them].&amp;#160; Well, I do get them (always have), and I’ve been developing long enough in this environment that I don’t really need anybody’s help to find the root cause of a bug like that.&amp;#160; The causes are always the ones I remember- acquiring a spin lock in pagable code- making a routine pagable that can be called at elevated IRQL- all the usual ways to screw up in that other language that is the hallmark of a true first-class kernel developer.&amp;#160; But none of them had anything to do with my choice of programming language.&amp;#160; Not once.&amp;#160; Not saying that it never happened across all those years, because in the early ones, the ability to catch a bug like that was severely limited- there was no Driver Verifier, no static analysis tools.&amp;#160; So it may not have been noticed early on.&amp;#160; But now that I have them, it’s still not happening…&lt;/p&gt;  &lt;p&gt;Now there can be plenty of reasons for that- but I look at what people take away from the paper, and I do a lot of the things they think aren’t safe.&amp;#160; I use polymorphism and inheritance freely.&amp;#160; I don’t use multiple inheritance a lot, but I have used it and have not observed problems arising from its use.&amp;#160; On the other hand, there are common features that I don’t use as a matter of personal preference or style that may bear on this.&amp;#160; I don’t expose the implementation of functions in header files (meaning the compiler is not going to start out by inlining them and then give up later, dumping them in some unintended segment) with the exception of trivial accessor functions.&amp;#160; I don’t use templates (I’m not sure they were a language feature when I started, but at any rate, during my learning curve I never needed them, so while I can handle code with templates, I don’t use them myself).&amp;#160; I almost always code my own constructors, destructors, copy constructors and assignment operators (I usually have to- I prefer references to pointers and if you have reference members, the compiler can’t generate default code for most of those routines).&lt;/p&gt;  &lt;p&gt;So now that its clear I’m not going to walk the company line on that topic [the opinions I expressed ought obviously to be clearly my own], I’ll proceed to something more useful…&lt;/p&gt;  &lt;h2&gt;Leveraging the KMDF Object Model&lt;/h2&gt;  &lt;p&gt;KMDF provides a nice object model, with managed lifetimes and one of the most delightful observations I had in my first KMDF driver was that it was easy for me to blend this with my usual coding patterns.&lt;/p&gt;  &lt;p&gt;As an aside, I’ll note that I never use sample code to learn anything.&amp;#160; I take the reference materials and code to them.&amp;#160; If there are samples, I treat them as the last resort- and I will deliberately change as much as I can of them [in part to see what knowledge of things that can go wrong wasn’t explicitly represented in the sample].&amp;#160; I judge the quality of the reference material by how rarely I have to look at a sample to figure something out [yes, I don’t find much reference material i would call “good”].&lt;/p&gt;  &lt;p&gt;So my first KMDF driver was a software bus driver, and I didn’t go near toaster in writing it.&amp;#160; In fact it was one of those “ActiveX” (OLE automation) test drivers I mentioned in our DDC presentation.&amp;#160; Now we had some samples for them, too- and not surprisingly, virtually no reference material.&amp;#160; The samples were fastidious about one thing- all the COM parts were in C++ (not a lot of choice there)- but all the parts using KMDF were in C- precisely because of said paper.&amp;#160; I might add that this was even though no attempt was made to mark any of the code or data pagable in those samples.&amp;#160; Well, I’m a stubborn &amp;lt;expletive of your choice here&amp;gt;, so I decided then and there I was going to write the whole driver in C++ in spite of the objections I received.&amp;#160; I was still in my “trial period” so they could always fire me if they wanted to, but the job market was good enough at that time that I was pretty sure I could find something…&lt;/p&gt;  &lt;p&gt;Back to the proper topic- one fine thing is that most of the KMDF macros are agnostic enough they can handle at least straightforward C++.&amp;#160; That was one of the happiest discoveries of that time.&lt;/p&gt;  &lt;p&gt;So the basic pattern as I use it:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Declare a static function in your class that takes a WDFOBJECT as input and returns a pointer to an object of your class. &lt;/li&gt;    &lt;li&gt;Declare a class-specific placement form new operator that takes as its additional input the type of handle you expect your object to live in the context of (that is, it can be more precise than the preceding function can and you can benefit from stronger typing in C++) &lt;/li&gt;    &lt;li&gt;Declare a class-specific delete operator that basically does nothing if you need to have your destructor invoked. &lt;/li&gt;    &lt;li&gt;If you have such a delete operator, also declare a static member with a void return that takes a WDFOBJECT as input. &lt;/li&gt;    &lt;li&gt;Use the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro to get the compiler to write that first function for you. &lt;/li&gt;    &lt;li&gt;Have your new operator implementation use the first function to return the address of the underlying context (you basically ignore or validate the size parameter) from the passed-in handle. &lt;/li&gt;    &lt;li&gt;When creating the context, and you need your destructor called, use a WDF_OBJECT_ATTRIBUTES structure with the EvtCleanupCallback set to the routine in item 4. &lt;/li&gt;    &lt;li&gt;Code that routine to use the routine in item 1 to get the context address out of the object handle- and delete that pointer.&amp;#160; This causes your destructor to be called at cleanup time (which is much more sensible than destroy time) and your do-nothing delete operator will also be invoked (or inlined out of existence if your compiler is any good).&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;There- you “create” your object when the KMDF object is created (or via a WdfObjectAllocateContext call if you add your object later), and “delete” it when the object dies.&amp;#160; But KMDF manages the memory and most of the object lifetime for you.&amp;#160; Sure works for me (a lot).&lt;/p&gt;  &lt;p&gt;The following snippet is from that first driver (I’ve since dropped the usage of “C” on class definitions in my general drive toward anarchic style).&amp;#160; This is slightly convoluted because I have logic allowing only one instance of a device with this driver- so I’ve deliberately intermingled driver-level and device-level usages (always pushing those boundaries- but I think that’s a good way for an SDET to think).&amp;#160; I’ll admit this is slightly doctored (I removed some things related to the COM technology as that I can’t disclose, plus I tried to include support for the standard bus interface and that just complicates things without illustrating this method), but it should show I practiced what I am preaching…&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; CTargetTestBus
{
    &lt;span class="kwrd"&gt;static&lt;/span&gt; WDFDEVICE                Owner;              &lt;span class="rem"&gt;//  WDF device that &amp;quot;owns&amp;quot; this bus object&lt;/span&gt;

    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt;*    &lt;span class="kwrd"&gt;operator&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;(size_t size, WDFDEVICE OwningDevice);
    CTargetTestBus(WDFDEVICE OwningDevice);
    ~CTargetTestBus() {}

    &lt;span class="rem"&gt;//  Private callbacks (ie, accessed from within this class' code)&lt;/span&gt;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; EVT_WDF_IO_QUEUE_IO_DEFAULT      OnIoDispatchDefault;

    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; &lt;span class="kwrd"&gt;operator&lt;/span&gt; delete(&lt;span class="kwrd"&gt;void&lt;/span&gt;*) {}
&lt;span class="kwrd"&gt;public&lt;/span&gt;:

    NTSTATUS    NewChild(LPCWSTR Name, &lt;span class="kwrd"&gt;int&lt;/span&gt; InstanceID);
    NTSTATUS    RemoveChild(LPCWSTR Name, &lt;span class="kwrd"&gt;int&lt;/span&gt; InstanceID);
    &lt;span class="kwrd"&gt;void&lt;/span&gt;        DoneWithBus();

    &lt;span class="kwrd"&gt;static&lt;/span&gt; CTargetTestBus*  GetThisTargetTestBus(__in WDFOBJECT Object);    &lt;span class="rem"&gt;//  WDF macro writes this code&lt;/span&gt;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; CTargetTestBus&amp;amp;  GetTheBus(&lt;span class="kwrd"&gt;bool&lt;/span&gt;&amp;amp; BusPresent);
    
    &lt;span class="rem"&gt;//  Driver callbacks (public, because used in DriverEntry)&lt;/span&gt;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; EVT_WDF_DRIVER_DEVICE_ADD        OnDriverDeviceAdd;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt;             OnDriverUnload(IN WDFDRIVER Driver);

    &lt;span class="rem"&gt;//  This one is accessed from a member in CChildInfo&lt;/span&gt;
    &lt;span class="kwrd"&gt;static&lt;/span&gt; EVT_WDF_CHILD_LIST_CREATE_DEVICE OnAddNewChild;
};


&lt;span class="rem"&gt;// Macros to get the context&lt;/span&gt;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CTargetTestBus, CTargetTestBus::GetThisTargetTestBus);&lt;/pre&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&lt;em&gt;Now playing:&amp;#160; Me (that old recording of Johnny B Goode again)!&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9471696" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/C_2B002B00_/default.aspx">C++</category></item><item><title>Automated Jobs and Library Jobs</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/03/12/automated-jobs-and-library-jobs.aspx</link><pubDate>Thu, 12 Mar 2009 14:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9471592</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9471592.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9471592</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9471592</wfw:comment><description>&lt;P&gt;I received an IM late yesterday evening (my time) from “James” (via the Web) asking what the difference is between an automated job and a library job.&amp;nbsp; Unfortunately, I wasn’t around to answer it (I started work about 2 AM PDT today, and the IM was from about 9:30 PM PDT yesterday), but it’s rare I get asked something I can flip an answer to off the top of my head, so…&lt;/P&gt;
&lt;P&gt;I’m assuming this is in the context of the Device Test Manager (DTM) in the Windows Logo Kit (WLK).&amp;nbsp; That is a derivative of a larger internal-use product we call WTT (Windows Test Technologies), so I’ll assume the same answer applies to both, because I’m sure it does (and if I’m wrong, feel free to correct me).&lt;/P&gt;
&lt;P&gt;If you’re a programmer, the fastest rough analogy is that an Automated Job is like a C / C++ “main” while the Library job is like a “function” in the runtime library (or some DLL, etc).&amp;nbsp; The important difference here being that a job can “call” a library job and pass it parameters, while you cannot “call” an automated job- you can schedule it (and give it parameters) just like you can invoke a program (and give it parameters) from a command shell- but we don’t have analogs like piping and redirection of I/O etc in this execution environment.&lt;/P&gt;
&lt;P&gt;They are a lot alike- both can be scheduled and given run-time parameters, and possess fairly similar capabilities.&lt;/P&gt;
&lt;P&gt;So why not make all Automated jobs Library Jobs?&amp;nbsp; One strong reason is that Automated Jobs can be constrained [have a set of circumstances spelled out to detail the requirements for running the job- one common one in device testing is the presence of a particular kind of hardware, for instance] while library jobs cannot.&amp;nbsp; Another one I use occasionally perhaps ventures into the realm of the political- making a job an automated job so that it doesn’t wind up being called as a library job if you expect such a usage to have untoward consequences.&lt;/P&gt;
&lt;P&gt;The best practice, especially initially, is to make most jobs library jobs- this gives you the most flexibility as you combine them later.&amp;nbsp; You can work on them in pieces and then combine the pieces fairly easily.&lt;/P&gt;
&lt;P&gt;Well, James- if you’re still searching for that answer, perhaps this will help.&amp;nbsp; If not, maybe it will help someone else later.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9471592" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/customer+service/default.aspx">customer service</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/DTM/default.aspx">DTM</category></item><item><title>Well, yes and no...</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/01/22/well-yes-and-no.aspx</link><pubDate>Fri, 23 Jan 2009 10:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9372304</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9372304.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9372304</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9372304</wfw:comment><description>&lt;P&gt;I got involved (probably quite foolishly) in &lt;A href="http://osronline.com/cf.cfm?PageURL=showThread.CFM?link=147413" target=_blank mce_href="http://osronline.com/cf.cfm?PageURL=showThread.CFM?link=147413"&gt;a discussion on the NTDEV mailing list&lt;/A&gt; that really wasn't much of my business yesterday, but I thought I'd expand a bit on my thoughts there, anyway.&lt;/P&gt;
&lt;P&gt;It probably sounds in one of my first posts there that I'm completely disagreeing with Peter Viscarola, although in fact, I don't.&amp;nbsp; I just think there's a lot more to the story than that- both the reasons why things are as they are, and the broad general effect it has.&lt;/P&gt;
&lt;H2&gt;The Purina Effect&lt;/H2&gt;
&lt;P&gt;I think I'll structure the rest as a Q &amp;amp; A with some imaginary and perhaps occasionally hostile interviewer- we'll see where that takes me.&amp;nbsp; Not that there's a need for this, but it's my blog, so I get to make these choices...&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;So why do so many people at Microsoft run the latest of everything?&lt;/LI&gt;&lt;/UL&gt;
&lt;OL&gt;
&lt;LI&gt;Because we hire a lot of technophiles- we are people who like new technology and believe innately in its transformative power.&amp;nbsp; We know such people do well in our environment, and make great contributions.&amp;nbsp; Its a good trait to have if you're seeking a job here.&amp;nbsp; You'll get picked on sometimes for using Office 2003 for the same reason some people will give you grief about out of date fashions, or a stodgy car, or...&amp;nbsp; So the desire for the latest and greatest is inbuilt.&lt;/LI&gt;
&lt;LI&gt;Because so many of us are involved in developing new products, we understand quickly the economics of their test, and that includes the idea that finding problems earlier is fixing them cheaper.&amp;nbsp; In part due to that first bullet, there's usually a ready pool of people available to help test your new product, and that's a good thing.&amp;nbsp; Most of the time, the problem is keeping them away from things before you're prepared for their input.&amp;nbsp; This is also good over the long run- we call it "&lt;EM&gt;&lt;STRONG&gt;dog food&lt;/STRONG&gt;&lt;/EM&gt;" [short for "eating the dog food"], and it is well-baked into the corporate culture.&amp;nbsp; It occurs on voluntary and ad-hoc bases and in planned deployments.&amp;nbsp; We always use things before you do.&amp;nbsp; We always will.&amp;nbsp; [And unfortunately we will still miss things- there is no perfect test process, at least, not that I know of].&amp;nbsp; I began running Windows 7 within weeks of the release of Windows Vista, and used it for most of my work (and most of my blog posts, except at times like this when I post from home).&amp;nbsp; Unlike most driver developers, I am used to an OS whose code changes each and every day, and exists in multiple forms at nearly the same time.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Just looking at the last couple of years, I've run beta or earlier versions of a couple of OS, Office, Windows Live, Halo 3, and Halo Wars.&amp;nbsp; I didn't have the big XBox Live update because I knew I wouldn't have time to work with it [but I know people who did].&amp;nbsp; I'm not particularly on the bleeding edge, usually, even with all that.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Why do things change and old ways no longer work?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Sometimes, it is much as Peter said [with my demurrals above flavoring it a bit]- a lot of focus on the new.&amp;nbsp; But many times these are done deliberately, and "cool" [in the sense of some form of hipness] may occasionally be a factor, but not one that gets much weight [sticking to the OS- different products, different markets, differenf factors].&lt;/P&gt;
&lt;P&gt;Most of the cases I can think of were the result of analysis of real data- watching and observing how things are really used.&amp;nbsp; Looking for the problem areas- trying to find ways to minimize the number of steps to accomplish the most important and the most common tasks.&amp;nbsp; Making things work better, and more easily.&amp;nbsp; I don't think that should be news- I expect several of the Windows team blogs say so directly or indirectly.&amp;nbsp; Now we think of that as "cool", but that's not the sense the word was being used in in that thread.&lt;/P&gt;
&lt;P&gt;But we don't always know the full impact of changes sometimes, and it never hurts to check things in the real world.&amp;nbsp; That's one reason we have beta tests.&amp;nbsp; The TARGETPATH issue is (in my opinion) something we will take as a lesson for the future, but I also think this is proof the beta test process works.&amp;nbsp; Would it have been better for it to be this way in the final version?&amp;nbsp; Was the entire beta so good that the only conclusion was that we would not change anything from the feedback resulting from the beta, making it some sort of trial balloon we'd pull back, buff up, and then reissue as the final thing?&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Is your "love of the new" [I won't repeat calling it the Purina Effect, although perhaps they'd be happy I find the name mnemonic for pet food] the sole reason you miss down-level breaks?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;No, we also miss them, in my opinion, because: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;We develop blind spots in our test procedures and our thinking about how our products are used.&amp;nbsp; Most test scenarios have large variability and we have to narrow down the problem spaces to develop workable solutions.&amp;nbsp; Sometimes this process leaves holes.&amp;nbsp; More on that in a minute.&lt;/LI&gt;
&lt;LI&gt;Peculiar to this case is the mechanisms through which our build tools reach the WDK.&amp;nbsp; As I'm sure has been discussed on the Engineering Windows 7 blog, we put a lot of time and effort into improving our internal processes, and that definitely included how we build Windows.&amp;nbsp; The new mechanisms for binplace versus the old targetpath mechanisms has been a big win for us in terms of working with the source code.&amp;nbsp; But to minimize the impact to product teams, a lot of the initial legwork for it was done by the tool developers, and pushed out to us along with the tool changes.&amp;nbsp; I did some rework in our test code [things I privately had but weren't part of the main Windows source], so I was aware of some of this work, but I suspect that for most developers, this just happened [and that's good- it saves a lot of R&amp;amp;D money when things work that way].&amp;nbsp; This "magic elf" phenomenon may have helped develop something of a blind spot.&lt;/LI&gt;&lt;/OL&gt;
&lt;UL&gt;
&lt;LI&gt;Did you, personally, test the WDK at all?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Actually, yes [and it has its own test organization, as well].&amp;nbsp; I and other members of our test team have installed it, built samples, run them, read the documentation and the source code, used the tools, and filed bugs as a result of what we've found.&amp;nbsp; That's happened more than once.&amp;nbsp; Periodically we have held what we call "bug bashes" where everyone in the organization that includes our team goes to an out-of-office location, splits up into teams, and competes to see who can find the most bugs, or the most interesting bugs, and so on.&amp;nbsp; But no, we didn't take SP1 DDK code and run it against the latest WDK [and there are multiple reasons that wouldn't work for WDF, anyway].&amp;nbsp; But I wouldn't be surprised to hear someone's considering that after all of this.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Is it your fault this happened?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I certainly ask myself that- or at least, if I shouldn't have done more, or paid more attention, and if I had, maybe I could have realized TARGETPATH would be an issue and flagged it before it went out the door.&amp;nbsp; But probably not- it was one of those mostly deprecated things that stayed in the WDK long after its need in Windows proper had passed on.&amp;nbsp; I developed a blind spot.&lt;/P&gt;
&lt;P&gt;I bet I'm not the only SDET in Device Platform Technologies (which encompasses the WDK and WDF groups) who's doing that kind of thinking these days, although I certainly haven't conducted a survey on the subject.&amp;nbsp; I said above I'd get back to test holes, and this is a good place for it.&lt;/P&gt;
&lt;P&gt;They exist.&amp;nbsp; We prefer when they're complicated enough it makes some sense to have missed them, but we're human enough it doesn't always work that way.&amp;nbsp; In a way, it should be hard to get too big a sense of oneself as a computer programmer.&amp;nbsp; The blasted thing always does exactly what you tell it to do.&amp;nbsp; You often don't tell it the right thing, even when you're sure that you have.&amp;nbsp; But being human, we get that sense sometimes anyway.&amp;nbsp; Maybe I had more of it than I should have when I made my first post on that thread.&lt;/P&gt;
&lt;P&gt;Time will tell.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Layoffs?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Not funny.&amp;nbsp; I've been laid off twice in my career, both times as an SDE, and both times in a difficult economy, and this economy is worse than it was either of those times.&amp;nbsp; Nobody I know well is affected, but I am on some mailing lists where affected people made their brief farewells.&lt;/P&gt;
&lt;P&gt;I sympathize with their situation and hope for the best for them.&amp;nbsp; I'll add that as far as I'm concerned, whomever hires them gets a good deal, because I can't remember the last time I saw a Microsoft FTE I thought wasn't a good employment catch.&amp;nbsp; I'll also add that I have a lot of faith in the people who made those decisions- I've seen enough to believe it had to be done, and it wasn't done lightly.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;So why did you hint at unemployment?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Someone taking that thread and blowing it up into a news story about Microsoft not trusting its own products?&amp;nbsp;&amp;nbsp; Not that it would (or will- I can't predict the future on something like this) get me terminated, but I wouldn't blame anyone but myself if it did.&amp;nbsp; For that matter, I may have said more about internal affairs than I should have.&amp;nbsp; Business procedures (and that includes security procedures) are proprietary information and covered by employment agreements.&amp;nbsp; By not checking first, I may have doomed myself, and that's life [corporate at any size- the principles don't differ that much from place to place].&lt;/P&gt;
&lt;P&gt;I don't think I was discussing anything other than recommended best practices, though, so I'm not really as worried now as I was when I first thought about it.&lt;/P&gt;
&lt;P&gt;Next time I intend to discuss something [anything] else- that's a certainty.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9372304" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/customer+service/default.aspx">customer service</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>Adaptive Fault Injection</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2008/11/12/adaptive-fault-injection.aspx</link><pubDate>Wed, 12 Nov 2008 22:18:43 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9063956</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9063956.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9063956</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9063956</wfw:comment><description>&lt;p&gt;One of the topics I covered in &lt;a href="http://blogs.msdn.com/iliast" target="_blank"&gt;Ilias&lt;/a&gt;' and my joint presentation at &lt;a href="http://microsoft.com/whdc/winhec/default.mspx" target="_blank"&gt;WinHEC&lt;/a&gt; this year was new requirements coming for getting a WHQL signature for drivers using KMDF (UMDF as well, but this discussion doesn't currently apply to them).&amp;#160; One part of those new requirements is that your driver survives a rigorous fault injection from the &lt;a href="http://msdn.microsoft.com/en-us/library/cc264231.aspx" target="_blank"&gt;WdfTester&lt;/a&gt; tool.&amp;#160; The method used for that is what I intend to discuss briefly in this post.&lt;/p&gt;  &lt;p&gt;By &amp;quot;survives&amp;quot;, I mean no bugchecks, hangs, or leaks- graceful failure, not fault tolerance, is the goal here.&lt;/p&gt;  &lt;p&gt;The method used is one I call adaptive fault injection.&amp;#160; The term &amp;quot;adaptive fault injection&amp;quot; is admittedly my invention (and I'm probably the only person that uses it)- but I thought it fit.&amp;#160; So this is an attempt to define what I mean by the term.&lt;/p&gt;  &lt;h2&gt;The Problem&lt;/h2&gt;  &lt;p&gt;For readily available fault injection, I had two tools available to me in 2006, when I began looking into ways to improve code coverage in the KMDF loader in an automated way.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Driver Verifier Low Resource Simulation- this did boost our numbers, but it took a long time,, and since it was random, it took extensive analysis to find out what was covered in terms of code paths, and the only way to cover a particular fault was to run until you finally hit it.&amp;#160; Not very predictable.&amp;#160; To me, it was a shotgun handed to me when what I really wanted was a needle.&lt;/li&gt;    &lt;li&gt;The always on, but programmable threshold mechanism in the KMDF Verifier.&amp;#160; For one thing, it didn't help me with the loader (but I was also looking for generic solutions), but for another, I wanted to be able to say- &amp;quot;I want just this one fault, period&amp;quot;.&amp;#160; So it was still a bludgeon, and not the precise instrument I desired.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Now, we had experimented with IAT hooks and had even used them experimentally for fault injection [the tool just failed pool allocations].&amp;#160; I could easily see that I could use them for precision, but the result could be a very high-maintenance mechanism- if I had to individually code each fault, the price for the technique would be way too high.&lt;/p&gt;  &lt;p&gt;I wanted something that could examine the system under test, find all the failure points, and then cover each and every one of them.&amp;#160; Something that would adapt to the system's behavior as it evolved.&lt;/p&gt;  &lt;p&gt;Hence &amp;quot;adaptive fault injection&amp;quot;.&amp;#160; So perhaps the basic idea is less of a mystery?&lt;/p&gt;  &lt;h2&gt;Feedback is almost always your friend&lt;/h2&gt;  &lt;p&gt;If you have an IAT hook, you can log the activity through the intercepted call- both the data going into the called routine, and the values returned.&amp;#160; You can't see state changes occurring on either side of the hook, but at least you've got a point you can begin at [and this situation reminds me a lot of the days when we were testing circuit boards via their external connectors].&lt;/p&gt;  &lt;p&gt;So the basic idea for the first iteration was quite simple:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Monitor all the points you can, and record the activity on them.&lt;/li&gt;    &lt;li&gt;Analyze the recorded activity, and determine where inputs going back into the system can be modified to simulate failures.&lt;/li&gt;    &lt;li&gt;Count the number of such failures you have identified.&lt;/li&gt;    &lt;li&gt;Repeat the original activity as many times as needed, and on each cycle, inject each failure in turn.&amp;#160; Log this activity much as was done in the first step [and the logging mechanism should report the injection activity, of course].&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;WdfTester was under development at the same time as my tool [which I named &amp;quot;SanAndreas&amp;quot; after the infamous fault line running up the West Coast of the USA], and utilized the same concept, although in a different form.&amp;#160; My trigger was a simple integral counter, making for a simple loop.&amp;#160; WdfTester instead injects a fault on a specific count of a given DDI call.&amp;#160; Neither method is perfect [I'll get back to that in a bit], but in highly repeatable traces, there's no real difference between them.&amp;#160; By the way, I have no idea if we both had the same idea, or if we discussed this [although we probably did, because when I first began that task I said I wanted this sort of injection mechanism, long before I did the implementing].&lt;/p&gt;  &lt;p&gt;So, this provides more precise injection, at the cost of potentially longer run times, but the times are deterministic and computable once the analysis step has completed.&amp;#160; But it also requires little programming or reprogramming, as it does adapt itself to the observed behavior of the system under test.&lt;/p&gt;  &lt;h2&gt;Where this still falls short&lt;/h2&gt;  &lt;p&gt;At least a couple of places come quickly to mind:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;In multithreaded cases, observed behavior may not be that deterministic.&amp;#160; In that case, we at least try to inject something, but there is potential for things to be missed, or even for the same fault to be injected multiple times.&lt;/li&gt;    &lt;li&gt;The state that cannot be observed may matter- I believe this is primarily a concern when designing the repeatable case you want to inject, or at least this risk can be mitigated by considering the state when deciding what sequence to apply this technique to.&lt;/li&gt;    &lt;li&gt;The system may adapt to the faults you inject [for instance a failed I/O may be retried].&amp;#160; This is bad only in the sense that it may prevent you from reaching paths you would still like to reach.&amp;#160; One could address this by recursively repeating the analysis and subsequent phases (and then using a more complicated injector- first inject this {series of} fault{s}, then in turn inject these].&amp;#160; Such a mechanism may need to have runtime bounds placed on it to prevent endless recursion...&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Still, even with these flaws, I've found the technique even in this most primitive of forms to be a step forward in having a more precise fault injection method available to me in my bag of tools.&lt;/p&gt;  &lt;h2&gt;As long as I'm typing...&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/888_umdf_4_you/archive/2008/11/04/9041879.aspx" target="_blank"&gt;Gee, Patrick- I've played all three&lt;/a&gt; [but I preorder at GameStop, even though the price is higher]- which reminds me that I need to pick up Call of Duty: World At War [and a day later- World of Warcraft: Wrath of the Lich King].&amp;#160; Didn't get far in Fallout 3, but one play-through each on Fable II and Gears of War 2.&lt;/p&gt;  &lt;p&gt;I've been pulling tunes off some really old cassette tapes [bands I played in during the 70's and 80's- recorded in mono on hand-helds, for the most part, along with some solo practice recordings]- think I'll use that nice USB stick I got at WinHEC to bring a few of the livable ones to the office- see if anyone can figure out which tunes I'm the guitarist or bass player and / or vocalist on...&amp;#160; Of course, the poor quality of the audio ought to be a clue.&amp;#160; If I find one I can live with, maybe I'll link it somewhere [I have a few I wrote myself, are public domain tunes, or are just instrumental noodling, so I can avoid the copyright bogeyman].&lt;/p&gt;  &lt;p&gt;Also, since things are now disclosed- this is what the new 1.9 controls in WdfVerifier will look like.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/bobkjelgaard/WindowsLiveWriter/AdaptiveFaultInjection_9F00/New-1.9-KMDF-Features.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="New-1.9-KMDF-Features" src="http://blogs.msdn.com/blogfiles/bobkjelgaard/WindowsLiveWriter/AdaptiveFaultInjection_9F00/New-1.9-KMDF-Features_thumb.png" width="555" height="462" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;em&gt;Now Playing: Grateful Dead Album: Built To Last- Victim or the Crime- seem to end on Dead tunes of late, not that I don't listen to plenty else&lt;/em&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9063956" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/XBox+360/default.aspx">XBox 360</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/WdfVerifier/default.aspx">WdfVerifier</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category></item><item><title>DDC starts in less than an hour</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2008/09/29/ddc-starts-in-less-than-an-hour.aspx</link><pubDate>Mon, 29 Sep 2008 16:21:36 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8968867</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/8968867.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=8968867</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=8968867</wfw:comment><description>&lt;p&gt;Plenty of good stuff for today- begin with Eliyas and Peter going over what's new in WDF for Windows 7 (or as we prefer to think of it WDF 1.9, since much of it also works all the back to Windows 2000 [KMDF] or Windows XP [UMDF]).&amp;#160; It continues later with our first presentation of talks on the &amp;quot;shared secrets&amp;quot; of the Windows Driver Frameworks.&amp;#160; The first talk discusses the implementation of the frameworks themselves, while the second presentation (my first of this conference, and my first in about 16 years) discusses how the frameworks are tested.&amp;#160; The latter talk will also be one of the final talks of the day.&lt;/p&gt;  &lt;p&gt;Tomorrow will include &lt;a target="_blank" href="http://blogs.msdn.com/bobkjelgaard/archive/2008/09/11/potpourri.aspx"&gt;Neslihan's talk about getting a logo for your WDF driver&lt;/a&gt; (yes we are adding logo requirements specifically for WDF drivers- primarily for KMDF at the moment).&amp;#160; It will include some excellent talks by Praveen Rao about work we have done on WDF drivers in the storage space, and again the final talk (at least in that room) is &lt;a target="_blank" href="http://blogs.msdn.com/iliast"&gt;Ilias&lt;/a&gt; and I discussing the WDF coinstallers.&lt;/p&gt;  &lt;p&gt;Wednesday we'll repeat all the talks I am in- the shared secrets talks will be back to back in the morning, but I won't catch part 1 that day because I'll be in another room with &lt;a target="_blank" href="http://blogs.msdn.com/iliast"&gt;Ilias&lt;/a&gt; repeating the presentation on the coinstallers.&lt;/p&gt;  &lt;p&gt;There's so much more, too- SDV, DSF, the innards of driver verifier, annotations for PFD and SDV, new test techniques from my colleagues James Moe and Dieter Achstettler, excellent talks on device installation, many driver technologies (several on printing, I can't help but notice).&amp;#160; I could go on and on, except I've got some work to get to this morning [and I'll be leaving soon so I can register and begin my bit of supporting the conference].&lt;/p&gt;  &lt;p&gt;Ask the experts session tomorrow night, bowling tonight, space set aside for us to talk with developers before and after talks, labs, panel discussions, Q &amp;amp; A with our most senior engineering staff, and a few surprises I'm not at liberty to mention even now.&lt;/p&gt;  &lt;p&gt;My plan for now is to try to attend the whole thing- how well that works depends upon how things go in the lab [we've got some critical work going on, but let's see how the junior staff handles things for a bit], and whether I'm providing any benefit by being there [if I can be more effective working on test tasks in my office, I'll return to it].&amp;#160; Of course, assuming my laptop works there, I may just blog a bit more than usual.&amp;#160; Not having a cell phone, it might be a bit hard for people to contact me if they need me back at the office [although they will know where I am, anyway].&lt;/p&gt;  &lt;p&gt;So, I hope to see a few of my readers there (both those within Microsoft, and especially those from the outside).&amp;#160; Hope all enjoy there time.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Now playing:&amp;#160; The acid rock classic jam &amp;quot;Dark Star&amp;quot; from Live / Dead (of course by the Grateful Dead)&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8968867" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/customer+service/default.aspx">customer service</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/debugging/default.aspx">debugging</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/UMDF/default.aspx">UMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/WdfVerifier/default.aspx">WdfVerifier</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/PFD/default.aspx">PFD</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/DSF/default.aspx">DSF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Driver+Verifier/default.aspx">Driver Verifier</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>Looking Ahead- Conferences!</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2008/09/10/looking-ahead-conferences.aspx</link><pubDate>Thu, 11 Sep 2008 07:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8943119</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/8943119.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=8943119</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=8943119</wfw:comment><description>&lt;P&gt;Since I noticed &lt;A href="http://blogs.msdn.com/888_umdf_4_you/" target=_blank mce_href="http://blogs.msdn.com/888_umdf_4_you/"&gt;Patrick&lt;/A&gt; has &lt;A href="http://blogs.msdn.com/888_umdf_4_you/archive/2008/09/03/8922376.aspx" target=_blank mce_href="http://blogs.msdn.com/888_umdf_4_you/archive/2008/09/03/8922376.aspx"&gt;spilled the beans&lt;/A&gt; [just before the second question], I might as well cover this topic while I wait for my dinner to bake [I eschew microwave ovens these days- just seems better to let it cook the old-fashioned- if early-to-mid-twentieth century is old-fashioned- way].&lt;/P&gt;
&lt;P&gt;I've been through some of my belongings of late and put a few items up on the corkboard in my office- pictures of me from the last several decades, ads from bands I played with in the 70's and 80's, and so on [along with my Master Chief calendar and pictures of my daughter and InuYasha].&amp;nbsp; Two of the recent additions are from my first time around at Microsoft.&amp;nbsp; One of them, which I showed off recently at a WDF team meeting related to this article's topic, is what I believe was my original Microsoft card key- a much different technology from those in use today, which are basically proximity read- I believe this was a magnetic stripe like a credit card [but can't be sure, because that part of the back of it is gone].&amp;nbsp; I think the big surprise for most was that 19 years ago, I had no facial hair and very short hair [almost no gray then, either].&amp;nbsp; Weighed a lot less, too, and still had two working eyes [even if they were near-sighted].&lt;/P&gt;
&lt;P&gt;The other [finally getting to my point] is a speaker's badge for "Microsoft Windows NT Device Driver Developer's Conference".&amp;nbsp; That was from 1992 [I wouldn't know for sure except that it turns out I still had the conference material with the dates on it], and it was the real "first DDC".&amp;nbsp; I was the last speaker on the final day- the track was about Win32 printing [and this was the very first release of Windows NT and the first 32-bit OS Microsoft released], and I was speaking about testing and logoing printer drivers- that was my first time hearing about WHQL, by the way- when I was preparing the talk and they asked me to add some slides related to it.&lt;/P&gt;
&lt;P&gt;Of course, my prized possession is the "Ship-It" award for OS/2 3.1 [which of course didn't exist as a Microsoft product- it was a typo, but I snuck mine out before the manual update processes in use then could correct it], but that just made this paragraph irrelevant and disruptive of the flow.&amp;nbsp; I'm like that...&lt;/P&gt;
&lt;H2&gt;DDC- what a long, strange trip it's been&lt;/H2&gt;
&lt;P&gt;The Driver Developer's Conference is an intensive high-level conference with some NDA-type restrictions [I'm no lawyer- it appears these aren't as strict as the MVP summit, but who am I to judge or care?].&amp;nbsp; It will be held on the Microsoft campus later this month.&amp;nbsp; The meeting I am alluding to was our team reviewing one of the presentations I will be participating in [and I've been slide-smithing ever since].&amp;nbsp; In one session, &lt;A href="http://blogs.msdn.com/iliast/" target=_blank mce_href="http://blogs.msdn.com/iliast/"&gt;Ilias&lt;/A&gt; and I will be discussing the WDF coinstallers.&amp;nbsp; Ilias will discuss the whys and hows, while I will finish up by telling you what you can do when things go wrong.&amp;nbsp; In the other technical session, I, Shyamal and Wei will tell you about how we test the frameworks, including things we do that can translate into your own test problems.&lt;/P&gt;
&lt;P&gt;There will be some Ask The Experts sessions, and I know WDF will be there, but I don't think the final lineup for that's been determined.&amp;nbsp; I can live with it myself, either way...&lt;/P&gt;
&lt;P&gt;As for the rest of the conference, well--- one of the more attractive nuisances of the past several days is that all the presentations go on a single sharepoint site, so I've been previewing a few that interested me.&amp;nbsp; Lots of good stuff- device installation, DSF [my favorite non-WDF tool], new technologies all across the space, etc.&amp;nbsp; I also see the world of printer testing tools is in great hands [probably better ones than mine ever were!].&lt;/P&gt;
&lt;H2&gt;WinHEC- a first time for everything&lt;/H2&gt;
&lt;P&gt;The &lt;A href="http://www.microsoft.com/whdc/winhec/default.mspx" target=_blank mce_href="http://www.microsoft.com/whdc/winhec/default.mspx"&gt;Windows Hardware Engineering Conference&lt;/A&gt;- well, you can use the link to find out what you need to know.&amp;nbsp; I'll be there too, with somewhat stripped-down versions of both talks [at least, I think that's what's happening].&amp;nbsp; It's still several weeks away, and there's DDC to get through first.&amp;nbsp; But it will be in LA.&amp;nbsp; Not certain who all else is going, yet, but I know Ilias is, and I can't believe it can be done without the likes of &lt;A href="http://blogs.msdn.com/doronh/default.aspx" target=_blank mce_href="http://blogs.msdn.com/doronh/default.aspx"&gt;Doron&lt;/A&gt; and &lt;A href="http://blogs.msdn.com/peterwie/default.aspx" target=_blank mce_href="http://blogs.msdn.com/peterwie/default.aspx"&gt;Peter&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;I've been on the mailing list for years, but never gone (I was supposed to go a couple of years back, when it was in Seattle, but had car trouble).&lt;/P&gt;
&lt;P&gt;So perhaps I'll meet a few of you there.&amp;nbsp; I'll be the one with all the hair and the wacky left eye [unless I can't pass the airport security checks, or the other passengers find me scary and demand I leave the plane]. Well, I've lived in LA a few times and driven from here to there and back before...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8943119" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/customer+service/default.aspx">customer service</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/UMDF/default.aspx">UMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/WdfVerifier/default.aspx">WdfVerifier</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/lifestyle/default.aspx">lifestyle</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/PFD/default.aspx">PFD</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/DSF/default.aspx">DSF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/DTM/default.aspx">DTM</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Driver+Verifier/default.aspx">Driver Verifier</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>Passion and Persistence</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2008/05/25/passion-and-persistence.aspx</link><pubDate>Mon, 26 May 2008 01:06:29 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8551564</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/8551564.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=8551564</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=8551564</wfw:comment><description>&lt;p&gt;Well, it's the Memorial Day weekend here in Redmond, and I am in my office working for the second of the three days of the weekend.&amp;#160; Just can't stay away.&lt;/p&gt;  &lt;h3&gt;Why?&lt;/h3&gt;  &lt;p&gt;Because for months now I have been trying to improve the efficiency of our team's automated tests, and also get all the content in them under control.&amp;#160; Over the years (I'm afraid it was the KMDF side of the team, from which I originally came, that was the biggest culprit), bits and pieces of content- test tool binaries, script files, and the like- were placed on a server accessible to both us and the lab- none of it under source control, nor with any idea in most cases where it could be built from or symbols to it procured.&amp;#160; Shefali and I have been whittling away at this problem for months now, and I'm finally close enough to having it work I'm determined to make that one last push to get the job done once and for all (except for the inevitable maintenance, and I've tried to be smart enough about designing my solution that this should also be easy).&lt;/p&gt;  &lt;p&gt;We've got many hours of tests overall between KMDF and UMDF, and I've got to make sure all of them work before I tell the lab that this new stuff is the way it's going to be from here on out [not to mention there is going to be some peer review first, as well].&amp;#160; It takes a lot of time, and of course, none of this is committed or budgeted work.&amp;#160; I'm filling in the idle time [among other things, I'm doing abusive searches of build release servers so I can figure out where some of the tools we've just stuck up there before actually appear in Windows builds- so my being here when almost no one else is proves to be somewhat considerate of me, as well] by writing blog entries, updating code, and working on even further out ideas I want to try out.&lt;/p&gt;  &lt;p&gt;Not that it's all hard work.&amp;#160; I've got the music turned way up (a live version of the Grateful Dead's &amp;quot;Casey Jones&amp;quot; of all things, right at the moment- so I hear my blog's title being raucously sung), and I'm having my usual whimsical fun with comment fields and the like.&amp;#160; For instance, the job itself (which is working rather well, so far) is named &amp;quot;&lt;a href="http://en.wikipedia.org/wiki/Sauron" target="_blank"&gt;Sauron&lt;/a&gt;&amp;quot;, and the Details tab (which is supposed to describe it) begins with this absurd off-the-cuff plagiarized quatrain [my apologies to the Tolkiens]:&lt;/p&gt; &lt;span lang="EN"&gt;   &lt;blockquote&gt;     &lt;p&gt;&lt;em&gt;One job to to run for all-&lt;/em&gt;&lt;/p&gt;      &lt;p&gt;&lt;em&gt;One job to find them;&lt;/em&gt;&lt;/p&gt;      &lt;p&gt;&lt;em&gt;One job to bring them all&lt;/em&gt;&lt;/p&gt;      &lt;p&gt;&lt;em&gt;And at the test box bind them.&lt;/em&gt;&lt;/p&gt;   &lt;/blockquote&gt;    &lt;h3&gt;So why do something this exhaustive,&lt;/h3&gt;    &lt;p&gt;and do it when I'm supposed to be relaxing, and when its unpaid time, and so on?&lt;/p&gt;    &lt;p&gt;Because I care about it (passion) and because I'm not going to just give up because it isn't easy (persistence).&lt;/p&gt;    &lt;p&gt;Besides, this reminds me of my early days at Microsoft (the days of OS/2, Windows 3.1, and what became Windows NT 3.1).&amp;#160; The days where the 70 and 80 hour week were common and I usually didn't mind.&amp;#160; The days when I slept on the floor of my office because I got to be too tired to drive home, even though it was only a block away [yes, I really should walk, but I find the idea daunting at the 1-5 AM hours I am usually coming to work- Redmond is usually safe, but why take the chance?].&amp;#160; The days when I wrote code because I thought I'd need it or because I wanted to try something that struck me as cool at the time.&amp;#160; The days when I may have worked hard, but I was enjoying it so much it didn't feel like work.&lt;/p&gt;  &lt;/span&gt;  &lt;p&gt;They came to an end- the reasons why don't matter.&amp;#160; At one point after that I was interviewed by a journalist / author (he was writing a book about the development of Windows NT, and I guess he thought I'd make for a mildly interesting highlight or side story), and I remember telling him &amp;quot;I'd sit at the keyboard and I couldn't type- I didn't want to type.&amp;#160; I wasn't interested in programming anything- I'd never had that happen before&amp;quot;.&amp;#160; While I didn't put it that way, it was like being dead, but still being capable of breath and movement.&amp;#160; In a very real way, that was behind my resigning at the time I did- partly protective (no way could I do a decent job in that state, and sooner or later that would result in some black marks on the record), and partly reactive (some of the roots were environmental, or so I felt- doesn't matter really, it was all so long ago).&lt;/p&gt;  &lt;p&gt;Ever since then, I've been looking for that feeling- that sense of wonder- that confident feeling that if I could think of it, I'd find a way to use the technology available to me and my own capabilities to make it happen.&amp;#160; I'd get occasional flashes of it, but never the full-blown, out and out desire to do nothing but work on something for endless hours, and actually achieving that goal.&amp;#160; The closest I came was gaming, but to me that was always &amp;quot;play&amp;quot;.&amp;#160; &amp;quot;Work&amp;quot; was a better use of time, but it just wasn't engaging me.&lt;/p&gt;  &lt;p&gt;When I decided to rejoin Microsoft, I was hoping I might finally find that desire and enthusiasm capable of being rekindled.&amp;#160; Working as a contractor, I'd had urges in that direction [but you must charge for those hours- so the kind of thing I am doing now would be an abuse of the business relationship to either my employer or to their customer].&amp;#160; But it just seemed to sputter- there were brief flashes, but nothing consistent.&lt;/p&gt;  &lt;p&gt;But now it looks like it is happening at last.&amp;#160; Perhaps I do get another bite at the apple- I already feel younger for some reason.&amp;#160; Perhaps I can take on big challenges and bring them to fruition, even though I am highly prone to &amp;quot;the lone wolf&amp;quot; style of addressing things.&amp;#160; If it's happened- I know who to thank- Shefali, Abdullah, Scott, Darren, and everyone from them right on up to Messrs. Ballmer and Gates.&amp;#160; For providing an environment (and yes, there is much more to that environment than just the chain I've listed) where I can be myself, and still accomplish things- maybe not great things, but at least things worthy of accomplishing.&amp;#160; For listening to sometimes petty concerns and putting up with my foibles, inconsistencies and mistakes (especially Shefali in this case).&lt;/p&gt;  &lt;p&gt;I hadn't thought about that before- perhaps the problem previously is I felt I had to be something other than what I am to succeed.&amp;#160; Now I finally feel otherwise, and it is very liberating.&lt;/p&gt;  &lt;p&gt;Well, perhaps I am deluded.&amp;#160; While I see this as a good thing to do, and an improvement over the existing conditions, perhaps it will be judged otherwise.&amp;#160; I am not using all the latest and greatest technologies to solve the problem, so perhaps it will lack appeal because of that.&amp;#160; Time will tell, in either event.&amp;#160; I'll deal with that as it comes.&lt;/p&gt;  &lt;p&gt;In the meantime, I am going to do my level best to make this thing work, and I don't mind the time it is taking.&lt;/p&gt;  &lt;p&gt;Because believe it or not, I am actually having quite a lot of fun...&lt;/p&gt;  &lt;p&gt;[Segue into Grateful Dead [Wake of the Flood] Mississippi Half Step Uptown Toodeloo.... &amp;quot;along the Rio Grande, oh-...&amp;quot;]&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8551564" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/lifestyle/default.aspx">lifestyle</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>The Forever Wait</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2008/05/23/the-forever-wait.aspx</link><pubDate>Sat, 24 May 2008 03:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8542879</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/8542879.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=8542879</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=8542879</wfw:comment><description>&lt;P&gt;Many thanks to &lt;A href="http://blogs.msdn.com/888_umdf_4_you/" target=_blank mce_href="http://blogs.msdn.com/888_umdf_4_you/"&gt;Patrick&lt;/A&gt; for &lt;A href="http://blogs.msdn.com/888_umdf_4_you/archive/2008/05/16/8514041.aspx" target=_blank mce_href="http://blogs.msdn.com/888_umdf_4_you/archive/2008/05/16/8514041.aspx"&gt;this reminder about another practice an SDET should avoid&lt;/A&gt; (actually, most SDE's should, as well- but they have their own masters and I'll leave that job to them).&amp;nbsp; Not that it's easy to pick the "right" amount of time.&amp;nbsp; In &lt;A href="http://blogs.msdn.com/bobkjelgaard/archive/2008/01/31/papa-s-wall-of-dumb.aspx" mce_href="http://blogs.msdn.com/bobkjelgaard/archive/2008/01/31/papa-s-wall-of-dumb.aspx"&gt;this much older post of mine&lt;/A&gt;, I mention a test case that took an incredible amount of time when we turned &lt;A href="http://msdn.microsoft.com/en-us/library/ms792872.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms792872.aspx"&gt;Driver Verifier&lt;/A&gt; on.&amp;nbsp; Well, that test case has been a rascal in many ways (it even found some unusual and rare bugs in Driver Verifier itself).&amp;nbsp; I was initially using the same wait time on all of my tests, but I had to stop- I set the wait on this one out to many minutes, but special cased it so the others wait a few seconds- if I didn't, a hardcore hang would potentially set runtime out to hours, not good for automation.&lt;/P&gt;
&lt;P&gt;Well, I ran it today [I'm spending time I shouldn't be trying to streamline our automation- in this case making the installation aspects of it smart enough to find their own content, instead of having people type an ever changing set of locations into WTT as parameters every time we have to make a run, which is, after all, every day or more- but at the same time I removed the copying of things we no longer use, or are getting from insecure places when there are secure places, etc- to make sure I didn't mess it up, I'm running all of our tests to make sure I didn't prune out the collection of something we need], and the test case AFTER it failed because it timed out.&amp;nbsp; I already know this is because the cleanup from all those allocations is hogging resources (I've even hit the "too long at dispatch level" break on machines with way too much memory), preventing me from getting time to get that next instance spawned off my test bus (serves me right for trying to squeeze some test performance by spinning up the next test while the first was spinning down).&lt;/P&gt;
&lt;P&gt;The forever wait would make life easier in this case- but it wouldn't be near as much fun.&lt;/P&gt;
&lt;P&gt;Now if any of you are thinking- "wait- why aren't you even talking about breaking and forcing people to look at the hang when it times out like this?"- well, &lt;A href="http://blogs.msdn.com/bobkjelgaard/archive/2007/11/07/someone-must-want-this-job.aspx" target=_blank mce_href="http://blogs.msdn.com/bobkjelgaard/archive/2007/11/07/someone-must-want-this-job.aspx"&gt;we still have an opening&lt;/A&gt; or two for more SDETs on our team (and our close buddies in Storage have plenty of good opportunities for you as well), and you're obviously beginning to think like one!&amp;nbsp; The best answer I ahve at the moment is that I serve multiple masters, one of which is regular automated checking, for which recording a failure and moving on is OK (as long as it isn't new, anyway).&amp;nbsp; I've been thinking about ways over the last few days to accommodate this [break conditionally, but not all of the time in way that's smart enough to suit our needs], but haven't hit upon that most desirable solution yet.&amp;nbsp; Not that I can't think of ways- but I need ways I can achieve with what's at hand- all the aggressive work we've done on hardening the test code so it doesn't break more often than the product it's testing have been working, so I've at least got time to move from "Stop all the bugchecks" to "what about attempt rates and failure rates" phase.&amp;nbsp; Actually, it's not just that- it's that Patrick and Wei have been stepping up and helping with some of that fixing and the never-ending job of triaging failures in our test labs.&lt;/P&gt;
&lt;P&gt;But, thanks to Patrick, that "things to do next time you crack that DDI test code" list now has another item:&lt;/P&gt;
&lt;H3&gt;Things to do the next time you crack that moldy old test code&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;Set USER_C_FLAGS to /TP&lt;/LI&gt;
&lt;LI&gt;Set the warning level to 4 (convert warnings to error is already on)&lt;/LI&gt;
&lt;LI&gt;PFD green before you're done, period.&lt;/LI&gt;
&lt;LI&gt;Look for suspicious coding patterns where failures are being masked or ignored- at the very least in the places the above changes have forced you to look.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;EM&gt;Examine KeWait... calls for NULL timeout and WaitFor... calls for INFINITE.&amp;nbsp; Take them out with the rest of the trash!&lt;/EM&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;[Edit 5/24&lt;/STRONG&gt;] Sorry , I just realized I revealed someone's email address wtihout permission [it made a fine pun, but still not the right thing to do]- stats say not likely anyone realized it yet, but mea culpa, anyway...&lt;/P&gt;
&lt;H3&gt;Just had to add this one&lt;/H3&gt;
&lt;P&gt;The title of this post keeps reminding me of &lt;A href="http://en.wikipedia.org/wiki/Forever_War" target=_blank mce_href="http://en.wikipedia.org/wiki/Forever_War"&gt;The Forever War&lt;/A&gt;- a science fiction novel that earned both Nebula and Hugo awards.&amp;nbsp; The awards probably speak for themselves- I'm quite pleased to have a copy of it in my personal library (I guess I'm pleased to have a personal library, but I leave that sort of thing to &lt;A href="http://bobkjelgaard.spaces.live.com/blog/" target=_blank mce_href="http://bobkjelgaard.spaces.live.com/blog/"&gt;my personal blog&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;As for the music- happens to be another bit of mellow fineness from &lt;A href="http://www.amazon.com/Best-1000-Field-View/dp/B000XT63QI/ref=pd_bbs_sr_2/104-8856427-0414362?ie=UTF8&amp;amp;s=music&amp;amp;qid=1211588830&amp;amp;sr=8-2" target=_blank mce_href="http://www.amazon.com/Best-1000-Field-View/dp/B000XT63QI/ref=pd_bbs_sr_2/104-8856427-0414362?ie=UTF8&amp;amp;s=music&amp;amp;qid=1211588830&amp;amp;sr=8-2"&gt;Field of View&lt;/A&gt; (sorry, I didn't come up with a more useful link, but I'm short on time, as always) at the moment- I may have paid what seemed an outrageous fee to import this CD set (not the one I linked to, that would take me a while to find, I'm afraid) from Japan, but it was soooooo worth it!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8542879" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/PFD/default.aspx">PFD</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Driver+Verifier/default.aspx">Driver Verifier</category></item><item><title>Why SDETS should be the most fastidious and paranoid coders in existence</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2008/05/09/why-sdets-should-be-the-most-fastidious-and-paranoid-coders-in-existence.aspx</link><pubDate>Sat, 10 May 2008 03:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8483055</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/8483055.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=8483055</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=8483055</wfw:comment><description>&lt;P&gt;Well, to follow up some more on my adventures in test code maintenance, I bring you a case study.&lt;/P&gt;
&lt;P&gt;As I whittled away at the 100+ PFD warnings &lt;A href="http://blogs.msdn.com/bobkjelgaard/archive/2008/05/07/reaping-the-benefits-of-static-analysis-tools.aspx" target=_blank mce_href="http://blogs.msdn.com/bobkjelgaard/archive/2008/05/07/reaping-the-benefits-of-static-analysis-tools.aspx"&gt;I mentioned in my previous article&lt;/A&gt;,&amp;nbsp; I did my paranoid best to look for dubious code above and beyond what PFD was telling me about when I noticed this in one of our oldest test drivers:&lt;/P&gt;&lt;PRE class=csharpcode&gt;NTSTATUS  _stdcall 
CTestDriver::SetupObjectHandleParameter(
    IN ULONG eHandle, 
    IN OBJECT_TYPE ObjectType,
    IN OUT PVOID * Handle
    )
{
    NTSTATUS status = STATUS_SUCCESS;

    &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
    &lt;SPAN class=rem&gt;//setup Queue Handle parameter&lt;/SPAN&gt;
    &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
    &lt;SPAN class=kwrd&gt;switch&lt;/SPAN&gt;(eHandle){
        
        &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; HANDLE_INVALID_NULL:
            *Handle = NULL;
            &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;

        &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; HANDLE_INVALID_OBJECT_DELETED:
            &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;//we will treat this as HANDLE_INVALID_NULL since we can not delete the default queue&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
            *Handle = NULL;
            &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;

        &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; HANDLE_INVALID_WRONG_OBJECT_TYPE:
            
            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt;(ObjectType != OBJECT_TYPE_DRIVER){ 
                
                *Handle = (PVOID)WdfGetDriver();
                
            }&lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;{
            
                *Handle = (PVOID)&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;-&amp;gt;m_pFdo;
            }
            &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;

        &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt;  HANDLE_VALID:
            
            &lt;SPAN class=kwrd&gt;switch&lt;/SPAN&gt;(ObjectType)
            {
                &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; OBJECT_TYPE_DEVICE:
                    *Handle = (PVOID)&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;-&amp;gt;m_pFdo;
                    &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;
                    
                &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; OBJECT_TYPE_QUEUE:
                    *Handle = WdfDeviceGetDefaultQueue(&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;-&amp;gt;m_pFdo);
                    &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;
                    
                &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; OBJECT_TYPE_REQUEST:
                    status = WdfRequestCreate(NULL, NULL, (WDFREQUEST *)Handle);
                    &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;
                    
                &lt;SPAN class=kwrd&gt;default&lt;/SPAN&gt;:
                    *Handle = NULL;
                    
            }
            &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;
            
        &lt;SPAN class=kwrd&gt;default&lt;/SPAN&gt;:
            DbgBreakPoint();
&lt;SPAN class=preproc&gt;#pragma&lt;/SPAN&gt; prefast(suppress:__WARNING_UNREACHABLE_CODE, &lt;SPAN class=str&gt;"Always runs under debugger, so not unreachable, merely deliberately annoying"&lt;/SPAN&gt;)
            *Handle = NULL;
            status = STATUS_INVALID_PARAMETER;
    }

&lt;/PRE&gt;
&lt;P&gt;The breakpoint and suppression pragma are my later addition [and I removed some invalid cases prior to this- in fact, it was the act of removing them that led me to even look at this code]. Why did I add them? Because this silently changes an invalid and unexpectedly out-of-range value without any notice or any indication that something unexpected and unwanted has happened.&amp;nbsp; I wanted to make sure that if this EVER happened, someone was forced to take a look (and yes, this is why people use ASSERT of course).&lt;/P&gt;
&lt;P&gt;Well, I finally got all my warnings cleaned up, and I built the dozens of drivers and assembled everything I needed so I could make a "dry run" of all the affected code under lab conditions.&amp;nbsp; I hit that breakpoint about a half hour into the run.&amp;nbsp; So I took a look, of course- that IS why I did this, after all [to force someone to look- I just also turned out to BE that someone].&lt;/P&gt;
&lt;P&gt;As one would expect from even middlin'-to-fair practice, those constants are in a header file, the appropriate snippet being this:&lt;/P&gt;&lt;PRE class=csharpcode&gt;typedef &lt;SPAN class=kwrd&gt;enum&lt;/SPAN&gt; {
    HANDLE_INVALID_NULL,
    HANDLE_INVALID_OBJECT_DELETED,
    TOTALLY_INVALID_AND_DO_NOT_USE_UNTIL_ALL_ARE_REMOVED_AND_THIS_CAN_BE_RECYCLED,
    HANDLE_VALID,
    HANDLE_INVALID_NOT_SET,
    HANDLE_VALID_NULL,
    HANDLE_INVALID_NOT_OPEN,
    HANDLE_INVALID_WRONG_OBJECT_TYPE,
    HANDLE_CALL_DDI_MULTIPLE_TIMES = 23
    } HANDLE_STATES;&lt;/PRE&gt;&lt;PRE class=csharpcode&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;P&gt;The long name was my addition- it was for the invalid case I was trying to prune from all those drivers [it passed -1 as&amp;nbsp; an "invalid handle value"- fine practice in user mode, but in KMDF they [wisely, IMO] decided NULL was enough to guard against].&amp;nbsp; The oddball value at the end is there because of one of the items that factors into my tale [but I won't mention it again].&lt;/P&gt;
&lt;P&gt;Soon after these early test drivers were developed, we off-shored the work of developing more of them to test the burgeoning KMDF DDI.&amp;nbsp; They basically made a copy of what we had, and then began developing more, extending and refining our techniques.&amp;nbsp; Now I'm about to describe an error of theirs, but if the original developers had been more paranoid, these folks could have known about this long before I found put about it!&amp;nbsp; People make mistakes, especially during those early stages of development, period.&amp;nbsp; They continue to make them in maintenance and addition of new features.&amp;nbsp; This isn't a "look at this fool" story- it's a "this is good and intelligent people just being human" story- please don't misunderstand me!&lt;/P&gt;
&lt;P&gt;To go back now to the present, a quick check in the debugger showed that "9" was the value for eHandle.&amp;nbsp; You'll notice it doesn't match any of the enumerated values.&amp;nbsp; So where did it come from?&amp;nbsp; Well these tests are driven from scripts, and the original developers being fastidious used the same names and definitions in their script-based engine. [I told you these people were good!]&amp;nbsp; So I found the test case used because it was readily available from the driver at the point this failed (drum roll, please):&lt;/P&gt;&lt;PRE class=csharpcode&gt;    var    eQueue    = HANDLE_INVALID_WRONG_OBJECT_TYPE;
    var    bStopComplete = POINTER_VALID;
    var    eContext   = POINTER_VALID_NULL;&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;Now HANDLE_INVALID_WRONG_OBJECT_TYPE is defined, but its value is 7, not 9- so why the mismatch?&amp;nbsp; Well, like I said, all the original files were forked off, and the offshore team maintained their copies.&amp;nbsp; At first I diff'd the original header to see if I'd done something totally bad, like deleting values from the enumeration without maintaining the value of those that were left- after all a stream of 14+ hour days leaves me quite capable of such a move!&amp;nbsp; But it wasn't me, &lt;U&gt;this time&lt;/U&gt;- so I went to their version of that same header, and found:&lt;/P&gt;&lt;PRE class=csharpcode&gt;typedef &lt;SPAN class=kwrd&gt;enum&lt;/SPAN&gt; 
{
    HANDLE_INVALID_NULL                             = 0,
    HANDLE_INVALID_OBJECT_DELETED                   = 1,
    INVALID_VALUE_NOT_TO_BE_USED_1                  = 2,
    HANDLE_VALID                                    = 3,
    HANDLE_INVALID_NOT_SET                          = 4,
    HANDLE_VALID_NULL                               = 5,
    HANDLE_INVALID_NOT_OPEN                         = 6,
    HANDLE_INVALID_REACQUIRE                        = 7,
    HANDLE_INVALID_NOTACQUIRED                      = 8,
    HANDLE_INVALID_WRONG_OBJECT_TYPE                = 9,
&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;P&gt;Oops (and yes my names for the value I ripped out were inconsistent, but then maybe some consistent inconsistency is useful in doing this sort of maintenance activity, and besides, none of this is finished yet]!&lt;/P&gt;
&lt;P&gt;I then went to the trouble of trolling through our configuration management system (mostly out of curiosity, as this bug isn't a killer in and of itself] to see when this breaking code change was made, and found it happened to have been made about 10 days after I walked out of New Employee Orientation and into my second SDET career at Microsoft [I probably couldn't even begin to use WTT {DTM to you} at that time].&amp;nbsp; This defect silently caused us to stop testing the effects of passing the wrong kind of object to the DDI tested in this driver [passing NULL instead, which as you can probably divine was already being done].&amp;nbsp; The test failed, but it was supposed to, so no visible change in outward results- just a silent loss of coverage of some paths in the product code for the last 3 years.&lt;/P&gt;
&lt;H2&gt;Umm, so what?&lt;/H2&gt;
&lt;P&gt;Granted- this is hardly the most important problem found on the planet this week (probably even in the last 10 seconds).&amp;nbsp; But I think there's a point here for any serious SDET.&amp;nbsp; Be paranoid!&amp;nbsp; Check everything!&amp;nbsp; Trust nothing!&amp;nbsp; Before you punt that oddball case, at least consider using an ASSERT or some other mechanism to focus attention on questionable results or behaviors.&amp;nbsp; If the code looks ratty as a result, and you'd never ship it, so what?&amp;nbsp; Your purpose isn't to make pretty code- leave that to the SDEs- your task is to find bugs [and preferably in the product- but if you find your own with these practices, the odds of your doing the same for your product are that much improved].&amp;nbsp; I don't personally care much where the braces go in your code- but I sure care a lot about what you do between them!&lt;/P&gt;
&lt;P&gt;Yes, someone inclined to point out errors and less-than-optimal practices can point out many more [like, oh, say- keeping two versions of the same header file about?]&amp;nbsp; But it takes time to sort out improving what you've got, and there's the continual need to add new stuff [which is what I was doing when I began this little detour this week, and I'd better get back to it, and soon].&amp;nbsp; I'll add removing that superfluous header to the ever growing list of "things that ought to get done when there's finally time to do it"...&lt;/P&gt;
&lt;P&gt;Enough of the soapbox rant for now.&amp;nbsp; I'll go put on my hat and find some of the other curmudgeons [someday I'll have to take a photo of it perkily perched on top of the replica Spartan helmet from the Halo 3 Legendary edition [someone once told me it gave them visions of John-117 as Indiana Jones, bullwhip in hand] in my office]...&lt;/P&gt;
&lt;H2&gt;Odds and Ends&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;Well, PFD eventually found well over 30 IRQL misusages by the times I was done- many of the pattern I showed in that last article, others more subtle- and some of those were more of a "risk of future maintenance trouble" issue- exactly the sort of maintenance error behind this bug.&amp;nbsp; PFD- it isn't just for developers- your test code ought to be as good as theirs and preferably better [so when something breaks you've got all the information you need to say what's going on].&amp;nbsp; It also focused attention on dozens more problem areas in this code base.&amp;nbsp; Being PFD clean doesn't guarantee your driver is rock-solid bulletproof, but it sure makes a nice foundation!&lt;/LI&gt;
&lt;LI&gt;Wei reminded me that you can combine the values when suppressing by separating them with white space.&amp;nbsp; Figures- I'd tried commas and got into too much of a hurry to look up the basics of those pragmas.&amp;nbsp; Also that the suppression is suppose to apply to a single source line (but I think stacking them as I did also works- can't say for sure).&lt;/LI&gt;
&lt;LI&gt;I've begun using some Analytical / tracking software on my blog to understand my readership better [nothing personally identifiable].&amp;nbsp; I see that I get a reasonable number of non-English speakers, so I'll see if I can rein in my vocabulary and use of idioms in the future.&lt;/LI&gt;
&lt;LI&gt;The web site I keep some of my blog content on (like my photograph) is undergoing maintenance for a couple of days.&amp;nbsp; The text files for fixing KMDF installation failres are there too.&amp;nbsp; They'll be back by Monday, May 12, 2008.&lt;/LI&gt;
&lt;LI&gt;No song lists- too busy to try to cpture thm this time [lucky you!].&lt;/LI&gt;
&lt;LI&gt;A good weekend to all!&lt;/LI&gt;&lt;/UL&gt;
&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;

&lt;STYLE type=text/css&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8483055" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/PFD/default.aspx">PFD</category></item><item><title>Reaping the Benefits of Static Analysis Tools</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2008/05/07/reaping-the-benefits-of-static-analysis-tools.aspx</link><pubDate>Wed, 07 May 2008 19:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8466072</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/8466072.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=8466072</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=8466072</wfw:comment><description>&lt;P&gt;Our team has a huge amount of legacy test driver code, much of it rather old, and originally created by somewhat less experienced developers.&amp;nbsp; I continually find myself going back and performing maintenance on that code, and as I've noted previously- &lt;A href="http://blogs.msdn.com/bobkjelgaard/archive/2007/09/28/serendipitous-prefast-or-a-day-in-the-life.aspx" target=_blank mce_href="http://blogs.msdn.com/bobkjelgaard/archive/2007/09/28/serendipitous-prefast-or-a-day-in-the-life.aspx"&gt;Static Analysis Tools are a great help in identifying problems in this code&lt;/A&gt;.&amp;nbsp; I'll put this "down time" (among other things, I've got PFD analyzing 40+ files that are rather large as I write this) to good use by describing both some further benefits and showing how easy it is to annotate your own code so you can recognize this sort of benefit.&lt;/P&gt;
&lt;H2&gt;Irql Tracking Finds Yet Another Flaw&lt;/H2&gt;
&lt;P&gt;One of the benefits PFD adds above regular PreFast is tracking IRQL changes in your code.&amp;nbsp; Of course, there are additional annotations used to support this, and I found them to be most useful in a very real-world way.&lt;/P&gt;
&lt;P&gt;In our tests of the KMDF DDI, we try to make a lot of invalid calls to assess how well the framework verifier works.&amp;nbsp; One of the things that we do is make calls at improper IRQL levels- since efficiency suggests you usually have one place that tests a particular call, this change has to be programmable.&amp;nbsp; Not the sort of thing you expect a static analysis tool to be able to do for you, eh?&amp;nbsp; Well one of our SDETs made an initial pass at this issue [after I told the team we were going to make all of our test drivers PFD clean over the next few months, instead of having me piecemeal it as I fixed bugs as I had done previously], and encountered some difficulties&lt;/P&gt;
&lt;P&gt;The original declarations looked like this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=rem&gt;/*******************************************************************************&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; KmdfTestRaiseAndPrintIRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Synopsis - Raises IRQL to DISPATCH_LEVEL and prints IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Parameters -&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   eIRQL    -   Enumerator for IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   OldIRQL  -   IRQL prior to raising to DISPATCH_LEVEL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;******************************************************************************/&lt;/SPAN&gt;
VOID 
KmdfTestRaiseAndPrintIRQL(
    __in    ULONG   eIRQL,
    __out   KIRQL   *OldIRQL
    );&lt;/PRE&gt;&lt;PRE class=csharpcode&gt;&lt;STRONG&gt;&lt;EM&gt;Initial code- nice enough, and PreFast annotated, but it changes IRQL and doesn't say a thing about that other than in comments&lt;/EM&gt;&lt;/STRONG&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;STYLE type=text/css&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;P&gt;There was no declaration for a function to lower IRQL- typically eIRQL was compared to a constant and KeLowerIrql was called when needed.&amp;nbsp; Well, PFD quickly noticed this function elevates IRQL on some paths, so the attempt was made to annotate it, and a paired restore function was also defined- thus:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=rem&gt;/*******************************************************************************&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; KmdfTestRaiseAndPrintIRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Synopsis - Raises IRQL to DISPATCH_LEVEL and prints IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Parameters -&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   eIRQL    -   Enumerator for IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   OldIRQL  -   IRQL prior to raising to DISPATCH_LEVEL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;******************************************************************************/&lt;/SPAN&gt;
__drv_raisesIRQL(DISPATCH_LEVEL)
VOID 
KmdfTestRaiseAndPrintIRQL(
    __in    ULONG   eIRQL,
    __out   __drv_out_deref(__drv_savesIRQL) PKIRQL   OldIRQL
    );

&lt;SPAN class=rem&gt;/*******************************************************************************&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; KmdfTestRestoreIRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Synopsis - Restore IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Parameters -&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   eIRQL    -   Enumerator for IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   OldIRQL  -   IRQL returned from KmdfTestRaiseAndPrintIRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;******************************************************************************/&lt;/SPAN&gt;
VOID
KmdfTestRestoreIRQL(
    __in    ULONG   eIRQL,
    __in __drv_restoresIRQL __drv_nonConstant KIRQL OldIRQL
    );&lt;/PRE&gt;&lt;PRE class=csharpcode&gt;&lt;STRONG&gt;&lt;EM&gt;First attempt- this says IRQL is changed and a restore function is added, but is it enough?&lt;/EM&gt;&lt;/STRONG&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;However, this didn't work out so well, when the implementation of these routines was analyzed by PFD, and since I had mandated cleanliness, warnings from PFD were suppressed, thus:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;__drv_raisesIRQL(DISPATCH_LEVEL)
VOID __stdcall
&lt;SPAN class=preproc&gt;#pragma&lt;/SPAN&gt; prefast(suppress:__WARNING_IRQL_NOT_SET, &lt;SPAN class=str&gt;"Intentionally save irql at specified condition"&lt;/SPAN&gt;);
KmdfTestRaiseAndPrintIRQL(
    __in    ULONG   eIRQL,
    __out   __drv_out_deref(__drv_savesIRQL) PKIRQL   OldIRQL
    )

&lt;SPAN class=rem&gt;// and then this&lt;/SPAN&gt;

VOID __stdcall
&lt;SPAN class=preproc&gt;#pragma&lt;/SPAN&gt; prefast(suppress:__WARNING_IRQL_NOT_USED, &lt;SPAN class=str&gt;"Intentionally restore irql at specified condition"&lt;/SPAN&gt;);
KmdfTestRestoreIRQL(
    __in    ULONG   eIRQL,
    __in __drv_restoresIRQL __drv_nonConstant KIRQL OldIRQL
    )&lt;/PRE&gt;&lt;PRE class=csharpcode&gt;&lt;STRONG&gt;&lt;EM&gt;These annotations must not be enough, because PFD is smart enough to find paths that put the lie to the annotated effects of these functions&lt;/EM&gt;&lt;/STRONG&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;STYLE type=text/css&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;P&gt;Why the need to suppress?&amp;nbsp; Because PFD correctly analyzed that there were paths through the code that did not do what the annotations say these functions do (raise IRQL to dispatch and restore it, respectively). These actions were conditional, and the annotations didn't reflect this.&lt;/P&gt;
&lt;H2&gt;Conditional Annotations: One Powerful Tool Makes One Effective Solution&lt;/H2&gt;
&lt;P&gt;I encountered the problem in different form.&amp;nbsp; I found myself working with the earliest of our drivers, written before these library routines were used.&amp;nbsp; They defined similar functions inline,&amp;nbsp;&amp;nbsp; At first, I made these same annotations there [but didn't suppress], as that let me borrow from the work already done.&amp;nbsp; But since I didn't suppress, I got the identical errors.&lt;/P&gt;
&lt;P&gt;When I realized why I was getting errors, I recalled reading about conditional annotations, so I read up on them and really, for a case like this they just weren't that hard to figure out.&amp;nbsp; I fixed the code I was working with, and then when I was sure this was the right thing to do, I made the same fix to the library code and header file I snipped above.&amp;nbsp; The end result looked like this (and I removed the suppression pragma from the library code, of course).&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=rem&gt;/*******************************************************************************&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; KmdfTestRaiseAndPrintIRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Synopsis - Raises IRQL to DISPATCH_LEVEL and prints IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Parameters -&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   eIRQL    -   Enumerator for IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   OldIRQL  -   IRQL prior to raising to DISPATCH_LEVEL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;******************************************************************************/&lt;/SPAN&gt;
__drv_when( eIRQL == EXECUTION_LEVEL_DISPATCH, __drv_raisesIRQL(DISPATCH_LEVEL))
VOID __stdcall
KmdfTestRaiseAndPrintIRQL(
    __in    ULONG   eIRQL,
    __out __drv_when( eIRQL == EXECUTION_LEVEL_DISPATCH, __drv_out_deref(__drv_savesIRQL))
            PKIRQL  OldIRQL
    );

&lt;SPAN class=rem&gt;/*******************************************************************************&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; KmdfTestRestoreIRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Synopsis - Restore IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt; Parameters -&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   eIRQL    -   Enumerator for IRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;   OldIRQL  -   IRQL returned from KmdfTestRaiseAndPrintIRQL&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;******************************************************************************/&lt;/SPAN&gt;
VOID __stdcall
KmdfTestRestoreIRQL(
    __in    ULONG   eIRQL,
    __in __drv_when( eIRQL == EXECUTION_LEVEL_DISPATCH, __drv_restoresIRQL)
            KIRQL   OldIRQL
    );&lt;/PRE&gt;&lt;PRE class=csharpcode&gt;&lt;STRONG&gt;&lt;EM&gt;Adding conditional annotations lets PFD correctly analyze the functions and code that uses them, removing the need to suppress perfectly valid warnings.&lt;/EM&gt;&lt;/STRONG&gt;&lt;/PRE&gt;&lt;PRE class=csharpcode&gt;&lt;STRONG&gt;&lt;EM&gt;It also more clearly states how the function works in a fairly readable way.&lt;/EM&gt;&lt;/STRONG&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;STYLE type=text/css&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;P&gt;The annotations are now more precise.&amp;nbsp; EXECUTION_LEVEL_DISPATCH is defined in a header always known when this is included, so PFD can properly analyze all usages.&amp;nbsp; It now knows that we change and restore when the eIRQL parameter is set to this value, and leave it alone otherwise.&lt;/P&gt;
&lt;H2&gt;Reaping The Benefits, Part 1- Finding a Real Bug at Build Time&lt;/H2&gt;
&lt;P&gt;Well, it didn't take long for it to turn up a real flaw [in one of those 40 files I alluded to earlier].&amp;nbsp; This is pseudo-code illustrating what it found.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;KmdfTestRaiseAndPrintIRQL(
    eIRQL, 
    &amp;amp;OriginalIRQL
    );

&lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (condition) {
    MakeTheCall();
    KmdfTestRestoreIRQL(
        eIRQL,
        OriginalIRQL
        );
}
&lt;STRONG&gt;&lt;EM&gt;Pseudocode for a bug the above annotations exposed- found by PFD in that ancient test code.&lt;/EM&gt;&lt;/STRONG&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;STYLE type=text/css&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;P&gt;Out of the 10's of thousands of source lines I'm working with, I don't think I could have noticed that- but PFD zeroed right in on it.&amp;nbsp; If the condition isn't met, we can raise IRQL without lowering it.&amp;nbsp; It's rare for the condition to not occur, which is one reason why nobody had found this before [another is that intermittent failures in these tests used to be routinely overlooked- but I don't work that way- I only give up when I absolutely have to].&amp;nbsp; Easily fixed, of course, just move the raise inside the conditional block as well.&lt;/P&gt;
&lt;H2&gt;Reaping the Benefits, Part 2- Clearer Documentation of Test Practices&lt;/H2&gt;
&lt;P&gt;By requiring the code to be clean (no errors or warnings) we have to use suppression in those places where we deliberately break the rules.&amp;nbsp; Now I could call this an annoyance, but actually I think it makes it a lot easier to understand better how we are testing the DDI in these cases.&amp;nbsp; So I'll leave this final sample:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INFO, 
            &lt;SPAN class=str&gt;"\nCalling DDI WdfDmaEnablerCreate\n\n"&lt;/SPAN&gt;);

&lt;SPAN class=preproc&gt;#pragma&lt;/SPAN&gt; prefast(suppress:__WARNING_INVALID_PARAM_VALUE_1, &lt;SPAN class=str&gt;"Intentionally passing 0 to test the DDI"&lt;/SPAN&gt;)
&lt;SPAN class=preproc&gt;#pragma&lt;/SPAN&gt; prefast(suppress:__WARNING_IRQ_TOO_HIGH, &lt;SPAN class=str&gt;"Deliberately done to test framework verifier"&lt;/SPAN&gt;)
        status = WdfDmaEnablerCreate(
                    device,          &lt;SPAN class=rem&gt;// Handle to device object&lt;/SPAN&gt;
                    pDmaConfig,      &lt;SPAN class=rem&gt;// Pointer to WDF_DMA_ENABLER_CONFIG structure&lt;/SPAN&gt;
                    pAttributes,     &lt;SPAN class=rem&gt;// Pointer to WDF_OBJECT_ATTRIBUTES&lt;/SPAN&gt;
                    pDmaEnabler      &lt;SPAN class=rem&gt;// Pointer to WDFDMAENABLER to create&lt;/SPAN&gt;
                    );&lt;/PRE&gt;&lt;PRE class=csharpcode&gt;&lt;STRONG&gt;&lt;EM&gt;For a further benefit, places where rules are deliberately broken for test purposes are now clearly marked by the suppression pragmas&lt;/EM&gt;&lt;/STRONG&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;STYLE type=text/css&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;P&gt;Now, we actually pass NULL values in some other parameters- one reason this isn't reflected is there are common routines that establish some of these pointer values, and they are not annotated to reflect that the values can be NULL on output.&amp;nbsp; Someday maybe I'll get to that task [or just try to make sure we do it upfront on new test code].&lt;/P&gt;
&lt;P&gt;Well, that run finished and I've got 128 bits of further errata to investigate [I sort by warning number, and I'd just finished the warnings for Irql too high when I saved it all off, recompiled to make sure I hadn't broken anything, and went on- I started with over 180 failures, so I'm making headway].&amp;nbsp; In case you were unaware of it, you can get the mnemonic constants for the errors [typically reported by number] from the file &lt;EM&gt;suppress.h&lt;/EM&gt; in the &lt;EM&gt;sdk\inc&lt;/EM&gt; directory.&lt;/P&gt;
&lt;P&gt;So, I'm off to do more cleanup [I started with one test driver, and this just sort of ballooned on me when I decided to rip out some less desirable things I've been meaning to rip out], and I'll let you get back to your regularly scheduled workday!&lt;/P&gt;
&lt;H1&gt;Tunes&lt;/H1&gt;
&lt;P&gt;&lt;STRONG&gt;Grateful Dead&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Aoxomoxoa] China Cat Sunflower&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Workingman's Dead] High Time, Black Peter&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Europe 72] Sugar Magnolia&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Wake Of The Flood] Eyes of the World&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Shakedown Street] If I had the World to Give [Bonus Track]&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Go To Heaven] Alabama Getaway&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Dead Set] Brokedown Palace, Rhythm Devils&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Reckoning] It Must Have Been The Roses&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Various Artists&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Record of Lodoss War] Instrumental [name untranslated]&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[InuYasha TV OST] Kagome and InuYasha 1&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Tsuneo Imahori&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Trigun the First Donuts] Knives&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Yoko Kanno /Seatbelts&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Cowboy Bebop] Car 24, The Egg and I&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Cowboy Bebop Blue] Farewell Blues&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Cowboy Bebop Knockin On Heaven's Door] Diggin'&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Yuki Kajiura / See-Saw&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[.hack//liminality] [name untranslated- also on "Dream Field"], [name untranslated- also on "Dream Field"], [name untranslated]&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[.hack//sign OST1] silent life, kiss&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[Fiction] Fiction&lt;/EM&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8466072" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/PFD/default.aspx">PFD</category></item><item><title>The light at the end of the WDF 1.7 tunnel</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2008/04/17/the-light-at-the-end-of-the-wdf-1-7-tunnel.aspx</link><pubDate>Thu, 17 Apr 2008 18:04:55 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8403315</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/8403315.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=8403315</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=8403315</wfw:comment><description>&lt;p&gt;I know people want to know about this, but firm dates still prove elusive.&amp;#160; My best guess is today or tomorrow at this point.&lt;/p&gt;  &lt;p&gt;Basically we're trying to put an interim package up that satisfies everyone and isn't going to cause us foreseeable problems in the future.&amp;#160; Eliyas keeps tweaking this MSI to satisfy one concern or another raised by members of the Dev, PM and QA teams, and once it's done, it will go to &lt;a href="http://connect.microsoft.com" target="_blank"&gt;Microsoft Connect&lt;/a&gt; and you'll have your coinstallers.&amp;#160; Sometime after that we'll have an updated WDK with everything tied together nicely again.&amp;#160; As I understand it, the links for it on MSDN will work eventually, but I have no idea when.&lt;/p&gt;  &lt;p&gt;As far as the real testing- all done, all good.&amp;#160; All the legal and licensing stuff, good.&amp;#160; Just have to make an MSI with everything in it that doesn't look like it was slapped together at the last minute-&amp;#160; even though it sort of is.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Now playing: Yoko Kanno [Ghost in the Shell Stand Alone Complex, V2]: Psychedelic Soul&lt;/em&gt;&lt;/p&gt;  &lt;h2&gt;Some follow up&lt;/h2&gt;  &lt;p&gt;Kumar fixed &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2008/04/11/now-for-a-different-umdf-coinstaller-story.aspx" target="_blank"&gt;the UMDF coinstaller build problem&lt;/a&gt; (which you'll never see) in fairly short order, and then went on vacation himself.&amp;#160; So of course, more build problems turned up- but until we get that MSI out, not likely I'll get any traction.&amp;#160; This time the x64 update package for WinXP and Win2K3 is missing some pieces- blocks me, but again, I doubt this is a problem that affects anybody but my team [call this an attempt to give you an idea what it can be like sometimes &amp;quot;on the inside&amp;quot;, because it's easy to get the idea everything is endlessly smooth and we spend all our time pondering the whichness of the why].&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Now Playing: Grateful Dead [Live / Dead] St Stephen [always a welcome album]&lt;/em&gt;&lt;/p&gt;  &lt;h1&gt;&lt;/h1&gt;  &lt;h1&gt;So &lt;u&gt;that's&lt;/u&gt; what they look like!&lt;/h1&gt;  &lt;p&gt;Yesterday I gave a brief presentation on WdfVerifier and WdfTester in a session on Driver Testing at the Global MVP summit.&amp;#160; Met Mikhail Vodicka, Gianlucca Varenni, Martin O Brien and Maxim Shatskih- or rather at least exchanged greetings face-to-face, either in the session or out in the hall afterward.&amp;#160; I'd dropped off the OSR lists for a bit to help manage my email and workload, but after talking to Martin a bit, I decided to re-subscribe again.&amp;#160; Hopefully I can better manage my impulses to jump in on some of the esoteric issues that occasionally surface there...&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Now Playing: Kraftwerk [The Mix] Musique Non Stop&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8403315" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/customer+service/default.aspx">customer service</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/UMDF/default.aspx">UMDF</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/WdfVerifier/default.aspx">WdfVerifier</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/lifestyle/default.aspx">lifestyle</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/test+development/default.aspx">test development</category></item></channel></rss>