Why does shlwapi import a nonexistent function?

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 shlwapi.dll was originally developed for Internet Explorer, which ran on Windows 95 as well as Windows NT. Internet Explorer checked the operating system and called the Windows 95-only function only after verifying that it was running on Windows 95. If it was running on Windows NT, then it never called the function and therefore never stepped on the land mine known as ERROR_PROC_NOT_FOUND.

Okay, so why does shlwapi still link to the function long after the Windows 95 series of operating systems have become obsolete?

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 shlwapi, then that program will fail to load, even though it never calls the offending function, and now you have an application compatibility problem on your hands.

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)
  1. Gabe says:

    You could leave the function in shlwapi, but take out its call to a non-existent function — just to get rid of the warning.

  2. Somone You Know says:

    @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.

  3. Steve says:

    @Medinoc – Im my experience filing bugs for several products at Microsoft, the main questions when considering hot fixes are:

    1. What is the problem you are fixing?
    2. What is the impact of the problem?

    3. What is the cost of the fix?

    4. 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.

  4. configurator says:

    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.

  5. porter says:

    So does WIN32 actually use lazy binding (resolve on first use)? Or is the import somehow marked ‘weak’?

    [Old topic. The import is runtime-generated via GetProcAddress, but there are tools which know how to decode the delay-load information. -Raymond]
  6. Absotively says:

    @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.

    [You’d be surprised what third-party applications redistribute where. -Raymond]
  7. Absotively says:

    @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.

  8. "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.

  9. Aaargh! says:

    "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 ?

  10. porter says:

    > When /are/ you allowed to ‘break’ stuff ?

    Situation normal. Any change should go through change management and impact analysis.

  11. someone else says:

    “When /are/ you allowed to ‘break’ stuff ?”

    When it seriously impacts security. See session 0 isolation for an example.

  12. John says:

    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.

  13. Alexandre Grigoriev says:

    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.

  14. porter says:

    > All those Path* functions lacking "buffer size" argument make me want to puke.

    It’s almost as if MAX_PATH had never been defined….

  15. Adrian says:

    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.

  16. Médinoc says:

    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").

  17. Anonymous Coward says:

    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 I remember correctly, its interfaces were published as a result of anti-trust lawsuit, which is a shame.

    If true, that is another fine example that lawyers can’t code and shouldn’t be able to force their broken code upon us.

  18. 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.

  19. Tihiy says:

    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.

  20. w9x 4ever says:

    There were hostilities between the teams. They didn’t play well.

  21. 640k says:

    The function could have been removed in 64-bit windows because there isn’t any 64-bit windows 95. But it wasn’t.

  22. GPBurth says:

    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?

  23. John says:

    One of our web logs shows someone accessing our site with IE 5.5 on Windows 95 on 10/5/2009

  24. Yuhong Bao says:

    "Windows 95-series"

    Are you confusing Win95 with Win9x, which also include 98 and Me?

  25. Yuhong Bao says:

    After reading this another time, no you aren’t, but I think "Win9x-series" would still be better.

  26. Yuhong Bao says:

    "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.

  27. Marc K says:

    >>> 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.

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index