Why is CWnd::CreateEx failing to create my window?

2019-08-14 16:30发布

问题:

I'm working on a sporadic production issue that's occurring within our 32 bit MFC VC2010 application. The application is running on Windows Server 2008 R2 Standard SP1 64-bit.

The issue is caused by a failure to create a CWnd derived class. When the failure occurs the AfxUnhookWindowCreate method returns false within CWnd::CreateEx. This is because the pThreadState->m_pWndInit variable is not NULL. It looks like _AfxCbtFilterHook should be setting this to NULL when HCBT_CREATEWND is hooked, but it appears this is not occurring. I've logged out the CREATESTRUCT and compared it to when the failure occurs vs. doesn't occur and the parameters are essentially the same.

Does anyone have ideas on what could cause this or how I could identify the cause? Thanks!

BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{
...
if (!PreCreateWindow(cs))
{
    PostNcDestroy();
    return FALSE;
}

AfxHookWindowCreate(this);
HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass,
        cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
        cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
...
if (!AfxUnhookWindowCreate())
    PostNcDestroy();        // cleanup if CreateWindowEx fails too soon
...

BOOL AFXAPI AfxUnhookWindowCreate()
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
  #ifndef _AFXDLL
if (afxContextIsDLL && pThreadState->m_hHookOldCbtFilter != NULL)
{
    ::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
    pThreadState->m_hHookOldCbtFilter = NULL;
}
  #endif
if (pThreadState->m_pWndInit != NULL)
{
    pThreadState->m_pWndInit = NULL;
    return FALSE;   // was not successfully hooked
}
return TRUE;
}

LRESULT CALLBACK
_AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
if (code != HCBT_CREATEWND)
{
    // wait for HCBT_CREATEWND just pass others on...
    return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
        wParam, lParam);
}

 ...
        pThreadState->m_pWndInit = NULL;

回答1:

I tracked the problem down to a window procedure hook that shouldn't have been executing at this time.