<?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>A Hole In My Head : Coding Thoughts</title><link>http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx</link><description>Tags: Coding Thoughts</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>What should you change in a sample before you ship it?</title><link>http://blogs.msdn.com/doronh/archive/2008/04/23/what-should-you-change-in-a-sample-before-you-ship-it.aspx</link><pubDate>Wed, 23 Apr 2008 21:41:19 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8419605</guid><dc:creator>doronh</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/doronh/comments/8419605.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=8419605</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=8419605</wfw:comment><description>&lt;p&gt;I was going to write about how to do this, but the awesome folks at WHDC got to it before I did.&amp;#160; I did get to review it before it was published, so I did have some influence in what is in the tip ;). So on this one my job is easy, just go read the &lt;a href="http://www.microsoft.com/whdc/driver/tips/SampleChange.mspx" target="_blank"&gt;tip&lt;/a&gt;!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8419605" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>one of the books that started it all...</title><link>http://blogs.msdn.com/doronh/archive/2008/03/12/one-of-the-books-that-started-it-all.aspx</link><pubDate>Wed, 12 Mar 2008 18:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8163222</guid><dc:creator>doronh</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/doronh/comments/8163222.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=8163222</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=8163222</wfw:comment><description>&lt;P&gt;During my sophomore year at &lt;A href="http://www.calpoly.edu/" target=_blank mce_href="http://www.calpoly.edu/"&gt;Cal Poly&lt;/A&gt;, I decided that I wanted to learn about threads, synchronization techniques and other topics associated modern operating systems.&amp;nbsp; Windows 95 had made its debut (yes, it is not a modern OS, but I didn't know that at the time!) and I had heard about Windows NT, but had never seen or used it.&amp;nbsp; Since I had Win95 on my machine at home, I decided that I would go to the &lt;A href="http://www.elcorralbookstore.com/" target=_blank mce_href="http://www.elcorralbookstore.com/"&gt;bookstore&lt;/A&gt; and buy a book on threading.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Well, needless to say there was not a book that was dedicated to threading, but I found a couple of books on Windows programming that included threading as topics.&amp;nbsp; It came down to 2 books, Jeffrey Richter's "Advanced Windows for Win95 and NT" (with &lt;A href="http://www.amazon.com/Advanced-Windows-Developers-Guide-Win32/dp/1556156774/ref=sr_1_11?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205277849&amp;amp;sr=1-11" target=_blank mce_href="http://www.amazon.com/Advanced-Windows-Developers-Guide-Win32/dp/1556156774/ref=sr_1_11?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205277849&amp;amp;sr=1-11"&gt;Napoleon&lt;/A&gt; on the cover) and some other book.&amp;nbsp; I obviously picked Richter's book ;), although now it is called &lt;A href="http://www.amazon.com/Windows-via-C%2B%2B-Pro-Developer/dp/0735624240/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205278444&amp;amp;sr=1-1" target=_blank mce_href="http://www.amazon.com/Windows-via-C%2B%2B-Pro-Developer/dp/0735624240/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205278444&amp;amp;sr=1-1"&gt;"Windows via C/C++&lt;/A&gt;."&lt;/P&gt;
&lt;P&gt;This book was, and still is, awesome.&amp;nbsp; I have both the original and new editions.&amp;nbsp; Great detail, very easy to read and met it my needs perfectly (unlike "&lt;A class="" href="http://www.amazon.com/Inside-Microsoft-Programming-Kraig-Brockschmidt/dp/1556158432/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205278587&amp;amp;sr=1-1" target=_blank mce_href="http://www.amazon.com/Inside-Microsoft-Programming-Kraig-Brockschmidt/dp/1556158432/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205278587&amp;amp;sr=1-1"&gt;Inside OLE&lt;/A&gt;" by Kraig Brockschmidt which was full of information, I just could not stay awake reading it :) ).&amp;nbsp; IMHO, it successfully started me down the road to becoming a well rounded developer and I think it helped in getting my foot in the door at Microsoft.&amp;nbsp; I have even had the pleasure of letting Jeff know personally what a great book it is and how it shaped me for years to com.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8163222" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>User empathy is a weird thing</title><link>http://blogs.msdn.com/doronh/archive/2007/06/25/user-empathy-is-a-weird-thing.aspx</link><pubDate>Mon, 25 Jun 2007 18:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3468600</guid><dc:creator>doronh</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/doronh/comments/3468600.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=3468600</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=3468600</wfw:comment><description>&lt;P&gt;I figured that I had a good deal of empathy for a developer who had to write a driver.&amp;nbsp; I have spent nearly 5 years creating and supporting WDF, learning from the community and drawing on my own experience in how drivers are written.&amp;nbsp; Two of the most common questions is "what IDE should I use" and "can I write and build a driver in Visual Studio (VS)"?&amp;nbsp; In terms of an IDE purely for writing code, no one can tell you what to use.&amp;nbsp; Everybody's style and workflow is different.&amp;nbsp; Sometimes you can't even pick, your employer will dictate that you must use program X. In this case, you are still using the WDK build window to build your driver. I understood this type of user pretty well, I am one of them.&amp;nbsp; I use Visual SlickEdit as my editor (in vi mode so my hands never leave the keyboard ;) ) and use razzle (essentially the internal version of the WDK build window) to compile my code.&lt;/P&gt;
&lt;P&gt;Writing and compiling my driver in VS is something I didn't fully grok until recently. I thought I understood the appeal of the integrated compilation results within the editor, that you could double click on an error and have that line be brought up in the editor, etc etc.&amp;nbsp; What I didn't fully understand the appeal of was the actual writing of code in VS.&amp;nbsp; The last time I used VS full time was in 1997 as a college undergrad working on a kiosk software project in C++ (no C# at the time ;) ).&amp;nbsp; There was some rudimentary intellisense there, but not much to write home about.&amp;nbsp; I just started using VS 2005 for another project and I am very impressed with the intellisense, automatching, refactoring and other features in the product.&amp;nbsp; It is pretty frackin' awesome in terms of productivity and discovery of features.&amp;nbsp; So I now get why a lot of you want to be able to write and&amp;nbsp;build a&amp;nbsp;driver in VS ;), it is a very compelling work environment. &lt;/P&gt;
&lt;P&gt;I hope that we wil get WDK integration into VS in the future, but I think that is just the first step.&amp;nbsp; There are so many things that we as Microsoft can integrate with other then getting intellisense and auto completion working.&amp;nbsp; If we are to take the time to integrate into VS, it should be deep and appropriate for the entire development cycle(s), not just the writing of code.&amp;nbsp; &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3468600" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>Better control over /GS stack checking in your driver</title><link>http://blogs.msdn.com/doronh/archive/2007/04/10/better-control-over-gs-stack-checking-in-your-driver.aspx</link><pubDate>Tue, 10 Apr 2007 19:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2057829</guid><dc:creator>doronh</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/doronh/comments/2057829.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=2057829</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=2057829</wfw:comment><description>&lt;P&gt;Michael Howard has a great &lt;A href="http://blogs.msdn.com/michael_howard/archive/2007/04/03/hardening-stack-based-buffer-overrun-detection-in-vc-2005-sp1.aspx" target=_blank mce_href="http://blogs.msdn.com/michael_howard/archive/2007/04/03/hardening-stack-based-buffer-overrun-detection-in-vc-2005-sp1.aspx"&gt;posting&lt;/A&gt; on improvements made in the compiler with respect to the /GS flag (stack checking using a "canary" on function exit). Before these changes, #pragmas to explicitly turn the functionality on or off, the compiler itself decided where it was appropriate to add the stack checks based on internal heuristics. The improvements were made to the VS2005 SP1 version of the compiler, but I just checked and the compiler in the WDK includes these changes. Use this functionality as another tool in the tool belt for writing secure drivers!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2057829" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>Creating your own InterlockedXxx operation</title><link>http://blogs.msdn.com/doronh/archive/2006/12/06/creating-your-own-interlockedxxx-operation.aspx</link><pubDate>Thu, 07 Dec 2006 01:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1225874</guid><dc:creator>doronh</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/doronh/comments/1225874.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=1225874</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=1225874</wfw:comment><description>&lt;P&gt;Sometimes your design requires an Interlocked operation that is not currently supported by the OS, runtime libraries, or the compiler (as an intrinsic). You then have a choice to make. Either remove all Interlocked operations for that particular field and use a lock or roll you own Interlocked function. Roll your own Interlocked function? Sounded scary to me the first time it was suggested, but in reality it is a rather easy thing to do. Here is the&amp;nbsp;basic algorithm (which I did not invent, it is a well tested and known algorithm)&amp;nbsp; and a couple of concrete examples&lt;/P&gt;&lt;PRE&gt;    LONG
    InterlockedYyy(
        __inout LONG  volatile *Target,
        [Additional parameters as needed for operation Yyy]
        )
    {
        LONG prevValue, prevCopy;
    
        prevValue = *Target;
    
        do {
            [Optional comparison]
    
            prevCopy = prevValue;
    
            //
            // prevValue will be the value that used to be Target if the exchange was made
            // or its current value if the exchange was not made.
            //
            prevValue = InterlockedCompareExchange(Target, Yyy operation on prevCopy, prevValue);
    
            //
            // If prevCopy == prevValue, then no one updated Target in between the deref at the top
            // and the InterlockecCompareExchange afterward and we are done
            //
        } while (prevCopy != prevValue);
    
        //
        // [value] can be anything you want, but it is typically either
        // a) The new value stored in Target.  This is the type of return value that 
        //    InterlockedIncrement returns
        // or
        // b) The new value is the previous value that was in Target.  This si the 
        //     type of return value that InterlockedOr or InterlockedExchange return
        //
        return [value];
    }
&lt;/PRE&gt;
&lt;P&gt;From this algorithm you can implement nearly anything you want. For instance, let's say that you want to increment Target if and only if it's current value is greater then zero. This allows you to never go from zero to one, a common problem when you implement a reference count. Since this Interlocked operation can "fail,"&amp;nbsp;we need a way to convey failure.&amp;nbsp; In this case I chose to return the Floor value since it is an not a value that could ever be returned in the success path.&amp;nbsp; Algorithm specific modifications to the generic algorithm are in &lt;SPAN style="COLOR: red"&gt;red&lt;/SPAN&gt; &lt;/P&gt;&lt;PRE&gt;    LONG
    MyInterlockedIncrementWithFloor(
        __inout LONG  volatile *Target,
        LONG Floor
        )
    {
        LONG prevValue, prevCopy;
    
        prevValue = *Target;
    
        do {
&lt;FONT color=#ff0000&gt;            if (prevValue &amp;lt;= Floor) {
                return Floor;
            }&lt;/FONT&gt;
    
            prevCopy = prevValue;
    
            //
            // prevValue will be the value that used to be Target if the exchange was made
            // or its current value if the exchange was not made.
            //
            prevValue = InterlockedCompareExchange(Target, &lt;FONT color=#ff0000&gt;prevCopy+1&lt;/FONT&gt;, prevValue);
    
            //
            // If prevCopy == prevValue, then no one updated Target in between the deref at the top
            // and the InterlockecCompareExchange afterward and we are done
            //
        } while (prevCopy != prevValue);
    
        //
        // prevCopy is the old value of Target. Since InterlockedIncrement returns the new
        // incremented value of Target, we should do the same here.
        //
        return &lt;FONT color=#ff0000&gt;prevCopy+1&lt;/FONT&gt;;
    }
&lt;/PRE&gt;
&lt;P&gt;Let's say you wanted to XOR in a value in the high word of the Target and clear the low word, you could implement it this way &lt;/P&gt;&lt;PRE&gt;    LONG
    MyInterlockedXorHighClearLowWord(
        __inout LONG  volatile *Target,
        SHORT HighWord
        )
    {
        LONG prevValue, prevCopy;
    
        prevValue = *Target;
    
        do {
           &lt;FONT color=#ff0000&gt; // No conditional check like the previous example&lt;/FONT&gt;&lt;/PRE&gt;&lt;PRE&gt;            prevCopy = prevValue;
    
            //
            // prevValue will be the value that used to be Target if the exchange was made
            // or its current value if the exchange was not made.
            //
            prevValue = InterlockedCompareExchange(
                Target, 
&lt;FONT color=#ff0000&gt;                (prevCopy ^ (HighWord &amp;lt;&amp;lt; 16) &amp;amp; (~0xFFFF),&lt;/FONT&gt;
                prevValue);
    
            //
            // If prevCopy == prevValue, then no one updated Target in between the deref at the top
            // and the InterlockecCompareExchange afterward and we are done
            //
        } while (prevCopy != prevValue);
    
        //
        // prevCopy is the old value of Target. Returns the old value of Target
        // (just to demonstrate the 2nd pattern for which return type you can use)     
        //
        return &lt;FONT color=#ff0000&gt;prevCopy&lt;/FONT&gt;;
    }
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1225874" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>Weird side affect of the day:  #defines can be used in your .def file</title><link>http://blogs.msdn.com/doronh/archive/2006/11/02/weird-side-affect-of-the-day-defines-can-be-used-in-your-def-file.aspx</link><pubDate>Fri, 03 Nov 2006 00:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:937244</guid><dc:creator>doronh</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/doronh/comments/937244.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=937244</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=937244</wfw:comment><description>I found this one out the hard way today. I was experimenting with the KMDF loader driver (wdfldr.sys). I added the following &lt;FONT face="Courier new"&gt;#define&lt;/FONT&gt; to my sources file so that I could share code between wdfldr and another component and control some functionality based on who was including the file &lt;PRE&gt;sources:
    TARGETNAME=wdfldr
    TARGETTYPE=EXPORT_DRIVER

    C_DEFINES=$(C_DEFINES) -DWDFLDR=1

    [...]
&lt;/PRE&gt;I then compiled my test driver (wdfrawbusenumtest.sys), but it failed to load! I was getting a code 39 (which meant Windows could not load my driver). I previously &lt;A href="http://blogs.msdn.com/doronh/archive/2006/03/13/550844.aspx" target=blank mce_href="http://blogs.msdn.com/doronh/archive/2006/03/13/550844.aspx"&gt;wrote&lt;/A&gt; on how to debug a missing export at runtime, and I tried to use that technique. It told me that "KeGetCurrentIrql" was unresolved, but that is not possible since hal.dll has exported this function since NT 3.1. It finally occurred to me look at the imports for my test driver to see if there was anything weird. Here is what I saw: &lt;PRE&gt;    link /dump /imports WdfRawBusEnumTest.sys

    [...]
        HAL.dll
                     18014 Import Address Table
                     1C290 Import Name Table
                         0 time date stamp
                         0 Index of first forwarder reference

                       4C KeGetCurrentIrql

        1.SYS
                     18000 Import Address Table
                     1C27C Import Name Table
                         0 time date stamp
                         0 Index of first forwarder reference

                        7 WdfVersionBind
                        9 WdfVersionUnbind
&lt;/PRE&gt;Huh? 1.sys? Where did that come from? I went back and checked the src file (which when compiled becomes the def file) and there were no changes there. This is what the def file looks like: &lt;PRE&gt;wdfldr.src:
    NAME WDFLDR.SYS

    EXPORTS
        WdfVersionBind
        WdfVersionUnbind
        [...]
&lt;/PRE&gt;Since I didn't change the def file, what was making the compiler think that the exports should resolve to 1.sys? I finally realized that my C_DEFINE of -DWDFDLR=1 was the culprit. When wdfldr.src was being built into wdfldr.def, my define changed &lt;FONT face="courier new"&gt;NAME WDFLDR.SYS&lt;/FONT&gt; into &lt;FONT face="courier new"&gt;NAME 1.SYS&lt;/FONT&gt;. Little did I know that the C preprocessor was used when compiling the src file. To fix the problem, all I needed to do was change the define to something else, &lt;FONT face="courier new"&gt;C_DEFINES=$(C_DEFINES) -D_WDFLDR_=1&lt;/FONT&gt;, and then update my shared headers to use the new define.&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=937244" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>The override keyword can be used in C++ afterall (redux on refactoring virtual functions)</title><link>http://blogs.msdn.com/doronh/archive/2006/10/27/the-override-keyword-can-be-used-in-c-afterall.aspx</link><pubDate>Fri, 27 Oct 2006 23:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:884065</guid><dc:creator>doronh</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/doronh/comments/884065.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=884065</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=884065</wfw:comment><description>&lt;P&gt;Yesterday I &lt;A class="" href="http://blogs.msdn.com/doronh/archive/2006/10/26/how-i-refactor-virtual-functions.aspx" target=_blank mce_href="http://blogs.msdn.com/doronh/archive/2006/10/26/how-i-refactor-virtual-functions.aspx"&gt;wrote &lt;/A&gt;about the two methods I use to refactor a virtual function and make sure that I find all of the derived implementations.&amp;nbsp; In the entry I lamented that I would like to have the C# keyword override implemented in C++.&amp;nbsp; Well, apparently it is (at least in the Microsoft compiler)!&amp;nbsp; Check it out for yourself on &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/41w3sh1c.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/41w3sh1c.aspx"&gt;MSDN&lt;/A&gt;.&amp;nbsp; Now since it was not a part of the language from the start, you cannot assume that when you change the super class's virtual function signature that the derived classes will not compile, but if you use the override&amp;nbsp;&lt;STRIKE&gt;keyboard &lt;/STRIKE&gt;keyword during development when you initially implement the derived classes, it will flag the mistake where you are creating a new virtual function instead of overriding an existing one.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;So, let's take yesterday's classes and use the override keyword &lt;PRE&gt;    class Base { public: virtual void Foo() {}; };

    class Derived : public Base { public: virtual void Foo() &lt;B&gt;&lt;FONT color=red&gt;override&lt;/B&gt;&lt;/FONT&gt; {}; };
&lt;/PRE&gt;Now when we change void Base::Foo() to void Foo(Bar* PBar), we get the following compiler error &lt;PRE&gt;    main.cpp(6) : error C3668: 'Derived::Foo' : method with override specifier 'override' did not override any base class methods
&lt;/PRE&gt;This is much better then the previous situation, although it is not as good as in the C# environment. If you forget to add the override keyword, you can still encounter the mistake of creating a new virtual function instead, but this is better then nothing!&lt;PRE&gt;&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=884065" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>How I refactor virtual functions</title><link>http://blogs.msdn.com/doronh/archive/2006/10/26/how-i-refactor-virtual-functions.aspx</link><pubDate>Fri, 27 Oct 2006 01:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:877468</guid><dc:creator>doronh</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/doronh/comments/877468.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=877468</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=877468</wfw:comment><description>As with many development projects, I had to refactor some code in KMDF. This refactor involved changing the signature of a virtual function to take additional parameters. The problem I faced is that C++ makes no distinction between declaring a new virtual function and a virtual function which overrides a base class (C# does not have this problem because you are required to use the &lt;FONT face="courier new"&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ebca9ah3.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/ebca9ah3.aspx"&gt;override&lt;/A&gt;&lt;/FONT&gt; keyword when overriding a base class virtual). The problem for me was finding all of the derivations across the entire code base.Before I explain into how I found all of the derivations, I want to explain the issue in more detail. Let's take the following classes: &lt;PRE&gt;    class Base { public: virtual void Foo(); }

    class Derived : public Base { public: virtual void Foo(); }
&lt;/PRE&gt;Derived::Foo() is a override of Base::Foo() and will be invoked correctly if using a Derived object pointer as a Base object pointer. The debugger confirms this &lt;PRE&gt;    0:000&amp;gt; dt der
    Local var @ 0xcfe60 Type Derived
       +0x000 __VFN_table : &lt;FONT color=red&gt;0x008e10cc &lt;/FONT&gt;

    0:000&amp;gt; dps  &lt;FONT color=red&gt;0x008e10cc&lt;/FONT&gt;  l1
    008e10cc  008e11f0 testsize!Derived::Foo
&lt;/PRE&gt;But let's say I want to change the signature of Foo to take a Bar* and forgot to change Derived &lt;PRE&gt;    class Base { public: virtual void Foo(Bar* PBar); }

    class Derived : public Base { public: virtual void Foo(); }
&lt;/PRE&gt;Now Derived::Foo() is not a derivation of Base::Foo, but it's new and very own virtual function (e.g. the vtable for the Derived object will have 2 slots instead of just one) as we can see from the debuggerA &lt;PRE&gt;    0:000&amp;gt; dt der
    Local var @ 0x13fd38 Type Derived
       +0x000 __VFN_table : &lt;FONT color=red&gt;0x001810cc&lt;/FONT&gt;

    Exact matches:
    0:000&amp;gt; dps &lt;FONT color=red&gt;0x001810cc&lt;/FONT&gt;  l2
    001810cc  00181250 testsize!Base::Foo
    001810d0  00181200 testsize!Derived::Foo
&lt;/PRE&gt;As you can see, the vtable accidentally grew when I changed Base::Foo's signature and unfortunately the compiler doesn't care. Even worse, the program will run and probably limp along with the error showing up as odd or unexplainable behavior. So, the challenge is to make the compiler find all of the derivations for you so you can fix them up. I use two techniques to make the compiler do the work for me. 
&lt;P&gt;The first technique is to change the return type of the function to refactor without changing the parameters themselves and then recompiling the project. This works because the rules for C++ name overloading allow for differences in the function's parameters, but if the parameters are the same, you cannot differentiate on return type. The error will be emitted in the class's implementation. So if you change Base::Foo to &lt;FONT face="courier new"&gt;ULONG Foo();&lt;/FONT&gt;, the compiler will give you an error like this for every derived class which overrides Base::Foo() &lt;PRE&gt;    main.cpp(7) : error C2555: 'Derived::Foo': overriding virtual function return type differs and is not covariant from 'Base::Foo'."
&lt;/PRE&gt;After flagging each derived class, you can change the change the return type back and then change the parameters. 
&lt;P&gt;The second technique is to change the Base::Foo() to a pure virtual fuction in addition to changing the parameters. So, now Base::Foo() is declared as &lt;FONT face="courier new"&gt;void Foo(Bar* PBar) =0;&lt;/FONT&gt;. Now for every class which is not an abstract base class itself, the compiler will emit an error wherever you try to instantiate the class, getting an error like this &lt;PRE&gt;    main.cpp(11) : error C2259: 'Derived' : cannot instantiate abstract class
&lt;/PRE&gt;The advantage of this technique is that you don't have to make 2 passes over the code to find and then alter the derived classes. A problem with this technique is that you are only notified of the problem where you try to &lt;I&gt;instantiate&lt;/I&gt; the&amp;nbsp;class instead of wheree you &lt;I&gt;implement or declare&lt;/I&gt; the class. Another problem is that if you are implementing a derivation in a class which itself is still an abstract base class, you push the compiler error into the second derived class, obscuring where the real error is occurring. 
&lt;P&gt;I personally prefer the first method because it is less error prone and I like to see compiler errors at the site of the implementation and not at the site of its use. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=877468" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>Hindsight is 20/20, EvtDriverUnload should have not been in KMDF</title><link>http://blogs.msdn.com/doronh/archive/2006/10/23/hindsight-is-20-20-evtdriverunload-should-have-not-been-in-kmdf.aspx</link><pubDate>Tue, 24 Oct 2006 01:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:865898</guid><dc:creator>doronh</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/doronh/comments/865898.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=865898</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=865898</wfw:comment><description>The KMDF model evolved over the entire development cycle. It was refined and refactored multiple times. A lot of WDM abstractions leak through the to the KMDF model. These leaks usually forced their way into the model because without them, KMDF cannot function properly. Other abstraction leaks were just design decisions that were not updated or removed as KMDF evolved through its v1.0 development cycle. 
&lt;P&gt;One abstraction that should have been refactored away but was not is the EvtDriverUnload routine. Our initial thought was that since the KMDF driver must implement a DriverEntry routine, an optional driver unload routine should also be a part of the model. The problem is that if &lt;FONT face="courier new"&gt;DriverEntry()&lt;/FONT&gt; returns !NT_SUCCESS, the WDM &lt;FONT face="courier new"&gt;DriverUnload&lt;/FONT&gt; (and hence &lt;FONT face="courier new"&gt;EvtDriverUnload&lt;/FONT&gt;) is not called. If you created global resources in DriverEntry and cleaned them up in &lt;FONT face="courier new"&gt;(Evt)DriverUnload&lt;/FONT&gt;, they would not be cleaned up becuase the unload routine would never be called. Normally drivers do not create such global data, so we (the KMDF team) didn't realize that this design issue was a problem. 
&lt;P&gt;There is an easy fix though that we have been advocating. Instead of putting your cleanup code in EvtDriverUnload, put all cleanup code in the &lt;FONT face="courier new"&gt;EvtObjectCleanup&lt;/FONT&gt; routine in the object attributes for the WDFDRIVER you create when calling &lt;FONT face="courier new"&gt;WdfDriverCreate()&lt;/FONT&gt;. The cleanup routine is guaranteed to be called in both cases (&lt;FONT face="courier new"&gt;DriverEntry()&lt;/FONT&gt; returning NT_SUCCESS() or !NT_SUCCESS()) once the WDFDRIVER has been created successfully. Note that important restriction, &lt;FONT face="courier new"&gt;WdfDriverCreate()&lt;/FONT&gt; must return success for this pattern to work! That means that the allocation and initialization of all global resources should occur &lt;I&gt;after&lt;/I&gt; &lt;FONT face="courier new"&gt;WdfDriverCreate()&lt;/FONT&gt; has been called. 
&lt;P&gt;In hindsight we should have never had a &lt;FONT face="courier new"&gt;EvtDriverUnload&lt;/FONT&gt; and should have had the WDFDRIVER's cleanup routine be the driver unload equivalent. Two things affected our decision to not make this change. First, we didn't realize the pattern was busted until late in the development process. By the time we did realize it, there were too many drivers in the wild and under developement to make such a significant change. Second, while EvtDriverUnload was created when KMDF development was first started, the standardized cleanup routine for each object was not introduced until much later. If both concepts were implemented at the same time in the development cycle, the unload routine would have been eliminated&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=865898" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/KMDF/default.aspx">KMDF</category><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>Annotating fall through case statements in a switch</title><link>http://blogs.msdn.com/doronh/archive/2006/10/20/annotating-fall-through-case-statements-in-a-switch.aspx</link><pubDate>Fri, 20 Oct 2006 19:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:846928</guid><dc:creator>doronh</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/doronh/comments/846928.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=846928</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=846928</wfw:comment><description>Accidental fall throughs in a &lt;FONT face="courier new"&gt;switch&lt;/FONT&gt; statement can lead to some nasty bugs. I have used the following banner for quite a long time to indicate that the fall through is &lt;I&gt;intentional&lt;/I&gt; and not an oversite (this banner is also a part of the KMDF coding guidelines). It has definitely helped me debug coding mistakes over the years. &lt;PRE&gt;    case IRP_MJ_DEVICE_CONTROL:
    case IRP_MJ_INTERNAL_DEVICE_CONTROL:
        //    ||  ||  Fall through  ||   ||
        //    \/  \/                \/   \/
    default:
        return NULL;
    }
&lt;/PRE&gt;While the banner is certainly human readable, it is not apparent to static analysis tools that the fall through was intentional. Today I discovered that there is a SAL annotation, &lt;FONT face="courier new"&gt;__fallthrough&lt;/FONT&gt;, which can indicate the intentional fall through. This means you can annotate the code and tools like PreFAST and PreFAST for Drivers can better understand and analyze the code. I have not yet decided if I want to use the annotation by itself without the current banner or addition to my current banner. I am leaning towards just using the annotation though. &lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=846928" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>Using ntintsafe.h is a great idea, but I don't know how readable the results are</title><link>http://blogs.msdn.com/doronh/archive/2006/10/19/using-ntintsafe-h-is-a-great-idea-but-i-don-t-know-how-readable-the-results-are.aspx</link><pubDate>Fri, 20 Oct 2006 03:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:846866</guid><dc:creator>doronh</dc:creator><slash:comments>13</slash:comments><comments>http://blogs.msdn.com/doronh/comments/846866.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=846866</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=846866</wfw:comment><description>The addition of ntintsafe.h for detecting integer overflow/underflow is a great addition to the WDK. It unifies how everyone detects these math errors, leading to common code that anyone can pickup and see what it does...BUT, I have found it does have a "tax." What is actually being computed can be become unclear! For instance, let's take this sample before we convert it to detect any math errors: &lt;PRE&gt;    USHORT cbImageNameLength;

    cbImageNameLength = ((USHORT) wcslen(wsImageName)) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
&lt;/PRE&gt;It is relatively straightforward and clear (depends on the viewer I guess) that we are computing the number of bytes to wsImageName requires. Here is the safe (and &lt;I&gt;longer!&lt;/I&gt;) version of the unsafe computation: &lt;PRE&gt;    USHORT cbImageNameLength;
    NTSTATUS status;

    do {
        status = RtlSizeTToUShort(wcslen(wsImageName), &amp;amp;cbImageNameLength);
        if (!NT_SUCCESS(status)) {
            break;
        }

        status = RtlUShortMult(cbImageNameLength, sizeof(WCHAR), &amp;amp;cbImageNameLength);
        if (!NT_SUCCESS(status)) {
            break;
        }

        status = RtlUShortAdd(cbImageNameLength, sizeof(UNICODE_NULL), &amp;amp;cbImageNameLength);
        if (!NT_SUCCESS(status)) {
            break;
        }

        // cbImageNameLength has now been computed...
    } while (FALSE);
&lt;/PRE&gt;Needless to say, that is not the most transparent code I have read or written. I certainly would not go back to the unsafe vesion and I cannot use safeint object which throws execptions on error because this code runs in the kernel. The only remedy I could think of is to create a comment at the top of the block which contains the plain version. (This rule is in the KMDF coding style guidelines.) As a result, the final source would look like this: &lt;PRE&gt;        //
        // cbImageNameLength = ((USHORT) wcslen(wsImageName)) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
        //
        status = RtlSizeTToUShort(wcslen(wsImageName), &amp;amp;cbImageNameLength);
        [...]
&lt;/PRE&gt;I think this is a decent tradeoff between correctness and readability. Another change you could make is to add begin/end comments around the entire computation block to further clarify the scope of which calls belong to which overall computation.&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=846866" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category><category domain="http://blogs.msdn.com/doronh/archive/tags/WDM/default.aspx">WDM</category></item><item><title>Apple's Secure Coding Guide</title><link>http://blogs.msdn.com/doronh/archive/2006/07/24/675304.aspx</link><pubDate>Mon, 24 Jul 2006 18:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:675304</guid><dc:creator>doronh</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/doronh/comments/675304.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=675304</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=675304</wfw:comment><description>While I don't write apps or drivers for the Macintosh, some of you out there probably do.&amp;nbsp; If you have not already seen it, they posted a &lt;A href="http://developer.apple.com/documentation/Security/Conceptual/SecureCodingGuide/index.html"&gt;Secure Coding Guide &lt;/A&gt;(&lt;A href="http://developer.apple.com/documentation/Security/Conceptual/SecureCodingGuide/SecureCodingGuide.pdf"&gt;PDF&lt;/A&gt;) which is focused on OS X, but has generic recommendations as well.&amp;nbsp; I just started reading it, so I don't have much of an opinion about it yet.&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=675304" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>Not a big fan of #ifdef or #ifndef</title><link>http://blogs.msdn.com/doronh/archive/2006/06/01/613925.aspx</link><pubDate>Fri, 02 Jun 2006 07:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:613925</guid><dc:creator>doronh</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/doronh/comments/613925.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=613925</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=613925</wfw:comment><description>&lt;p&gt;I am not a big fan of the C/C++ preprocessor directives
&lt;font face="courier new"&gt;#ifdef&lt;/FONT&gt;
or
&lt;font face="courier new"&gt;#ifndef&lt;/FONT&gt;.
I am not denying that they certainly have their place and usage in the language.
I'll first write about where I think they &lt;i&gt;are&lt;/i&gt; useful and then about the situations
where I feel they are not.
&lt;font face="courier new"&gt;#ifndef&lt;/FONT&gt; is very useful for preventing multiple
inclusions of a header which will cause redefinition errors.

&lt;pre&gt;
#ifndef __FOO_H__ // only proceed if the token is not yet defined
#define __FOO_H__ // define the token so that subsequent includes have it defined

[...contents of the header...]

#endif // __FOO_H__, end for #ifndef statement
&lt;/PRE&gt;

&lt;p&gt;
Of course, you can use
&lt;font face="courier new"&gt;#pragma once&lt;/FONT&gt; to do the same thing, but that is a
Microsoft specific extension to the language so not everyone will use it.  This
usage is error prone though.  I can't count the number of times that I copied one
header to create another header in the same project and forgot to change the
&lt;font face="courier new"&gt;#ifndef &lt;I&gt;token&lt;/i&gt;&lt;/FONT&gt; to a new &lt;I&gt;token&lt;/I&gt; and couldn't
figure out why my new header wasn't being evaluated properly.

&lt;p&gt;&lt;font face="courier new"&gt;#ifdef&lt;/FONT&gt; is useful in a header to switch between
ANSI and wide versions of the function, such as this example from
&lt;font face="courier new"&gt;winbase.h&lt;/FONT&gt;:

&lt;pre&gt;
#ifdef UNICODE
#define CreateFile  CreateFileW
#else
#define CreateFile  CreateFileA
#endif // !UNICODE
&lt;/PRE&gt;

&lt;P&gt;Now, the reason I don't like these 2 directives is that they behave differently
then
&lt;font face="courier new"&gt;#if &lt;i&gt;token&lt;/i&gt;&lt;/FONT&gt;
or
&lt;font face="courier new"&gt;#if !&lt;i&gt;token&lt;/i&gt;&lt;/FONT&gt;.
&lt;font face="courier new"&gt;#if &lt;i&gt;token&lt;/i&gt;&lt;/FONT&gt; evaluates the value of
&lt;font face="courier new"&gt;&lt;i&gt;token&lt;/i&gt;&lt;/FONT&gt;.
If
&lt;font face="courier new"&gt;&lt;i&gt;token&lt;/i&gt;&lt;/FONT&gt; is not defined, it defaults to zero and the
&lt;font face="courier new"&gt;#if &lt;i&gt;token&lt;/i&gt;&lt;/FONT&gt; phrases evaluates to zero.  On the other hand,
&lt;font face="courier new"&gt;#ifdef &lt;i&gt;token&lt;/i&gt;&lt;/FONT&gt; evaluates to &lt;i&gt;token&lt;/I&gt; to see if it is
&lt;b&gt;defined&lt;/B&gt;, regardless of the value of
&lt;font face="courier new"&gt;&lt;i&gt;token&lt;/i&gt;&lt;/FONT&gt;.  That means that the following code

&lt;PRE&gt;
#define FOO 0x0

#ifdef FOO
printf("FOO!");
#else
printf("NOT FOO!");
#endif
&lt;/PRE&gt;

will print out "FOO!" even though FOO evaluates to zero.  As I have written previously
in my blog and in the newsgroups, I am big on maintainance of the code I write
because the code I write will have to be maintained for years and its connection
to me will eventually be lost by the developer who inherits it.  What I don't like
about
&lt;font face="courier new"&gt;#ifdef/ifndef&lt;/FONT&gt;
in a source file (vs the header file examples above) is that at first glance, I
mentally evaluate a
&lt;font face="courier new"&gt;#ifdef&lt;/FONT&gt;
as a
&lt;font face="courier new"&gt;#if&lt;/FONT&gt;
and more often then not, pick the wrong result when reviewing the code.  Furthermore,
everytime I see
&lt;font face="courier new"&gt;#ifndef&lt;/FONT&gt;
I need to spend a minute or two staring at the entire statement to figure out
what is going on, it is not immediately apparent to me what it is doing.  Anytime
I have to stare at something to figure out what it does, it is an indicator to me
that others will probably do the same and it will eventually be a problem spot
in the code in the future.

&lt;P&gt;A lot of you may not agree with me and I am fine with that ;).  Please let me
know why though.&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=613925" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category></item><item><title>How to break in at the call site that invokes the break point</title><link>http://blogs.msdn.com/doronh/archive/2006/05/08/592735.aspx</link><pubDate>Tue, 09 May 2006 01:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:592735</guid><dc:creator>doronh</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/doronh/comments/592735.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=592735</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=592735</wfw:comment><description>&lt;P&gt;I think everyone at some point in time wants to embed a break point in there code, whether it be for debugging purposes, path tracing, or detecting edge conditions that have not yet been tested. When I hit a break point, I would prefer that the debugger break in at the call frame which needs the break point and &lt;I&gt;not&lt;/I&gt; another function which implements the break point. I have seen two different patterns over the years.&lt;/P&gt;
&lt;P&gt;The first pattern is to call &lt;FONT face="courier new"&gt;DbgBreakPoint()&lt;/FONT&gt;. This works well enough. It is portable across different processor architectures so you don't have to worry about new platforms, but it has one major problem. When you break into the debugger, you are in the wrong call site! You end up in the middle of &lt;FONT face="courier new"&gt;DbgBreakPoint()&lt;/FONT&gt; itself and not the caller. You can use the &lt;FONT face="courier new"&gt;gu&lt;/FONT&gt; command, but that requires typing ;).&lt;/P&gt;
&lt;P&gt;The second pattern is to create a #define for some inline assembly, something akin to:&lt;/P&gt;&lt;PRE&gt;#define TRAP __asm { int 3 }
&lt;/PRE&gt;
&lt;P&gt;This satisfies my requirement that the point of execution when we stop is in the function of interest, but this solution is platform specific. You would need enough knowledge per supported platform for this to work and that platform must support inline assembly (which x64 does not for our compilers). You could compromise and &lt;FONT face="courier new"&gt;#define TRAP&lt;/FONT&gt; to &lt;FONT face="courier new"&gt;DbgBreakPoint()&lt;/FONT&gt; for those platforms, but then you have a satisfactory solution on a subset of platforms.&lt;/P&gt;
&lt;P&gt;Enter the &lt;FONT face="courier new"&gt;__debugbreak()&lt;/FONT&gt; intrinsic that I just learned about this weekend from the OSR WinDBG mailing list (courtesy of Pavel A.) Yes, it is a Microsoft specific extension, but generating a break point is inheritly platform specific already. &lt;FONT face="courier new"&gt;__debugbreak()&lt;/FONT&gt; is the best of both patterns. You get platform independence &lt;B&gt;and&lt;/B&gt; when you break in to the debugger, you are sitting at the right call frame and not inside a system routine. That rocks in my book!&lt;/P&gt;
&lt;P&gt;PS: I don't know which version of the compiler this intrinsic was introduced, but it is used in the Server 2003 SP1 DDK, so I know it has been implemented for awhile.&lt;/P&gt;
&lt;P&gt;PPS:&amp;nbsp; I never call __debugbreak() in production code, and IMHO, neither should you.&amp;nbsp; To control this in a DDK build environment, I do the following&lt;/P&gt;&lt;PRE&gt;#if DBG
  #define TRAP() __debugbreak()
#else  // DBG
  #define TRAP()
#endif // DBG
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=592735" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category><category domain="http://blogs.msdn.com/doronh/archive/tags/WinDBG_2F00_KD+Fun/default.aspx">WinDBG/KD Fun</category></item><item><title>Avoiding #defines for constant data and using enums instead</title><link>http://blogs.msdn.com/doronh/archive/2006/03/27/562502.aspx</link><pubDate>Tue, 28 Mar 2006 03:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:562502</guid><dc:creator>doronh</dc:creator><slash:comments>26</slash:comments><comments>http://blogs.msdn.com/doronh/comments/562502.aspx</comments><wfw:commentRss>http://blogs.msdn.com/doronh/commentrss.aspx?PostID=562502</wfw:commentRss><wfw:comment>http://blogs.msdn.com/doronh/rsscomments.aspx?PostID=562502</wfw:comment><description>&lt;P&gt;I think that the C preprocessor is a very powerful tool, but I like to limit my use of #defines. I have already touched on this when i talked about why &lt;A href="/doronh/archive/2006/02/16/533933.aspx"&gt;I liked FORCEINLINE&lt;/A&gt; and I want to talk about it some more. I realize I can't eliminate the use of #defines throughout all of my code for various reasons, among them being:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;They can have unintended side affects. The classic example of this is #define MAX(a, b) (a &amp;gt;= b ? a : b) and invoking it with MAX(foo++, bar) such that foo++ is evaluated twice leading to a double increment. 
&lt;LI&gt;Other headers use them to enable/disable certain pieces of functionality or functions. 
&lt;LI&gt;They are the only way to wrap up other preprocessor macros like __FILE__ and __LINE__ to allow for easier logging without more pushing more typing onto the caller. 
&lt;LI&gt;They are the only way you can generate code on the fly in C (a poor man's C++ template if you will) 
&lt;LI&gt;They are the only way you can use the quotify (#) or concat (##) functions within the preprocessor &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The main reason I try to limit my usage of the preprocessor is that because it is a pure substitution, you generally don't have type information available to you when debugging the application or driver. A great example of this is constant numeric values within your application. You could do this to define values in a bit field:&lt;/P&gt;&lt;PRE&gt;#define OPTION_ONE   (0x00000001)
#define OPTION_TWO   (0x00000002)
#define OPTION_THREE (0x00000004)
&lt;/PRE&gt;
&lt;P&gt;but you will not be able to evaluate OPTION_ONE in the debugger because there is no OPTION_ONE symbol in the PDB. The preprocessor substituted OPTION_ONE with 0x0000001 before the linker was ever involved. To look up the value of OPTION_ONE you would have to open up a source file. Instead, I do the following when I have bit field values that I want to define and use within my app/driver: &lt;PRE&gt;#include &amp;lt;windows.h&amp;gt;

typedef enum _OPTION_FLAGS {
    OptionOne =   0x00000001,
    OptionTwo =   0x00000002,
    OptionThree = 0x00000004,
} OPTION_FLAGS;

typedef union _OPTIONS {
    ULONG Bits;

    // NOTE:  this is for debugging only, *always* use Bits in code
    struct {
        ULONG One : 1;   // OptionOne
        ULONG Two : 1;   // OptionTwo
        ULONG Three: 1;  // OptionThree
    } BitsByName;
} OPTIONS;

int _cdecl main(int argc, char *argv[])
{
    OPTIONS o;

    o.Bits = OptionTwo;

    return 0;
}
&lt;/PRE&gt;
&lt;P&gt;For now, let's ignore the fact that I can use protected or public to abstract how the values are set and read and that I am using an unnamed union. (Some folks feel that unnamed unions are unholy, but I find them very practical in this pattern.) There are 2 key concepts to what I am doing here: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;The enumeration remains in the symbols so you can dump it within the debugger [1]. Now you don't have to look up the value in a source file. 
&lt;LI&gt;By creating a union of the true value (Bits) [3] and a bit field of the value (BitsByName) [4] I can see what each bit means without having to look at the enum at all! This means that you can see the value without digging into the structure at all if you don't need to [2]. &lt;/LI&gt;&lt;/OL&gt;&lt;PRE&gt;I have broken into the debugger right before returning.

[1] 0:000&amp;gt; dt OptionsFlags
   OptionOne = 1
   OptionTwo = 2
   OptionThree= 4

[2] 0:000&amp;gt; dt o Bits
Local var @ 0x6ff78 Type Options
   +0x000 Bits : 2

[3] 0:000&amp;gt; dt o BitsByName.
Local var @ 0x6ff78 Type Options
   +0x000 BitsByName  :
      +0x000 One         : 0y0
      +0x000 Two         : 0y1
      +0x000 Three       : 0y0

[4] 0:000&amp;gt; dt o
Local var @ 0x6ff78 Type Options
   +0x000 Bits             : 2
   +0x000 BitsByName       : Options::&amp;lt;unnamed-tag&amp;gt;
&lt;/PRE&gt;

&lt;p&gt;&lt;b&gt;March 28, 2006:  Updated the enum and union definitions to be C compliant and match my style guidelines.&lt;/b&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=562502" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/doronh/archive/tags/Coding+Thoughts/default.aspx">Coding Thoughts</category><category domain="http://blogs.msdn.com/doronh/archive/tags/WinDBG_2F00_KD+Fun/default.aspx">WinDBG/KD Fun</category></item></channel></rss>