Date: | November 16, 2009 / year-entry #363 |
Tags: | history |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20091116-00/?p=16023 |
Comments: | 27 |
Summary: | Commenter charless asks why shlwapi.dll imports a nonexistent function from mpr.dll, which shows up in dependency tools as a broken import. Because that function did exist at one point, although it doesn't exist any more. The function in question was available only on Windows 95-series versions of Windows. It never existed on Windows NT or any of... |
Commenter charless asks why shlwapi.dll imports a nonexistent function from mpr.dll, which shows up in dependency tools as a broken import. Because that function did exist at one point, although it doesn't exist any more. The function in question was available only on Windows 95-series versions of Windows. It never existed on Windows NT or any of its successors. But remember that Okay, so why does Removing a function, even a function that doesn't do anything, even an undocumented function that doesn't do anything, is a dangerous endeavor. Suppose you have a program that links to the function, but just like Internet Explorer, it is clever and checks whether it is running on Windows NT before calling it. If you remove the useless function from Since it's a small function that doesn't do anything, it's a lot less risky simply to leave the function in. Even though it doesn't do anything except fail. |
Comments (27)
Comments are closed. |
You could leave the function in shlwapi, but take out its call to a non-existent function — just to get rid of the warning.
@Médinoc, Gabe:
Removing the call to the non-existent function would break software that needs to be able to use the function when running on Win95. I am not sure whether this is still a valid concern at this point.
@Medinoc – Im my experience filing bugs for several products at Microsoft, the main questions when considering hot fixes are:
What is the impact of the problem?
What is the cost of the fix?
What is the risk of this code change?
If you think through those questions as they relate to this scenario, the average dev team would reject the fix request.
I think simply because nobody cares. The cost of "developing" and testing the emptiness of the method is much more costly than leaving it in.
So does WIN32 actually use lazy binding (resolve on first use)? Or is the import somehow marked ‘weak’?
@Someone You Know: It seems very, very unlikely that a new version of shwlapi would be distributed to Win95 at this point in time. It can’t break on Win95 if it isn’t installed on Win95.
@Raymond: Oh, good point. I think this is what I love about your blog; the skillful mixture of neat technical tidbits and spine-chilling horror stories.
"The import is runtime-generated via GetProcAddress, but there are tools which know how to decode the delay-load information"
Okay, so shlwapi is actually doing the Right Thing for calling a foreign function that may or may not exist. And dependency tools choose to report that as a "broken import" just because they find themselves running in an environment where the function in fact doesn’t exist (which is one of the two cases that one must assume that code using GetProcAddress will know how to handle)?
I’d call those dependency tools "broken" instead.
"Removing a function, even a function that doesn’t do anything, even an undocumented function that doesn’t do anything, is a dangerous endeavor."
But if you can’t even remove a function that is undocumented, doesn’t do a thing and is only used by a few misbehaving applications, what /can/ you actually remove or change when building the next version of Windows ? Do you just add code and leave the old in ? Is anything ever deprecated ? When /are/ you allowed to ‘break’ stuff ?
Situation normal. Any change should go through change management and impact analysis.
“When /are/ you allowed to ‘break’ stuff ?”
When it seriously impacts security. See session 0 isolation for an example.
Henning Makholm: And how can a dependency tool tell the difference between running on a platform where the function doesn’t exist (by design) and running on a platform where the DLL is broken? Are you advocating that all missing delay load dependencies be ignored? THAT design would be broken.
Shlwapi should never have been exposed to the ISVs in the first place. At least, it should have been went through through interface design review. If I remember correctly, its interfaces were published as a result of anti-trust lawsuit, which is a shame. All those Path* functions lacking "buffer size" argument make me want to puke.
It’s almost as if MAX_PATH had never been defined….
As usual, a timely post.
I spent Thursday and Friday in DLL Hell, trying to find a tool that could explain why XP failed to load a particular executable. The only problem indicated by depends.exe was this shlwapi issue. I lost a couple hours chasing that red herring.
The actual problem was a side-by-side version mismatch. Unfortunately depends.exe doesn’t understand side-by-side.
Now I’m going to ask the only slightly less stupid question before anyone does it without hanging a lampshade on it:
Why has this function in shlwapi not been replaced with a stub that *doesn’t* reference the imported function?
(I feel that the answer is of the style of "if it ain’t broke, don’t fix it").
According to the documentation, the only argument with a Unicode concern is the volume name:
Pointer to a null-terminated Unicode string that specifies the local name of the drive to connect to, such as "Z:". If this parameter is NULL, the function reconnects all persistent drives stored in the registry for the current user.
(documentation from the wide version of the function)
So why was this particular design chosen, a wide function on NT and an ansi function on 9x?
Why didn’t they do what they normally do with functions like this, having both available and working on NT, and the wide version either working on 9x or supported by MSLU, or even only an ansi version?
Given that since the parameter is a drive letter or NULL neither solution would have posed problems and both would have allowed developers to call the function in a platform agnostic manner.
If true, that is another fine example that lawyers can’t code and shouldn’t be able to force their broken code upon us.
It can’t break on Win95 if it isn’t installed on Win95. -Absotively
[You’d be surprised what third-party applications redistribute where. -Raymond]
I’m afraid if the modern version of shlwapi.dll is installed on Win95, this import from mpr.dll will be the least of the user’s problems ;) It probably was not tested for Win95 for a long time, and this means things will break.
Well it’s just unscientific that win95 has WNetRestoreConnectionA and NT WNetRestoreConnectionW only… But i guess they have different parameters due to 9x/NT teams weird cooperation.
There were hostilities between the teams. They didn’t play well.
The function could have been removed in 64-bit windows because there isn’t any 64-bit windows 95. But it wasn’t.
ok, so another "I’m ignorant on the exact workings"-question:
if removing the reference is so costly why not adding the missing function in mpc.dll as a do-nothing stub?
Sure, that *could* shuffle bytes around etc showing some bugs not otherwise seen, but when doing major testing for a new windows version anyhow, this shouldn’t be a major problem, right?
One of our web logs shows someone accessing our site with IE 5.5 on Windows 95 on 10/5/2009
"Windows 95-series"
Are you confusing Win95 with Win9x, which also include 98 and Me?
After reading this another time, no you aren’t, but I think "Win9x-series" would still be better.
"Okay, so why does shlwapi still link to the function long after the Windows 95 series of operating systems have become obsolete? "
Seems that the Vista version of shlwapi finally got rid of this import.
>>> All those Path* functions lacking "buffer size" argument make me want to puke.
> It’s almost as if MAX_PATH had never been defined….
Yeah, MAX_PATH and the Path* functions are responsible for the hoards of apps out there that can’t handle file paths longer than 255 characters.