2010-05-10 38 views
0

請參閱評論直列足夠的緩衝區時調用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; 
     }   
    } 
} 
+0

投射到LPWSTR *從未*是正確的。如果必須使用DocumentPropertiesA()。 – 2010-05-11 01:40:59

+0

對DocumentProperties()的第二次調用實際上失敗了嗎?在這種情況下,通過返回一個小於0的值來表示失敗。如果它沒有失敗,那麼GetLastError()的值是沒有意義的。 – Luke 2010-05-11 03:10:13

+0

@Hans Passant m_currPrinterName是std :: wstring,我認爲用這種方法進行投射是安全的。 – Quincy 2010-05-11 16:37:59

回答

1

如果對DocumentProperties()的第二次調用返回1(即IDOK),那麼它不會失敗,因此GetLastError()的值是沒有意義的。這可能是在DocumentProperties()內引發和處理的預期條件。使用GetLastError()的慣例是你只在失敗時進行設置;你通常不會在成功時清楚它。每個函數的文檔都要解釋錯誤是如何返回的。 DocumentProperties()的文檔甚至沒有提到GetLastError(),因此檢查它可能沒有意義(儘管通常假設所有Win32函數都通過GetLastError()返回錯誤是安全的)。

0

你並不需要調用GlobalLock因爲你傳遞給GPTR的GlobalAlloc。您只需在通過GMEM​​_MOVEABLE時調用GlobalLock。

但是,您不應該使用GlobalAlloc/GlobalFree,除非您傳遞內存的API的文檔說明了其他情況。喜歡HeapAlloc/HeapFree或者只是新/刪除。 GlobalAlloc是一個較舊的API,旨在與16位Windows兼容。

0

在某些情況下,DocumentProperties將返回-1來表示某些機器的DEVMODE大小 - MS論壇上有一個關於它的完整線程(從2008年開始),但MS並不認爲它是一個問題,儘管它們的示例代碼從不檢查返回代碼(或者愉快地嘗試分配-1內存並失敗的PrintDlg()通用對話框)。

你不能完全依賴這個功能,因爲它可以在你的機器上工作,但在客戶機上失敗。檢查-1,如果它返回,只是組成一個大數字(2 * sizeof(DEVMODE)或其他)並使用它。