When does SHLoadInProc unload a DLL?


The SHLoadInProc function instructs Explorer to create an instance of a particular CLSID. This causes the DLL responsible for that CLSID to be loaded.

But when is it unloaded?

This is one of those puzzles you should be able to figure out by thinking about it.

Consider: The object is created by calling CoCreateInstance and then immediately releasing the returned object. That’s all. Explorer pays no attention to your DLL from then on.

With this hint, maybe now you can answer the question: When is it unloaded?

Still don’t know? Here’s another hint: The issue is no longer a shell issue. Now it’s a COM issue.

When is any DLL loaded via CoCreateInstance unloaded?

Answer: The DLL is periodically asked whether it is safe to unload. Once the DLL response in the affirmative (via S_OK), COM will unload it.

Comments (13)
  1. That’s not quite true – it actually waits 10 minutes AFTER you respond that it’s safe to unload. The CoFreeUnusedLibraries API can force them to be unloaded.

    I ran into this issue when stopping audiosrv on longhorn :)

  2. Jack Mathews says:

    Haha, I like how you make it seems like the answer is cut and dry, but yeah, the actual answer is "whenever explorer feels like unloading it after DllCanUnloadNow." Which is sensible enough, because if it was constantly loading and unloading context menu or icon shell extensions, that would be a performance nightmare.

  3. Serge Wautier says:

    What’s the purpose of this function ? Why would one want the shell to create an object and then release it immediately ?

    TIA for your lights.

  4. Mike Dunn says:

    Serge> Getting a DLL into another process is the first step in spying on APIs, or subclassing windows, or other neat tricks.

  5. M Knight says:

    Larry Osterman > That’s not quite true – it actually waits 10 minutes AFTER you respond that it’s safe to unload.

    You can force windows to upload the DLL directly after instead of the ten minute wait.

    I know this is supported in the Windows 9x line, but I’m not to sure if its officially supported under Windows 2000 and onwards.

  6. Cooney says:

    Why would one want the shell to create an object and then release it immediately ?

    So that you can examine its unload behavior. Don’t want other stuff cluttering your view.

  7. M Night: According to CoFreeUnusedLibrariesEx(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmf_a2c_19yw.asp), if the 10 minute delay wasn’t in place, there could be a deadlock.

    Of course calling CoUninitialize for the last time in an apartment causes all the DLL’s loaded in that apartment to be unloaded, so…

  8. David Candy says:

    I think M Knight is referring to the reg key for debugging to unload dll straight away

    It is for system prior to 2000

    Unloading the DLL

    The Shell automatically unloads a DLL when the DLL’s usage count is zero, but only after the DLL has not been used for a period of time. This inactive period might be unacceptably long at times, especially when a Shell extension DLL is being debugged. For operating systems prior to Windows 2000, you can shorten the inactive period by adding the following information to the registry.

    HKLM

    Software

    Microsoft

    Windows

    CurrentVersion

    Explorer

    AlwaysUnloadDll

  9. A long time ago, the shell did its own COM activation of shell extensions instead of actually calling through to COM. This caused no end of grief so they eventually fixed it.

    I bet that this API is left over from the non-COM activation.

  10. Skywing says:

    Presumably the dll’s reference count becomes positive again and it’s reused.

    This optimization is probably why dlls aren’t unloaded instantly by COM in the first place…

  11. Waleri says:

    OK, but if COM waits 10 min. *AFTER* call DllCanUnloadNow() and then unloads the DLL, what will happens if one create another object from this DLL?

  12. Tom Mason says:

    This reminds me of a bug in ATL to do with window subclassing.

    When an ATL based dll creates a control window using CContainedWindow or CWindowImpl

    it registers a window class with an address for the windowproc but then fails to

    unregister it when the window is destroyed. If a second dll is later loaded at

    the same base address as the first and creates a window with the same class

    name, the original windowproc address is not overwritten. This then caused an

    access violation when windowproc was called at an invalid address, or more often in an unexpected bit of code. see MSDN KB article

    Q248400 for more details. What made me think of this was that the bug only occured when the first DLL was unloaded and typically this happened whenever windows thought it would cause most confusion.

    We solved this bug by adding a fix into atlwin.h to always unregister

    window classes. IIRC the bug could also be avoided by linking to ATL.dll rather than by building in release min dependency because then the windowproc address for AtlAxWindow was always the same.

  13. Ben Hutchings says:

    Larry Osterman: The way I read the description, the delay is recommended for compatibility with broken COM DLLs that lie and claim to be ready for unloading too early. There’s no inherent risk of deadlock (and if there was, merely delaying a bit surely wouldn’t eliminate it).

Comments are closed.