Parks Computing

Welcome to the personal web site of Paul M. Parks. This is where I keep my web development skills current while sharing snippets of code, utilities, libraries, and what little development wisdom I've gathered in my career. It's also where I show off my family, talk about my hobbies, or just pontificate from time to time.

If you find the articles interesting, or if you'd like more information on a particular topic, let me know [paul@parkscomputing.com].

An API is Forever

An API is an interface. Those of you that have worked with COM already know that once an interface is published, it can never, ever change. Ever. Not until the end of time. The reason is that some bit of code somewhere is going to be using that interface, and if you change it you've just broken that code. Of course, not changing an interface also means not deleting a portion of it.

At my job I have worked on, and currently maintain, a few APIs implemented in Windows DLLs, some of which have been around for a long time. I had to rewrite significant portions of the internal implementation of one particular DLL in order to add some new features, fix several bugs, and improve the overall performance of the DLL. The old API exposed from the DLL wasn't able to take advantage of the new features, and it wasn't designed all that well to begin with. Since nearly all of the use of that API was through a C++ template wrapper implemented a header, I just added a new set of API functions and changed the wrapper to use the new API.

I did some digging around in the code base (it's a huge code base) to see what else was using the class wrapper around the DLL, and I found out that the component was in far more widespread use than I had anticipated. There were components in all corners of the code base using it now.

The component was still desperately in need of a new API, so what I did was write a new one and forward the old API to the new API. I changed the header file that declared the API functions to look like this:

FICTIONAL_API void NaDoStuff(
HANDLE hFict,
DWORD flags,
LPCSTR name,
LPCVOID bytes,
DWORD byteCount,
LPCSTR desc);

// The rest of the new API was declared here...
// ...
// ...

/************************************************************************
Old, deprecated API. This API is still supported, but calls to all of
these functions are now forwarded to the new API described above.
Please use only the new API in new code.
************************************************************************/

/* DEPRECATED: Use NaDoStuff instead. */
FICTIONAL_API BOOL OaDoStuff(
HANDLE hFict,
DWORD flags,
LPCSTR desc,
LPCVOID bytes,
DWORD byteCount);

// The rest of the old API was declared here...
// ...
// ...

I hoped that the comments would make clear that the use of the old API is discouraged, and that any clients should move to the new API. Likewise, in the implementation, I forwarded the old API functions to the new API functions:

FICTIONAL_API void NaDoStuff(
HANDLE hFict,
DWORD flags,
LPCSTR name,
LPCVOID bytes,
DWORD byteCount,
LPCSTR desc)
{
// Go do stuff
}

// Elsewhere in the code..

FICTIONAL_API BOOL OaDoStuff(
HANDLE hFict,
DWORD flags,
LPCSTR desc,
LPCVOID bytes,
DWORD byteCount)
{
NaDoStuff(hFict, flags, "", bytes, byteCount, desc);
return TRUE;
}

In some cases, forwarding the old API to the new API meant that I had to make the new API implement the semantics of the old API whenever it was being called through the old API functions. For example, the old API had a nasty habit of writing sub-keys all over the company's registry key under HKLM\SOFTWARE. I made the new API put these settings into a tidy sub-key that belonged to the API, like HKLM\SOFTWARE\ComanyName\Fictional. It would even hunt down the all of the old keys created by the old API and move them into the new sub-key. In a later story I'll explain why I had to preserve that behavior in the old API, but for now just remember that I did.

Recently, a co-worker changed a customer-specific branch of the archive so that it would point to the newest implementation of this component. He was writing an application using some libraries that called this component's API. He asked me to help with at a problem he was having, and when I went to look in the registry at some of the settings the API had written, I was dismayed to find that the settings were in the old location, all over the root of the company's HKLM\SOFTWARE key. At first, I thought that he was still somehow using the old DLL, but when I checked the version information on the DLL it was, indeed, the new one. How could this be?

As I mentioned above, most clients use this DLL through a C++ wrapper, since most of the archive is now C++. Only a handful of older C modules call this API directly. The wrapper is a C++ template class, which means it is implemented in a header file. This customer archive was still pointing at the old version the header that called the old API. As I mentioned above, the new API preserves the semantics of the old API when it is called through the old API, and that's what we were seeing here.

My first suggestion, without really thinking about it, was to change the archive to point at the newer header. My co-worker pointed out that this would mean rebuilding all of the components in the archive that used the header, not just the one he was working on.

We left it alone, and everything is working as it should be. At some point in the future we'll move all of the other components up to the newer version of the wrapper, and they'll start seeing the behavior associated with the new API. In the meantime, the customer still benefit from a less buggy and more efficient component.

Labels: , , ,

Posted May 8, 2009 2 Comments

Useless Gadget Features

I guess I would never make it as the CEO of some electronic gadget company, because I would never dream of loading down every gadget with a web browser and a picture viewer. I love my Nintendo Wii; I've spent hours playing Mario Kart or bowling with the kids. I even got Wii Fit, though I use the Balance Board more for Shaun White Snowboarding (and get a better workout doing it). But I've never looked at pictures on my Wii. I've only browsed the web just to see what it looks like, and whether a couple of my sites were readable (not very).

So, I'm dying to know why gadget companies feel that it's necessary to load down every product with useless stuff like this? If a professional geek like me doesn't even bother to use these features, then who is using them?

I'd much rather see gadget makes spend some time and resources on the core functionality of their gadgets (do you hear me, phone people?) than on browsing, social networking, or photo viewing.

Labels: , ,

Posted May 6, 2009 0 Comments

Looking for Havanafolks.com?

The site www.havanafolks.com should be working fine now. If you still can't get there, please let me know. I apologize for messing up the redirect yesterday. I share web space with my brother Phil, and yesterday when I was converting to Blogger I messed up the redirect that forwards his traffic to his folder. He actually gets a lot more hits than I do, so I feel pretty bad. Sorry, bro!

By the way, the picture is of me and my brothers, Phil and Steve. It was taken at my parent's 50th wedding anniversary / family reunion a couple of years ago, and I think it probably says all I need to say.

Labels: ,

Posted April 27, 2009 0 Comments

Guitar Videos

I've uploaded some videos of me playing the guitar to my YouTube site. Go take a look and let me know what you think.

I've got a lot more stuff that I plan to upload, such as a step-by-step instructional video series on how to play Spanish Fly, which is so far the second most-difficult piece I've ever learned. The most difficult, by far, is Paganini's Caprice No. 24. I'm still trying to polish that one before I post it.

Here's a sample:

Labels: ,

Posted April 26, 2009 0 Comments

Updating More Often

I wired my site up to Blogger so now I won't have any excuse for not updating my site more often. Maybe now I'll drop a new entry in every few days, or perhaps even start writing regular articles.

There's still a lot of content linked from my top menu that's old and out of date. I will probably start moving a lot of that to archive eventually and replace it with more up-to-date content.

Labels: ,

Posted 0 Comments

Pre-emptive Snarkiness

It's all about the sense of humor, people. First of all, read the "pre-emptive snarky comment" that I wrote in the earlier entry about the dragsens utility. It's pretty clear that, first of all, I'm tipping my hat to Raymond Chen by even adding a pre-emptive snarky comment. Second, it should also be clear that I'm mentioning the size only because I'm trying to head off any snarky comments about it. Alas, that just doesn't stop some people.

In my first comment to Raymond's article I mentioned that it took me only eleven minutes to write the utility. That was the entire point of the exercise, really. If the utility happens to be useful as well, that's fantastic. In fact, the reason that I bothered to take an extra 30 seconds and link in the C runtime was to make it easier to use. Just copy it to your favorite USB drive, and off you go. If you don't have 84KB free on your drive for the ZIP file, then that's still okay. You can download the source and VS project and build it any way you like. Not a problem.

So, despite the fact that I clearly stated that I was aware that I could make the utility very tiny if I wanted to take the time to do so (when I said, "Of course you could. So could I."), someone still didn't get it. I guess quoting me out of context, or perhaps even putting words in my mouth, is more fun.

If I wanted to make it smaller, perhaps I could dispense with the CRT altogether. Perhaps I could write it in assembly language. Who knows. It doesn't matter. I just wasn't inclined to take any more time gold-plating what I regarded as a very simple exercise. The utility does what it is supposed to do, with a very tiny investment in programming time. That's all I was out to prove. I made the source freely available, with no strings, in case anyone wanted to tweak it to handle some situation that I didn't think about, or perhaps wanted a different implementation (like setting the width and height separately).

As Raymond might say, I can't believe I had to write that.

Labels: ,

Posted April 15, 2009 0 Comments

Windows Drag Sensitivity Utility

Inspired by an article by Raymond Chen about how to correctly change the Windows mouse drag sensitivity, I wrote a quick utility called dragsens. It's a small command-line utility that will allow you to change the number of pixels the mouse has to travel before a drag operation is initiated. Just download and unzip the utility, then run it at the command line, supplying a single parameter that is the number of pixels for the mouse to travel.

In Raymond's honor, I'll provide my own pre-emptive snarky comment: "That executable is 164KB! I could write that in for in only 4KB!"

Of course you could. So could I. I linked in the C runtime library so you wouldn't have to install the Visual Studio 2008 distributable package just to run a simple command-line utility. I don't normally do that with typical desktop applications, but for small utilities like this is saves a lot of trouble.

If you'd like modify the utility, or examine its source, you may download the Visual Studio 2008 project. If you just want the utility itself, you may download a ZIP of the executable.

About the Utility

The utility is actually very simple. It accepts a single parameter, which is the number of pixels the mouse must travel with a button depressed before the motion registers as a drag action. Rather than separate out the width and height, I just set both to the same number since this is generally all that's necessary.

BOOL success = FALSE;

success = SystemParametersInfo(SPI_SETDRAGWIDTH, numPixels, NULL, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

if (!success)
{
DWORD error = GetLastError();
std::wcout << L"Error " << std::hex << error << std::dec << " while setting drag width." << std::endl;
return 1;
}

success = SystemParametersInfo(SPI_SETDRAGHEIGHT, numPixels, NULL, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

if (!success)
{
DWORD error = GetLastError();
std::wcout << L"Error " << std::hex << error << std::dec << " while setting drag height." << std::endl;
return 1;
}


It would be fairly simple to modify the application to set the width and height independently, if you so desired.

Update

I'm already at version 1.1. I decided to add a version resource and support for a "/?" parameter.

About the Snarky Comments

Please see the entry entitled Pre-emptive Snarkiness for my response to the comments about my utility that were posted on Raymond's blog.

Labels: , ,

Posted April 10, 2009 1 Comments

A New, New Wiki

I've replaced the old Wiki with a new Wiki based on the Mediawiki engine. This is now the official Wiki for the Undernet IRC channels #c++ and #c++/cli. It's still in the beginning stages, so feel free to create an account and start adding articles.

Labels: ,

Posted June 7, 2007 0 Comments

Barcode Generator

More fun with one of my favorite languages: A barcode generator written in JavaScript that will create an EAN-13 barcode. The page is completely self-contained and uses no graphics or server-side code.

I've only tested the page in Internet Explorer 6, Internet Explorer 7 beta, and Firefox 1.5. I'm not going to target older browsers, but I am interested in hearing about problems in current browsers other than those mentioned above.

Labels: , ,

Posted May 18, 2006 0 Comments

Lisp Interpreter in JavaScript

Lisp is becoming a theme here, apparently. I suppose I've read so many Paul Graham essays that I'm becoming a fan of the language. In order to become more familiar with it, I decided to write a Lisp interpreter in JavaScript. It's not quite complete, and the semantics are definitely not entirely correct, but it's at least usable. The page is even partially scripted in Lisp, and as I debug the interpreter and add more to it (such as loop constructs) I'll convert more (and eventually all) of the JavaScript to Lisp. Once you browse to the page, view the source and scroll down until you see a <script type="text/lisp"> block.

I have only tested the interpreter in Firefox and Internet Explorer 6, so I'd like to know how it works in other browsers. If you want to look over the interpreter code, download it and play around with it. If you make any additions, changes, or corrections, I'd love to hear about them so I can incorporate them into the code.

Labels: ,

Posted February 23, 2005 0 Comments

Lisp for C++ Templates

I'm not working quite as many hours as I was earlier in the year, so I'm able to concentrate on more long-term projects of my own in addition to my regular work responsibilities. Before I get back to the Accelerated C++ Solutions I'm going to play around a little bit with extreme template meta-programming in C++. Toward this end, I am implementing Lisp primitives with C++ templates for manipulating typelists. So far I only have the primitives online, but I'll hopefully have some examples of their usage up soon.

Labels: ,

Posted December 16, 2004 0 Comments

The pbrain Programming Language

I've been working really hard lately - 70 or more hours a week. Consequently, I haven't had many opportunities for diversion. After staring at the same application all day, every day, though, it's important to step away and give my brain another puzzle to solve now and then. One such late-night/early-morning excursion produced The pbrain Programming Language. This language is an extension of an extremely tiny Turing-complete language called Brainf**k (yes, the name contains a really, really bad word).

Update: A pbrain Compiler for .NET

Since I was halfway home with the interpreter, I decided to go ahead and write a compiler for .NET platforms.

Labels: , , , ,

Posted July 14, 2004 0 Comments

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]