diff --git a/CHANGES.txt b/CHANGES.txt index 493acce1c8..d3e1a20684 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,8 @@ Note that build 228 was the last version supporting Python 2. Since build 303: ---------------- +* Add `PRINTER_INFO_6` support for Set/GetPrinter (#1853, @CristiFati) + * Fixed codepage/mojibake issues when non-ascii characters were included in COM exceptions raised by Python apps. This should be invisible, but might break any workarounds which were used, such as using specific encodings in diff --git a/win32/src/win32print/win32print.cpp b/win32/src/win32print/win32print.cpp index d18fba180e..e1ad38a1d6 100644 --- a/win32/src/win32print/win32print.cpp +++ b/win32/src/win32print/win32print.cpp @@ -213,6 +213,10 @@ static PyObject *PyWinObject_FromPRINTER_INFO(LPBYTE printer_info, DWORD level) "pPortName", PyWinObject_FromTCHAR(pi5->pPortName), "Attributes", pi5->Attributes, "DeviceNotSelectedTimeout", pi5->DeviceNotSelectedTimeout, "TransmissionRetryTimeout", pi5->TransmissionRetryTimeout); + case 6: + PRINTER_INFO_6 *pi6; + pi6 = (PRINTER_INFO_6*)printer_info; + return Py_BuildValue("{s:k}", "Status", pi6->dwStatus); case 7: PRINTER_INFO_7 *pi7; pi7 = (PRINTER_INFO_7 *)printer_info; @@ -328,6 +332,17 @@ void PyWinObject_FreePRINTER_INFO(DWORD level, LPBYTE pbuf) free(pbuf); } +#define AsPRINTER_INFO__INIT_PRINTER_INFO_X(_PRINTER_INFO_X, _PIX_PTR) \ + _PRINTER_INFO_X *_PIX_PTR; \ + bufsize = sizeof(_PRINTER_INFO_X); \ + if ((*pbuf = (LPBYTE)malloc(bufsize)) == NULL) { \ + PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", bufsize); \ + break; \ + } \ + ZeroMemory(*pbuf, bufsize); \ + _PIX_PTR = (_PRINTER_INFO_X*)*pbuf; + + BOOL PyWinObject_AsPRINTER_INFO(DWORD level, PyObject *obinfo, LPBYTE *pbuf) { BOOL ret = FALSE; @@ -380,15 +395,7 @@ BOOL PyWinObject_AsPRINTER_INFO(DWORD level, PyObject *obinfo, LPBYTE *pbuf) *obDriverName = Py_None, *obComment = Py_None, *obLocation = Py_None, *obDevMode = Py_None, *obSepFile = Py_None, *obPrintProcessor = Py_None, *obDatatype = Py_None, *obParameters = Py_None, *obSecurityDescriptor = Py_None; - PRINTER_INFO_2 *pi2; - bufsize = sizeof(PRINTER_INFO_2); - if (NULL == (*pbuf = (LPBYTE)malloc(bufsize))) { - PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", bufsize); - break; - } - ZeroMemory(*pbuf, bufsize); - pi2 = (PRINTER_INFO_2 *)*pbuf; - + AsPRINTER_INFO__INIT_PRINTER_INFO_X(PRINTER_INFO_2, pi2); ret = PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi2_format, pi2_keys, &obServerName, &obPrinterName, &obShareName, &obPortName, &obDriverName, &obComment, &obLocation, &obDevMode, &obSepFile, &obPrintProcessor, &obDatatype, &obParameters, @@ -414,14 +421,7 @@ BOOL PyWinObject_AsPRINTER_INFO(DWORD level, PyObject *obinfo, LPBYTE *pbuf) static char *pi3_keys[] = {"pSecurityDescriptor", NULL}; static char *pi3_format = "O:PRINTER_INFO_3"; PyObject *obSecurityDescriptor; - PRINTER_INFO_3 *pi3; - bufsize = sizeof(PRINTER_INFO_3); - if (NULL == (*pbuf = (LPBYTE)malloc(bufsize))) { - PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", bufsize); - break; - } - ZeroMemory(*pbuf, bufsize); - pi3 = (PRINTER_INFO_3 *)*pbuf; + AsPRINTER_INFO__INIT_PRINTER_INFO_X(PRINTER_INFO_3, pi3); ret = PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi3_format, pi3_keys, &obSecurityDescriptor) && PyWinObject_AsSECURITY_DESCRIPTOR(obSecurityDescriptor, &pi3->pSecurityDescriptor, FALSE); break; @@ -430,14 +430,7 @@ BOOL PyWinObject_AsPRINTER_INFO(DWORD level, PyObject *obinfo, LPBYTE *pbuf) static char *pi4_keys[] = {"pPrinterName", "pServerName", "Attributes", NULL}; static char *pi4_format = "OOk:PRINTER_INFO_4"; PyObject *obPrinterName = Py_None, *obServerName = Py_None; - PRINTER_INFO_4 *pi4; - bufsize = sizeof(PRINTER_INFO_4); - if (NULL == (*pbuf = (LPBYTE)malloc(bufsize))) { - PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", bufsize); - break; - } - ZeroMemory(*pbuf, bufsize); - pi4 = (PRINTER_INFO_4 *)*pbuf; + AsPRINTER_INFO__INIT_PRINTER_INFO_X(PRINTER_INFO_4, pi4); ret = PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi4_format, pi4_keys, &obPrinterName, &obServerName, &pi4->Attributes) && PyWinObject_AsTCHAR(obPrinterName, &pi4->pPrinterName, TRUE) && @@ -453,15 +446,7 @@ BOOL PyWinObject_AsPRINTER_INFO(DWORD level, PyObject *obinfo, LPBYTE *pbuf) NULL}; static char *pi5_format = "OOkkk:PRINTER_INFO_5"; PyObject *obPrinterName = Py_None, *obPortName = Py_None; - - PRINTER_INFO_5 *pi5; - bufsize = sizeof(PRINTER_INFO_5); - if (NULL == (*pbuf = (LPBYTE)malloc(bufsize))) { - PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", bufsize); - break; - } - ZeroMemory(*pbuf, bufsize); - pi5 = (PRINTER_INFO_5 *)*pbuf; + AsPRINTER_INFO__INIT_PRINTER_INFO_X(PRINTER_INFO_5, pi5); ret = PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi5_format, pi5_keys, &obPrinterName, &obPortName, &pi5->Attributes, &pi5->DeviceNotSelectedTimeout, &pi5->TransmissionRetryTimeout) && @@ -469,18 +454,20 @@ BOOL PyWinObject_AsPRINTER_INFO(DWORD level, PyObject *obinfo, LPBYTE *pbuf) PyWinObject_AsTCHAR(obPortName, &pi5->pPortName, TRUE); break; } + case 6: { + static char *pi6_keys[] = { + "Status", + NULL }; + static char *pi6_format = "k:PRINTER_INFO_6"; + AsPRINTER_INFO__INIT_PRINTER_INFO_X(PRINTER_INFO_6, pi6); + ret = PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi6_format, pi6_keys, &pi6->dwStatus); + break; + } case 7: { static char *pi7_keys[] = {"ObjectGUID", "Action", NULL}; static char *pi7_format = "Ok:PRINTER_INFO_7"; PyObject *obObjectGUID = Py_None; - PRINTER_INFO_7 *pi7; - bufsize = sizeof(PRINTER_INFO_7); - if (NULL == (*pbuf = (LPBYTE)malloc(bufsize))) { - PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", bufsize); - break; - } - ZeroMemory(*pbuf, bufsize); - pi7 = (PRINTER_INFO_7 *)*pbuf; + AsPRINTER_INFO__INIT_PRINTER_INFO_X(PRINTER_INFO_7, pi7); ret = PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi7_format, pi7_keys, &obObjectGUID, &pi7->dwAction) && PyWinObject_AsTCHAR(obObjectGUID, &pi7->pszObjectGUID, TRUE); @@ -491,14 +478,7 @@ BOOL PyWinObject_AsPRINTER_INFO(DWORD level, PyObject *obinfo, LPBYTE *pbuf) static char *pi8_keys[] = {"pDevMode", NULL}; static char *pi8_format = "O:PRINTER_INFO_8"; PyObject *obDevMode; - PRINTER_INFO_8 *pi8; - bufsize = sizeof(PRINTER_INFO_8); - if (NULL == (*pbuf = (LPBYTE)malloc(bufsize))) { - PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", bufsize); - break; - } - ZeroMemory(*pbuf, bufsize); - pi8 = (PRINTER_INFO_8 *)*pbuf; + AsPRINTER_INFO__INIT_PRINTER_INFO_X(PRINTER_INFO_8, pi8); ret = PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi8_format, pi8_keys, &obDevMode) && PyWinObject_AsDEVMODE(obDevMode, &pi8->pDevMode, FALSE); break; diff --git a/win32/test/test_win32print.py b/win32/test/test_win32print.py new file mode 100644 index 0000000000..6b99058608 --- /dev/null +++ b/win32/test/test_win32print.py @@ -0,0 +1,25 @@ +# Tests (scarce) for win32print module + +import os +import unittest + +import win32print as wprn + + +class Win32PrintTestCase(unittest.TestCase): + def setUp(self): + self.printer_idx = 0 + self.printer_levels_all = list(range(1, 10)) + self.local_printers = wprn.EnumPrinters(wprn.PRINTER_ENUM_LOCAL, None, 1) + + def test_printer_levels_read_dummy(self): + if not self.local_printers: + print("Test didn't run (no local printers)!") + return + ph = wprn.OpenPrinter(self.local_printers[self.printer_idx][2]) + for level in self.printer_levels_all: + wprn.GetPrinter(ph, level) + + +if __name__ == "__main__": + unittest.main()