
Programming Pitfalls: Off the beaten PATH
Learn why you shouldn't always rely on the target environment to match your own.
Welcome to Brain Food!
This is the first in a series of articles sharing the knowledge and experience we’ve gained from building and running OpenCandy, and provoking the kind of thinking that we hope will lead to better software. We work with everything from JavaScript, HTML, PHP and MySQL through C/C++, the Win32 APIs, and a wide range of installer platforms to design intuitive products and services. Our articles will vary in the topics covered, level of detail and technical discussion, and will include everything from general overviews and development- anecdotes to detailed designs and source code.
Today’s Brain Food is sustenance for developers, and is a small but useful reminder about some of the assumptions often made when spawning processes with well-known image names, such as RunDll32.exe. In brief, don’t make too many assumptions about the PATH environment variable when using Windows process APIs, such as _spawn().
Let’s look at a quick example. Say we wanted to launch the Internet Options control panel. One way to do so is using the process APIs provided by Visual Studio’s Runtime libraries, specifically _spawnl().
This is what it looks like:
intptr_t _spawnl(int mode, const char *cmdname, const char *arg0, const char *arg1, ... const char *argn, NULL );
The following code looks like it will launch the control panel we want. It’s done by spawning a RunDLL32.exe and calling the Control_RunDLL export procedure from shell32.dll.
intptr_t ret=_spawnlp(_P_NOWAIT, "RunDll32.exe","RunDll32.exe", "shell32.dll,Control_RunDLL inetcpl.cpl", 0);
The only problem is when the code runs, no control panel appears. After monitoring the system you determine the Control_RunDLL procedure isn’t being called so you check the usual suspects:
- Is the process being spawned?
- Does the RunDll32.exe process crash?
- Is there something wrong with the MessageBoxA function or the way it’s being called?
- Is there something wrong with the loading of shell32.dll?
Everything looks fine, so what could be wrong? Chances are the PATH environment variable doesn’t include a reference to the System32 directory, preventing _spawnl() from locating RunDll32.exe!
The lesson? Don’t always expect relative paths to be resolved automatically. Calling GetSystemDirectory to get an absolute path to both RunDll32.exe and inetcpl.cpl is well worth the trouble from a robustness perspective.
That’s it for this time! Stay tuned to Brain Food for more information, tips and hints.
Adrian Bourke is a handyman at OpenCandy working on everything. Check out Adrian’s bio.

This post is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.
