<?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</title><link>http://blogs.msdn.com/bobkjelgaard/default.aspx</link><description>Bob Kjelgaard writes about WDF, Testing, QA, and (occasionally) life at Microsoft</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>New WDF debugging videos on WHDC</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/09/22/9898002.aspx</link><pubDate>Tue, 22 Sep 2009 16:41:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9898002</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9898002.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9898002</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9898002</wfw:comment><description>&lt;p&gt;&lt;a href="http://www.microsoft.com/whdc/devtools/debugging/kmdf.mspx" target="_blank"&gt;Several for KMDF here&lt;/a&gt;, and &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/umdftraining.mspx" target="_blank"&gt;several more for UMDF here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Thus endeth today’s PR blitzen.&amp;#160; Have fun!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9898002" 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></item><item><title>Time Doth Flee</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/09/15/9895368.aspx</link><pubDate>Tue, 15 Sep 2009 16:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9895368</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9895368.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9895368</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9895368</wfw:comment><description>&lt;P&gt;Just realized I’ve now been blogging on MSDN for a bit over two years- that covers two OS releases [Windows Server 2008 and Windows 7] and WDF releases [1.7 and 1.9].&amp;nbsp; To bow to the Dead again- a long, strange trip it has been.&amp;nbsp; I started out wanting to write troubleshooting stories (something like Mark Russinovich often does).&amp;nbsp; But unfortunately, I found many of my best efforts turned up bugs in products that haven’t been shipped yet, and their owners typically don’t want such things disclosed or discussed in a public forum.&amp;nbsp; So I’ve wandered a bit all over the map, intellectually and topically speaking, since then.&lt;/P&gt;
&lt;P&gt;I’ve got more important things to write, though, so I’m tempted to leave this post at its current state.&amp;nbsp; It’s been over two years, now.&amp;nbsp; But I ain’t done- not yet!&lt;/P&gt;
&lt;H3&gt;Why I Work (part of it, anyway)&lt;/H3&gt;
&lt;P&gt;So for a moment, I’m going back to my “life at Microsoft” series…&lt;/P&gt;
&lt;P&gt;The bulletin board in my office is quite a bit of narcissism- one photo of my daughter, and &lt;A href="http://blogs.msdn.com/bobkjelgaard/archive/2007/09/25/my-halo-heaven.aspx" mce_href="http://blogs.msdn.com/bobkjelgaard/archive/2007/09/25/my-halo-heaven.aspx"&gt;the Halo3 calendar someone from Bungie gave me&lt;/A&gt;- opened to a picture of the Master Chief and the Arbiter, of course, since it’s for last year.&amp;nbsp; Also the outside cover of an InuYasha CD full of Kanji and an old poster for the Steve Pope band [which I played in when I was a Caltech undergrad].&amp;nbsp; The rest is all pictures of myself- from Caltech, from my years at IBM, from the Laundromat.&amp;nbsp; One is of very unique construction, and forms a nice background for the rest of today’s story.&lt;/P&gt;
&lt;P&gt;It’s a very high-tech etching, basically- constructed as follows:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;I’m contacted by a Wall Street Journal reporter who had written a book about Windows NT and had mentioned me in it [because I left Microsoft to run a Laundromat, and it seemed to be an interesting burnout story].&amp;nbsp; I’d mentioned what a disaster the laundry was for me, and he wants to do “a cautionary tale” about it. &lt;/LI&gt;
&lt;LI&gt;As part of that process, along with the interviews, he takes a few pictures, including one of myself (short hair, glasses, and just a moustache) and one of the Laundromat. &lt;/LI&gt;
&lt;LI&gt;An artist then combines those two photos and produces a detailed pencil sketch of them. &lt;/LI&gt;
&lt;LI&gt;When the article is published, the sketch accompanies it. &lt;/LI&gt;
&lt;LI&gt;My brother John scans this artwork, and uses it to create a “glass master” [how he got permission, I’m not sure I want to know]… &lt;/LI&gt;
&lt;LI&gt;He then gets permission to use that to produce several printed circuit boards with this image on an IBM manufacturing line in Endicott, NY [again, he said he had permission- they must have really liked him!]. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;So yes, (a) I was the subject of a Wall Street Journal story (but not the kind most people would want) and (b) I’ve got an IBM printed circuit board with my picture on it- several of them, actually [one I keep at home actually also has the engraved signatures of almost everyone in my immediate family].&lt;/P&gt;
&lt;P&gt;I keep them partially for the memories [and their uniqueness, of course], but also to remind me of the costs of some choices.&amp;nbsp; That venture bankrupted me in all but legal state [I could file, but I did not].&amp;nbsp; On the heels of that, I got divorced, and then hit a series of short-term jobs punctuated by periods of unemployment.&amp;nbsp; I was debt-free, but had a lot of future obligations (child support and so on).&amp;nbsp; Unemployment didn’t pay enough to cover child support [I could ask to have it reduced in such cases, but I wanted to take care of my daughter].&amp;nbsp; So&amp;nbsp; I was counting the months and weeks I could get through with negative income before I was truly homeless, and not liking how small those numbers were.&lt;/P&gt;
&lt;P&gt;That was the state of affairs when I came to Microsoft.&amp;nbsp; So I’ll be frank about it- there are a lot of reasons I work here, but a paycheck is most certainly one of them.&amp;nbsp; And the pay is good.&lt;/P&gt;
&lt;P&gt;I’ll skip the details, here- but I’ve come a long way financially, since then.&amp;nbsp; I’ve still got some very old computers that should be replaced, and some furniture in even worse state- and I still try to live pretty frugally [that was part of the reason I originally began not eating during the workday, over a decade ago].&amp;nbsp; But I’ve replaced some items already, I’ve got a decent savings cushion put together, my only debt is a mortgage which will be paid off well ahead of schedule, and I skip meals because it’s become an occasionally useful habit, instead of a necessity.&lt;/P&gt;
&lt;P&gt;My present is definitely tolerable, and my future becomes ever more secure.&amp;nbsp; That matters to me,and because I can remember when both were much more uncertain, I recognize Microsoft’s role in that.&lt;/P&gt;
&lt;P&gt;I suppose one key for me here is that this isn’t really a case of trading pay for some other intangible or tangible inducement.&amp;nbsp; The environment is good, the work is challenging and exciting- and relevant and meaningful.&lt;/P&gt;
&lt;P&gt;So for the moment, I’ll celebrate not just having a job [which I realize is a problem in and of itself for some people today], but having a good one- in spite of all my past mistakes and current shortcomings.&lt;/P&gt;
&lt;P&gt;Next time, I’ll get back to something more technical, because I do realize this sort of article wastes most readers’ precious time…&lt;/P&gt;
&lt;P&gt;I’ll see if this publishes this time around (I wrote it quite a while ago, but occasionally things don’t work very well around here)- if it does, I should note I can also celebrate a birthday tomorrow…&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9895368" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>Yet another WDF Blogger</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/09/02/9890416.aspx</link><pubDate>Wed, 02 Sep 2009 17:44:03 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9890416</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9890416.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9890416</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9890416</wfw:comment><description>&lt;p&gt;But that is a good thing.&amp;#160; &lt;a href="http://blogs.msdn.com/nebulut/archive/2009/09/01/device-driver-logo-using-wdf-co-installers.aspx"&gt;With a post yesterday&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/nebulut/"&gt;Neslihan&lt;/a&gt; has made her MSDN blogs debut. &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2008/06/28/potential.aspx"&gt;As I said long ago&lt;/a&gt;, you can expect great things to come from her.&amp;#160; She is already our resident expert on all things WLK and particularly with respect to WHQL for WDF devices. I’ve already added her to my list of colleagues here, so adieu for now…&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9890416" 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/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item><item><title>Driver Packages and Drivers- Shall We Disambiguate?</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/08/22/9880836.aspx</link><pubDate>Sat, 22 Aug 2009 22:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9880836</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9880836.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9880836</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9880836</wfw:comment><description>&lt;P&gt;So you want to know how to sign your driver, eh?&amp;nbsp; Let us step aside and improve our thinking for a moment, so we can be smarter about what we are asking for- because I don’t think it’s the driver you actually want to sign…&lt;/P&gt;
&lt;H2&gt;What is a Driver Package?&lt;/H2&gt;
&lt;P&gt;At a minimum. it is ALL of the files that should be present to make sure your device’s driver and all associated support software installs, begins working, and continues to work when it is plugged in:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The driver binaries, including any coinstallers, or other support binaries.&lt;/LI&gt;
&lt;LI&gt;The INF file, which tells the OS how to install the “driver” and hook all those things together properly.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;You may want more than that in the package- perhaps you have useful value-added utilities to install that you also want on the disk.&amp;nbsp; &lt;A href="http://download.microsoft.com/download/5/E/6/5E66B27B-988B-4F50-AF3A-C2FF1E62180F/CON-T612_WH08.pptx" target=_blank mce_href="http://download.microsoft.com/download/5/E/6/5E66B27B-988B-4F50-AF3A-C2FF1E62180F/CON-T612_WH08.pptx"&gt;That can be done, and Microsoft encourages you to do so&lt;/A&gt;.&lt;/P&gt;
&lt;H3&gt;&lt;/H3&gt;
&lt;H3&gt;How do I know what needs to be in the package?&lt;/H3&gt;
&lt;P&gt;The simplest answer is the best, here- every file listed in the INF as something that needs to be copied is a part of your package, as is the INF and any catalog file (about time I mentioned that) listed in the header.&amp;nbsp; Telling us you need those files copied means they are a part of the software supporting your hardware.&lt;/P&gt;
&lt;P&gt;Why even mention that?&amp;nbsp; Well, to make things easy for our joint customer- the person who bought your software [and usually your hardware, as well]- we will copy all of those files to a “driver store” on their machine.&amp;nbsp; Then, if installation needs to happen again (or happens later, as can be the case with a “software first” installation), they won’t need to find your media a second time- everything is already there, and the installation can be very silent [this is a bit of a simplification- if you provide coinstallers, you have options for UI and all kinds of other mayhem that exceed my intended scope- may I suggest perusing some of the &lt;A href="http://www.microsoft.com/whdc/winhec/2008/pres.mspx" target=_blank mce_href="http://www.microsoft.com/whdc/winhec/2008/pres.mspx"&gt;WinHec&lt;/A&gt; or &lt;A href="http://www.microsoft.com/whdc/winhec/2008/pres.mspx" target=_blank mce_href="http://www.microsoft.com/whdc/winhec/2008/pres.mspx"&gt;DDC&lt;/A&gt; content?].&lt;/P&gt;
&lt;P&gt;Well, as long as we’re looking there- consider &lt;A href="http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DDE-T675_DDC08.pptx" target=_blank mce_href="http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DDE-T675_DDC08.pptx"&gt;getting your driver package on Windows Update&lt;/A&gt;, and having it “just work” when the user connects it to their computer…&amp;nbsp; Look at the presentation before you make assumptions- we may well be willing to let you do a lot more than you think we will…&lt;/P&gt;
&lt;H3&gt;Could You Get To The Point?&lt;/H3&gt;
&lt;P&gt;Sure:&amp;nbsp; &lt;U&gt;You probably don’t want to&lt;/U&gt; [or at least don’t really need to] &lt;U&gt;sign your driver&lt;/U&gt;.&amp;nbsp; &lt;U&gt;&lt;STRONG&gt;You want to sign the package&lt;/STRONG&gt;&lt;/U&gt;.&lt;/P&gt;
&lt;P&gt;Why?&amp;nbsp; Because signing protects your customer (and by reflection, you) from tampering and corruption of the entire thing which is signed.&amp;nbsp; You don’t want someone replacing your coinstaller with one that also installs a keylogger, do you?&amp;nbsp; Or hiding that logger inside one of your support DLLs?&amp;nbsp; Or simply modifying your INF to install their malware for them when your driver is installed?&amp;nbsp; A lot of good it is going to do our customer to have a single driver binary safe and secure when everything else is open to attack.&lt;/P&gt;
&lt;H3&gt;OK- So How Do I Do This?&lt;/H3&gt;
&lt;P&gt;A quick summary:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;You create a “catalog”, which lists all of the files in your package (except for the catalog itself, of course).&lt;/LI&gt;
&lt;LI&gt;This catalog also has reasonably secure checksums for all of the files at the time they were cataloged.&lt;/LI&gt;
&lt;LI&gt;You then digitally sign the catalog, putting yourself on the line for everything within it, and knowing that if ANY of it gets changed, the change will be noticed.&lt;/LI&gt;
&lt;LI&gt;Now anyone that trusts you can trust your entire package.&amp;nbsp; Wouldn’t you rather have that than one binary?&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;This process is often called “catalog signing” as a distinction from “driver signing”- my rant here is that this is a focus on mechanism rather than intent.&amp;nbsp; Yes, you sign the catalog- but your intent is to vouch for the integrity of the entire package you present.&lt;/P&gt;
&lt;P&gt;If you want instructions, you can check &lt;A href="http://www.microsoft.com/whdc/driver/install/default.mspx" target=_blank mce_href="http://www.microsoft.com/whdc/driver/install/default.mspx"&gt;here&lt;/A&gt;.&amp;nbsp; But for my testing friends, I’ll promise to show how we roll in WDFQA (that’d be Windows Driver Frameworks Quality Assurance), because signing driver packages is a hurdle you have to clear for agile and reliable test automation when multitudes of drivers are involved.&lt;/P&gt;
&lt;H2&gt;When do I sign the binary?&lt;/H2&gt;
&lt;P&gt;The focus here is 64-bit systems.&amp;nbsp; Of course to me, those are the only ones worth having anymore…&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If your driver is needed to make the system boot, then you should also sign the binary itself.&lt;/LI&gt;
&lt;LI&gt;If your driver is not a WDM driver (yes I happen to have a few of these myself)- or in KMDF parlance- a non-PnP driver, then you may not have an INF.&amp;nbsp; So again, you should sign the binary.&lt;/LI&gt;
&lt;LI&gt;Of course, if you are inclined to sign it anyway, go ahead.&amp;nbsp; Knock yourself out. No harm done.&amp;nbsp; Your driver will load somewhat faster on a 64-bit system if you do, so there’s even reasonable benefit to be claimed.&amp;nbsp; But it isn’t a necessity.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Why I wrote this?&amp;nbsp; Let’s just say I’ve seen a few too many competent people run afoul of the terminology here and do something less than optimal as a result.&amp;nbsp; You hear “sign the driver”, so you do, and then you still get all the popups, and have to ask for help you wouldn’t have needed if someone had just given you the right information or asked you to do the right task in the first place.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9880836" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/driver+installation/default.aspx">driver installation</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/signing/default.aspx">signing</category></item><item><title>The Case of the Unexpected Overload</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/08/03/9856270.aspx</link><pubDate>Mon, 03 Aug 2009 17:31:44 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9856270</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9856270.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9856270</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9856270</wfw:comment><description>&lt;p&gt;So are you using C++ in a KMDF driver and scratching your head over some unexpectedly unresolved references?&lt;/p&gt;  &lt;p&gt;I recently engaged in a somewhat prolonged conversation with &lt;a href="http://blogs.msdn.com/doronh" target="_blank"&gt;Doron&lt;/a&gt; and a dev I won’t name [since I didn’t ask for permission] about C++ in KMDF driver.&amp;#160; This dev (a very good dev, by the way) had hit a stumbling point converting a driver from C to C++ and was wondering if we had ever tried this in QA.&lt;/p&gt;  &lt;p&gt;Yes, I know that means he/she doesn’t read this blog, since I’ve mentioned doing just that on more than one occasion.&amp;#160; But that’s OK, not many people do- and since I’ve got a tendency to write about whatever strikes my fancy at any moment, and I’m not the most dazzlingly brilliant human on the face of the planet, that’s not much of a surprise to me.&amp;#160; You are of course free to believe what you like about that statement.&lt;/p&gt;  &lt;p&gt;But in an attempt to be useful today- the problem was one of those that I guess I’ve hit so many times I don’t give it much thought.&amp;#160; But it gave our dev a bit of trouble, and not much gives this person that kind of trouble.&amp;#160; So perhaps a word to the wise will give the three or four of you still reading this a leg up the next time you use C++ in a KMDF driver.&lt;/p&gt;  &lt;h4&gt;The Lesson for Today Is…&lt;/h4&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;p&gt;It was just a simple conversion of a driver from C to C++ (to gauge my familiarity with the process, I did that with a half dozen or more drivers last week, and it was far from the only thing I did that week- in fact the big job was actually that I also made them W4 and PFD clean along with quite a few more drivers I’d already converted to C++- almost two dozen drivers total), but it ran afoul of this little bit of goodness:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;typedef
__drv_functionClass(EVT_WDF_OBJECT_CONTEXT_CLEANUP)
__drv_sameIRQL
__drv_maxIRQL(DISPATCH_LEVEL)
VOID
EVT_WDF_OBJECT_CONTEXT_CLEANUP(
    __in
    WDFOBJECT Object
    );

typedef EVT_WDF_OBJECT_CONTEXT_CLEANUP *PFN_WDF_OBJECT_CONTEXT_CLEANUP;&lt;/pre&gt;

&lt;p&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;p&gt;That’s the “role typedef” for any WDF object’s context cleanup routine.&amp;#160; The SDV tool can use role typedefs to do a better job of statically verifying your driver code, so some special cleanup typedefs are defined to make it a better tool, and you can see them in this (by the way, everything I’m posting is from the WDK- no deep dark secrets here).&lt;/p&gt;

&lt;pre class="csharpcode"&gt;typedef EVT_WDF_OBJECT_CONTEXT_CLEANUP EVT_WDF_DEVICE_CONTEXT_CLEANUP;
typedef EVT_WDF_OBJECT_CONTEXT_DESTROY EVT_WDF_DEVICE_CONTEXT_DESTROY;
typedef EVT_WDF_OBJECT_CONTEXT_CLEANUP EVT_WDF_IO_QUEUE_CONTEXT_CLEANUP_CALLBACK;
typedef EVT_WDF_OBJECT_CONTEXT_DESTROY EVT_WDF_IO_QUEUE_CONTEXT_DESTROY_CALLBACK;
typedef EVT_WDF_OBJECT_CONTEXT_CLEANUP EVT_WDF_FILE_CONTEXT_CLEANUP_CALLBACK;
typedef EVT_WDF_OBJECT_CONTEXT_DESTROY EVT_WDF_FILE_CONTEXT_DESTROY_CALLBACK;&lt;/pre&gt;

&lt;p&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;p&gt;So, what the original driver, being a good sample [because SDV suitability also matters], had was something like this (not exactly like this- nobody with my twisted sense of humor writes sample code, because humor never works globally- someone always takes offense- I’m just not inclined to care about that anymore, because I’m a callous old bastard with less than a dozen years to retirement age and not much “career” left to lose):&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;// In the header file:&lt;/span&gt;

EVT_WDF_DEVICE_CONTEXT_CLEANUP HideTheBodies;

&lt;span class="rem"&gt;// In the implementation&lt;/span&gt;
VOID
HideTheBodies(
    __in WDFDEVICE MortTheMortuaryTechnicianIsOnTheJob
    )
{
...&lt;/pre&gt;

&lt;p&gt;Of course, in C, that sort of works- but&lt;u&gt; &lt;strong&gt;in C++, that says you have two overloaded versions&lt;/strong&gt;&lt;/u&gt;&lt;strong&gt; &lt;/strong&gt;of &lt;strong&gt;&lt;em&gt;HideTheBodies&lt;/em&gt;&lt;/strong&gt;- one takes a WDFOBJECT as input, and isn’t defined, because nobody wrote it that way.&amp;#160; The one that is defined takes a WDFDEVICE as input.&amp;#160; More annoying, of course, is that from the typedef name, you’d expect it would take a WDFDEVICE as input, so it isn’t an error that’s glaringly obvious.&lt;/p&gt;

&lt;p&gt;As is- the code will compile fine, and PFD will be happy, too [they’re not the same function, remember].&amp;#160; But when you link it, you get an unresolved reference for &lt;em&gt;&lt;strong&gt;HideTheBodies&lt;/strong&gt;&lt;/em&gt;- decorated to indicate it has a WDFOBJECT parameter.&amp;#160; Now, unless you really look closely at such decorations (something my fine history of mistyping the simplest of code has taught me to do), you’re looking at a mystery.&amp;#160; It took my colleague digging through preprocessor output and object files and such to finally hit upon the error- a reasonably annoying circumstance!&lt;/p&gt;

&lt;p&gt;Another thing you can do (and this is what I usually do) is tie the callbacks to the context itself (with the context a class) as static member functions, as &lt;a href="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"&gt;I described earlier&lt;/a&gt; (effectively you do the cleanup by calling the context’s “delete” operator).&amp;#160; PFD currently doesn’t match the roletype if you do this, so I suppress those warnings (and there is no SDV for C++)- I think we’re trying to get that fixed…&amp;#160; But the compiler will catch the parameter type mismatch- a bit earlier than the linker.&lt;/p&gt;

&lt;p&gt;But I’ve hosed this both ways- so, until something on the subject gets posted by a recognized authority, this post can at least be found by the diligent searcher…&lt;/p&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=9856270" 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/PFD/default.aspx">PFD</category><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/C_2B002B00_/default.aspx">C++</category></item><item><title>Having trouble with WTT Logger from your WDTF script?</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/07/30/having-trouble-with-wtt-logger-from-your-wdtf-script.aspx</link><pubDate>Thu, 30 Jul 2009 14:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9853224</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9853224.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9853224</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9853224</wfw:comment><description>&lt;P&gt;Just a quick note, since someone asked about this recently on one of the WDTF support aliases and for a change, I actually knew the answer without looking it up.&lt;/P&gt;
&lt;P&gt;The sample scripts will try to create a COM automation object from the ProgId WTTLogger.Logger.&lt;/P&gt;
&lt;P&gt;The file you are looking for is named WTTLogCM.Dll, and all you need to do is register it:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Open a command prompt (administrative, I believe).&lt;/LI&gt;
&lt;LI&gt;Regsvr32 &amp;lt;path to WTTLogCM.DLL&amp;gt;&lt;/LI&gt;
&lt;LI&gt;Popup should say DllRegisterServer succeeded.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;That’s it!&amp;nbsp; You can unregister it later with regsvr32 /u.&lt;/P&gt;
&lt;P&gt;You can find the file in the WDK- in the server 2008 WDK (6001.18002) it lives in tools\wdtf\&amp;lt;arch&amp;gt;\redist\Extras.&amp;nbsp; If you look through the WDK tree, you may also find a wttlog.dll- wrong one!&amp;nbsp; For the curious, that’s got a direct call interface for native code apps- but that’s not suitable for scripting.&lt;/P&gt;
&lt;P&gt;Happens I’ve been developing a couple of COM automation in-process servers of the same type for some of my own test tools, and I live and die by WTT, anyway- so for a change, the answer was a no-brainer…&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9853224" 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/WDTF/default.aspx">WDTF</category></item><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>Not all of them</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/05/07/not-all-of-them.aspx</link><pubDate>Thu, 07 May 2009 20:44:33 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9594305</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9594305.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9594305</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9594305</wfw:comment><description>&lt;p&gt;Alas, all that stuff I mentioned in &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2009/04/18/exceptions-rule.aspx"&gt;my last post&lt;/a&gt; won’t make it into the Windows 7 WDK.&lt;/p&gt;  &lt;p&gt;As we get close to the final days of the product cycle, it gets harder to justify code changes.&amp;#160; In this case, my own choices in handling odd cases were my undoing.&lt;/p&gt;  &lt;p&gt;In a nutshell, if I can’t identify the KMDF client driver version, I treat it as if it is the same as the runtime.&amp;#160; Since the only version I can’t identify is KMDF 1.9, and a 1.9 driver won’t even load unless the runtime is 1.9 or higher and there is nothing higher, I can’t really claim something is broken besides some text that says what the real version is.&amp;#160; All the rest of the relevant UI function will be correct, as de facto, it will be treated as a 1.9 driver, and that is what it is.&lt;/p&gt;  &lt;p&gt;Well, they say there will be service packs for the WDK, perhaps this will make one.&amp;#160; If not, at least I had my fun, and the tool does work pretty much as it should.&lt;/p&gt;  &lt;p&gt;I just designed it too well- yeah, that’s the excuse du jour…&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9594305" 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/WdfVerifier/default.aspx">WdfVerifier</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>Progress</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/03/13/progress.aspx</link><pubDate>Fri, 13 Mar 2009 16:22:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9473128</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9473128.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9473128</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9473128</wfw:comment><description>&lt;p&gt;When I first got the idea of digging up my old tapes and digitizing them before I lost them for good, I was chatting with another ‘softie (I believe it may have been Craig Ziegler, who manages the test team for the WDK) at the big party during WinHEC 2008 (so I did do something there besides play Halo 3).&amp;#160; At about that time, the music being played switched to the Donna Summer classic “(She works) Hard For The Money”.&amp;#160; That was one of the tunes I wanted to see if I could capture one of my “covers” of.&lt;/p&gt;  &lt;p&gt;Perhaps in part because of that Grateful Dead influence, I was always a very improvisational player- that song was a part of my bands’ repertoire through much of the 80’s, both when I played the bass, and later after i switched to the guitar.&amp;#160; I always liked it, and my approach to it was always laden with drama- lots of energy, catchy motifs [well, I though they were catchy], strong attacks on key parts- perhaps overly bombastic- but hey, that’s how I thought it should be played and I was the one with the instrument.&amp;#160; While I was aware of the underlying theme the song had, I always treated it more as an anthem for women in the workforce.&amp;#160; In part because my career included an era where things were a lot tougher than they are now.&amp;#160; “She works hard for her money, and you better treat her right”.&lt;/p&gt;  &lt;p&gt;I’ve managed to find two instances that I play in my office (and in my car, and on my xBox, thanks to that fine SanDisk USB thumb drive I got as a WinHEC freebie)- one where I play the bass in a live performance [and I thought it captured the nuance of that night well]- the other with guitar- but it was at a practice, and fairly early one- so the leads aren’t very inspired, there are presentational inconsistencies [more than usual], and I make a few more flubs than usual.&amp;#160; I know I had at least one solid live performance on guitar, but I may have lost that tape.&amp;#160; Ahh well, now that I’m practicing again, maybe I can recreate those lost glories- not that anyone but me actually cares, but one ought to have some purpose in life, right?&lt;/p&gt;  &lt;p&gt;At any rate, while listening to the two of them back-to-back last week, the basic idea of this article came to me.&amp;#160; So perhaps this will be less half-baked than others have been…&lt;/p&gt;  &lt;p&gt;I’ve been fortunate enough to have had several women as managers or coworkers [I also employed quite a few at the Laundromat, had more sisters than brothers, and my mother was herself a strong influence on me].&amp;#160; I owe most of them some debt of gratitude.&lt;/p&gt;  &lt;p&gt;My first long-term job after graduating from Caltech was at IBM in Owego, NY.&amp;#160; The interviews there were interesting to me- I had two in their Electronic Design Automation group, and it was one of those experiences where you just light up and enjoy it.&amp;#160; I’d been working as an electronics technician on and off since graduation (one of the things I had acquired and needed to rid myself of during my college years was a distaste for computer programming, which had been one of my first loves prior to that- I had decided I’d rather work toward being a EE, instead), and had been thinking about application of computers to digital circuit design and testing.&amp;#160; I’d discussed some of them with coworkers and had the “not possible- way too hard- you’re crazy to think like that” kind of response- but here I was interviewing with a group that was doing exactly that- and it was working quite well.&amp;#160; Since I’d already been thinking along those lines, I could ask intelligent questions, etc.&amp;#160; The interviews went well.&lt;/p&gt;  &lt;p&gt;But I did terrible things at Caltech- things like skipping exams because I knew I would get a passing grade without taking them [not a good grade, just a passing one]- so I had a rather poor GPA.&amp;#160; Low enough I did not meet the corporate hiring guidelines.&amp;#160; The hiring manager seemed to consider me a bit of a nerd, and he also judged a lot on those numbers.&amp;#160; His manager was a woman- she had attended grade school near Caltech, and I had also interviewed with her.&amp;#160; She intervened, and I was hired in spite of some resistance.&amp;#160; So I definitely owe a woman my first good start in the high-tech industry.&lt;/p&gt;  &lt;p&gt;But the things I used to hear!&amp;#160; That she had to agree not to have a family life in order to have the management job, for instance.&amp;#160; Or later, assertions of tokenism.&amp;#160; In those days, I was pretty naive- so it was hard to judge how much was true, how much was cattiness, how much was just plain made up out of spite and jealousy.&amp;#160; So I may have accepted more of it as truthful than I should have.&amp;#160; But it didn’t seem fair.&amp;#160; So as she progressed (at least as far as a divisional vice president, last I knew) I gave a few silent cheers, and didn’t contribute to or spread all the gossipy stuff.&lt;/p&gt;  &lt;p&gt;The working environment certainly wasn’t friendly- that much was true.&amp;#160; One incident I recall later in my tenure there was my mentioning pointedly in an employee poll the plight I observed of one of my fellow engineers.&amp;#160; The men hired at about the same time as she was had been given desirable assignments and good career paths- high-profile design and engineering tasks.&amp;#160; Her assignment was to track equipment being checked in and out of the equipment closet.&amp;#160; When she agitated for something a bit more technical, she was given a project that was clearly doomed to spectacular failure (budget had already been spent, technical approach was flawed in the opinion of most of the experienced engineers on the team, etc).&amp;#160; I had a distinct sense that this was deliberate and retributive and found it reprehensible.&amp;#160; Such opinions of course had to be written, and my writing style is distinct enough it was clear who raised the issue- only deliberate obfuscation of submitted material could have hid it, and no place I’ve ever been that conducts such surveys resorts to that.&amp;#160; So I shouldn’t have been surprised that the next project that came along that I had a strong interest in was given to her.&amp;#160; But that was probably a good choice, as it turned out- I pushed way beyond my limits in those days- she was a bit more sensible.&lt;/p&gt;  &lt;p&gt;Now I don’t think what I was seeing matched the desires of the top management of the company, even then [and I’m equally certain it would not be regarded positively now].&amp;#160; I’m merely discussing perceived changes from my viewpoint.&amp;#160; Cultural changes- both societal and within other aggregations such as a corporation, take time.&amp;#160; Personal change as well, [and there’s been a bit of that, fortunately] for that matter.&lt;/p&gt;  &lt;p&gt;After coming to Microsoft, I experienced what at the time I would have termed a more “liberal” working environment.&amp;#160; Family leaves, etc.&amp;#160; While women were rare, there wasn’t quite the same sense of class difference.&amp;#160; I tried to take some of those lessons to heart when I was the boss [the Laundromat again].&amp;#160; I tried to provide flexible arrangements, allowed employees to bring children to work when there were day care problems, etc.&amp;#160; The pay was terrible (as I’ve noted elsewhere, the venture bankrupted me in all but the legal sense of seeking the protection), but I wouldn’t have paid a man more.&amp;#160; I always paid more than minimum wage- but not much more.&amp;#160; So I suppose in that sense my employment of them could be deemed exploitation- but that certainly wasn’t my intent.&lt;/p&gt;  &lt;p&gt;I’ll skip over a few bits of reminiscence- don’t need them.&amp;#160; Today I find myself working for a woman again [and one could even argue she was promoted to the spot over my head- it happens I don’t have a problem with that, though].&lt;/p&gt;  &lt;p&gt;Now I could go on about how well I think that turned out [she’s a good leader, I’ve said it before, and I still believe it, and try to do what I can to help], but that’s not what I intend.&amp;#160; It’s the difference in environments across that span of time, and the direction of the progress as I see it.&amp;#160; Sometimes she works from home- sometimes she has to drop things to attend to family and child care issues.&amp;#160; Nobody sees anything wrong with that, as far as I can tell.&amp;#160; It doesn’t affect her being an effective leader or manager.&amp;#160; The organization supports it, and we as her team support it.&lt;/p&gt;  &lt;p&gt;After mentally composing much of that, I found we have new board member- again a woman, and computer science professor…&lt;/p&gt;  &lt;p&gt;With a daughter of my own soon to enter the work force- it’s good to consider these things.&amp;#160; There has been progress- the journey may not be over, perhaps many are not satisfied with the pace- but at least it’s the right direction.&amp;#160; I consider myself fortunate to work for the company I work for- that it values these things, and makes these efforts- to produce a more inclusive and diverse workforce.&amp;#160; One that respects these things and its employees.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Now Playing: Troy- Ghost in the Shell: Stand-Alone Complex Soundtrack- Monochrome&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9473128" width="1" height="1"&gt;</description><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>Motivation</title><link>http://blogs.msdn.com/bobkjelgaard/archive/2009/02/09/motivation.aspx</link><pubDate>Tue, 10 Feb 2009 10:14:07 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9410058</guid><dc:creator>BobKjelgaard</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/bobkjelgaard/comments/9410058.aspx</comments><wfw:commentRss>http://blogs.msdn.com/bobkjelgaard/commentrss.aspx?PostID=9410058</wfw:commentRss><wfw:comment>http://blogs.msdn.com/bobkjelgaard/rsscomments.aspx?PostID=9410058</wfw:comment><description>&lt;p&gt;What makes a person do what they do?&amp;#160; One thing we try to be at Microsoft (and another good attribute to have) is self-critical- to be able to objectively [to the best of our innate abilities,as it is hard to avoid some subjectivity in this domain] analyze our actions, our strengths, our weaknesses- in many aspects of our work.&lt;/p&gt;  &lt;p&gt;Two other key parts of the Microsoft culture that bear upon this article, and which is in some sense motivated by a nexus of all of these:&amp;#160; the intrinsic value of open and honest communication, and a sense of respect to others with whom we deal that tries to assume the best interpretation when multiple alternatives present themselves.&lt;/p&gt;  &lt;p&gt;The final element in today's mix is some of my own motivators- to blog, to work on WDF, and to work for Microsoft.&amp;#160; I'll start with the final one.&lt;/p&gt;  &lt;p&gt;Microsoft is an amazing place to work.&amp;#160; The Core Operating Systems Division- the heart and soul of a platform literally used on a global basis.&amp;#160; I was a part of it years ago [and it was a thrill to be there then, when it was the Systems Division, and Steve Ballmer was just the president of the division], and to be back there again- at a place close to the kernel, which is a place I'd always hoped to be but doubted I'd ever achieve.&amp;#160; Those bottom-most layers, where hardware meets software- the foundation that holds up the entire software building.&amp;#160; I should pinch myself to make sure it's really true.&lt;/p&gt;  &lt;p&gt;But its much much more than just the raw technology.&amp;#160; I am surrounded by people of great skill and intellect, united in one form or another with a common purpose- the broad purpose of &amp;quot;improving human lives through the application of technology&amp;quot; is one way it could be stated at the company level.&amp;#160; But where I sit, it's focused a bit more on the hardware, the people who make that hardware and see having it work on Windows as a means for them to achieve their personal goals [financial, professional, and so on].&amp;#160; We want drivers to work on Windows.&amp;#160; We want to make them easier to use.&amp;#160; We want that whole end-user experience to be better, safer, and more trustworthy.&amp;#160; We want the people who make that hardware and build those drivers find their jobs getting easier and the process more efficient and effective for all.&amp;#160; We think about it and talk about it in some form practically every day.&amp;#160; Historically, I think a lot of progress has been made, and we aren't resting upon that- we're pressing forward.&amp;#160; We strive to improve and achieve some form of excellence.&lt;/p&gt;  &lt;p&gt;Better yet to me, though, is that these are people I can trust- those values of honesty and integrity and ethical behavior aren't shams.&amp;#160; I see that as well in interactions throughout my day.&amp;#160; And I see that respect for diverse and differing viewpoints- it isn't always easy, and in none of this am I trying to say everything is perfect.&amp;#160; But it's a good place to work and good people to be working with, and we're in a reasonable sense making our living trying to do good things.&amp;#160; In a way, it is living a dream [sometimes the technology turns it into a nightmare, but that's the nature of human frailty- we push our limits, sometimes we have to fall back].&lt;/p&gt;  &lt;p&gt;So I'm passionate about my job and about Microsoft.&amp;#160; I blog because of this.&amp;#160; When I was trying to solve &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2007/08.aspx" target="_blank"&gt;that installation problem in my initial set of articles&lt;/a&gt;, I tried to live up the corporate standards in my treatment of both sets of customers [the engineer at the company using our technology and the end users who were experiencing this issue]- the fact that they closely align with my own beliefs certainly helps- but that alignment is what helps drive me.&amp;#160; It leads me to take hours out of my day at times investigating other issues, or doing other tasks.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2009/02/07/bad-advice-no-matter-where-it-came-from.aspx" target="_blank"&gt;the first article I wrote over the weekend&lt;/a&gt;, this is some background to further explain myself:&amp;#160; I spent at least a couple of hours reading megabytes of logs to determine what had happened on an end user machine for another support engineer at a hardware company.&amp;#160; It was an experience I'd mentioned before- the problem wasn't just affecting his driver, it had affected others.&amp;#160; Somewhere out there what was probably a perfectly good piece of hardware got discarded as useless- it's manufacturer derided as producing garbage.&amp;#160; This person's company was in danger of the same thing.&amp;#160; The first conclusion was unfair, and the second would have been.&amp;#160; That offends a basic sense of justice and fairness I find myself afflicted with...&lt;/p&gt;  &lt;p&gt;So I got upset, and I vented.&amp;#160; In response, I got &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2009/02/07/bad-advice-no-matter-where-it-came-from.aspx#9407301" target="_blank"&gt;this reply&lt;/a&gt;.&amp;#160; It is capable of ambiguous interpretation, whether deliberately or just through a lack of finesse in English [some of the constructions hint at someone for whom it is a second language- although I am capable of that and worse at times, particularly when tired].&amp;#160; So at first, I opted for the less confrontational interpretation, and &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2009/02/07/bad-advice-no-matter-where-it-came-from.aspx#9407902" target="_blank"&gt;simply replied with what was on my mind already&lt;/a&gt;, anyway.&amp;#160; I'm never at my best when angry, and I try not to let it happen [and to let it pass when it does].&amp;#160; I still need to take some of those more curative steps, but I will get them done.&lt;/p&gt;  &lt;p&gt;But at the moment, my inner priorities have me blogging again- in part because of that second interpretation.&amp;#160; My deepest and sincerest apologies up front if I have misjudged and was closer to the truth with my first estimation, by all means.&amp;#160; But the ambiguity exists, the fire is in my heart, and I shall answer:&lt;/p&gt;  &lt;p&gt;Registration on MSDN provides access to useful features- my registration, for instance, let' me update my blog from anywhere.&amp;#160; If we intended it as a deterrent, it would be a lot harder than it was.&amp;#160; Sites where I've seen this particular bad advice [just delete KMDF] weren't hard to find [and I really don't remember seeing many registration barriers]- but the threads were old, and in my own view, there were better uses of my time than trying to challenge each utterance individually.&amp;#160; Of course, all that happened BEFORE I saw those logs and some of the real effects of that advice.&amp;#160; Perhaps I should have tried that.&amp;#160; But I can't unwind the clock, and the genie is out of the bottle.&lt;/p&gt;  &lt;p&gt;As for the quality of my own posts- I know I'm not perfect.&amp;#160; People that actually take the time to know me know that about me.&amp;#160; But I do know what happens when you remove the KMDF service or delete the binaries, or even stop making it boot start [all of this specifically referring to Vista and above].&amp;#160; I've done all those things in testing it- repeatedly.&amp;#160; On multiple machines.&amp;#160; My parents have a Vista machine, and I wouldn't do it to them.&amp;#160; And I would be every bit as angry at someone who gave them the same advice I was ranting about.&lt;/p&gt;  &lt;p&gt;Marketing?&amp;#160; I have seen my blog featured for brief periods on the &lt;a href="http://www.microsoft.com/whdc/winhec/default.mspx" target="_blank"&gt;WinHEC&lt;/a&gt; and &lt;a href="http://www.microsoft.com/whdc/default.mspx" target="_blank"&gt;WHDC&lt;/a&gt; sites [and in both cases,&amp;#160; I found it a bit disconcerting- I'm sure I shall always pale in comparison to &lt;a href="http://blogs.msdn.com/doronh/default.aspx" target="_blank"&gt;Doron&lt;/a&gt;, or to &lt;a href="http://blogs.technet.com/markrussinovich/default.aspx" target="_blank"&gt;Mark Russinovich&lt;/a&gt;, and I can easily rattle off &lt;a href="http://www.microsoft.com/whdc/resources/blogs.mspx" target="_blank"&gt;many more names&lt;/a&gt;- I take it as a rotation of sorts meant to give me some success as a blogger, but how well that chance works out is up to me].&amp;#160; I suppose it's a form of marketing, so point taken.&amp;#160; But I can't see yet what's wrong with it- I'm no star, and I doubt I ever shall be.&lt;/p&gt;  &lt;p&gt;Sycophants?&amp;#160; Doubt I've met any- one can agree with something, even enthusiastically, and not be a sycophant.&amp;#160; Contrarian- same thing only flipped around.&amp;#160; Both agreement and disagreement have value in a conversation meant to go somewhere and achieve a goal- I see that in my job every day, as well.&amp;#160; With all due respect, that seems to be an unfair and dismissive characterization (whether directed toward me or not).&amp;#160; Real people do these things- they innately deserve more than being dismissed as stereotypes.&lt;/p&gt;  &lt;p&gt;Hiding all Microsoft content from the Internet?&amp;#160; Or just MSDN?&amp;#160; Or just my own blog?&amp;#160; If it's the latter, there are times I'd be inclined to agree- I often denigrate my own work- I can be one of my harshest critics.&amp;#160; But perhaps the thought that since its in those indices (that's the proper plural for index, by the way), anybody can see for themselves what a blowhard I am can be a form of consolation.&amp;#160; If my incompetence rises to the level of termination, perhaps those indices will save a future potential employer from a grave error.&amp;#160; On the other hand, if it was one of those earlier two- that's just totalitarian.&amp;#160; If you don't care about the walled garden, don't look.&amp;#160; Why be bothered that others do?&amp;#160; If the underlying claim is that the content is harmful, I'll just not agree- I used that content at times when I wasn't an employee and didn't particularly like the company or think it was a good thing it held its market position.&amp;#160; It may not have been perfect, but it wasn't deliberately harmful [and yes, claims like that are indeed something that upset me- I just don't see a point in wasting time dealing with them- not unless there's something concrete and not just endless assertion, which is all I was presented with here]. &lt;/p&gt;  &lt;p&gt;But to go back to thinking the best, I can take this again as a criticism of the ineffective nature of my choices in how to blog.&amp;#160; It's too hard to separate the good stuff from the rest of my verbage.&amp;#160; That is something that I am aware of, and occasionally try to correct.&amp;#160; But it's hard for me to not be me, especially when blogging- the act of composition drives itself in these directions.&lt;/p&gt;  &lt;p&gt;As my final afterthought I'll go back a bit further- my responses on NTDEV a couple of weeks back were fueled by what seemed to me to be an endless stream of negative criticism, shallow, caricatured stereotypes and unfair, unwarranted assumptions about who and what I and my colleagues are.&amp;#160; Calvin Guan was in some ways an innocent- his comment was just the verbal straw that broke the Bob camel's back.&amp;#160; I've worked with him briefly and he's not a bad sort at all.&amp;#160; But my tone may not have been respectful enough...&amp;#160; I did want to counter those opinions though, I felt they delivered a skewed picture [and hence &lt;a href="http://blogs.msdn.com/bobkjelgaard/archive/2009/01/22/well-yes-and-no.aspx" target="_blank"&gt;that subsequent post&lt;/a&gt;].&lt;/p&gt;  &lt;p&gt;So, I'll leave this missive in those indices, and let things fall out as they may.&amp;#160; Tomorrow I'll go to work and try in my own way to make the world a better place.&amp;#160; I'm lucky to have a place where I can do that, and luckier still to have some people about who really accept that as being part of my motivation [yes, I also like having a place to sleep that's warm, and food, and so forth, too- those are additional motivators]...&amp;#160; Beyond that, I'm not sure how concerned I should need to be.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9410058" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/bobkjelgaard/archive/tags/Life+at+Microsoft/default.aspx">Life at Microsoft</category></item></channel></rss>