The ShellExecuteEx wrapper in MSLU

by Michael S. Kaplan, published on 2005/02/22 08:14 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2005/02/22/377992.aspx


The ShellExecuteEx wrapper in MSLU is a little bit broken.

Recently posted to the microsoft.public.platformsdk.mslayerforunicode:

The code looks a bit like this:

TCHAR filename[MAX_PATH];
TCHAR paramStr[MAX_PATH];
_tcscpy (filename, _T("C:\myapp.exe"));
_tcscpy(paramStr, _T("params"));

[...]

SHELLEXECUTEINFO ShExecInfo;
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = filename;
ShExecInfo.lpParameters = paramStr;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;

BOOL bExec = ShellExecuteEx(&ShExecInfo);

And it crashes within the ShellExecuteEx() call. I should also mention that this does not happen with every parameter string. However, I experimented a bit further, and found that the crash goes away if I initialize the SHELLEXECUTEINFO structure to zero, ie:

SHELLEXECUTEINFO ShExecInfo = {0};

Not really sure why or if this truely fixes the problem, but hopefully it'll prevent the crash.

Well, his workaround works, and quite well at that. And it is indeed an MSLU bug.

The problem? Well, MSLU is a tad over-eager, converting every string in the struct. Despite the fact that there are flags that one can pass to the API that limit which strings are valid. Obviously the NULL case works well, but the case where it is not NULL due to the memory not being initialized? Not so lucky there -- and the crash happens.

The workaround? Simple, as given above -- just initialize the SHELLEXECUTEINFO struct.

Obviously not a great answer, but so few reports over these past few years and who knows how many downloads? It is on the list as something that could be fixed if there is a future release, but looking at the Product Life-Cycle Information for Win9x. Obviously given all this and the fact that all Win9x platforms are in paid support phases (or no longer supported), the bar has to go up for MSLU fixes. It was over a year since the release before last (1.0.4018.0) to the most recent release (1.1.3790.0), and there are currently no bugs that meet the bar of not reasonably fixable by developers using MSLU.

I'm not expecting this to be the most popular decision with which I have ever been involved, but nearly four years after its release, the bulk of the bugs that have been reported have been fixed, and things have been slowing down for a while now.

So let's take a look at the infomation about overriding MSLU APIs. It is discussed here and here and with samples here and here. Any time one does not like a wrapper provided by MSLU, one can override it. Inside that override, one can even use LoadLibrary/GetProcAddress to call the MSLU API eventually. Such as after making sure to clear out unused fields in a SHELLEXECUTEINFO struct. :-)

I'm still around, I still watch the microsoft.public.platformsdk.mslayerforunicode newsgroup, and I still will post stuff here when it might be of interest....

This post brought to you by "₯" (U+20af, a.k.a. DRACHMA SIGN)


# Mike Dunn on 22 Feb 2005 10:28 AM:

This just reinforces the good practice of always zero-initializing your structs. I often see questions from people who are having trouble with a list or tree control, and many times their code can be fixed by zeroing the structs that are passed to the control (LVITEM, TVINSERTSTRUCT, etc).

# Michael Kaplan on 22 Feb 2005 9:43 PM:

That is very true -- and a point that people usually do not take into account when looking at the problem. :-)

go to newer or older post, or back to index or month or day