调用 DocumentProperties 时缓冲区不足,全局解锁也无法解锁
请参阅内嵌评论
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;
}
}
}
please see comments inline
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;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果第二次调用 DocumentProperties() 返回 1(即 IDOK),那么它并没有失败,因此 GetLastError() 的值没有意义。这可能是在 DocumentProperties() 内部引发和处理的预期条件。使用 GetLastError() 的约定是仅在失败时设置它;你通常不会在成功时清除它。由每个函数的文档来解释如何返回错误。 DocumentProperties() 的文档甚至没有提到 GetLastError(),因此检查它可能毫无意义(尽管通常可以安全地假设所有 Win32 函数都通过 GetLastError() 返回错误)。
If the second call to DocumentProperties() is returning 1 (i.e. IDOK) then it is not failing, thus the value of GetLastError() is meaningless. It is probably an expected condition that is raised and handled inside of DocumentProperties(). The convention of using GetLastError() is that you only set it on failure; you don't usually clear it on success. It is up to the documentation of each individual function to explain how errors are returned. The documentation for DocumentProperties() doesn't even mention GetLastError(), so checking it at all might be meaningless (though usually it is safe to assume that all Win32 functions return errors via GetLastError()).
由于您将 GPTR 传递给了 GlobalAlloc,因此您不需要调用 GlobalLock。你只需要在传递GMEM_MOVEABLE时调用GlobalLock即可。
但是,您不应该使用 GlobalAlloc/GlobalFree,除非您将内存传递给的 API 的文档另有说明。更喜欢 HeapAlloc/HeapFree 或只是新建/删除。 GlobalAlloc 是一个较旧的 API,旨在与 16 位 Windows 兼容。
You do not need to call GlobalLock since you passed GPTR to GlobalAlloc. You only need to call GlobalLock when you pass GMEM_MOVEABLE.
But, you shouldn't be using GlobalAlloc/GlobalFree, unless the documentation for the API you're passing the memory to says otherwise. Prefer HeapAlloc/HeapFree or just new/delete. GlobalAlloc is an older API intended for compatibility with 16-bit Windows.
在某些情况下,DocumentProperties 对于某些机器的 DEVMODE 大小将返回 -1 - MS 论坛上有一个关于它的完整线程(大约从 2008 年开始),但 MS 并不认为这是一个问题,尽管他们的示例代码从未检查返回代码(或 PrintDlg() 公共对话框,它愉快地尝试分配 -1 内存并失败)。
您不能仅仅依赖此功能,因为它可以在您的计算机上运行,但在客户端的计算机上失败。检查 -1 ,如果它返回则构成一个大数字(2 * sizeof(DEVMODE)或其他)并使用它。
DocumentProperties will return -1 for the DEVMODE size for certain machines under certain circumstances - there's a whole thread on the MS forums about it (started about 2008) but MS don't see it as an issue, despite their example code never checking the return code (or the PrintDlg() common dialog which happily tries to allocate -1 memory and fails).
You just can't rely solely on this function, as it could work on your machine but fail on a client's machine. Check for -1 and if it returns that just make up a big number (2*sizeof(DEVMODE) or something) and use that.