调用DocumentProperties时缓冲区不足,全局解锁也无法解锁

时间:2010-05-10 22:46:22

标签: c++ windows printing getlasterror

请参阅内联评论

bool res = false;
DWORD dwNeeded = DocumentPropertiesW(NULL, m_currPrinterHandle, (LPWSTR) m_currPrinterName.c_str(), NULL, NULL, 0); 
if (m_devmode_buf)
{
    GlobalFree(m_devmode_buf);      
}
m_devmode_buf = GlobalAlloc(GPTR, dwNeeded);
GetLastError(); // = 0;
if (m_devmode_buf)
{
    LPDEVMODEW devmode_buf = (LPDEVMODEW) GlobalLock(m_devmode_buf);        
    GetLastError(); // = 0
    if (devmode_buf)
    {           
        if (devmode_buf)
        {
            lala = DocumentPropertiesW(NULL, m_currPrinterHandle, (LPWSTR) m_currPrinterName.c_str(), devmode_buf, NULL, DM_OUT_BUFFER);
            if (lala == IDOK)
            {
                res = true;
            }
            GetLastError(); // = 122. insufficient buffer here. why????
        }
        UInt32 res1 = GlobalUnlock(m_devmode_buf); // res1 is 1. should be 0
        res2 = GetLastError(); // = 0
        if (!(res1 == 0 && (res2 == ERROR_NOT_LOCKED || res2 == NO_ERROR)))
        {
            //res = false;
        }           
    }
}

3 个答案:

答案 0 :(得分:1)

如果对DocumentProperties()的第二次调用返回1(即IDOK),那么它没有失败,因此GetLastError()的值没有意义。它可能是在DocumentProperties()内部引发和处理的预期条件。使用GetLastError()的惯例是你只在失败时设置它;你通常不会在成功时清除它。由每个单独函数的文档来解释如何返回错误。 DocumentProperties()的文档甚至没有提到GetLastError(),因此检查它可能毫无意义(尽管通常可以安全地假设所有Win32函数都通过GetLastError()返回错误。)

答案 1 :(得分:0)

您将GPTR传递给GlobalAlloc后无需调用GlobalLock。您只需在传递GMEM_MOVEABLE时调用GlobalLock。

但是,您不应该使用GlobalAlloc / GlobalFree,除非您传递内存的API文档另有说明。首选HeapAlloc / HeapFree或只是新建/删除。 GlobalAlloc是一种较旧的API,旨在与16位Windows兼容。

答案 2 :(得分:0)

对于某些情况下某些机器的DEVMODE大小,DocumentProperties将返回-1 - 在MS论坛上有一个关于它的整个帖子(从2008年开始),但MS不会将其视为一个问题,尽管他们的示例代码永远不会检查返回代码(或者PrintDlg()公共对话框,它很乐意尝试分配-1内存并失败)。

您不能完全依赖此功能,因为它可以在您的计算机上运行但在客户端的计算机上失败。检查-1,如果它返回只是组成一个大数字(2 * sizeof(DEVMODE)或其他东西)并使用它。