#256 Problems in CPrintDialogExImpl::GetDefaults()

v1.0 (example)
closed-fixed
None
5
2014-02-22
2012-08-23
Anonymous
No

The function CPrintDialogExImpl:: GetDefaults() in atldlgs.h is implemented like this in WTL81_12085 (and WTL81_11324):

HRESULT GetDefaults()
{
m_pdex.Flags |= PD_RETURNDEFAULT;
ATLASSERT(m_pdex.hDevMode == NULL); // must be NULL
ATLASSERT(m_pdex.hDevNames == NULL); // must be NULL

return ::PrintDlgEx(&m_pdex);
}

There are two problems with this function:

1 - The flag PD_RETURNDEFAULT is set but not cleared on exit. DoModal() will therefore assert and fail thereafter.

2 - ::PrintDlgEx() fails with error E_HANDLE if m_pdex.hwndOwner is NULL.
(tested on Windows XP (32bit) and Windows 7 (64 bits))

Both problems can be handled on the outside, but this is very easy to forget. The preferred solution is to fix the function. Here is a possible fix:

HRESULT GetDefaults()
{
ATLASSERT(m_pdex.hDevMode == NULL); // must be NULL
ATLASSERT(m_pdex.hDevNames == NULL); // must be NULL

if (m_pdex.hwndOwner == NULL)
if ((m_pdex.hwndOwner = ::GetActiveWindow()) == NULL)
m_pdex.hwndOwner = ::GetDesktopWindow();

m_pdex.Flags |= PD_RETURNDEFAULT;
HRESULT hr = ::PrintDlgEx(&m_pdex);
m_pdex.Flags &= ~PD_RETURNDEFAULT;
return hr;
}

Perhaps the m_pdex.hwndOwner should be set to NULL on exit if set by this function, but DoModal() does not do that.

How to reproduce the problem:

#include <atldlgs.h>
CPrintDialogEx pd;
ATLVERIFY(SUCCEEDED(pd.GetDefaults())); // Asserts here
if (FAILED(hr = pd.DoModal()))
{
ATLASSERT(false); // Asserts here
}

Discussion

    • assigned_to: Nenad Stefanovic
    • Group: --> v1.0 (example)
     
    • status: open --> closed-fixed
     
  • Fixed, commit #493