According to the docs for the DllMain function:
and the "best practices" document
What you can do inside the DllMain, and by extention, what you can do in the constructors and destructors of global objects is severly limited.
We have an MFC based COM server. In it's history it has occasionally caused various issues at some of our customers but we never really managed to pinpoint it.
In a recent build of the product, however we're getting crashes in the component almost each time.
Spending lots of time debugging trying to track down the issue, it appears to be a memory overwrite in a section of memory that is *ONLY* touched via calls to ::LoadLibrary and ::FreeLibrary.
Knowing about the dllmain issues, we started to dive into our code to attempt to figure out problem points.
One obvious violation is that EVERY MFC extention dll violates the "best practices" by using CRT's new to allocate CDynLinkLibrary. in doing so it also violates the "Don't call dll's other than Kernel32".
What's causing these particular calls to MFC (CDynLinkLibrary constructor and AfxInitExtentionModule (and the matching term)), and call to new to be guaranteed safe ?
The MFC document on initializing extension DLL's
Says it is guaranteed, although it's unclear why. I can only guess it's saying that assuming that you have an application that uses MFC and loads your etention DLL. if you have an COM object that uses an extention DLL, that's created from an application that doesn't use MFC what still gives you that guarantee ?
Furthering on the issue however, there's a massive amount of the DllMain and Best practices guideline violations buried inside the MFC dll itself.
In afxglobals.cpp, there's this 'little' hidden item.
This is a global object constructed during DllMain (well the CRT version of DllMain at least) and is destroyed there as well.
The constructor violates the DllMain 'ruels' because:
- It does LoadLibrary and FreeLibrary several times
- it calls GetProcAddress
- It uses AfxActLoadLibrary/AfxActFreeLibrary, which is synchronisation (also not allowed)
- It calls functions from user32.dll (GetSystemMetrics, GetSysColor, EnumDisplayMonitors, ...)
- It calls functions from Gdi32.dll (CWindowDC constructor/destructor, DeleteObject, CreateFontIndirect, CreateStockObject, CreatePen, CreateBrush...)
- it calls functions from Shell32.dll (SHAppBarMessage)
Is all the above guaranteed to be safe when MFC dll is being loaded and unloaded dynamically as a result of it being part of the implicit linking of a COM dll ?
The crash we're having now would seem to indicate that at least "something" is going wrong somewhere in the LoadLibrary/FreeLibrary sequences.
I'm having the suspicion that at current MFC is intended only for implicit linking to applications, but in-process COM servers that are loading MFC extension DLL's aren't supported ?
This is in VS2008, we can't yet swap to VS2010 (we still need to support Win2000).
But as far as I had a chance to look at the MFC100 code, this is still more or less the same.