开发者

insufficient buffer when call DocumentProperties, also, global unlock wouldn't unlock

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 开发者_C百科== NO_ERROR)))
        {
            //res = false;
        }           
    }
}


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()).


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 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜