I am currently in the process of migrating some UI DLLs from VC6/MFC4
to VS2005/MFC8. I have hit a backward-compatibility issue that seems to
suggest that either something is very wrong in MFC8 or there are some
wrong assumptions in my DLLs that MFC4 doesn't catch.

My app/DLL arrangement is as follows:

[Third-party app].exe -- dynamically loads --> MyWin32DLL.dll --
statically linked to --> MyMFCDLL.dll

MyWin32DLL.dll is a pretty standard Win32 (UI) DLL whereas MyMFCDLL.dll
is a Regular (UI) DLL which is linked statically with MFC (although
with regard to the following problem it doesn't actually matter whether
I link MyMFCDLL with MFC statically or dynamically).

As shown above, MyWin32DLL.dll is bound to the main app at run-time
(using LoadLibrary etc.); MyWin32DLL is statically linked to
MyMFCDLL.dll.

MyMFCDLL is a regular DLL which has a static CWinApp instance. The
CWinApp constructor is therefore called when MyWin32DLL is loaded
(since MyMFCDLL is statically linked to it).

Within that constructor,the standard AFX state initialization takes
place

// initialize CWinThread state
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
ENSURE(pModuleState);
AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
ENSURE(pThreadState);
ASSERT(AfxGetThread() == NULL);
pThreadState->m_pCurrentWinThread = this;
ASSERT(AfxGetThread() == this);
m_hThread = ::GetCurrentThread();
m_nThreadID = ::GetCurrentThreadId();

but note that the current thread will be whatever thread is used to
load MyMFCDLL (automatically when MyWin32DLL is loaded).

Later, when MyWin32DLL needs to call the functions exported by
MyMFCDLL, another thread (out of my control) is used i.e. the UI thread
of MyWin32DLL.
[Remember the golden rule that a window's message processing must take
place on the same thread that was used to created the window - there is
no reference to CWinApp construction in that though that I'm aware of]

All my exported functions in MyMFCDLL.DLL do call
AFX_MANAGE_STATE(AfxGetStaticModuleState()) as required (and are called
by MyWin32DLL on the same thread).

One of MyMFCDLL's exported functions results in displaying a modal
property sheet and that works fine except...

in the property sheet's OnHelpInfo implementation which looks like:

BOOL CMyPropertySheet::OnHelpInfo(HELPINFO* pHelpInfo)
{
if (pHelpInfo->iContextType == HELPINFO_WINDOW) {
AfxGetApp()->WinHelp(pHelpInfo->dwContextId,
HELP_CONTEXTPOPUP);
}

return(TRUE);
}

This in turn causes the following to be called:

void CWinApp::WinHelp(DWORD_PTR dwData, UINT nCmd)
{
CWnd* pMainWnd = AfxGetMainWnd();
ENSURE_VALID(pMainWnd);