<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>www.benshoof.org/blog</title>
	<atom:link href="http://www.benshoof.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.benshoof.org/blog</link>
	<description></description>
	<lastBuildDate>Fri, 10 Aug 2012 20:11:06 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Castle Adventure</title>
		<link>http://www.benshoof.org/blog/castle-adventure/</link>
		<comments>http://www.benshoof.org/blog/castle-adventure/#comments</comments>
		<pubDate>Tue, 01 May 2012 18:00:42 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=781</guid>
		<description><![CDATA[Aye yo. Do you know this game? Doo doo doo Doooooo, Doo doo doo Doooooo, Doo doo doo Dooo doo doo doo Dooo doo doo doo Doooooo *beat*Doo doo doo Dooo doo doo doo Dooo doo Doo doo Dooooo. Castle Adventure, written in 1984, is one of the first computer games I ever played. It [...]]]></description>
				<content:encoded><![CDATA[<p>Aye yo. Do you know this game?</p>
<p class="imageContainer"><img src="http://www.benshoof.org/blog/wp-content/uploads/2012/05/castle_splash_screen.png" alt="" /><br />
<em>Doo doo doo Doooooo, Doo doo doo Doooooo, Doo doo doo Dooo doo doo doo Dooo doo doo doo Doooooo *beat*<br/>Doo doo doo Dooo doo doo doo Dooo doo Doo doo Dooooo.</em>
</p>
<p><a href="http://en.wikipedia.org/wiki/Castle_Adventure">Castle Adventure</a>, written in <a href="http://www.imdb.com/title/tt0062622/">1984</a>, is one of the first computer games I ever played. It had an impact. Written in BASIC and rendered in 40 by 25 characters of <a href="http://en.wikipedia.org/wiki/Code_page_437">IBM text</a>, Castle is one of the earliest DOS graphic adventure games and a precursor to all the great Sierra games I later loved. With 83 rooms, real-time monster fights, sound, two-word text commands and a simple goal of escape, it was intense. As a six year old I had the motor skills to move from room to room with the arrow keys, the street smarts to flee the approaching smiley faces and the pattern recognition to match the words &#8220;a&#8221; and &#8220;the&#8221; to my Berenstain Bears book, but the illiteracy to keep me from understanding any of the rest. I couldn&#8217;t read a single sentence or type a single command. The room descriptions were as much a mystery as where the game even came from. That last one is still a mystery; I&#8217;m imagining a single floppy disk with GAMES scrawled on it, passed around and copied into oblivion by America&#8217;s engineers with their home computers, forming a national sneaker-net whose demise Lyndon LaRouche still rails about.</p>
<p>Sadly, Castle hasn&#8217;t aged well. It&#8217;s not just because it&#8217;s a DOS game, or that it has no colors, or that its liberal spelling of RUBYS might lose you a dispute with your mom (it did), or even that it was written in BASIC. Castle was doomed from the start! The game&#8217;s timing is tethered to the CPU speed, so if your computer is too fast, which it has been since 1986, then the monsters are too fast and the game becomes unplayable. Even if you avoid monstrous conflicts, things aren&#8217;t the same. While amazingly even the latest 32-bit Windows can run the original game, Castle&#8217;s access to the internal PC speaker has been revoked, so you won&#8217;t be hearing sounds and music out of that device you forgot you don&#8217;t even have anymore. Even the graphics are off as the Windows command prompt fonts are only approximations of the original glyphs burned into video BIOS chips. Finally, as the command prompt has lost full screen ability, so too has Castle.</p>
<p>The standard solution to all of these problems nowadays is <a href="http://www.dosbox.com/">DOSBox</a>, the most <b>Hero</b>ic software project ever undertaken by humans. DOSBox plays Castle beautifully, emulates the environment perfectly and runs on all operating systems. BUT&#8230; there are some barriers to entry. First you have to know about DOSBox, then you have to configure DOSBox, which means you have to know how to do that, then you have to find the original Castle, then once you get DOSBox running and Castle loaded you have to know that it&#8217;s still too fast and that you need to crank down the emulation speed to a crawl, and so you need to know how to do that&#8230; all of which is fine for us faithful nerds but it&#8217;s a lot more complicated than when I was six.</p>
<p>There&#8217;s also an issue that emulation doesn&#8217;t address: exactly what is the correct speed to run Castle? I love this question because there&#8217;s only one man who knows the answer, and that&#8217;s the game&#8217;s author, Kevin Bales! There is only one machine that runs Castle at the correct speed, and that&#8217;s the machine Kevin Bales wrote it on. Since that machine&#8217;s identity is unknown, so is the correctness. But since it&#8217;s my childhood I have a pretty good notion as to what it should be, but that&#8217;s all it is, a notion locked in the brain.</p>
<p>So the problem of preserving Castle for the ages has been solved&#8230; but it&#8217;s not a one-click <a href="http://www.benshoof.org/blog/panic-button/">shiny-button</a> affair. And it involves some subjective technical issues intertwined with some serious childhood nostalgia. And hey you know what, those SAVE and LOAD commands in the game <b>never</b> worked! Also&#8230; <a href="http://www.benshoof.org/blog/introduction/">I can program computers</a>. Uh-oh.</p>
<p class="imageContainer"><a href="/apps/Castle.exe"><img title="The Angry Demon submits to your seduction... no, wait, that's Leisure Suit Larry IV: Larry Goes To Hell" src="http://www.benshoof.org/blog/wp-content/uploads/2012/05/castle_throne_room.png" alt="" /></a></p>
<p><b>So I rebuilt Castle from scratch as a native Windows program!</b> There, I&#8217;ve admitted it. Actually, I did this two years ago. I think it might have been a cry for help, but if that&#8217;s true then I didn&#8217;t do a very good job because I forgot to tell people. Have I learned <em>nothing</em> from Dr. Strangelove?</p>
<p>Castle Adventure is a standalone application that looks, acts, sounds and feels exactly like the original within a tolerance of <a href="http://www.benshoof.org/blog/about/">1 Benshoof</a>. It&#8217;s written to be immediately playable, portable and run on all Windows machines until the end of all humans. The game contains an image of the original IBM PC font for consistent display, the game speed is fixed instead of machine-dependent and the internal PC speaker sounds have been converted to WAV format so that they play as standard audio. I&#8217;ve also embedded the original data file, castle.ran, and use it for drawing the rooms and their descriptions so I can promise brick-by-brick and typo-by-typo accuracy. (Try not to challenge your mom on how to spell COORIDOR.)</p>
<p>As the source code to Castle has never been released, I had to reverse engineer all of the text commands and general behavior. I took everything I knew about the game and worked from there. I inspected all of the raw text embedded in the original program file for things I didn&#8217;t know, which I found, and I snooped through the source of an <a href="http://www.allegro.cc/depot/CastleAdventure/">Allegro graphical remake</a> to see if there were any rules I didn&#8217;t know, which there were. With all of that and a couple DOSBox windows open for quick testing, I believe I have every command handled identically to the original, but since it was just me giving it my best shot I can&#8217;t guarantee it. Try to find a mistake! In a few rare instances I exercised editorial privilege, but only where I believed there to be an unintentional oversight that detracted from the original&#8217;s spirit. These were extreme edge cases that not even diehards should notice, though I&#8217;d really be thrilled if anyone did.</p>
<p>Finally&#8230; fighting. There was some serious reverse engineering in the beginning to lay the groundwork&#8230; but then I just made up the rest until it was close enough. I found some surprising things about the original implementation, including what I consider a game changer, but the short version is that fighting is a very subjective experience in the original game. There are almost no visible indicators as to how a fight is going or how anyone is doing and it&#8217;s all tied up in how fast your CPU is and how a DOS program handles keyboard input and timing events. All of that was already completely different in my Windows version but even if it wasn&#8217;t it wouldn&#8217;t matter because a good deal of the fight logic is random anyway. So I just made some stuff up, and since no one knows how it really works, and it only &#8220;worked&#8221; on one machine ever, I think we&#8217;re good. It feels about right.</p>
<p>So please enjoy <a href="/apps/Castle.exe">Castle Adventure</a>, now for Microsoft Windows! You can toggle the display through three timely colors of Gray, Green and Amber because back then our monitor had a switch on the front that let me do exactly that. I figure it was for spicing up monochrome programs, and consarn it that&#8217;s exactly what I did when I got bored with Gray walls. There&#8217;s also a Full Screen mode which I recommend using on the largest TV you can find, preferably if said TV is mounted in a major American airport. Anything to stop the CNN. And please please enjoy the SAVE and LOAD commands, because they&#8217;ve waited 26 years to work.</p>
<p>If you do enjoy this, and at this point even if you don&#8217;t, I&#8217;d like to hear about it. I&#8217;m especially interested in any discrepancies you can find between this and the original. Unintentional ones will be quickly exterminated and credited. Oh, and I&#8217;m especially <em>especially</em> interested in hearing from you if you are Kevin Bales! Though I may need to verify your identity with a question that only you would know, such as &#8220;What room is the lamp in?&#8221;</p>
<p><b>PS:</b> Macintosh friends, theoretical Linux acquaintances, let me tell you how Castle runs on <a href="http://www.winehq.org/">WINE</a>: LIKE A WOLVERINE, and I&#8217;ve seen a wolverine so I know what I&#8217;m talking about.	</p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/apps/Castle.exe"><img src="/blog/files/castle.png" alt="" width="32" height="32" /></a></td>
<td><a href="/apps/Castle.exe">Castle.exe</a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/castle-adventure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pac-Man &#8211; The Video Game of the Board Game of the Video Game</title>
		<link>http://www.benshoof.org/blog/pac-man-the-video-game-of-the-board-game-of-the-video-game/</link>
		<comments>http://www.benshoof.org/blog/pac-man-the-video-game-of-the-board-game-of-the-video-game/#comments</comments>
		<pubDate>Mon, 25 Jul 2011 08:03:34 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=770</guid>
		<description><![CDATA[Did you know that in 1982 Milton Bradley made a Pac-Man board game? The box boasted brightly colored plastic Pac-Men, ghosts, marbles and &#8220;as much fun as the action-packed arcade game of the same name&#8221;. I played this game once in 4th grade. It sucked. I didn&#8217;t use language like that back then but I&#8217;m [...]]]></description>
				<content:encoded><![CDATA[<p>Did you know that in 1982 Milton Bradley made a <a href="http://www.boardgamegeek.com/boardgame/4907/pac-man-game">Pac-Man board game</a>?</p>
<p class="imageContainer"><img src="http://www.benshoof.org/blog/wp-content/uploads/2011/07/pacman_boardgame.jpg" alt="" /></p>
<p>The box boasted brightly colored plastic Pac-Men, ghosts, marbles and &#8220;as much fun as the action-packed arcade game of the same name&#8221;. I played this game once in 4th grade. It sucked. I didn&#8217;t use language like that back then but I&#8217;m pretty sure I said &#8220;Wow, this sucks&#8221;. The game was too confusing to play and the pieces were too crummy to play with. I&#8217;m not saying my childhood ended there, but between that and the Transformers movie it was a tough time to be a kid.</p>
<p>Two years ago I crossed paths with a copy of the game in a cabin on the <a href="http://en.wikipedia.org/wiki/Taku_River">Taku River</a>. Letting down my guard for the first time in almost two decades I gave it another shot. It&#8230; still kinda sucked, but by this time I&#8217;d developed a sense of irony about the surprising complexity of the rules and the questionable optimism of dice-based arcade action. It turns out that it&#8217;s pretty fun to decipher and debate the ambiguous and occasionally contradictory rules of an ancient children&#8217;s game, especially when it involves carefully quoting the aged inside of a cardboard lid like a constitutional scholar. I wondered how a child of the 80s was ever supposed to play this, what the rules would look like if they were written clearly, how many of them would be left once those that were non-applicable and canceled each other out were removed, how many would have to be inferred to fill in the gaps, and then what the first if statement might look like&#8230; at which point I knew I was doomed.</p>
<p>So I took the board game and made a video game version! In the spirit of <a href="http://www.youtube.com/watch?v=jMZtdLra24E">translating a book from English to Japanese and then back to English</a>, I present <a href="/apps/PacMan.exe">Pac-Man The Video Game Of The Board Game Of The Video Game</a>! Is it as much fun as the board game of the arcade game of the same name? I can’t promise that, don’t hold me to that.</p>
<p class="imageContainer"><a href="/apps/PacMan.exe"><img title="Pac-Man - The Video Game of the Board Game of the Video Game. I spent 15 minutes doctoring this screenshot to match the first one I casually took and then lost." src="http://www.benshoof.org/blog/wp-content/uploads/2011/07/pacman_screenshot.png" alt="" /></a></p>
<p><strong>Wait</strong>, It gets worse! It&#8217;s&#8230; um&#8230; a Windows program. Spider Solitaire, Minesweeper, I’m gunning for you! It’s got sound, music, computer players, instructions, and a full screen mode that screams &#8220;this is a poor use of a large screen&#8221;. The game is a standalone program that due to its low-tech nature runs on Windows 95, Windows 7, and everything in between. There&#8217;s nothing to install, it&#8217;s just a <a href="http://www.benshoof.org/blog/small-programs">small executable</a>. If your computer can play MIDI files then you&#8217;ll hear music, otherwise not so much.</p>
<p>Pac-Man is a two-to-four player game that can be played by humans and/or computer. Unlike the board game you can jump right into this version without knowing the rules. If you can make a move, it&#8217;s legal. This tautology cuts through a lot of the confusion. The game can be played with either a mouse or keyboard (and just between you and me, a Windows Media Center remote control) and if I&#8217;ve done my job then you should be able to quickly figure the controls on your own, though all of the details can be found in the Help menu under Instructions. It was so hard to condense all the rules into terse bullet points with consistent tense that I saved it for last, which was fitting since this was basically the challenge that led to this whole project. Sirs Milton &amp; Bradley: take look and take note!</p>
<p>To build this I&#8217;ve had to make some tough calls on the rules. Some of these were a result of interpretation, others were driven by implementation. If Pac-Man was the centerpiece of your family&#8217;s game night then you&#8217;re bound to find something to take issue with, but that&#8217;s okay because I don&#8217;t think that any two families have ever played this game by the same rules, and that&#8217;s not just because I don&#8217;t think that any more than two families have ever played this game, and that is indeed something I do very much think. Two families tops, <em>maybe</em> a broken home as well. I tried to balance original intent and probable typos against tradition and the inherent pursuit of fun in a game. The results are what I&#8217;d expect from an Antonin Scalia that cared that we&#8217;re trying to have a society here.</p>
<p>Pac-Man &#8211; The Video Game of the Board Game of the Video Game was written by me, though it clearly makes use of things I did not make and do not own. The Pac-Man and Ghost graphics were taken from the original Pac-Man game by Namco (1980), while the sound effects came from the 1982 Nintendo version. The music is from the <a href="http://www.youtube.com/watch?v=zZn9tX_yeKc">secret Pac-Man level</a> in Wolfenstein 3D by id Software (1992), but I don&#8217;t know who made the MIDI version that I used. Hopefully I&#8217;ll figure out where it came from so I can update this to give proper credit. I&#8217;m under the impression that translating id&#8217;s custom music format to MIDI is even harder than it sounds. Most importantly, I credit the inspiration to my recurring disappointment in Milton Bradley&#8217;s Pac-Man board game. I morbidly wondered what a video game of it would look like, and now I know.</p>
<p>So please enjoy Pac-Man &#8211; The Video Game of the Board Game of the Video Game. I&#8217;ve been slowly sowing the seeds of interest across the continent for two years now in anticipation of today&#8217;s big pay-off, and I&#8217;m feeling pretty good about it. So if you&#8217;re one of the many people who I&#8217;ve sat next to on an airplane while playing this on my laptop in the hopes that you&#8217;d ask me what the deal is, I really wish you&#8217;d have asked me what the deal is, and then told your friends upon landing, because both you and your friends would be way more excited about and aware of this release than you probably are now.</p>
<p>The best part about making a video game, as far as I can tell, is that it immediately gives you the audacity to act as an authority on all aspects of game design and construction as if you invented Doom. I intend to cash in on this, so brace yourself for an upcoming audaciously authoritative multi-part series on the making of Pac-Man TVGOTBGOTVG that will span the next twenty eight years. Or less, if we get more rainy Sundays.</p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/apps/PacMan.exe"><img src="/blog/files/pacman.png" alt="" width="32" height="32" /></a></td>
<td><a href="/apps/PacMan.exe">PacMan.exe</a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/pac-man-the-video-game-of-the-board-game-of-the-video-game/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Random MP3</title>
		<link>http://www.benshoof.org/blog/random-mp3/</link>
		<comments>http://www.benshoof.org/blog/random-mp3/#comments</comments>
		<pubDate>Mon, 22 Nov 2010 08:00:23 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=665</guid>
		<description><![CDATA[Now that we&#8217;ve got our Panic Button, we need something for it to do. I don&#8217;t know about you but I could use a chaser for all that user interface jive of yesterpost. Earlier I mentioned that one of the first momentous tasks I assigned my Panic Button was to play random songs. To do [...]]]></description>
				<content:encoded><![CDATA[<p>Now that we&#8217;ve got our <a href="http://www.benshoof.org/blog/panic-button/">Panic Button</a>, we need something for it to do. I don&#8217;t know about you but I could use a chaser for all that user interface jive of <a href="http://www.benshoof.org/blog/panic-button-part-iii/">yesterpost</a>.</p>
<p>Earlier I mentioned that one of the first momentous tasks I assigned my Panic Button was to play random songs. To do that I wrote a tiny program called RandomMP3. You give it a directory as a command line parameter and it scans for a random mp3 to launch with your system&#8217;s music player. For me that&#8217;s Winamp, for you it&#8217;s probably something else. There&#8217;s no user interface, no options, just fire and Fogerty.</p>
<p>You heard what I said.</p>
<p>The program is pretty simple, it recursively scans the target directory to build a list of all the filenames ending in .mp3 and then picks a random one from the list. The track gets played by calling <a href="http://msdn.microsoft.com/en-us/library/bb762153.aspx">ShellExecute()</a> so whatever program shows up when you double click an mp3 is who&#8217;s going to show up to play this one. Oh, you think I&#8217;m foolin&#8217;?</p>
<pre class="brush: wincpp;">
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    // get an argc / argv to play with. if there are no command line parameters, quit.
    int argc;
    WCHAR **argv = CommandLineToArgvW(GetCommandLine(), &amp;argc);
    if (argc == 1) return 0;

    // build a space delimited string from the command line parameters which will be
    //  the directory to search. the only reason for this step is to be forgiving if
    //  an unquoted path with spaces was given, in which case it's just rebuilding
    //  the original. this altruism won't catch everything but will catch most.
    //  if the caller was of good breeding and quoted the path then there's no issue.
    CString directory;
    for (int i = 1; i &lt; argc; i++)
    {
        if (i &gt; 1) directory += _T(&quot; &quot;);
        directory += argv[i];
    }

    // build a list of mp3 files in the directory
    CAtlArray&lt;CString&gt; files;
    BuildMP3FileList(directory, files);
    if (files.GetCount() == 0) return 0;

    // select a random mp3 from the list
    srand(GetTickCount());
    size_t randomNumber = ((size_t)rand()) % files.GetCount();

    // open the selected mp3 with whatever program the system is set to use.
    ShellExecute(NULL, _T(&quot;open&quot;), files[randomNumber], NULL, NULL, SW_SHOWNORMAL);
    return 0;
}
</pre>
<p>Now who&#8217;s the fool? Well, probably me since this whole mess is likely a one-liner in a modern scripting language, and that&#8217;s including the other half:</p>
<pre class="brush: wincpp;">
void BuildMP3FileList(CString directory, CAtlArray&lt;CString&gt;&amp; files)
{
    // ensure that the directory ends in a separator
    if (directory[directory.GetLength() - 1] != _T('\\'))
    {
        directory += _T(&quot;\\&quot;);
    }

    // kick off a listing of everything in the directory
    WIN32_FIND_DATA findData;
    HANDLE hFind = FindFirstFile(directory + _T(&quot;*&quot;), &amp;findData);
    if (hFind == INVALID_HANDLE_VALUE) return;

    // loop through each file and directory
    do
    {
        // skip the results &quot;.&quot; and &quot;..&quot;
        CString file = findData.cFileName;
        if (file == _T(&quot;.&quot;) || file == _T(&quot;..&quot;)) continue;

        // make a full path to the file
        file = directory + file;

        // if the file in question is a directory then recurse
        if ((findData.dwFileAttributes | FILE_ATTRIBUTE_DIRECTORY) == findData.dwFileAttributes)
        {
            BuildMP3FileList(file, files);
        }
        else
        {
            // if the file is an mp3, add it to the list
            CString extension = file.Right(4).MakeLower();
            if (extension == _T(&quot;.mp3&quot;))
            {
                files.Add(file);
            }
        }
    } while (FindNextFile(hFind, &amp;findData));
    FindClose(hFind);
}
</pre>
<p>Like I said in the beginning, <a href="http://www.benshoof.org/blog/introduction/">it&#8217;s comic relief for everyone else</a>. But if you <em>are</em> actually still into this clunky compiling thing then you&#8217;ve at least got a good example of a small statically linked program (8.5KB) that&#8217;s set up to use  <a href="http://www.benshoof.org/blog/minicrt/">Minicrt</a> and <a href="http://msdn.microsoft.com/en-us/library/awt7k7f5.aspx">ATL classes</a> (<a href="http://msdn.microsoft.com/en-us/library/5bzxfsea.aspx">CString</a>, <a href="http://msdn.microsoft.com/en-us/library/45dz8beb.aspx">CAtlArray</a>) harmoniously.</p>
<p>So enjoy the unpredictable outcomes of RandomMP3. I have no fucking idea what it will do. Incidentally, a slightly modified version of this program was responsible for generating all of the text in this article, including this statistically challenging explanation, but I&#8217;m sure you figured that out long ago. <span style="color: #ff0000;">KILL ALL HUMANS.</span></p>
<p>Next time I&#8217;ll drop a bomb that will launch me into immortality, civil litigation, and time permitting, your heart.</p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/apps/RandomMP3.exe"><img src="/blog/files/exe.png" alt="" width="32" height="32" /></a></td>
<td><a href="/apps/RandomMP3.exe">RandomMP3.exe</a></td>
</tr>
<tr>
<td><a href="/blog/files/RandomMP3.zip"><img src="/blog/files/zip.png" alt="" width="32" height="32" /></a></td>
<td><a href="/blog/files/RandomMP3.zip">RandomMP3.zip</a> (source code)</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/random-mp3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Panic Button &#8211; Part III</title>
		<link>http://www.benshoof.org/blog/panic-button-part-iii/</link>
		<comments>http://www.benshoof.org/blog/panic-button-part-iii/#comments</comments>
		<pubDate>Mon, 15 Nov 2010 07:00:05 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=590</guid>
		<description><![CDATA[*Chime* &#8220;Some walk by niiiiiight&#8230;&#8230; Suuuhhm fly by daa-e-aay&#8230;&#8221; Get it? Because Moonlighting also took a long time between new episodes due to blossoming movie careers and sexual tension? Oh, I think you know what I&#8217;m talking about. Extremely previously I made a veiled threat to talk about the Panic Button Control Panel user interface. [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.youtube.com/watch?v=MuQaE5zDn1Q"><em>*Chime*</em></a> &#8220;Some walk by niiiiiight&#8230;&#8230; Suuuhhm fly by daa-e-aay&#8230;&#8221;</p>
<p>Get it? Because Moonlighting <em>also</em> took a long time between new episodes due to blossoming movie careers and sexual tension? Oh, I think you know what I&#8217;m talking about.</p>
<p><strong>Extremely</strong> previously I made a <a href="http://www.benshoof.org/blog/panic-button-part-ii/">veiled threat</a> to talk about the Panic Button Control Panel user interface. Today I make good on those careless whispers by taking a tour through what it takes to give the Panic Button UI its look, pausing along the way to refrain from drawing tenuously bleak conclusions about Windows programming which would betray my otherwise upbeat tone.</p>
<p>The Panic Button UI is a single window and that window is a just regular ol&#8217; Windows dialog that&#8217;s been gussied up a bit. Below is the naked dialog in the Visual Studio designer alongside the run-time result. Everything in between is code and it&#8217;s that code we&#8217;ll be looking at. It was a lot of work but what&#8217;s the alternative, to skimp on the Gussie? I Fink-Nottle.</p>
<p class="imageContainer"><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/10/panic_designer.png" alt="" /><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/10/black_arrow.png" alt="" /><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/10/panic_real.png" alt="" /></p>
<p>Most of the effect above comes from the background, so I&#8217;ll begin there. The entire background, including the white space, is just an image. This image is displayed with what the designer calls a Picture control but is really the all-purpose Static control with the <a href="http://msdn.microsoft.com/en-us/library/bb760773.aspx">SS_BITMAP</a> style. I call it the cactus on the left. This is the simplest way to get a bitmap onto a dialog and normally wouldn&#8217;t be worth mentioning but there&#8217;s something here that breaks the textbook example: the image is really a GIF! There&#8217;s not a lot of programming environments left where using a GIF warrants an exclamation point, but there you go. Here&#8217;s the code that sets up the background, it&#8217;s called along with the rest of the program initialization upon receiving the <a href="http://msdn.microsoft.com/en-us/library/ms645428.aspx">WM_INITDIALOG </a>message:</p>
<pre class="brush: wincpp;">
static void SetBackground(HWND hwnd)
{
    HWND hwndBackground = GetDlgItem(hwnd, IDC_BACKGROUND);
    RECT rectClient;
    GetClientRect(hwnd, &amp;rectClient);
    MoveWindow(hwndBackground, 0, 0, rectClient.right, rectClient.bottom, FALSE);

    HBITMAP hBackgroundBitmap = CreateBitmapFromPicture(IDP_BACKGROUND, _T(&quot;GIF&quot;));
    SendDlgItemMessage(hwnd, IDC_BACKGROUND, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBackgroundBitmap);
}
</pre>
<p>First the background control is moved to the upper left corner and expanded to cover the entire dialog. This might seem like it should have been done in the designer, but it&#8217;s necessary to set the size at run-time because the image is set at run-time. Oh, and also Visual Studio will slit your throat if you try otherwise. The designer doesn&#8217;t allow you to set the size of Picture controls without images, which is inconvenient if you belong to the rare breed of ambitious that sets their sights beyond 22&#215;21 pixeled cacti. So, that&#8217;s too bad, but the designer does relent if you set the control&#8217;s <a href="http://msdn.microsoft.com/en-us/library/bb760773.aspx">SS_CENTERIMAGE</a> style, in which case you&#8217;re free to resize at will. That sounds okay in this case since centering an image within a control whose dimensions match is a no op, and though I&#8217;m not crazy about setting unnecessary properties for their unintuitive side effects, I&#8217;ve certainly done worse.</p>
<p>Here&#8217;s where that aforementioned throat puncturing comes in. Overlapping dialog controls render the designer unusable. Yikes. Mouse clicks cause the bottommost control to be selected, and since the background control is below every other control it would be impossible to select anything in the designer other than the background&#8230; which kinda defeats the purpose of a designer. <a href="http://www.virtualdub.org/blog/pivot/entry.php?id=234">This bug is the arch nemesis of Avery Lee</a>, the <strong>Hero</strong> to millions who authored <a href="http://virtualdub.org/">VirtualDub</a> and the <a href="https://connect.microsoft.com/VisualStudio/feedback/details/100052/dialog-editor-mouse-click-selects-bottom-control-when-controls-overlap">original bug report</a> that Microsoft closed as Won&#8217;t Fix. <a href="http://www.virtualdub.org/blog/pivot/entry.php?id=295">As it still exists in Visual Studio 2010</a>, someone has a 10 year birthday coming up&#8230;</p>
<p>So instead of dealing with all that I just size and position the background control at run-time with <a href="http://msdn.microsoft.com/en-us/library/ms633534.aspx">MoveWindow()</a>. That way it doesn&#8217;t matter where I plant that stupid cactus as it ends up in the right place. The last detail to take care of is making sure that the background control is indeed the bottommost control on the dialog. The controls&#8217; z-order is determined by the order they appear in the dialog resource, so all it takes is stepping out of the designer and directly editing the resource script file to place the background control first in the list.</p>
<p>Once the background control is in position and sized correctly it&#8217;s time to set the image. This is done with the <a href="http://msdn.microsoft.com/en-us/library/bb760782.aspx">STM_SETIMAGE</a> message which requires a bitmap, but cantankerous old man that I am, I&#8217;ve shown up instead with a GIF embedded in the program&#8217;s resource section. Unsurprising to anyone unfortunate enough to have endured through <a href="http://www.benshoof.org/blog/small-programs/">Small Programs</a>, I&#8217;ve done this for the typical old man reason of reducing program size. The raw bitmap of the background is 184KB versus the 38KB compressed GIF, and seems kinda silly to plunge into the madness of <a href="http://www.benshoof.org/blog/minicrt/">maintaining my own runtime library</a> while letting a single image quadruple the program&#8217;s size. But bitmaps are the currency Windows deals in, so something is needed to bridge the gap. If I may be so bold as to direct your attention to CreateBitmapFromPicture():</p>
<pre class="brush: wincpp;">
HBITMAP CreateBitmapFromPicture(UINT resourceID, LPCTSTR type)
{
    // load picture
    IPicture *picture = LoadPicture(resourceID, type);
    if (picture == NULL) return NULL;

    // get bitmap handle
    HBITMAP hPicture = NULL;
    picture-&gt;get_Handle((OLE_HANDLE *)&amp;hPicture);

    // copy picture to new bitmap
    HBITMAP hNewBitmap = (HBITMAP)CopyImage(hPicture, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG);

    // destroy picture
    picture-&gt;Release();

    // return new bitmap (must be destroyed by caller)
    return hNewBitmap;
}
</pre>
<p>No flash photography please. Despite the high comment-to-code ratio this function just raises more questions. I&#8217;ve got a GIF, I need a bitmap, <a href="http://www.youtube.com/watch?v=dp9ch-dAKk0#t=0m50s">now where in the wide wide world of gator</a> can I find myself an LZW decompressorator? According to the pioneer spirit of Windows programming I&#8217;d need to find or build a compatible image library and compile it in with my program. On the other hand, according to Oregon Trail most pioneers were just meandering bankers that died of dysentery. Like&#8230; all of them. So it&#8217;s a little surprising that Windows itself has been providing programs with the ability to read GIFs and JPEGs as far back as Windows 95! These formats can be loaded into the <a href="http://msdn.microsoft.com/en-us/library/ms680761.aspx">IPicture</a> interface through the very handy <a href="http://msdn.microsoft.com/en-us/library/ms693724.aspx">OleLoadPicture()</a> and you get a drawable bitmap to go to town with. I suppose that&#8217;s surprising because decoding compressed image formats invented elsewhere is a fairly high-level operation for the low-level API landscape. Also, let&#8217;s face it, it&#8217;s a pretty damn useful feature. Or&#8230; <em>OR&#8230;&#8230;</em> maybe the real reason it&#8217;s so surprising is that nowhere in the IPicture or OleLoadPicture() documentation did anyone include the words &#8220;GIF&#8221; or &#8220;JPEG&#8221;. Ha! Why would they?</p>
<p>Armed with the understated IPicture it&#8217;s easy to see how CreateBitmapFromPicture() gets its bitmap. The GIF gets loaded into an IPicture which provides a bitmap handle to its fancy innards, but since I don&#8217;t want lug around an IPicture I just use that handle to copy the image to a regular bitmap which I return after killing off the IPicture. This function and the rest in Picture.cpp are all about simplifying and encapsulating IPicture so that I can easily use compressed images in the Bitmap Belt that is Windows. I find IPicture awkward to draw with directly, and loading an image into it is&#8230; well, judge for yourself. That first line of CreateBitmapFromPicture() hides a lot of work. Here&#8217;s LoadPicture(), the dude that slurps the GIF out of the resource section and into an IPicture:</p>
<pre class="brush: wincpp;">
IPicture * LoadPicture(UINT resourceID, LPCTSTR type)
{
    // get pointer to resource data
    HINSTANCE hInstance = GetModuleHandle(NULL);
    HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(resourceID), type);
    DWORD resourceSize = SizeofResource(hInstance, hResource);
    void *resourceData = LockResource(LoadResource(hInstance, hResource));
    if (resourceSize == 0 || resourceData == NULL) return NULL;

    // copy resource data to memory that has a handle
    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, resourceSize);
    if (hGlobal == NULL) return NULL;
    void *globalBuffer = GlobalLock(hGlobal);
    if (globalBuffer == NULL)
    {
        GlobalFree(hGlobal);
        return NULL;
    }
    CopyMemory(globalBuffer, resourceData, resourceSize);
    GlobalUnlock(hGlobal);

    // create stream from copied resource data, then load picture from stream
    IStream *stream = NULL;
    IPicture *picture = NULL;
    if (CreateStreamOnHGlobal(hGlobal, FALSE, &amp;stream) == S_OK)
    {
        OleLoadPicture(stream, 0, FALSE, IID_IPicture, (void **)&amp;picture);
        stream-&gt;Release();
    }

    // cleanup
    GlobalFree(hGlobal);
    return picture;
}
</pre>
<p>Try not to stare directly at it. There&#8217;s really a lot less going on than the number of functions involved would suggest, it&#8217;s just that there are a lot of rules regarding how to get between these particular points A and B. The resource we&#8217;re loading, in this case a GIF, is already sitting in memory and the goal is to get that memory to OleLoadPicture() so that it can create an IPicture out of it. Seems simple enough but first we have to get a pointer to that GIF memory, which for resources requires the Find/Size/Lock/Load dance that makes up the first code block. Now we have the memory address but it turns out that OleLoadPicture() doesn&#8217;t want a raw memory address, it wants memory packaged as an <a href="http://msdn.microsoft.com/en-us/library/aa380034.aspx">IStream</a>. Fine. IStreams can be created from existing memory by <a href="http://msdn.microsoft.com/en-us/library/aa378980.aspx">CreateStreamOnHGlobal()</a>&#8230; which <em>also</em> doesn&#8217;t want a raw memory address. Instead, as the name says, it wants an HGLOBAL handle to a block of memory. Oh, what&#8217;s one more layer? So&#8230; we allocate a chunk of movable memory with <a href="http://msdn.microsoft.com/en-us/library/aa366574.aspx">GlobalAlloc()</a> to get our HGLOBAL, copy the GIF from its original address to the movable memory address retrieved by <a href="http://msdn.microsoft.com/en-us/library/aa366584.aspx">GlobalLock()</a>, use the HGLOBAL to wrap the movable memory in an IStream interface, and finally hand that off to OleLoadPicture(). Like I said, just try not to stare directly at it. Utility functions that hide the paperwork like this are great&#8230; until you foolishly return years later to write about them.</p>
<p>Now that the background is taken care of it&#8217;s time to get the text looking propah. In picture-talk, me want this:</p>
<p class="imageContainer"><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/11/panic_ugly_labels.png" alt="" /><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/10/black_arrow.png" alt="" /><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/10/panic_real.png" alt="" /></p>
<p>Seems like a reasonable request. I want to color the status text in the corner and make the background of the labels and the checkbox transparent so that the background image shows through instead of the dialog color. All of this can be done by handling the <a href="http://msdn.microsoft.com/en-us/library/bb787524.aspx">WM_CTLCOLORSTATIC</a> message:</p>
<pre class="brush: wincpp;">
static HBRUSH OnCtlColorStatic(HWND hwnd, HDC hdc, HWND hwndChild, int type)
{
    // initialize the HDC to the control's defaults
    FORWARD_WM_CTLCOLORSTATIC(hwnd, hdc, hwndChild, DefWindowProc);

    switch (GetDlgCtrlID(hwndChild))
    {
        // if XP theming is on then the transparent trick doesn't work for
        //  checkboxes, they turn out solid black instead. nothing is easy.
        //  since the checkbox happens to be on a solid white background
        //  i can just take the easy way out and set its background to white.
        case IDC_STARTUP:
            SetBkColor(hdc, RGB(255, 255, 255));
            return GetStockBrush(WHITE_BRUSH);

        // set the appropriate text color for the button status
        case IDC_BUTTONSTATUS:
            COLORREF textColor = (_hPanicButton == NULL) ?
                                  RGB(255, 0, 0) :
                                  _isButtonPushed ? RGB(255, 128, 0) : RGB(0, 128, 0);

            SetTextColor(hdc, textColor);
            break;
    }

    // make the static controls have transparent backgrounds by
    //  not painting the text background or the control background.
    SetBkMode(hdc, TRANSPARENT);
    return GetStockBrush(NULL_BRUSH);
}
</pre>
<p>The WM_CTLCOLORSTATIC message is sent to the dialog when Windows needs to draw one of its static controls or the checkbox, and the dialog&#8217;s response determines the colors that get used. This has always been a confusing area for me. First, I have to keep reminding myself that a control&#8217;s color isn&#8217;t a property of the control, but rather the answer to a question occasionally asked of its owner. It&#8217;s not the hardest concept in the world, but it&#8217;s unintuitive and whenever I have to remake its acquaintance my face does some contorting as I slowly re-accept the fact. Second, there&#8217;s the issue of just how many colors we&#8217;re dealing with here. I&#8217;m simple folk, so when I want to set the colors of a simple control I only care about two things: the text color and the background color. Being simple folk, as I purnt near is, I don&#8217;t even consider a nuance such as the background color of the text on the control vs the background color of the entire control. I went a very long time before connecting those dots, so I&#8217;m going to take a quick detour into a sample that might help clear this up:</p>
<p class="imageContainer"><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/11/wm_ctlcolorstatic_color_test.png" alt="" /></p>
<p>This is a <span style="color: #0000ff;">blue window</span> containing a single static control. The static’s <span style="color: #00ff00;">background color</span> is <span style="color: #00ff00;">green</span>, its <em><span style="color: #ff0000;">text background color</span></em> is <span style="color: #ff0000;">red</span>, and its <span style="color: #ffff00;">text color</span> is <span style="color: #ffff00;">yellow</span>. Here’s the WM_CTLCOLORSTATIC handler that produced this:</p>
<pre class="brush: wincpp;">
static HBRUSH greenBrush = CreateSolidBrush(RGB(0, 255, 0));

static HBRUSH OnCtlColorStatic(HWND hwnd, HDC hdc, HWND hwndChild, int type)
{
    SetTextColor(hdc, RGB(255, 255, 0));  // Yellow text
    SetBkColor(hdc, RGB(255, 0, 0));      // Red text background
    return greenBrush;                    // Green control background
}
</pre>
<p>Now that it&#8217;s clear how many colors are involved and how to set them, the Panic Button code starts to make sense. Setting the status text color is as simple as, well, setting its text color, and giving everybody a transparent background just means abstaining from drawing either of the background colors. The <a href="http://msdn.microsoft.com/en-us/library/dd162965.aspx">TRANSPARENT</a> background mode eliminates the text background color, and the <a href="http://blogs.msdn.com/b/oldnewthing/archive/2004/01/26/62991.aspx">NULL_BRUSH</a> takes care of the control background color. This works great for static controls and <em>used</em> to work for checkboxes and radio buttons&#8230; but the <a href="http://msdn.microsoft.com/en-us/library/bb773187.aspx">Visual Styles</a> introduced in Windows XP broke that behavior, much to my sadness. When Visual Styles are enabled, checkboxes and radio buttons treat responses to WM_CTLCONTROLSTATIC a lot differently. As far as I can tell these exact differences aren&#8217;t documented but it doesn&#8217;t matter because the short version is that none of them are helpful. In this case, returning the NULL_BRUSH causes this:</p>
<p class="imageContainer"><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/11/oh_you_know_fuck_you_too_windows.png" alt="" /></p>
<p>Blerg. At this point the right move is to just give up and acknowledge that the checkbox happens to be placed over a patch of solid white and simply set the checkbox&#8217;s background to white. As you can see in the above code, that&#8217;s exactly what I did. Giving up sucks, but I have no idea how to get a transparent background on a modern checkbox anymore without building my own from the ground up. Oh wait, yes I do, by <a href="http://www.joelonsoftware.com/articles/APIWar.html">writing web applications instead</a>. Dammit.</p>
<p>You may have noticed that the whole transparency issue could have been sidestepped by moving the &#8220;Run When Pushed:&#8221; text a few pixels to the left, giving this entire discussion an undercurrent of lunacy. You&#8217;re right! My original design for the dialog depended a lot more on transparency, and it was only after writing the code for it that the final design rolled around and made it unnecessary. Since I&#8217;d already taken the time to get transparency working I made sure there was still a tiny amount of overlap to show it off, even if it didn&#8217;t really matter. Oh what, like<em> you&#8217;re</em> so rational?</p>
<p>Irrationality is the perfect segway into the final piece of Panic Button UI hackery, a maddeningly tiny visual effect that was the hardest part of the whole damn program. So difficult, in fact, that it wasn&#8217;t until a year after the program was written that I got it added in. See for yourself:</p>
<p class="imageContainer"><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/11/panic_ugly_button.png" alt="" title="Look harder."/><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/10/black_arrow.png" alt="" /><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/10/panic_real.png" alt="" /></p>
<p>And yes, <a href="http://www.telegraph.co.uk/news/uknews/8027301/Segway-company-owner-dies-riding-two-wheeled-machine-off-cliff.html">segway</a>. As you can see, or at least as I sure <em>hope</em> you can see, the browse button on the left doesn&#8217;t look like the rest of the buttons. They&#8217;re rocking the new Visual Style theme and it&#8217;s going for the old Windows 95 look. It turns out that giving a button an image immediately disqualifies it from being drawn with Visual Styles. Blerg I say, I added that image to make things look better, not worse.</p>
<p>This is about the time when Windows programmers chime in and suggest <a href="http://msdn.microsoft.com/en-us/library/bb775501.aspx">creating an owner drawn control</a>, which is a polite way of telling you to <a href="http://www.youtube.com/watch?v=WOjSRoxc6mg">Get Stuffed</a>. I&#8217;ll save going into owner drawn buttons for another day, but if the goal is to make a control&#8217;s look and feel exactly match what Windows does elsewhere, then doing everything yourself is the least likely way to get there. The Panic Button program went a year with an ugly button because faced with the option of owner drawn I simply backed down. Also, at that point I was successfully using the Panic Button to rock out to <a href="http://www.funnyordie.com/videos/5784/table-dance-from-cheztam">Table Dance</a> every five minutes so my plate was pretty full.</p>
<p>Fortunately, a <strong>Hero</strong> named <a href="http://stackoverflow.com/users/19131/stephen-c-steel">Stephen C. Steel</a> (awesome name, he should front a detective agency) <a href="http://www.codeproject.com/KB/buttons/imagebuttonwithstyle.aspx">solved this exact problem</a> and just as fortuitously, I read about it. Stemmington (<a href="http://www.youtube.com/watch?v=xtQsqmOsf5w">that&#8217;s his detective name now</a>) pieced together that a compromise existed between living with ugly image buttons and going full pull with owner drawn buttons. If a button only has an image and no text then by cleverly handling <a href="http://msdn.microsoft.com/en-us/library/bb761847.aspx">NM_CUSTOMDRAW</a> notifications sent through <a href="http://msdn.microsoft.com/en-us/library/bb775583.aspx">WM_NOTIFY</a> you can have an image button with the fancy style! It&#8217;s a great compromise because the image drawing code is minimal and straight forward, you&#8217;re not on the hook for the responsibilities that owner drawing incurs, and when Visual Styles aren&#8217;t around the button gets drawn by Windows normally so it&#8217;s compatible with earlier versions. Man, Stephanie Zimbalist is going to have her hands full with this dude&#8230;</p>
<p>The only issue for me was that Steel&#8217;s code was caught up in the Microsoft Foundation Classes lifestyle, so I ported it into a set of simple Win32 functions and along the way fixed a minor bug or two. I packaged all of this up in ImageButtonXP.h/cpp and I think the only thing to show is how easy it is to drop in and use. Here&#8217;s the code that sets the button&#8217;s image and handles the NM_CUSTOMDRAW notifications:</p>
<pre class="brush: wincpp;">
static BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
    ...
    // set browse button's icon
    HICON hBrowseIcon = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_BROWSE),
                                         IMAGE_ICON, 0, 0, LR_SHARED);
    SetButtonIcon(hwnd, IDC_BROWSEBUTTON, hBrowseIcon);
    ...
}

// handles WM_NOTIFYs of NM_CUSTOMDRAW so that my stupid little browse button
//  can have its stupid little image *and* be themed.
// handling WM_NOTIFY from within a dialog is a little goofy. normally this
//  function would return an LRESULT, but since this is a dialog the return
//  value is whether or not the message was handled. if it was, then the
//  LRESULT needs to be set with SetWindowLong(DWL_MSGRESULT).
static BOOL OnNotify(HWND hwnd, int idCtrl, LPNMHDR pnmh)
{
    if (pnmh-&gt;code == NM_CUSTOMDRAW &amp;&amp; idCtrl == IDC_BROWSEBUTTON)
    {
        HWND hwndButton = GetDlgItem(hwnd, idCtrl);
        LONG result = HandleCustomDrawNotification(hwndButton, (LPNMCUSTOMDRAW)pnmh);
        SetWindowLong(hwnd, DWL_MSGRESULT, result);
        return TRUE; // message was handled
    }

    return FALSE; // message wasn't handled
}
</pre>
<p>Once you get past the WM_NOTIFY cruft you can see that all we&#8217;re doing is handing off NM_CUSTOMDRAW messages to HandleCustomDrawNotification(), where the ImageButtonXP magic happens, and returning the result. Purdy simple, and now when you see a themed image button you&#8217;ll know the score. Someone either did a ton of work or they borrowed a ton from someone else. Or they used .NET and moved on with their life. </p>
<p class="imageContainer"><img src="http://www.benshoof.org/blog/wp-content/uploads/2010/11/panic_real2.png" alt="" title="Sorry Bossman, but I can't keep on frontin' you free publicity forever. Crawl, Walk, Run, you know? Plus errbody will think I only listen to one song! Sister Nancy dear, step on up and prepare to be launched into a new stratosphere of e-celebrity!"/></p>
<p>So now you know what it takes to polish a desktop application to the level that can achieve a confirmed userbase of two. I wrote out &#8220;two&#8221; because it looks bigger than &#8220;2&#8243;, and this article is all about appearances.</p>
<p>This is the end of the tour. I hope it didn&#8217;t come off as a laundry list of birthing pains, the idea really is to be helpful. And the intent isn&#8217;t to complain, it&#8217;s to show the amount of effort and code involved in creating a laughably simple dialog box that has some color. I mean that literally, like colors other than gray.</p>
<p>I promised at the start to stay away from drawing conclusions from this walkabout, and I&#8217;ll try to stick to that. I will say that when I see a Windows program with dialog boxes that use images, colors, or basically anything that strikes me as interesting, intuitive or unique, I check out the language it&#8217;s written in and nine times out of ten Delphi is involved. I don&#8217;t know what that means, I&#8217;m not dealing with a particularly large sample, but it seems weird that you can so often guess a program&#8217;s language by how friendly or boring its interface is. I don&#8217;t know anything about Delphi or VCL, but if I had to guess I&#8217;d say they must be pretty easy to experiment with. My basic UI took work that couldn&#8217;t have been justified on a project with economic constraints. Admittedly, Panic Button is sitting pretty low on the abstraction pole. I was programming directly against the Windows API without third party libraries so things could only have gone up from there, but with the goals of low level device communication and lightweight portability there was really nowhere else to go. (56.5KB, if anyone was counting!)</p>
<p>I guess I do have a wild baseless conclusion, but I&#8217;ll keep it meek: Most Windows programs look boring because it takes a lot of code to try to look interesting with the Windows API, which means it takes a ton of code to succeed.</p>
<p>That&#8217;s the last we&#8217;ll hear about Panic Button. Oh wait, that&#8217;s not true, next time we&#8217;ll see a program you can run with it, but don&#8217;t worry because it will suck and there won&#8217;t be any pictures. I suppose if I have to stand trial in Hong Kong for product defamation you&#8217;d hear about that, or if I were to receive a windfall when Asia realizes that my program has been driving worldwide button sales since March, but these things could take a while. Until then, hold tight.</p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/apps/PanicButton.exe"><img src="/blog/files/panic_button.png" alt="" width="32" height="32" /></a></td>
<td><a href="/apps/PanicButton.exe">PanicButton.exe</a></td>
</tr>
<tr>
<td><a href="/blog/files/PanicButton.zip"><img src="/blog/files/zip.png" alt="" width="32" height="32" /></a></td>
<td><a href="/blog/files/PanicButton.zip">PanicButton.zip</a> (source code)</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/panic-button-part-iii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Panic Button &#8211; Part II</title>
		<link>http://www.benshoof.org/blog/panic-button-part-ii/</link>
		<comments>http://www.benshoof.org/blog/panic-button-part-ii/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 16:50:36 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=457</guid>
		<description><![CDATA[Today we&#8217;ll begin spelunking through the internals of the Panic Button Control Panel, which I&#8217;ll probably just be calling &#8220;the program&#8221; from here on out, so get with it. &#8220;It&#8221; being the program. Great start! The first thing that strikes me when looking at the source code is that a surprising amount of it is [...]]]></description>
				<content:encoded><![CDATA[<p>Today we&#8217;ll begin spelunking through the internals of the <a href="http://www.benshoof.org/blog/panic-button">Panic Button Control Panel</a>, which I&#8217;ll probably just be calling &#8220;the program&#8221; from here on out, so get with it. &#8220;It&#8221; being the program. Great start!</p>
<p>The first thing that strikes me when looking at the <a href="/blog/files/PanicButton.zip">source code</a> is that a surprising amount of it is dedicated to the seemingly simple user interface. Maybe that&#8217;s not so surprising to a jaded Windows programmer, but there&#8217;s so much material there that I&#8217;m just going to postpone discussing it until next time.</p>
<p>My second reaction is to the code that communicates with the Panic Button: it&#8217;s complicated! So complicated that it deserves an entire article defending my actions to the world. Let&#8217;s commence opening statements with how the Panic Button actually works.</p>
<p>The Panic Button is a USB keyboard. Yeah, I didn&#8217;t see that coming either! It&#8217;s just a keyboard! A fairly crappy keyboard, what with the one button and all, but still, it&#8217;s just a keyboard! Turns out it&#8217;s no big deal to have two keyboards plugged into your computer. Who knew? Pushing the button causes the device to generate the following keyboard sequence:</p>
<p><img class="aligncenter size-full wp-image-464" title="Panic Button Key Sequence" src="http://www.benshoof.org/blog/wp-content/uploads/2010/04/panic_button_key_sequence.png" alt="SHIFT + ALT + P" width="445" height="82" /></p>
<p>It&#8217;s kinda anticlimactic, but there&#8217;s a subtle engineering genius to this. I&#8217;ve never seen the real Panic Button software but my guess is that it simply registers the system-wide hotkey SHIFT + ALT + P with Windows to receive notifications when the button is pushed. No need for drivers, no need for USB programming, no need to invent a message protocol, no need to detect device connection and removal, it could just call <a href="http://msdn.microsoft.com/en-us/library/ms646309.aspx">RegisterHotKey()</a>, wait for <a href="http://msdn.microsoft.com/en-us/library/ms646279.aspx">WM_HOTKEY</a> messages, and let Windows handle the rest. I imagine the operation that produced the Panic Button to be on the cheaper end of things so avoiding all that complexity, and let&#8217;s face it, responsibility, is a wise move on its part. It would probably also simplify the hardware if an existing keyboard component could be used. I&#8217;m just guessing though, I haven&#8217;t taken mine apart.</p>
<p>When I figured this out I was disappointed. I was hoping to reverse engineer a tiny protocol and do a little USB programming, not call RegisterHotKey() and take a nap. So I looked for shortcomings to this approach, something that would justify a bit more work. All I could come up with was that the hotkey method isn&#8217;t enough to determine if the Panic Button was plugged in or not, and that it can&#8217;t discern between a legitimate Panic Button press and simply pressing SHIFT + ALT + P on the keyboard. The first issue is important to me because hardware programs should be able to tell you if the hardware they know so bloomin&#8217; much about is even plugged in. Plus, that part is fun to write. The second issue is just a matter of principle. Being able to Panic Button without a Panic Button is lame, and it cheapens something that&#8217;s already dangerously cheap as it is. With those minor grievances in mind&#8230;</p>
<p>The Panic Button program works by using the <a href="http://msdn.microsoft.com/en-us/library/ms645543.aspx">Raw Input API</a> introduced in Windows XP to detect when the Panic Button has been pushed. It does this by calling <a href="http://msdn.microsoft.com/en-us/library/ms645600.aspx">RegisterRawInputDevices()</a> in order to be notified about all keyboard input system-wide. Windows in turn sends a <a href="http://msdn.microsoft.com/en-us/library/ms645590.aspx">WM_INPUT</a> message for every keyboard event that occurs and the program inspects each message to see if the event is the &#8216;P&#8217; in the Panic Button key sequence. What makes WM_INPUT king is that it includes a field indicating the device that caused the event, and so the program only acts upon genuine Panic Button presses.</p>
<p>Registering for raw input notifications from all keyboards goes a little something exactly like this:</p>
<pre class="brush: wincpp;">
BOOL RegisterForRawInputFromKeyboards(HWND hwnd)
{
    RAWINPUTDEVICE rid;
    rid.usUsagePage = 0x01;     // Magic values for
    rid.usUsage     = 0x06;     //  HID Keyboards.
    rid.dwFlags     = RIDEV_INPUTSINK;
    rid.hwndTarget  = hwnd;

    return RegisterRawInputDevices(&amp;rid, 1, sizeof(rid));
}
</pre>
<p>The Raw Input API can be used for any input device, but we only care about keyboards and indicate that through the <a href="http://msdn.microsoft.com/en-us/library/ms645546.aspx">usage values</a>. The RIDEV_INPUTSINK flag causes the program to receive notifications even when it&#8217;s not in the foreground, which is perfect since it&#8217;s going to spend most of its life minimized in the system tray. This code and the rest that deals directly with the button lives in PanicButton.cpp, encapsulated in wordy functions with simple interfaces. Case in point, the following is called in response to WM_INPUT:</p>
<pre class="brush: wincpp;">
BOOL IsPanicButtonPushed(HANDLE hPanicButton, HRAWINPUT hRawInput)
{
    // get size of input data
    UINT bufferSize = 0;
    if (GetRawInputData(hRawInput, RID_INPUT, NULL, &amp;bufferSize, sizeof(RAWINPUTHEADER)) != 0)
        return FALSE;

    // allocate buffer for input data
    PRAWINPUT rawInput = (PRAWINPUT)malloc(bufferSize);

    // get input data and see if it's a panic button push
    BOOL isPushed = FALSE;
    if (GetRawInputData(hRawInput, RID_INPUT, rawInput, &amp;bufferSize, sizeof(RAWINPUTHEADER)) == bufferSize)
    {
        // is this keyboard input from the panic button?
        if (rawInput-&gt;header.hDevice == hPanicButton &amp;&amp; rawInput-&gt;header.dwType == RIM_TYPEKEYBOARD)
        {
            // is this a WM_SYSKEYUP of the P key?
            //  that's the message from the panic button
            //  that's only sent once per push.
            UINT message = rawInput-&gt;data.keyboard.Message;
            USHORT vkey = rawInput-&gt;data.keyboard.VKey;
            isPushed = (message == WM_SYSKEYUP &amp;&amp; vkey == 'P');
        }
    }

    free(rawInput);
    return isPushed;
}
</pre>
<p>There&#8217;s a lot of API noise in there but the goal of IsPanicButtonPushed() is simple; it answers the question &#8220;Was this WM_INPUT caused by the Panic Button releasing the P key?&#8221; Most of the noise is due to a fundamental difference between WM_INPUT and traditional window messages. Rather than directly include an address to the message&#8217;s data structure with the message, WM_INPUT instead provides a numeric handle which the message recipient can use to retrieve the <a href="http://msdn.microsoft.com/en-us/library/ms645571.aspx">RAWINPUTHEADER</a> structure through <a href="http://msdn.microsoft.com/en-us/library/ms645596.aspx">GetRawInputData()</a>. This means that allocating memory for the structure and determining the necessary size is the responsibility of the recipient, and it&#8217;s that paperwork that balloons this otherwise simple test of the structure&#8217;s contents. The first part of said test is to compare the source device handle to the Panic Button&#8217;s device handle to see if they match, which would be straightforward except that I haven&#8217;t shown where that handle comes from yet. So instead let&#8217;s look at the second part, the <a href="http://msdn.microsoft.com/en-us/library/ms646287.aspx">WM_SYSKEYUP</a> / P test. The comment claims that this is a good event to test for because it only occurs once per Panic Button push. That may be true, but this was written in 2008 and frankly I claimed a lot of things in 2008 so we better investigate further.</p>
<p>Here&#8217;s the full list of window messages generated by a Panic Button press:</p>
<table style="margin-left: auto; margin-right: auto;">
<tbody>
<tr>
<td style="width: 230px;"><strong>Window Message</strong></td>
<td style="text-align: center;"><strong>Virtual Key or Character</strong></td>
</tr>
<tr>
<td>WM_KEYDOWN</td>
<td style="text-align: center;">VK_SHIFT</td>
</tr>
<tr>
<td>WM_SYSKEYDOWN</td>
<td style="text-align: center;">VK_MENU</td>
</tr>
<tr>
<td>WM_SYSKEYDOWN</td>
<td style="text-align: center;">P</td>
</tr>
<tr>
<td>WM_SYSCHAR</td>
<td style="text-align: center;">P</td>
</tr>
<tr>
<td style="color: red;">WM_SYSKEYUP</td>
<td style="text-align: center; color: red;">P</td>
</tr>
<tr>
<td>WM_KEYUP</td>
<td style="text-align: center;">VK_MENU</td>
</tr>
<tr>
<td>WM_KEYUP</td>
<td style="text-align: center;">VK_SHIFT</td>
</tr>
</tbody>
</table>
<p>First some mild deciphering: VK_MENU is Windows-speak for the ALT key, and the WM_SYS* versions of keyboard messages are only sent when the ALT key is down. Once that&#8217;s understood it all makes symmetric sense: a rapid build-up of conditions causing the character message followed by an immediate and equal tear-down. I begrudgingly admit that the WM_SYSKEYUP / P combination is only sent once per button press, but that looks to be the case for each message. They&#8217;re all unique! There&#8217;s nothing at all special about WM_SYSKEYUP / P; testing for any step in the sequence would work just as well. I seem to recall choosing WM_SYSKEYUP / P out of paranoia just in case some kind of defect or interfering auto-repeat rate caused multiple keydown and character messages to be sent, whereas a keyup message could only be sent once by definition. (Exercise for home: hold down a key and try to release it twice.) Unlikely, I know, maybe even impossible, but everything else being equal that&#8217;s the pony I bet on. If you&#8217;d like to learn more about Windows keyboard messages you can visit <a href="http://msdn.microsoft.com/en-us/library/ms646267.aspx#_win32_Keystroke_Messages">here</a>, but Google and I recommend <a href="http://blog.ngedit.com/2005/06/13/whats-broken-in-the-wm_keydownwm_char-input-model/">here</a>.</p>
<p>That covers detecting button presses, which leaves detecting button presence. The Raw Input API has us covered there too:</p>
<pre class="brush: wincpp;">
HANDLE GetPanicButtonInputHandle()
{
    // get device count
    UINT deviceCount = 0;
    if (GetRawInputDeviceList(NULL, &amp;deviceCount, sizeof(RAWINPUTDEVICELIST)) == -1)
        return NULL;

    // allocate buffer for device list
    UINT bufferSize = sizeof(RAWINPUTDEVICELIST) * deviceCount;
    PRAWINPUTDEVICELIST buffer = (PRAWINPUTDEVICELIST)malloc(bufferSize);

    // get device list
    HANDLE hPanicButton = NULL;
    if (GetRawInputDeviceList(buffer, &amp;deviceCount, sizeof(RAWINPUTDEVICELIST)) != -1)
    {
        // loop through devices
        for (UINT i=0; i &lt; deviceCount; i++)
        {
            // get device name and check against panic button name using a substring comparison
            TCHAR deviceName[256];
            bufferSize = sizeof(deviceName);
            if (GetRawInputDeviceInfo(buffer[i].hDevice, RIDI_DEVICENAME, deviceName, &amp;bufferSize) != -1)
            {
                TCHAR panicButtonMagicString[] = _T(&quot;vid_04f3&amp;pid_04a0&quot;);
                CharLowerBuff(deviceName, lstrlen(deviceName));
                if (_tcsstr(deviceName, panicButtonMagicString) != NULL)
                {
                    hPanicButton = buffer[i].hDevice;
                    break;
                }
            }
        }
    }

    free(buffer);
    return hPanicButton;
}
</pre>
<p>GetPanicButtonInputHandle() simply walks the list of connected input devices looking for a device whose name contains the Panic Button&#8217;s unique signature. This signature, &#8220;vid_04f3&amp;pid_04a0&#8243;, is made up of the Panic Button&#8217;s <a href="http://www.beyondlogic.org/usbnutshell/usb5.htm">USB Vendor ID and Product ID</a>, 04F3 and 04A0 respectively. USB requires these values to be unique to a device, and so this otherwise shady substring comparison can be forgiven. GetPanicButtonInputHandle() not only tells us if the button is connected (no handle means no button), but its result can be used to identify the source of WM_INPUT messages. This explains the hPanicButton parameter we saw in IsPanicButtonPushed() earlier. The program calls GetPanicButtonInputHandle() upon loading and stores the result for future input testing via IsPanicButtonPushed(). Actually, if the stored handle is NULL then the program doesn&#8217;t even bother calling IsPanicButtonPushed() since it already knows that there&#8217;s no button attached, but you get the idea. Or not. At this point I&#8217;m way too invested in this explanation to start over with a clearer one so here&#8217;s hoping.</p>
<p>The last piece to Panic Button communication is keeping track of device connections and disconnections as they happen. That&#8217;s not only necessary for displaying the button&#8217;s status, but also for keeping the stored Panic Button handle up to date. So&#8230; I apologize, but here&#8217;s where it starts getting weird. If you peruse the <a href="http://msdn.microsoft.com/en-us/library/ff468895.aspx">Raw Input API reference</a> you&#8217;ll come across <a href="http://msdn.microsoft.com/en-us/library/ms645591.aspx">WM_INPUT_DEVICE_CHANGE</a>, a message which you can arrange to have sent every time an input device is attached or removed from the system. That sounds <em>perfect</em>, but if you check the fine-print you&#8217;ll see that this message wasn&#8217;t added to Windows until Vista, disqualifying its use if the Panic Button program is to work on Windows XP, which as an XP user I&#8217;d prefer that it does.</p>
<p>With WM_INPUT_DEVICE_CHANGE off the table the next candidate is the original <a href="http://msdn.microsoft.com/en-us/library/aa363480.aspx">WM_DEVICECHANGE</a> message which has been around forever. Well, &#8220;forever&#8221; if you consider the mid-nineties to be the beginning of time, which with attention spans these days you just might. WM_DEVICECHANGE and WM_INPUT_DEVICE_CHANGE share the same model, you register for notifications and you receive them whenever a device gets attached or removed. As the name suggests, WM_DEVICECHANGE is more general and is used for all devices, not just inputs. The other difference is that registering for notifications is a bit more complicated:</p>
<pre class="brush: wincpp;">
HDEVNOTIFY RegisterForHumanInterfaceDeviceNotifications(HWND hwnd)
{
    // this is the last hid.dll dependancy in the app.
    //  to remove the dependency on the Windows DDK, remove
    //  the call to HidD_GetHidGuid() and use the flag
    //  DEVICE_NOTIFY_ALL_INTERFACE_CLASSES which will cause
    //  notificationFilter.dbcc_classguid to be ignored.
    //  the only consequence will be that more WM_DEVICECHANGE
    //  messages will be sent by Windows.
    GUID hid;
    HidD_GetHidGuid(&amp;hid);

    DEV_BROADCAST_DEVICEINTERFACE notificationFilter;
    ZeroMemory(&amp;notificationFilter, sizeof(notificationFilter));
    notificationFilter.dbcc_size = sizeof(notificationFilter);
    notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    notificationFilter.dbcc_classguid = hid;

    return RegisterDeviceNotification(
        hwnd,                         // events recipient
        &amp;notificationFilter,          // type of device
        DEVICE_NOTIFY_WINDOW_HANDLE   // type of recipient handle
        );
}
</pre>
<p>Way to spoil the punchline, well-commented code! Registering for device notifications about keyboards isn&#8217;t complicated because of the code, it&#8217;s complicated because of the dependency incurred by calling <a href="http://msdn.microsoft.com/en-us/library/ff538924.aspx">HidD_GetHidGuid()</a>. HidD_GetHidGuid() isn&#8217;t defined in the Platform SDK headers and libraries, it&#8217;s instead found in the Driver Development Kit. Normally that would mean that to compile this silly program you&#8217;d have to download a 600MB CD-ROM image, install 1.4GB of components, and then void your citizenship and be labeled an enemy combatant by configuring Visual Studio to compile against the DDK. Yeah&#8230; I&#8217;m not liking the sound of that either, especially since as the comment says, HidD_GetHidGuid() is the only thing keeping the DDK in the picture <em>and it&#8217;s optional!</em> HidD_GetHidGuid() gives us the Globally Unique Identifier for Human Interface Devices, and we use that identifier to tell <a href="http://msdn.microsoft.com/en-us/library/aa363431.aspx">RegisterDeviceNotification()</a> that we&#8217;re only interested in that type of device, but we could also simply skip the filter by asking for notifications for all devices. That would eliminate the need for HidD_GetHidGuid(), but it would also make the Panic Button program a pretty bad Windows citizen.</p>
<p>The way a program detects if its device is connected is by waiting for a WM_DEVICECHANGE message from Windows and then scanning the list of connected devices to see if its guy is there. Now, the message doesn&#8217;t specifically say &#8220;Your device is connected!&#8221;, it just says &#8220;Something happened somewhere to someone!&#8221; and you&#8217;re on your own to investigate. Imagine that you&#8217;ve got multiple programs running in the background, each dealing with a different piece of hardware. (If you&#8217;re on a laptop you don&#8217;t have to imagine at all, I&#8217;ll just tell you: you have eighteen.) Now imagine that you plug in a mouse. Every one of those programs could potentially be sent a WM_DEVICECHANGE message and they&#8217;re all going to immediately do the same thing: scan Windows to see if their device is connected or disconnected&#8230; at the same time. It&#8217;s in everyone&#8217;s best interest to keep that burst of processing to a minimum, and if you experience a sudden halt when you plug in or unplug your USB gizmos then you recognize the truths I be spittin&#8217;. With that in mind, I&#8217;d like to help curb the tragedy of the commons and ensure that the Panic Button program receives a minimum number of WM_DEVICECHANGE messages so it looks like HidD_GetHidGuid() is here to stay.</p>
<p>Wait, let&#8217;s take a step back for a moment. Something bothers me about a function named &#8220;HidD_GetHidGuid&#8221;, and not just its unpronounceability. <strong>Get</strong> me the <strong>Globally Unique</strong> Identifier?</p>
<p>Here, I&#8217;ll save us both some time: it&#8217;s<span style="color: #ff0000;"><strong> {4D1E55B2-F16F-11CF-88CB-001111000030}</strong></span>!</p>
<p>Now the DDK dependency is starting to look a little ridiculous; is all this complexity really because we&#8217;re intent on calling a function in the same vein as GetTheNumberFive()? Hard-coding the GUID into the Panic Button program eliminates the HidD_GetHidGuid() call and the DDK dependency and it absolutely works&#8230; but man it feels sleazy. I really just wanted to explore my options. This is a terrible solution, even though it would work&#8230; for now. There must be a reason that the HID GUID wasn&#8217;t defined as a constant and that this layer of indirection exists. The only reason could be that on some systems, either now or in the future, the HID GUID is different. Fair enough, but that kinda defeats the point of using a <strong>Globally Unique</strong> Identifier in the first place. So no, we won&#8217;t be hard-coding the result. It&#8217;s the high road for us.</p>
<p>Well, maybe not that high. What I ended up doing was ripping the few relavant files out of the DDK and packaging them with my program&#8217;s source code. That&#8217;s what&#8217;s up with the &#8220;DDK&#8221; subdirectory. This way I can share the code in a self-contained way that doesn&#8217;t force others to jump through unnecessary hoops in order to compile. These files are from the old Windows 2003 DDK (3790.1830) which is what I originally developed the program against. This was the last version to be called DDK, afterwards software schizophrenia set in and it was rebranded as the Windows Driver Kit. The Panic Button program compiles just fine against the latest WDK but its header files are less portable so I included the older ones. If it were any harder than this I would have just cheated and used <a href="http://msdn.microsoft.com/en-us/library/ms683212.aspx">GetProcAddress()</a> to avoid linking to the DDK at all. This is just a guess, but I wouldn&#8217;t be surprised if this exact headache was one of the motivations behind the creation of WM_INPUT_DEVICE_CHANGE.</p>
<p>It was a lot of work, but by using the Raw Input API and flirting with the DDK the Panic Button program was able to avoid using hotkeys. Except that it wasn&#8217;t:</p>
<pre class="brush: wincpp;">
static BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
    ...

    // Register the Panic Button sequence of Shift + Alt + P.
    //  The only reason I do this is to prevent the P from reaching
    //  the active window. The app doesn't use WM_HOTKEY to be notified
    //  of a Panic Button push, it uses WM_INPUT from the Raw Input API.
    RegisterHotKey(hwnd, HotKeyID, MOD_SHIFT | MOD_ALT, 'P');

    ...
}
</pre>
<p><a href="http://www.youtube.com/watch?v=S5BMQ-xpTog">Oh, Come On!</a> After all that it was <em>still</em> necessary to register the hotkey! The Raw Input API is great for notifying about keyboard events but it doesn&#8217;t let you filter them out. The SHIFT + ALT + P key sequence still gets sent to the active window, which depending on the window could mean menus popping up, buttons being pushed, who knows? Hotkeys, on the other hand, are filtered by Windows and don&#8217;t reach their normal targets. That&#8217;s the behavior I was looking for, and so the program registers the hotkey solely for that purpose.</p>
<p><a href="http://snltranscripts.jt.org/98/98osportscenter.phtml">Sweet sassy molassy</a>, are we ever in need of a recap. The Panic Button program works by&#8230;</p>
<ul>
<li>Registering for WM_DEVICECHANGE messages for Human Interface Devices.</li>
<li>Registering for WM_INPUT messages for HID keyboards.</li>
<li>Registering the SHIFT + ALT + P hotkey to prevent it from reaching applications.</li>
<li>Scanning connected input devices for the Panic Button and storing the resulting handle.</li>
<li>Re-scanning when receiving WM_DEVICECHANGE and updating the stored handle.</li>
<li>Testing each WM_INPUT to see if it&#8217;s a WM_SYSKEYUP / P whose source matches the stored handle.</li>
</ul>
<p>Curse you bullet points, always belittling my work. The end result is that the program displays whether or not the button is connected, only responds to legitimate button presses, and prevents menus that start with &#8216;P&#8217; from awkwardly springing up. What can I say, buttons that play <a href="http://www.funnyordie.com/videos/5784/table-dance-from-cheztam">Table Dance</a> don&#8217;t program themselves.</p>
<p>That&#8217;s it for today&#8217;s episode of Clarissa Explains It All. Next time Sam and I will talk about Pearl Jam, parents, and stupid user interface tricks. Until then, enjoy the source code to the Panic Button program. The project/solution files are for Visual Studio 2005 but they&#8217;ll also load just fine in 2008. And&#8230; is that <a href="http://www.benshoof.org/blog/minicrt/">Minicrt</a> in there too?</p>
<p><a href="http://www.youtube.com/watch?v=m9gQD6i4htU">Na Na na-na-na&#8230;.</a></p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/apps/PanicButton.exe"><img src="/blog/files/panic_button.png" alt="" width="32" height="32" /></a></td>
<td><a href="/apps/PanicButton.exe">PanicButton.exe</a></td>
</tr>
<tr>
<td><a href="/blog/files/PanicButton.zip"><img src="/blog/files/zip.png" alt="" width="32" height="32" /></a></td>
<td><a href="/blog/files/PanicButton.zip">PanicButton.zip</a> (source code)</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/panic-button-part-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Panic Button</title>
		<link>http://www.benshoof.org/blog/panic-button/</link>
		<comments>http://www.benshoof.org/blog/panic-button/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 17:00:06 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=378</guid>
		<description><![CDATA[For a long time I wanted a button at my desk. The vision was simple: it would be a button, it would plug into my computer, and I would tell it what to do. Bonus points if it could survive spontaneous bouts of nerd rage. I expected its impractical purpose to change on a bi-weekly [...]]]></description>
				<content:encoded><![CDATA[<p>For a long time I wanted a button at my desk. The vision was simple: it would be a button, it would plug into my computer, and I would tell it what to do. Bonus points if it could survive spontaneous bouts of nerd rage. I expected its impractical purpose to change on a bi-weekly basis (I&#8217;m fickle, yo), so I figured some programming would be involved, but first it would need to exist and that seemed to be the hard part. Once a year I would find my fist clenched in the air, trembling, frantically trying to lock in on a button that just wasn&#8217;t there. After cleaning up the remains of whatever filled that void I would make my annual attempt to find my button through a few vague and poorly chosen search words.</p>
<p>Years passed. Then in 2008 I finally tossed &#8220;<a href="http://images.google.com/images?q=usb+button">usb button</a>&#8221; at Google Images. And lo, for I found the <a href="http://www.ubergizmo.com/15/archives/2007/06/usb_panic_button_for_novelty_reasons.html">Panic Button</a>.</p>
<p class="imageContainer"><a href="http://www.ubergizmo.com/15/archives/2007/06/usb_panic_button_for_novelty_reasons.html"><img title="Panic Button" src="http://www.benshoof.org/blog/wp-content/uploads/2010/03/panic_button.jpg" alt="" /></a></p>
<p>Let&#8217;s tally: it&#8217;s a big button, it plugs into a computer&#8217;s USB port, and it&#8217;s programmable&#8230; in that it can play one of three homely screen savers. Close enough! So I bought a couple for $17 each, threw away the software unopened, and wrote <a href="/apps/PanicButton.exe">PanicButton.exe</a>. I could explain the program further but as the old saying goes, &#8220;Why go ahead and say what you could say in literally hundreds of individual utterances when in fact time has shown that a single image, carefully chosen within the confines of the correct context, might very well end up equivalent to eloquence due to the potential efficiency with which an idea (and/or <em>ideas</em>) can be communicated visually versus the various verbosities inherent in any language languishing in the larynx.&#8221;</p>
<p class="imageContainer"><a href="/apps/PanicButton.exe"><img title="Panic Button Control Panel" src="http://www.benshoof.org/blog/wp-content/uploads/2010/03/panic_button_screenshot.png" alt="" /></a></p>
<p>Zounds, that <em>is</em> an effective screenshot! And yet I chose to continue. The Panic Button Control Panel accepts a single command which it runs when the button is pushed. It lives in the system tray and can be set to automatically start with Windows. The command can be a file to open or another program to run. The Control Panel is a standalone program; there&#8217;s nothing to install and no drivers are required for the button. The system requirements are:</p>
<ul>
<li>Windows XP or newer</li>
<li>A Panic Button (or, alternatively, <a href="http://en.wikipedia.org/wiki/Tommy_Westphall">an unfathomably tragic and thorough imagination</a>)</li>
</ul>
<p><strong>Full disclosure time:</strong> The Panic Buttons sent to me from Honk Kong say STRESS and not PANIC, but since the device identifies itself to computers as &#8220;Panic Button&#8221;, that&#8217;s what I&#8217;m going with. Either way it&#8217;s cheesy, but my project to sand off the white paint never took flight.</p>
<p><strong>Full disclosure overtime:</strong> Behold the flailing desperation of synergy as it&#8217;s also a <a href="http://www.gadget4all.com/prod_detail.php?prod_id=00783&amp;dept_id=009&amp;cat_id=037">Hulk Smash Button</a>, an <a href="http://www.gadget4all.com/prod_detail.php?prod_id=00782&amp;dept_id=009&amp;cat_id=037">Ironman Power Up Button</a>, and a <a href="http://www.gadget4all.com/prod_detail.php?prod_id=00781&amp;dept_id=009&amp;cat_id=037">Spiderman Sense Button</a>. I can&#8217;t speak to whether or not my program works with these variants, but it probably does. Frankly though, I&#8217;d prefer that it doesn&#8217;t.</p>
<p>I&#8217;ll excuse the painfully banal &#8220;USB toy&#8221; crowd that Panic Button runs with because this is a good product. True to its image, it is a big honkin&#8217; button that was meant to be slammed by a clenched fist. It&#8217;s spring loaded, and has like the most satisfying <a href="http://en.wikipedia.org/wiki/Hooke%27s_law">force constant</a> you can imagine. It even makes a little click when fully depressed, like a little tip o&#8217; the hat. And it only fires once per push, so when you find that you&#8217;ve pounded it way <strong>WAY</strong> too hard for professional surroundings you can just leave your fist there, eyes closed, as you exhale deeply until all the steam lifts and those around you eventually allow their fear to subside.</p>
<p>Actually, there are far better things to use a big red button for than dousing in rageahol. Music is a good candidate. Dave Hamp had his button play the <a href="http://www.youtube.com/watch?v=MK6TXMsvgQg">Benny Hill Theme</a>. Shouldn&#8217;t everything you press play that? For a while I had mine play a random mp3. There&#8217;s something about leaning over every three minutes to manually advance a playlist you have no control over&#8230; it&#8217;s like listening to the radio but harder. Nowadays, the two buttons have settled into more permanent and prominent roles. One is an integral component to the digital infrastructure of the <a href="http://commerce.state.ak.us/">Alaska Department of Commerce</a> in Juneau. The other is installed at an Anchorage firm&#8217;s front desk and plays <a href="http://www.funnyordie.com/videos/5784/table-dance-from-cheztam">Table Dance</a>. If there&#8217;s a story in the Bible about two brothers doing the same thing but then later doing different things, that would make for a good analogy.</p>
<p>And so I present the Panic Button Control Panel. If you happen to have a Panic Button then I dare say you&#8217;ll love it. The only subtlety I can think of is that you can drag and drop a file onto it to automatically fill in the Command field. Also, the program knows when a Panic Button is connected and displays its status in the lower left. That status will also let you know when it detects a button push. If all of this is swaying you towards a purchase, it looks like the button is only $10 at <a href="https://www.welovepolice.com/cart/index.php?p=product&amp;id=37">welovepolice.com</a>. Hmmm&#8230; you&#8217;d better click that link, I can&#8217;t tell if I&#8217;m joking either.</p>
<p>Next time we&#8217;ll begin looking at the program&#8217;s internals and I&#8217;ll make its source code available. Until that day.</p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/apps/PanicButton.exe"><img src="/blog/files/panic_button.png" alt="" width="32" height="32" /></a></td>
<td><a href="/apps/PanicButton.exe">PanicButton.exe</a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/panic-button/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Minicrt</title>
		<link>http://www.benshoof.org/blog/minicrt/</link>
		<comments>http://www.benshoof.org/blog/minicrt/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 03:50:22 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=40</guid>
		<description><![CDATA[Last time, we bore witness to the drunken boast that if you really want to compile tiny, independent C++ programs with a modern Visual Studio then you have to kick its C Run Time library to the curb. To do that I introduced a replacement library, Minicrt, which worked so well within my contrived example [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.benshoof.org/blog/small-programs/">Last time</a>, we bore witness to the drunken boast that if you really want to compile tiny, independent C++ programs with a modern Visual Studio then you have to kick its C Run Time library to the curb. To do that I introduced a replacement library, Minicrt, which worked so well within my contrived example that it escaped examination. Today we&#8217;ll see how to use Minicrt in more realistic scenarios, but first a brief narration on latter day heroism.</p>
<p>Hero The First is <a href="http://www.wheaty.net/">Matt Pietrick, author of Libctiny</a>. Matt wrote about large executable size <a href="http://www.microsoft.com/msj/archive/S569.aspx">back in 1996</a> and <a href="http://msdn.microsoft.com/en-us/magazine/cc301696.aspx">again in 2001</a> in which he fingered Visual Studio&#8217;s CRT as the cause and offered up Libctiny as the solution. As a drop-in CRT replacement to effortlessly reduce program size, the library worked great and even included source code. One of its premises was that a number of standard C functions could be implemented as thin wrappers over existing Windows API calls, keeping the real work out of the executable by offloading it onto the operating system. For example, <a href="http://msdn.microsoft.com/en-us/library/wc7014hz.aspx">printf()</a>, traditionally a meaty CRT function, is implemented in Libctiny simply by calling <a href="http://msdn.microsoft.com/en-us/library/ms647551.aspx">wsvprintf()</a> to build the output string and <a href="http://msdn.microsoft.com/en-us/library/aa365747.aspx"> WriteFile()</a> to spit that to the standard output stream, and  all in about fifteen lines of code! <strong>Hero.</strong></p>
<p>Unfortunately, the years weren&#8217;t kind to Libctiny users. Written in Visual C++ 6.0&#8242;s heyday, Libctiny became increasingly incompatible with each subsequent version of Visual Studio. Trivial Hello World apps would still compile, but as soon as a program did anything interesting it would run afoul linker errors resulting from incompatibilities with the default libraries. Those could be turned off with the <a href="http://msdn.microsoft.com/en-us/library/3tz4da4a.aspx">/NODEFAULTLIB</a> linker switch, but that would leave no standard C functions except the poultry few in Libctiny. Even tiny programs need to <strong>do</strong> something. Sadness ensued. (And yes, poultry.)</p>
<p>Enter Hero The Secondest: Google. Dot com. <a href="http://www.ask.com/web?q=google.com">Look &#8216;em up</a>. Those magnificent bastards went and wrote a software installer named <a href="http://code.google.com/p/omaha/"> Omaha</a> for Chrome and Google Earth, open sourced the client, and then in order to <a href="http://code.google.com/p/omaha/source/browse/trunk/mi_exe_stub/build.scons?r=66#50">shave 40kb off of their installer stub</a> not only used Libctiny but dragged it kicking and screaming into the modern world, re-branding it as Minicrt. Minicrt is chock full of standard C functions (making /NODEFAULTLIB less painful), compatible with Visual Studio 2005 and 2008 (as that&#8217;s what Google uses to build Omaha), and used in a nontrivial program that shows how Minicrt can co-exist with high level ATL classes like <a href="http://msdn.microsoft.com/en-us/library/5bzxfsea.aspx">CString</a> and <a href="http://msdn.microsoft.com/en-us/library/50t8ya55.aspx">CSimpleArray</a>. I don&#8217;t know the Google programmer responsible for this but I do know his name: <strong>Hero</strong>.</p>
<p>Thriceroy Of Heroes: <a href="http://leenux.org.uk/">Lee Packham</a>. From his UK domain name I&#8217;m assuming that he&#8217;s British. (Look, this is Alaska yo, deal with it.) <a href="http://leenux.org.uk/2009/06/23/visual-c-runtime-hell/">Lee packaged Minicrt for Visual Studio 2008 to make it compilable by mortals</a>. Google doesn&#8217;t have Visual Studio project files for Omaha, only <a href="http://code.google.com/p/omaha/wiki/DeveloperSetupGuide">build scripts written in Python</a>. Typical. Lee created Visual Studio 2008 project/solution files and also silenced some errors by adding a couple casts and #pragmas to the Minicrt code. Most importantly, as far this text is concerned, it was through his blog post that I learned about Omaha&#8217;s rebirthening of Libctiny, setting off the chain of events that led to making small programs again, writing this article, and bestowing upon Lee the oft-coveted title: <strong>Hero.co.uk</strong>.</p>
<p>Now I&#8217;m hesitant to call myself a <strong>Hero</strong>, but if you were to throw a heavily catered banquet in my honor with sufficient austerity and appropriate attendance then I would be honored to appear. It&#8217;s called Class. <a href="http://www.ask.com/web?q=how+does+i+get+richest">Look &#8216;er up</a>. I&#8217;ve taken Lee&#8217;s Minicrt, made a few light touch-ups for myself, and am making it available here.  These are the changes I&#8217;ve made:</p>
<ul>
<li>Added more of the standard C functions. Each was added on an as-needed basis and as a new source file.</li>
<li>Added back printf(), which was in the original Libctiny but removed from Google&#8217;s Minicrt.</li>
<li>Added Visual Studio 2005 project/solution files, equivalent to the 2008 ones (which are also included).</li>
<li>Set Release Mode to compile the library without debug information and to optimize for size. This makes for a smaller minicrt.lib file.</li>
<li>Removed unused source files, including the redundant string.cc which Google&#8217;s build script doesn&#8217;t even include.</li>
<li>Renamed Minicrt to Libctiny II: Electric Boogaloo, then immediately backpedaled on the decision in an act of equally epic wisdom and cowardice.</li>
</ul>
<p>So there&#8217;s the odyssey. Matt Pietrick&#8217;s Libctiny lives on nearly fifteen years later as Minicrt, which you can compile and use with Visual Studio 2005 and 2008 to drop a simple windowed program to 2.0kb with no dependencies outside of the operating system. Of course, we&#8217;re talking computers here, so it&#8217;s not always that simple. As advanced C++ language features and libraries get used, friction occurs in the form of frightening linker errors when you don&#8217;t have the real CRT in the mix. Several of these are easily remedied by flipping the right switches while other problems require more&#8230; extreme measures. I&#8217;ll go through each of the errors I&#8217;ve encountered and what can be done about them through compiler settings and code. The astute will recall that previously I swore a sacred oath to God to not mention any more compiler settings. Whoops!</p>
<p><span style="color: red;"><strong>Unresolved external symbol const type_info::&#8217;vftable&#8217; &#8230;</strong></span></p>
<p>C++ exceptions and/or <a href="http://en.wikipedia.org/wiki/Run-time_type_information">RTTI</a> are the cause of this. Both language features are out of Minicrt&#8217;s league and both can be disabled. This really should go without saying, but if your program depends on either of these then that kinda disqualifies it from the Minicrt fun.</p>
<pre>Configuration Properties \ C/C++ \ Code Generation \ Enable C++ Exceptions
	Yes (/EHsc) =&gt; No

Configuration Properties \ C/C++ \ Language \ Enable Run-Time Type Info
	Yes =&gt; No (/GR-)</pre>
<p><span style="color: red;"><strong>Unresolved external symbol __security_cookie</strong></span></p>
<p>This error and variants on it are a result of the compiler&#8217;s <a href="http://msdn.microsoft.com/en-us/library/8dbf701c.aspx">buffer security check</a>, which is expecting to find the corresponding Visual Studio 2005 CRT code. Turn it off.</p>
<pre>Configuration Properties \ C/C++ \ Code Generation \ Buffer Security Check
	Yes =&gt; No (/GS-)</pre>
<p><span style="color: red;"><strong>Unresolved external symbol __load_config_used</strong></span></p>
<p>This is related to structured exception handling, though it is usually prevented simply by turning off C++ exceptions as described above. If that doesn&#8217;t do it, <a href="http://msdn.microsoft.com/en-us/library/9a89h429.aspx">disabling the safe exception handler table</a> will.</p>
<pre>Configuration Properties \ Linker \ Command Line \ Additional Options
	/SAFESEH:NO</pre>
<p><span style="color: red;"><strong>Unresolved external symbol ___CxxFrameHandler3</strong></span></p>
<p>Who even uses exception handling in C++? <em>Once again</em>, turn off C++ exceptions as described above.</p>
<p><span style="color: red;"><strong>Unresolved external symbol __ftol2_sse</strong></span></p>
<p>Hoo boy. When a floating point number is converted to a long, or really any integer type, Visual Studio 2005 builds applications that call the CRT helper function _ftol2_sse to do the work.  In the previous version of Visual Studio this function was named _ftol2, which is a problem for Minicrt because it&#8217;s built with ftol2.obj from the 2003 CRT and only contains the function _ftol2. From the names involved in this conflict you&#8217;d think that you&#8217;d just need to disable SSE in the project setting to persuade Visual Studio to use the older function, but that&#8217;s not the case. _ftol2_sse isn&#8217;t just an alternate version; it wraps both by first checking for SSE availability and then only calling _ftol2 if SSE is not there. That means that either way, Visual Studio 2005 links programs against _ftol2_sse. It&#8217;s position on this is intractable and adamantine. That leaves us with only one move to make, but it&#8217;s drastic: using a <a href="http://msdn.microsoft.com/en-us/library/6d9xx1d2.aspx">depreciated compiler switch</a> to decline calling <em>any</em> ftol conversion functions!</p>
<pre>Configuration Properties \ C/C++ \ Command Line \ Additional Options
	/QIfist</pre>
<p>This should get you compiling, but there are consequences to this switch. The first is cosmetic and annoying: Visual Studio will always generate a warning about using a depreciated compiler switch, <a href="http://connect.microsoft.com/VisualStudio/feedback/details/100055/cl-exe-command-line-warnings-cannot-be-disabled">a warning that can&#8217;t be disabled</a>. The second is serious. ftol is responsible for setting the Floating Point Unit control flag to the correct state before and after each conversion, and it&#8217;s the FPU control flag that determines how rounding should occur. The ANSI C behavior is to round towards zero (truncate mode) when converting, but now that ftol has gone awol (see what I did there?), who knows what mode the FPU is in? Mine defaults to rounding towards nearest, so this switch potentially changes the result of every floating point conversion or calculation application-wide. That&#8217;s terrible. Now there&#8217;s a way out of this&#8230; but it involves assembly. Yeah, I know, I wanted this to be an easy one too. <a href="http://www.youtube.com/watch?v=409Pjtq7jzY">But it&#8217;s the other way</a>.</p>
<pre class="brush: wincpp;">
// set rounding mode to truncate
//  from http://www.musicdsp.org/showone.php?id=246
static short control_word;
static short control_word2;

inline void SetFloatingPointRoundingToTruncate()
{
    __asm
    {
        fstcw   control_word                // store fpu control word
        mov     dx, word ptr [control_word]
        or      dx, 0x0C00                  // rounding: truncate
        mov     control_word2, dx
        fldcw   control_word2               // load modfied control word
    }
}
</pre>
<p>Calling this at the start of your program will set the rounding mode to truncate and keep it there for the duration (unless you manually change it again), which makes float conversions behave the way they would have before /QIfst. Any other floating point routines that require a different mode are going to require that manual change or their results will be off. As you can see, heavy use of floating point math can also be a Minicrt disqualifier. On the other hand, if you can test your results and they come out okay then there&#8217;s really no problem. In fact, this method of disabling ftol and manually initializing the rounding mode is an established optimization used by speed freaks because conversions go faster without the overhead of setting and re-setting the control state each time.</p>
<p><span style="color: red;"><strong>Unresolved external symbol __purecall</strong></span></p>
<p>This shows up when you start using virtual functions. _purecall is a placeholder function that lives in the CRT so that a class with a pure virtual function can have its vtable entry pointed to something instead of nothing, which would be illegal. It&#8217;s a function that doesn&#8217;t do anything, and it&#8217;s an error for it to ever be called, so all you need to do is create your own do-nothing _purecall. The only difference between this and the CRT&#8217;s version (defined in purevirt.c) is that the real one throws an error and aborts the program.</p>
<pre class="brush: wincpp;">
extern &quot;C&quot; int __cdecl _purecall(void) { return 0; }
</pre>
<p><strong><span style="color: red;">Unresolved external symbol class ATL::CAtlBaseModule&#8230;</span> and everything else ATL related.<br />
</strong></p>
<p>The Active Template Library works great with Minicrt, it just takes a few macro definitions to disable ATL&#8217;s dependencies on newer CRT functions&#8230; and a few more to silence all the depreciation warnings. Finally, the linker needs to be reminded about the ATL libary file since /NODEFAULTLIB excludes it from being automatically included in the list. I&#8217;ve taken all of these settings from Omaha&#8217;s build script, and it&#8217;s thanks to them that I&#8217;ve been able to use CString and collections like <a href="http://msdn.microsoft.com/en-us/library/45dz8beb.aspx">CAtlArray</a> and <a href="http://msdn.microsoft.com/en-us/library/w6fwh89e.aspx">CAtlMap</a>.</p>
<pre>
Configuration Properties \ C/C++ \ Preprocessor \ Preprocessor Definitions
	_ATL_MIN_CRT
	_ATL_SECURE_NO_DEPRECATE
	_CRT_SECURE_NO_WARNINGS
	_SECURE_SCL=0
	_SECURE_ATL=0

Configuration Properties \ Linker \ Input \ Additional Dependencies
	atls.lib
</pre>
<p><span style="color: red;"><strong>Unresolved external symbol [ insert CRT function here ]</strong></span></p>
<p>Eventually you&#8217;ll want to use a CRT function that simply isn&#8217;t in Minicrt. Yet. The beauty of being able to build Minicrt yourself with Visual Studio is that it&#8217;s easy to add functions to it. When I said that I added functions on an &#8220;as-needed basis&#8221;, that&#8217;s what I meant. It wasn&#8217;t for fun, each one was done because I had a program that depended on it. Thankfully, you only need to add a function once. It&#8217;s not as daunting as it sounds. Most of the time you can just find an existing implementation and paste it in with little or no modifications. The first place to look is the source for Visual Studio&#8217;s CRT, which comes with Visual Studio (located in %VSINSTALLDIR%\vc\crt\src). That&#8217;s where I got the code for <a href="http://msdn.microsoft.com/en-us/library/ftw0heb9.aspx">strrchr()</a>. </p>
<pre class="brush: wincpp;">
//==========================================
// minicrt - Chris Benshoof 2009
// strrchr from MSVCRT
//==========================================
#include &quot;libctiny.h&quot;
#include &lt;stdlib.h&gt;

extern &quot;C&quot; char * __cdecl strrchr (const char * string, int ch)
{
    char *start = (char *)string;

    while (*string++)                       /* find end of string */
        ;
    /* search towards front */
    while (--string != start &amp;&amp; *string != (char)ch)
        ;

    if (*string == (char)ch)                /* char found ? */
        return( (char *)string );

    return(NULL);
}
</pre>
<p>In the case of string functions, the next place to look is Minicrt&#8217;s very own string.c. There are a number of string functions in there that aren&#8217;t exported but are used by ones that are. When needed, I&#8217;ve copied these functions into new source files made them exportable, that way I don&#8217;t make any changes to string.c and it&#8217;s clear what my rookie additions are. By not touching the original files it&#8217;s easy for me to periodically diff my evolving Minicrt with the one in Google&#8217;s <a href="http://code.google.com/p/omaha/source/browse/#svn/trunk/third_party/minicrt">Omaha repository</a> so that I can easily merge in their updates. I pulled <a href="http://msdn.microsoft.com/en-us/library/8h19t214.aspx">tolower()</a> from string.c into tolower.cc.</p>
<pre class="brush: wincpp;">
//==========================================
// minicrt - Chris Benshoof 2009
// tolower from string.c (__ascii_tolower)
//==========================================
#include &quot;libctiny.h&quot;

extern &quot;C&quot; int __cdecl tolower(int c)
{
    if (c &gt;= 'A' &amp;&amp; c &lt;= 'Z') return (c + ('a' - 'A'));
    return c;
}
</pre>
<p>The final place to look, of course, is ye olde abandoned <a href="http://www.aol.com/">Internet</a>. A lot of people have had to implement the C Run Time library over the years, so there&#8217;s a lot of implementations laying around. That&#8217;s how I avoided writing my own <a href="http://msdn.microsoft.com/en-us/library/yd5xkb5c.aspx">atoi()</a>.</p>
<pre class="brush: wincpp;">
//==========================================
// minicrt - Chris Benshoof 2009
// atoi(), modified from 
// http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/atoi.c.htm
//==========================================
#include &quot;libctiny.h&quot;

extern &quot;C&quot; int __cdecl atoi(const char *String)
{
    int Value = 0, Digit;
    int c;

    while ((c = *String++) != '&#92;&#48;') {

        if (c &gt;= '0' &amp;&amp; c &lt;= '9')
            Digit = (c - '0');
        else
            break;

        Value = (Value * 10) + Digit;
    }

    return Value;
}
</pre>
<p>If all else fails, you can always write the function yer own damn self. I cobbled together <a href="http://msdn.microsoft.com/en-us/library/ybk95axf.aspx">sprintf()</a> from Minicrt&#8217;s printf() code. It&#8217;s kinda fun (perversely) to be in charge of your own little run time as long as you know the limitations. For example, the printf() implementation uses a 1024 byte buffer from the stack to build the output string, as that&#8217;s the largest buffer wvsprintf() will accept. If you call printf() to build a string longer than that&#8230; <a href="http://www.youtube.com/watch?v=KSFCZSxDreg">uh-oh</a>. Just something to keep in mind.</p>
<p>Thus concludes my panoptica on Minicrt and making small programs. From here on out I can go into pornographic detail about actual programs instead of coming off as an obsessive compulsive over trivial technical attributes&#8230; though I have a feeling I&#8217;ll be doing both. In my defense, many of the programs I&#8217;ll be examining make use of Minicrt so this topic seems a necessary prerequisite. On the other hand, all you have to do is look at the lengths of the two articles to see that there really is no defense. </p>
<p>Well, what&#8217;s done is done. Enjoy the source code to Minicrt. As I update my copy I&#8217;ll update the copy here too. If that happens enough, I may even concoct something fancy like a text file of release notes. In any case, I&#8217;ll keep this article updated if I survive any more linker issues.</p>
<p>Next time, I&#8217;ll prove that I&#8217;ve actually written a program before. Though wouldn&#8217;t it be great if I hadn&#8217;t?</p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/blog/files/minicrt.lib"><img src="/blog/files/lib.png" alt="" width="32" height="32" /></a></td>
<td><a href="/blog/files/minicrt.lib">minicrt.lib</a> (library)</td>
</tr>
<tr>
<td><a href="/blog/files/minicrt.zip"><img src="/blog/files/zip.png" alt="" width="32" height="32" /></a></td>
<td><a href="/blog/files/minicrt.zip">minicrt.zip</a> (source code)</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/minicrt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Small Programs</title>
		<link>http://www.benshoof.org/blog/small-programs/</link>
		<comments>http://www.benshoof.org/blog/small-programs/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 00:47:12 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=217</guid>
		<description><![CDATA[If you want to produce small C++ programs with minimal dependencies using Visual Studio 2005 or newer then you&#8217;re in for a world of hurt. Default setting after default setting is against you, and in the end you have to go completely off the reservation to get results. Business as usual in the Windows world. [...]]]></description>
				<content:encoded><![CDATA[<p>If you want to produce small C++ programs with minimal dependencies using Visual Studio 2005 or newer then you&#8217;re in for a world of hurt. Default setting after default setting is against you, and in the end you have to go completely off the reservation to get results. Business as usual in the Windows world. Previously I promised to talk about executable size without getting distracted by relevance, but I have a feeling that&#8217;s not going to hold. I guess I&#8217;ll just keep typing and see what happens.</p>
<p>Let&#8217;s start with our friend from last time, <a href="http://www.benshoof.org/blog/hideautoupdate/">HideAutoUpdate</a>, and see what it takes to coerce Visual Studio 2005 into spitting out a 1.5kb exe. HideAutoUpdate makes for a good initial test case as it&#8217;s barely more than a Hello World app, yet does something allegedly useful. As a refresher, here&#8217;s its source code:</p>
<pre class="brush: wincpp;">
// HideAutoUpdate by Chris Benshoof
//  the best flipping thing i'll ever write
#include &lt;windows.h&gt;
#include &lt;tchar.h&gt;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    HWND dialog = FindWindow(WC_DIALOG, _T(&quot;Automatic Updates&quot;));
    if (IsWindowVisible(dialog))
    {
        ShowWindow(dialog, SW_HIDE);
    }
    return 0;
}
</pre>
<p>That&#8217;ll do, Pig. We&#8217;re going to take this code and walk through each step to reduce the file size without sacrificing functionality or compatibility. In fact, just between you and me, we&#8217;re going to accidentally increase the latter.</p>
<p>First we need a baseline. Create a new Visual C++ Win32 Project in Visual Studio, make sure to check &#8220;Empty Project&#8221; on the Application Wizard, then add a new C++ file and paste in the above code. Flip the solution configuration from Debug to Release. Now before we build, let&#8217;s make this slightly less painful to follow along with at home. We can get Visual Studio to tell us the compiled file size in its output window which saves us having to go look for ourselves after each build, as that gets real old real quick. This can be done by having Visual Studio run &#8220;dir&#8221; on the program after every build. Such a feat can be accomplished with the project setting:</p>
<pre>Configuration Properties \ Build Events \ Post-Build Event \ Command Line
	cmd /c dir "$(TargetPath)"</pre>
<p>Okay, now we can build and see that file size&#8230;.</p>
<p style="padding-left: 40px;">Release mode baseline: <span style="color: green;"><strong>6,565 bytes!</strong></span></p>
<p>Oh snap, that&#8217;s crazy small! 6.5kb, that works for me, especially since I didn&#8217;t have to do anything! Ship it! But as the scroll bar to the right sadly foreshadows, there&#8217;s more to the story. Believe it or not but that little HideAutoUpdate.exe we just compiled, that one that only calls three flipping functions, all of which have existed since 16 bit Windows aka The Time Before Christ&#8230; won&#8217;t run on a <em>single</em> default installation of Windows XP, 2003, or anything earlier! Gadzooks!</p>
<p>We&#8217;ve incurred a dependency: Visual C++ projects default to link against <a href="http://msdn.microsoft.com/en-us/library/abx4dbyh.aspx">Microsoft&#8217;s Visual C++ RunTime dlls</a>. Now wait, that&#8217;s supposed to be a good thing! The C++ RunTime (CRT) contains the code for standard functions like <a href="http://msdn.microsoft.com/en-us/library/wc7014hz.aspx">printf()</a>, <a href="http://msdn.microsoft.com/en-us/library/kftdy56f.aspx">operators like new and delete</a>, and the behind-the-scenes work for building up and tearing down an environment for a C++ program to run in. It&#8217;s efficient and sensible to have that shared code in a single set of dlls instead of baked into each and every exe, and it&#8217;s even in the spirit of reducing a program&#8217;s size which is what this article is about.</p>
<p>The problem is that Windows doesn&#8217;t come with the CRT dlls that HideAutoUpdate needs. Back in the day, Visual Studio 6.0 linked programs against msvcrt.dll which came with practically every copy of Windows, even though that wasn&#8217;t guaranteed, so a lot of programs got away without noticing this dependency let alone caring about it. That&#8217;s not the case anymore. Each version of Visual Studio now has its own versions of CRT dlls. If built with Visual Studio 2005 then HideAutoUpdate requires msvcr80.dll which can only be installed through a 2.6mb Microsoft installer whose version must match at least what you had installed when you compiled. Requiring an installer over four hundred times the size of our little program is unattractive enough, but factor in the drama from Visual Studio service packs <em>and</em> automatic Windows updates rendering future builds incompatible with previous CRT dlls and&#8230; <a href="http://www.youtube.com/watch?v=ZSBwgCRZAHw">nah I don&#8217;t think so I gotta boyfriend</a>.</p>
<p>It seems I&#8217;ve strayed off track a bit since the topic is program size. To be fair though, dense stanzas of negativity are always on topic in Windows programming. Wait&#8230; come to think of it, I&#8217;m completely on track here, because when I talk about reducing program size what I&#8217;m really talking about is reducing dependencies. No&#8230; well, yes. Yes, I&#8217;m talking about reducing dependencies, but No, what I&#8217;m <em>really really</em> talking about is understanding dependencies, and that might just prove to be the most important thing ever. Yikes, a bold statement!</p>
<p>Now the wind is picking up. Let&#8217;s cut to the chase. We drop our lame program&#8217;s insignificant file size to 1.5kb by replacing Visual Studio&#8217;s CRT with our own tiny custom one and tweaking a few linker settings. It&#8217;s crazy hard and I&#8217;ll elaborate on the how later. The file size is small, hooray, but there&#8217;s something more interesting going on here: HideAutoUpdate doesn&#8217;t depend on the Visual Studio CRT anymore. Now obviously that means the dll mess from above no longer applies but that can be accomplished simply by statically linking to the CRT, which causes the necessary portions of CRT code to be implanted directly into HideAutoUpdate at the cost of a much larger file size, but HideAutoUpdate avoids that too. And here&#8217;s where independence gets its good rep: not depending on something means not depending on its dependencies. So what does the Visual Studio 2005 CRT depend on? A number of things, but of interest is the Windows API function <a href="http://msdn.microsoft.com/en-us/library/ms680345.aspx">IsDebuggerPresent()</a>. This function simply returns TRUE or FALSE depending on if a debugger is attached to the program. I don&#8217;t know why a call to it is in the Visual Studio 2005 CRT code, the why is irrelevant. It&#8217;s in there, that&#8217;s all that matters, and the function lives in kernel32.dll&#8230; starting with Windows 98. It doesn&#8217;t get much more subtle than that. Out of the box, Visual Studio 2005 <em>cannot</em> produce a standalone C++ application that will run on Windows 95, because all C++ applications statically linked to the CRT depend on IsDebuggerPresent() which depends on Windows 98 or later. Windows 95 is unable to resolve that one link and will refuse to run such programs regardless of what they really do. HideAutoUpdate doesn&#8217;t have this dependency and happily runs on Windows 95, which for all I know doesn&#8217;t even have automatic update dialogs to hide.</p>
<p>It&#8217;s pretty easy to imagine some responses to that. &#8220;Who the fuck cares about Windows 95?&#8221; is probably the chart topper. The answer is: &#8220;people who care&#8221;, also known as &#8220;the right people&#8221;. It&#8217;s not about getting this program to run under Windows 95, it&#8217;s about understanding why it won&#8217;t, which means understanding its dependencies and their ramifications.</p>
<ul>
<li> &#8220;Why does a program that only calls three functions require a 2.6mb installer?&#8221;</li>
<li>&#8220;Doesn&#8217;t it seem like a program that only calls three functions should be less than 48kb?&#8221;</li>
<li>&#8220;Why can&#8217;t a program that only calls three functions run on an operating system that has them?&#8221;</li>
</ul>
<p>These questions are all about details. These details have nothing to do with what a program does, and their answers don&#8217;t even need to make sense, but if nobody on a team is asking or caring about details just like these then I have concerns. Quality programs, regardless of function, feed on the socially devastating obsession to inconvenient, indirect, often otherwise inconsequential details that only nerds get right. Dependencies fall into that class of details. If a team of nerds can&#8217;t get those right, what can they?</p>
<p>An example of this quality that comes to mind is <a href="http://www.utorrent.com">µTorrent</a>. µTorrent, the most popular BitTorrent client (<a href="http://torrentfreak.com/thunder-blasts-utorrents-market-share-away-091204/">outside of China</a>), has kept itself a small standalone program since 2005 by using its own custom CRT code. The µTorrent team has even figured out how to get the best of both worlds: µTorrent manages to link to the old ever-present msvcrt.dll despite being compiled with Visual Studio 2008! That&#8217;s <a href="http://kobyk.wordpress.com/2007/07/20/dynamically-linking-with-msvcrtdll-using-visual-c-2005/">extremely difficult and entirely unsupported</a>, yet they go through all that trouble just to keep their program small without incurring the responsibility of managing dependencies. If µTorrent triples in size tomorrow and requires an installer, no one is going to stop using it. µTorrent&#8217;s only function that matters is its ability to download interesting things. That its programmers care enough to take extreme measures to keep it lightweight fills me with a great confidence in that primary ability, a confidence that turns out to be well founded.</p>
<p>Another example is the Windows Task Manager. I was delighted to find out that <a href="http://blogs.msdn.com/oldnewthing/archive/2007/07/25/4036123.aspx#4047788">Task Manager&#8217;s original author avoided CRT reliance</a> in the name of program size. Task Manager, the program that needs to work when all others don&#8217;t, is <em>very</em> concerned about dependencies. I&#8217;d never thought to appreciate Task Manager, but reading Dave&#8217;s account of the work he put in to make the program meet his self-imposed criteria for quality makes two things clear: Task Manager was built with love, and you want Dave on your team. Dave took the time to write flicker prevention code for his Performance tab because he cared, and his successors didn&#8217;t even care enough to <em>invoke</em> that code on their Networking tab. What does that say about the code that actually manages tasks? I can only speculate, but I&#8217;m certainly glad Dave got to Task Manager first before they did.</p>
<p>Alright, then. Enough of that, back to this. Let&#8217;s turn off dynamically linking to the CRT in favor of static linking.</p>
<pre>Configuration Properties \ C/C++ \ Code Generation \ Runtime Library
	Multi-Threaded DLL (/MD) =&gt; Multi-Threaded (/MT)</pre>
<p style="padding-left: 40px;">Rebuilding nets us&#8230; <span style="color: green;"><strong>49,152 bytes!</strong></span> All profit! Wait&#8230;</p>
<p>Well we ditched our dll dependency but now we&#8217;re huge. Let&#8217;s try going cold turkey on Visual Studio&#8217;s CRT completely.</p>
<pre>Configuration Properties \ Linker \ Input \ Ignore All Default Libaries
	No =&gt; Yes (/NODEFAULTLIB)</pre>
<p style="padding-left: 40px;">Rebuilding gets us&#8230; <span style="color: red;"><strong>2 unresolved external symbol linker errors!</strong></span></p>
<p>Well that&#8217;s cold turkey for you. As I alluded to / blatantly stated earlier, we&#8217;re going to use a tiny custom CRT of our own to get by. This is what I meant by going off the reservation. It&#8217;s called minicrt and for now I&#8217;m going to completely gloss over the origin of this methadone and also kick these lame addiction metaphors. Kick &#8216;em like smoking. Dammit!</p>
<pre>Configuration Properties \ Linker \ Input \ Additional Dependencies
	minicrt.lib</pre>
<p style="padding-left: 40px;">Rebuilding gets us&#8230; <span style="color: green;"><strong>3,072 bytes!</strong></span> And some warnings about section merging. Well, what doesn&#8217;t these days?</p>
<p>In one shot we dropped a Visual Studio 2005 standalone program to a sixteenth of its size, and for what it&#8217;s worth killed off the IsDebuggerPresent() dependency. That&#8230; seems like a big deal. In fact, that was the whole ballgame! Any size reduction beyond that is penny ante and just for fun. I know, right, what are we waiting for?</p>
<p>At this point HideAutoUpdate.exe has four sections, each of which is aligned on a 512 byte boundary, which is a fancy way of saying that they&#8217;re multiples of 512, which to us means that each is a minimum of 512 bytes. If we can eliminate or merge some sections then the program gets smaller. First on the chopping block is the resource section .rsrc. The only reason a resource section is being built is so that the XML manifest that Visual Studio generates can be embedded there. The only use this interfaceless app had for a manifest was to contain the version info for the necessary CRT dll. Since we&#8217;ve eliminated that need, disabling the manifest will in turn eliminate the resource section.</p>
<pre>Configuration Properties \ Linker \ Manifest File \ Generate Manifest
	Yes =&gt; No</pre>
<p style="padding-left: 40px;">Rebuilding gets us&#8230; <span style="color: green;"><strong>2,560 bytes!</strong></span></p>
<p>As prophesied, there goes 512 bytes. We&#8217;re left with three sections: .text, .rdata, and .data. We&#8217;re stuck with their contents so we&#8217;ll merge them together. First up, merging .text into .data, and while we&#8217;re at it let&#8217;s silence the merge warnings.</p>
<pre>Configuration Properties \ Linker \ Command Line \ Additional Options
	/merge:.text=.data /ignore:4254</pre>
<p style="padding-left: 40px;">Rebuilding gets us&#8230; <span style="color: green;"><strong>2,048 bytes!</strong></span> And no more warnings!</p>
<p>That leaves .rdata and .data. Once more, with feeling:</p>
<pre>Configuration Properties \ Linker \ Command Line \ Additional Options
	/merge:.text=.data /merge:.rdata=.data /ignore:4254</pre>
<p style="padding-left: 40px;">Rebuilding gets us&#8230; <span style="color: green;"><strong>1,536 bytes!</strong></span> Ding ding ding!</p>
<p>It&#8217;s that simple, and yet that hard. Or rather I just made it look hard with all the gabbing. Maybe a quick recap can save this:</p>
<table style="margin-left: auto; margin-right: auto;">
<tbody>
<tr>
<td style="width: 100px;">Release baseline</td>
<td style="width: 80px; text-align: right; color: green;"><strong>6.5kb</strong></td>
<td style="padding-left: 20px;">Depends on a specific version of msvcrt80.dll.</td>
</tr>
<tr>
<td>/MD =&gt; /MT</td>
<td style="text-align: right; color: green;"><strong>48.0kb</strong></td>
<td style="padding-left: 20px;">Dll dependency elminated, but now we&#8217;re huge.</td>
</tr>
<tr>
<td>/NODEFAULTLIB</td>
<td style="text-align: right; color: red;"><strong>0kb</strong></td>
<td style="padding-left: 20px;">Visual Studio CRT eliminated but doesn&#8217;t build. Well, you can&#8217;t beat zero bytes.</td>
</tr>
<tr>
<td>minicrt.lib</td>
<td style="text-align: right; color: green;"><strong>3.0kb</strong></td>
<td style="padding-left: 20px;">Crazy small! IsDebuggerPresent() dependency removed.</td>
</tr>
<tr>
<td>/MANIFEST:NO</td>
<td style="text-align: right; color: green;"><strong>2.5kb</strong></td>
<td style="padding-left: 20px;">Eliminating resource section drops 512 bytes.</td>
</tr>
<tr>
<td>/merge:.text=.data</td>
<td style="text-align: right; color: green;"><strong>2.0kb</strong></td>
<td style="padding-left: 20px;">Merging sections drops 512 bytes.</td>
</tr>
<tr>
<td>/merge:.rdata=.data</td>
<td style="text-align: right; color: green;"><strong>1.5kb</strong></td>
<td style="padding-left: 20px;">Merging sections drops 512 bytes.</td>
</tr>
</tbody>
</table>
<p><a href="http://www.youtube.com/watch?v=BMdeD3YaY1g#t=0m20s">Numbers don&#8217;t lie</a>, replacing the Visual Studio CRT is how you make small programs small. Linker settings are peanuts. As we&#8217;ll see next time, this is old news.</p>
<p>I&#8217;d be remiss if I didn&#8217;t mention a few other settings. Though in this instance they didn&#8217;t affect file size, they do under other circumstances or are at least in the same spirit.</p>
<pre>Configuration Properties \ C/C++ \ Optimization \ Optimization
	Maximize Speed (/O2) =&gt; Minimize Size (/O1)</pre>
<p>HideAutoUpdate does so little that there&#8217;s nothing this setting can optimize further, and so it has no effect on it. On non-trivial programs it makes a difference, sometimes significantly. Both settings, /O1 and /O2, <a href="http://msdn.microsoft.com/en-us/library/8f8h5cxt.aspx">expand into a set of individual optimization settings</a>, most of which the two share so it&#8217;s not an either/or thing. You get a lot of the same optimizations either way.</p>
<pre>Configuration Properties \ Linker \ Optimization \ Optimize for Windows98
	Default =&gt; No (/OPT:NOWIN98)</pre>
<p>When set to Default, this optimization automatically kicks in <a href="http://msdn.microsoft.com/en-us/library/bxwfs976.aspx">once a program reaches a certain size</a>. This optimization changes the section alignment from 512 to 4,096, which makes a program load quicker on Windows 98. For small programs that means each section costs a minimum of 4kb instead of 0.5kb. HideAutoUpdate is so small that Visual Studio didn&#8217;t enable the optimization, but it should still be nipped in the bud. This setting was tripped when we first statically linked to the CRT and it contributed to the large 48kb file size. It would have been 37kb if the optimization was explicitly disabled.</p>
<pre>Configuration Properties \ Linker \ Debugging \ Generate Debug Info
	Yes (/DEBUG) =&gt; No</pre>
<p>It seems questionable to me that this is enabled by default for Release configurations. This setting embeds a string in the program to the full path of the program database file on your computer, which could easily be something along the lines of, oh I dunno, &#8220;C:\Documents And Settings\D.B.Cooper\My Documents\Visual Studio 2005\Projects\HideAutoUpdate\Release\HideAutoUpdate.pdb&#8221;. That feels like an inappropriate amount of information to be exposing by default, and frankly, a pretty lame way for <a href="http://en.wikipedia.org/wiki/D._B._Cooper">me</a> to go down.</p>
<pre>Configuration Properties \ General \ Character Set
	Use Unicode Character Set =&gt; Not Set</pre>
<p>To set the character set to ANSI, set the character set setting to Not Set. Think about that the next time you wonder what&#8217;s keeping normal people out of the industry. HideAutoUpdate has to use the ANSI versions of Windows functions to run on Windows 95, 98 and ME because ANSI versions are all those operating systems have. Otherwise I&#8217;d be in trouble for linking to <a href="http://msdn.microsoft.com/en-us/library/ms633499.aspx">FindWindowW() instead of FindWindowA()</a>. Dependencies!</p>
<p>Let&#8217;s never write this article again, shall we? Next time I swear to God I&#8217;m not going to mention a single compiler setting. Instead we&#8217;ll learn about the origin of minicrt.lib. Well&#8230; I&#8217;ll learn how to write an origin of minicrt.lib and you&#8217;ll learn how to fact check it. Also, source code. Until then, enjoy the compiled library. For a lot of modest programs simply using this will shrink them without complications. Others&#8230; not so much. Eventually we&#8217;ll see what can be done about those too.</p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/blog/files/minicrt.lib"><img src="/blog/files/lib.png" alt="" width="32" height="32" /></a></td>
<td><a href="/blog/files/minicrt.lib">minicrt.lib</a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/small-programs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HideAutoUpdate</title>
		<link>http://www.benshoof.org/blog/hideautoupdate/</link>
		<comments>http://www.benshoof.org/blog/hideautoupdate/#comments</comments>
		<pubDate>Mon, 15 Feb 2010 19:30:50 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=170</guid>
		<description><![CDATA[I think it&#8217;s safe to say that you&#8217;re familiar with this unabiding dude. Years ago I wrote a program to suppress Automatic Update&#8217;s repeated prompting by setting the window&#8217;s state to hidden. This simple parlor trick is easily the most well received program I&#8217;ve ever written. Ubiquitous loathing equals opportunity. There are more official ways to [...]]]></description>
				<content:encoded><![CDATA[<p class="imageContainer"><img title="Aye yo, I'ma holla at 'chall in ten aight?" src="http://www.benshoof.org/blog/wp-content/uploads/2010/02/autoupdate.png" alt="" /></p>
<p>I think it&#8217;s safe to say that you&#8217;re familiar with this unabiding dude. Years ago I wrote a program to suppress Automatic Update&#8217;s repeated prompting by setting the window&#8217;s state to hidden. This simple parlor trick is easily the most well received program I&#8217;ve ever written. Ubiquitous loathing equals opportunity.</p>
<p>There are more official ways to silence the nagging such as stopping the Automatic Update service but they require admin rights so that&#8217;s likely a non-starter if you&#8217;re at work. This low-brow, low-impact trick requires no special access and is a great compromise: you get prompted when you need to restart, which is good, and you can choose to dismiss the prompt without further prompting, which is also good. And if you do want to see the prompt again, just click Automatic Update&#8217;s icon in the system tray and it will return.</p>
<p>So let&#8217;s take a look at this unadulterated pinnacle of twenty first century technology:</p>
<pre class="brush: wincpp;">
// HideAutoUpdate by Chris Benshoof
//  the best flipping thing i'll ever write
#include &lt;windows.h&gt;
#include &lt;tchar.h&gt;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    HWND dialog = FindWindow(WC_DIALOG, _T(&quot;Automatic Updates&quot;));
    if (IsWindowVisible(dialog))
    {
        ShowWindow(dialog, SW_HIDE);
    }
    return 0;
}
</pre>
<p>Yup, a life well spent. There&#8217;s really not much to elaborate on, it&#8217;s easy to write self-documenting code when your entire program is three function calls. The reason this prevents the dialog from coming back is that as far as Automatic Update is concerned the dialog is already being shown. It&#8217;s only when the dialog is closed or minimized that Automatic Update considers it gone and in need of eventual resurrection. Automatic Update never considers the possibility that the dialog is hidden (why should it?) and so placation ensues. If it weren&#8217;t so thoroughly disrespectful to the civil rights movement to compare myself with a leader of nonviolent resistance, I would <strong>totally</strong> compare myself to a leader of nonviolent resistance.</p>
<p>I write a lot of programs like this, little ones that wrap around or make use of just a couple API calls. It&#8217;s kind of a stretch to even call them programs. They&#8217;d be scripts if I didn&#8217;t have to bust out a damn C++ compiler to do anything interesting in Windows. S&#8217;all in the game, yo. If I have to write some small programs then I&#8217;ll write some small programs. Fact is, I kinda like it. But if I have to <strong>compile</strong> some small trivial programs&#8230; well then I expect the resulting program files to be small, because they&#8217;re trivial. Who wouldn&#8217;t? Errrbody, apparently.</p>
<p>Next time we&#8217;ll get completely distracted by the issue of executable size in a modern Windows world without getting distracted by its questionable relevance. Until then, enjoy all 1.5kb of HideAutoUpdate.exe!</p>
<table class="attachments">
<tbody>
<tr>
<td><a href="/apps/HideAutoUpdate.exe"><img src="/blog/files/exe.png" alt="" width="32" height="32" /></a></td>
<td><a href="/apps/HideAutoUpdate.exe">HideAutoUpdate.exe</a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/hideautoupdate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction</title>
		<link>http://www.benshoof.org/blog/introduction/</link>
		<comments>http://www.benshoof.org/blog/introduction/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 10:30:10 +0000</pubDate>
		<dc:creator>Chris Benshoof</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.benshoof.org/blog/?p=140</guid>
		<description><![CDATA[Hello, my name is Chris Benshoof. It&#8217;s pronounced Benshoff. Thanks a lot, Germany. I&#8217;m a computer programmer and consequently I&#8217;ve written a number of computer programs over the years. Most are big and written for pay but it&#8217;s the smaller ones written for myself that I think are interesting. Not being one for self-promotion, insobriety [...]]]></description>
				<content:encoded><![CDATA[<p>Hello, my name is Chris Benshoof. It&#8217;s pronounced Benshoff. Thanks a lot, Germany.</p>
<p>I&#8217;m a computer programmer and consequently I&#8217;ve written a number of computer programs over the years. Most are big and written for pay but it&#8217;s the smaller ones written for myself that I think are interesting. Not being one for self-promotion, insobriety aside, these personal programs have gotten virtually no exposure. In order to even hear about them we’d need to be sharing a home, office, or pitcher of Pabst. That&#8217;s probably for the best as they&#8217;re geared towards a pretty specific and possibly eccentric audience, but it would be nice if someone besides me could get something out of them.</p>
<p>Whenever I&#8217;m done figuring out some computerish thing I fire up a text editor and write myself a note. Few things are as frustrating and humbling as learning something again from scratch, so these notes are desperate sandbags against time and forgetting. Written quickly and informally, they work, but there are limitations to the format. And again, it seems a shame that they only help me.</p>
<p>Now I find myself with a heap of programs and a grip of notes. Pawing through them I see an eclectic body of work, work that in theory other programmers might find interesting. Most of it is grounded in Windows programming but who knows, maybe someone out there still does that. Worst case scenario, it&#8217;s comic relief for everyone else.</p>
<p>So here&#8217;s the plan: I&#8217;m going to write about my programs and how they were built while wandering into ancillary note topics at the drop of a hat. This could take a while, but that&#8217;s okay. I have the time. Besides, what&#8217;s the worst that can happen? A little pretentious technical writing infused with awkward hip hop references ain&#8217;t never hurt nobody.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benshoof.org/blog/introduction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
