/win32/src/win32print/win32print.cpp
https://bitbucket.org/jaraco/pywin32 · C++ · 2829 lines · 2445 code · 144 blank · 240 comment · 352 complexity · e109620777c9a665812db8ce8dbe814a MD5 · raw file
Large files are truncated click here to view the full file
- /***********************************************************
- win32printmodule.cpp -- module for interface into printer API
- Note that this source file contains embedded documentation.
- This documentation consists of marked up text inside the
- C comments, and is prefixed with an '@' symbol. The source
- files are processed by a tool called "autoduck" which
- generates Windows .hlp files.
- @doc
- ******************************************************************/
- #include "PyWinTypes.h"
- #include "PyWinObjects.h"
- #include <stdarg.h>
- #define CHECK_PFN(fname)if (pfn##fname==NULL) return PyErr_Format(PyExc_NotImplementedError,"%s is not available on this platform", #fname);
- typedef BOOL (WINAPI *EnumFormsfunc)(HANDLE,DWORD,LPBYTE,DWORD,LPDWORD,LPDWORD);
- static EnumFormsfunc pfnEnumForms=NULL;
- typedef BOOL (WINAPI *AddFormfunc)(HANDLE,DWORD,LPBYTE);
- static AddFormfunc pfnAddForm=NULL;
- typedef BOOL (WINAPI *DeleteFormfunc)(HANDLE, LPWSTR);
- static DeleteFormfunc pfnDeleteForm=NULL;
- typedef BOOL (WINAPI *GetFormfunc)(HANDLE,LPWSTR,DWORD,LPBYTE,DWORD,LPDWORD);
- static GetFormfunc pfnGetForm=NULL;
- typedef BOOL (WINAPI *SetFormfunc)(HANDLE, LPWSTR, DWORD, LPBYTE);
- static SetFormfunc pfnSetForm=NULL;
- typedef BOOL (WINAPI *AddJobfunc)(HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
- static AddJobfunc pfnAddJob=NULL;
- typedef BOOL (WINAPI *ScheduleJobfunc)(HANDLE, DWORD);
- static ScheduleJobfunc pfnScheduleJob=NULL;
- typedef BOOL (WINAPI * EnumPortsfunc)(LPWSTR,DWORD,LPBYTE,DWORD,LPDWORD,LPDWORD);
- static EnumPortsfunc pfnEnumPorts=NULL;
- static EnumPortsfunc pfnEnumMonitors=NULL; // same args as EnumPorts
- typedef BOOL (WINAPI *GetPrintProcessorDirectoryfunc)(LPWSTR,LPWSTR,DWORD,LPBYTE,DWORD,LPDWORD);
- static GetPrintProcessorDirectoryfunc pfnGetPrintProcessorDirectory=NULL;
- static GetPrintProcessorDirectoryfunc pfnGetPrinterDriverDirectory=NULL; // same as GetPrintProcessorDirectory
- typedef BOOL (WINAPI *DeletePrinterDriverExfunc)(LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD);
- static DeletePrinterDriverExfunc pfnDeletePrinterDriverEx=NULL;
- typedef BOOL (WINAPI *FlushPrinterfunc)(HANDLE, LPVOID, DWORD, LPDWORD, DWORD);
- static FlushPrinterfunc pfnFlushPrinter=NULL;
- typedef BOOL (WINAPI *GetDefaultPrinterfunc)(LPWSTR, LPDWORD);
- static GetDefaultPrinterfunc pfnGetDefaultPrinter=NULL;
- typedef BOOL (WINAPI *SetDefaultPrinterfunc)(LPWSTR);
- static SetDefaultPrinterfunc pfnSetDefaultPrinter=NULL;
- static PyObject *dummy_tuple=NULL;
- // To be used in PyArg_ParseTuple with O& format
- BOOL PyWinObject_AsPrinterHANDLE(PyObject *obhprinter, HANDLE *phprinter){
- return PyWinObject_AsHANDLE(obhprinter, phprinter);
- }
- // @object PyPrinterHANDLE|Handle to a printer or print server.
- // <nl>Created using <om win32print.OpenPrinter> or <om win32print.AddPrinter>
- // <nl>Inherits all methods and properties of <o PyHANDLE>.
- // <nl>When object is destroyed, handle is released using ClosePrinter.
- class PyPrinterHANDLE: public PyHANDLE
- {
- public:
- PyPrinterHANDLE(HANDLE hInit) : PyHANDLE(hInit) {}
- virtual BOOL Close(void){
- BOOL ret=ClosePrinter(m_handle);
- if (!ret)
- PyWin_SetAPIError("ClosePrinter");
- m_handle = 0;
- return ret;
- }
- virtual const char *GetTypeName(){
- return "PyPrinterHANDLE";
- }
- };
- PyObject *PyWinObject_FromPrinterHANDLE(HANDLE hprinter)
- {
- PyObject *ret=new PyPrinterHANDLE(hprinter);
- if (ret==NULL)
- PyErr_NoMemory();
- return ret;
- }
- void PyWinObject_FreePRINTER_DEFAULTS(PPRINTER_DEFAULTS pdefaults)
- {
- PyWinObject_FreeTCHAR(pdefaults->pDatatype);
- }
- // @object PRINTER_DEFAULTS|A dictionary representing a PRINTER_DEFAULTS structure
- // @prop string|pDatatype|Data type to be used for print jobs, see <om win32print.EnumPrintProcessorDatatypes>, optional, can be None
- // @prop <o PyDEVMODE>|pDevMode|A PyDEVMODE that specifies default printer parameters, optional, can be None
- // @prop int|DesiredAccess|An ACCESS_MASK specifying what level of access is needed, eg PRINTER_ACCESS_ADMINISTER, PRINTER_ACCESS_USE
- BOOL PyWinObject_AsPRINTER_DEFAULTS(PyObject *obdefaults, PPRINTER_DEFAULTS pdefaults)
- {
- static char *printer_default_keys[]={"DesiredAccess","pDataType","pDevMode",NULL};
- static char *printer_default_format="k|OO";
- ZeroMemory(pdefaults,sizeof(PRINTER_DEFAULTS));
- PyObject *obDataType=Py_None, *obdevmode=Py_None;
- if (!PyDict_Check(obdefaults)){
- PyErr_SetString(PyExc_TypeError, "PRINTER_DEFAULTS must be a dictionary");
- return FALSE;
- }
- return PyArg_ParseTupleAndKeywords(dummy_tuple,obdefaults,printer_default_format,printer_default_keys,
- &pdefaults->DesiredAccess, &pdefaults->pDatatype, &obdevmode)
- &&PyWinObject_AsDEVMODE(obdevmode, &pdefaults->pDevMode, TRUE)
- &&PyWinObject_AsTCHAR(obDataType, &pdefaults->pDatatype, TRUE);
- }
- // Printer stuff.
- // @pymethod <o PyPrinterHANDLE>|win32print|OpenPrinter|Retrieves a handle to a printer.
- static PyObject *PyOpenPrinter(PyObject *self, PyObject *args)
- {
- TCHAR *printer;
- HANDLE handle;
- PRINTER_DEFAULTS printer_defaults = {NULL, NULL, 0};
- PRINTER_DEFAULTS *pprinter_defaults=NULL;
- PyObject *obprinter, *obdefaults=Py_None, *ret=NULL;
- if (!PyArg_ParseTuple(args, "O|O:OpenPrinter",
- &obprinter, // @pyparm string|printer||Printer or print server name. Use None to open local print server.
- &obdefaults)) // @pyparm dict|Defaults|None|<o PRINTER_DEFAULTS> dict, or None
- return NULL;
- if (obdefaults!=Py_None){
- if (!PyWinObject_AsPRINTER_DEFAULTS(obdefaults, &printer_defaults))
- return NULL;
- pprinter_defaults=&printer_defaults;
- }
- if (PyWinObject_AsTCHAR(obprinter, &printer, TRUE)){
- if (OpenPrinter(printer, &handle, pprinter_defaults))
- ret=PyWinObject_FromPrinterHANDLE(handle);
- else
- PyWin_SetAPIError("OpenPrinter");
- }
- PyWinObject_FreePRINTER_DEFAULTS(&printer_defaults);
- PyWinObject_FreeTCHAR(printer);
- return ret;
- }
- // @pymethod |win32print|ClosePrinter|Closes a handle to a printer.
- static PyObject *PyClosePrinter(PyObject *self, PyObject *args)
- {
- PyObject *obhprinter;
- if (!PyArg_ParseTuple(args, "O:ClosePrinter",
- &obhprinter)) // @pyparm <o PyPrinterHANDLE>|hPrinter||handle to printer object
- return NULL;
- /* If the object is a PyPrinterHANDLE, its Close method must be called to ensure that the m_handle member is cleared.
- A second handle with the same value can be created as soon as the first handle is closed here, and if
- this happens between the time this function is executed and the first object is deref'ed, the original object's
- destruction would close a valid handle contained in the second object. */
- if (PyHANDLE_Check(obhprinter)){
- // Make sure we can't Close any other type of handle
- const char *handletype=((PyHANDLE *)obhprinter)->GetTypeName();
- if (strcmp(handletype, "PyPrinterHANDLE")!=0)
- return PyErr_Format(PyExc_TypeError, "ClosePrinter: Object must be a printer handle, not %s", handletype);
- if (((PyHANDLE *)obhprinter)->Close()){
- Py_INCREF(Py_None);
- return Py_None;
- }
- return NULL;
- }
- HANDLE hprinter;
- if (!PyWinObject_AsPrinterHANDLE(obhprinter, &hprinter))
- return NULL;
-
- if (!ClosePrinter(hprinter))
- return PyWin_SetAPIError("ClosePrinter");
- Py_INCREF(Py_None);
- return Py_None;
- }
- static PyObject *PyWinObject_FromPRINTER_INFO(LPBYTE printer_info, DWORD level)
- {
- switch (level){
- case 1:
- PRINTER_INFO_1 *pi1;
- pi1=(PRINTER_INFO_1 *)printer_info;
- return Py_BuildValue("{s:k,s:N,s:N,s:N}",
- "Flags",pi1->Flags,
- "pDescription",PyWinObject_FromTCHAR(pi1->pDescription),
- "pName",PyWinObject_FromTCHAR(pi1->pName),
- "pComment",PyWinObject_FromTCHAR(pi1->pComment));
- case 2:
- PRINTER_INFO_2 *pi2;
- pi2=(PRINTER_INFO_2 *)printer_info;
- return Py_BuildValue("{s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:k,s:k,s:k,s:k,s:k,s:k,s:k,s:k}",
- "pServerName",PyWinObject_FromTCHAR(pi2->pServerName),
- "pPrinterName",PyWinObject_FromTCHAR(pi2->pPrinterName),
- "pShareName",PyWinObject_FromTCHAR(pi2->pShareName),
- "pPortName",PyWinObject_FromTCHAR(pi2->pPortName),
- "pDriverName",PyWinObject_FromTCHAR(pi2->pDriverName),
- "pComment",PyWinObject_FromTCHAR(pi2->pComment),
- "pLocation",PyWinObject_FromTCHAR(pi2->pLocation),
- "pDevMode",PyWinObject_FromDEVMODE(pi2->pDevMode),
- "pSepFile", PyWinObject_FromTCHAR(pi2->pSepFile),
- "pPrintProcessor",PyWinObject_FromTCHAR(pi2->pPrintProcessor),
- "pDatatype",PyWinObject_FromTCHAR(pi2->pDatatype),
- "pParameters",PyWinObject_FromTCHAR(pi2->pParameters),
- "pSecurityDescriptor",PyWinObject_FromSECURITY_DESCRIPTOR(pi2->pSecurityDescriptor),
- "Attributes",pi2->Attributes, "Priority",pi2->Priority,
- "DefaultPriority",pi2->DefaultPriority,
- "StartTime",pi2->StartTime, "UntilTime",pi2->UntilTime,
- "Status",pi2->Status, "cJobs",pi2->cJobs, "AveragePPM",pi2->AveragePPM);
- case 3:
- PRINTER_INFO_3 *pi3;
- pi3=(PRINTER_INFO_3 *)printer_info;
- return Py_BuildValue("{s:N}","pSecurityDescriptor",PyWinObject_FromSECURITY_DESCRIPTOR(pi3->pSecurityDescriptor));
- case 4:
- PRINTER_INFO_4 *pi4;
- pi4=(PRINTER_INFO_4 *)printer_info;
- return Py_BuildValue("{s:N,s:N,s:k}",
- "pPrinterName",PyWinObject_FromTCHAR(pi4->pPrinterName),
- "pServerName",PyWinObject_FromTCHAR(pi4->pServerName),
- "Attributes",pi4->Attributes);
- case 5:
- PRINTER_INFO_5 *pi5;
- pi5=(PRINTER_INFO_5 *)printer_info;
- return Py_BuildValue("{s:N,s:N,s:k,s:k,s:k}",
- "pPrinterName",PyWinObject_FromTCHAR(pi5->pPrinterName),
- "pPortName",PyWinObject_FromTCHAR(pi5->pPortName),
- "Attributes",pi5->Attributes,
- "DeviceNotSelectedTimeout",pi5->DeviceNotSelectedTimeout,
- "TransmissionRetryTimeout",pi5->TransmissionRetryTimeout);
- case 7:
- PRINTER_INFO_7 *pi7;
- pi7=(PRINTER_INFO_7 *)printer_info;
- return Py_BuildValue("{s:N,s:k}",
- "ObjectGUID",PyWinObject_FromTCHAR(pi7->pszObjectGUID),
- "Action",pi7->dwAction);
- case 8: // global printer defaults
- PRINTER_INFO_8 *pi8;
- pi8=(PRINTER_INFO_8 *)printer_info;
- return Py_BuildValue("{s:N}","pDevMode", PyWinObject_FromDEVMODE(pi8->pDevMode));
- case 9: // per user printer defaults
- PRINTER_INFO_9 *pi9;
- pi9=(PRINTER_INFO_9 *)printer_info;
- return Py_BuildValue("{s:N}","pDevMode", PyWinObject_FromDEVMODE(pi9->pDevMode));
- default:
- return PyErr_Format(PyExc_NotImplementedError,"Level %d is not supported",level);
- }
- }
- // @pymethod dict|win32print|GetPrinter|Retrieves information about a printer
- // @rdesc Returns a dictionary containing PRINTER_INFO_* data for level, or
- // returns a tuple of PRINTER_INFO_2 data if no level is passed in.
- static PyObject *PyGetPrinter(PyObject *self, PyObject *args)
- {
- HANDLE hprinter;
- DWORD needed, level;
- BOOL backward_compat;
- LPBYTE buf=NULL;
- PyObject *rc=NULL;
- PRINTER_INFO_2 *pi2;
- // @comm Original implementation used level 2 only and returned a tuple
- // Pass single arg as indicator to use old behaviour for backward compatibility
- if (PyArg_ParseTuple(args, "O&:GetPrinter",
- PyWinObject_AsPrinterHANDLE, &hprinter)){ // @pyparm <o PyPrinterHANDLE>|hPrinter||handle to printer object as returned by <om win32print.OpenPrinter>
- backward_compat=TRUE;
- level=2;
- }
- else{
- PyErr_Clear();
- if (!PyArg_ParseTuple(args, "O&k:GetPrinter",
- PyWinObject_AsPrinterHANDLE, &hprinter,
- &level)) // @pyparm int|Level|2|Level of data returned (1,2,3,4,5,7,8,9)
- return NULL;
- backward_compat=FALSE;
- }
- // first allocate memory.
- GetPrinter(hprinter, level, NULL, 0, &needed );
- if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
- return PyWin_SetAPIError("GetPrinter");
- buf=(LPBYTE)malloc(needed);
- if (buf==NULL)
- return PyErr_Format(PyExc_MemoryError,"GetPrinter: Unable to allocate buffer of %d bytes", needed);
- if (!GetPrinter(hprinter, level, buf, needed, &needed )) {
- free(buf);
- return PyWin_SetAPIError("GetPrinter");
- }
- if (backward_compat){
- pi2=(PRINTER_INFO_2 *)buf;
- rc = Py_BuildValue("NNNNNNNONNNNOkkkkkkkk",
- PyWinObject_FromTCHAR(pi2->pServerName),
- PyWinObject_FromTCHAR(pi2->pPrinterName),
- PyWinObject_FromTCHAR(pi2->pShareName),
- PyWinObject_FromTCHAR(pi2->pPortName),
- PyWinObject_FromTCHAR(pi2->pDriverName),
- PyWinObject_FromTCHAR(pi2->pComment),
- PyWinObject_FromTCHAR(pi2->pLocation),
- Py_None,
- PyWinObject_FromTCHAR(pi2->pSepFile),
- PyWinObject_FromTCHAR(pi2->pPrintProcessor),
- PyWinObject_FromTCHAR(pi2->pDatatype),
- PyWinObject_FromTCHAR(pi2->pParameters),
- Py_None,
- pi2->Attributes, pi2->Priority, pi2->DefaultPriority, pi2->StartTime, pi2->UntilTime,
- pi2->Status, pi2->cJobs, pi2->AveragePPM);
- }
- else
- rc = PyWinObject_FromPRINTER_INFO(buf, level);
- free(buf);
- return rc;
- }
- void PyWinObject_FreePRINTER_INFO(DWORD level, LPBYTE pbuf)
- {
- if ((level==0) || (pbuf==NULL))
- return;
- switch(level){
- case 2:{
- PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)pbuf;
- PyWinObject_FreeTCHAR(pi2->pServerName);
- PyWinObject_FreeTCHAR(pi2->pPrinterName);
- PyWinObject_FreeTCHAR(pi2->pShareName);
- PyWinObject_FreeTCHAR(pi2->pPortName);
- PyWinObject_FreeTCHAR(pi2->pDriverName);
- PyWinObject_FreeTCHAR(pi2->pComment);
- PyWinObject_FreeTCHAR(pi2->pLocation);
- PyWinObject_FreeTCHAR(pi2->pSepFile);
- PyWinObject_FreeTCHAR(pi2->pPrintProcessor);
- PyWinObject_FreeTCHAR(pi2->pDatatype);
- PyWinObject_FreeTCHAR(pi2->pParameters);
- break;
- }
- case 4:{
- PRINTER_INFO_4 *pi4 = (PRINTER_INFO_4 *)pbuf;
- PyWinObject_FreeTCHAR(pi4->pPrinterName);
- PyWinObject_FreeTCHAR(pi4->pServerName);
- break;
- }
- case 5:{
- PRINTER_INFO_5 *pi5 = (PRINTER_INFO_5 *)pbuf;
- PyWinObject_FreeTCHAR(pi5->pPrinterName);
- PyWinObject_FreeTCHAR(pi5->pPortName);
- break;
- }
- case 7:{
- PRINTER_INFO_7 *pi7 = (PRINTER_INFO_7 *)pbuf;
- PyWinObject_FreeTCHAR(pi7->pszObjectGUID);
- break;
- }
- default:
- break;
- }
- free(pbuf);
- }
- BOOL PyWinObject_AsPRINTER_INFO(DWORD level, PyObject *obinfo, LPBYTE *pbuf)
- {
- BOOL ret=FALSE;
- size_t bufsize;
- *pbuf=NULL;
- if (level==0)
- if (obinfo==Py_None)
- return TRUE;
- else{
- *pbuf = (LPBYTE)PyInt_AsLong(obinfo);
- if ((*pbuf==(LPBYTE)-1)&&PyErr_Occurred()){
- PyErr_Clear();
- PyErr_SetString(PyExc_TypeError,"Info must be None or a PRINTER_STATUS_* integer when level is 0.");
- return FALSE;
- }
- return TRUE;
- }
- if (!PyDict_Check (obinfo)){
- PyErr_Format(PyExc_TypeError, "PRINTER_INFO_%d must be a dictionary", level);
- return FALSE;
- }
- switch(level){
- case 2:{
- static char *pi2_keys[]={"pServerName","pPrinterName","pShareName","pPortName",
- "pDriverName","pComment","pLocation","pDevMode","pSepFile","pPrintProcessor",
- "pDatatype","pParameters","pSecurityDescriptor","Attributes","Priority",
- "DefaultPriority","StartTime","UntilTime","Status","cJobs","AveragePPM", NULL};
- static char *pi2_format="OOOOOOOOOOOOOkkkkkkkk:PRINTER_INFO_2";
- PyObject *obServerName=Py_None, *obPrinterName=Py_None, *obShareName=Py_None,
- *obPortName=Py_None, *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;
- ret=PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi2_format, pi2_keys,
- &obServerName, &obPrinterName, &obShareName, &obPortName,
- &obDriverName, &obComment, &obLocation,
- &obDevMode,
- &obSepFile, &obPrintProcessor, &obDatatype, &obParameters,
- &obSecurityDescriptor,
- &pi2->Attributes, &pi2->Priority, &pi2->DefaultPriority, &pi2->StartTime,
- &pi2->UntilTime, &pi2->Status, &pi2->cJobs, &pi2->AveragePPM)
- &&PyWinObject_AsTCHAR(obServerName, &pi2->pServerName, TRUE)
- &&PyWinObject_AsTCHAR(obPrinterName, &pi2->pPrinterName, TRUE)
- &&PyWinObject_AsTCHAR(obShareName, &pi2->pShareName, TRUE)
- &&PyWinObject_AsTCHAR(obPortName, &pi2->pPortName, TRUE)
- &&PyWinObject_AsTCHAR(obDriverName, &pi2->pDriverName, TRUE)
- &&PyWinObject_AsTCHAR(obComment, &pi2->pComment, TRUE)
- &&PyWinObject_AsTCHAR(obLocation, &pi2->pLocation, TRUE)
- &&PyWinObject_AsDEVMODE(obDevMode, &pi2->pDevMode,FALSE)
- &&PyWinObject_AsTCHAR(obSepFile, &pi2->pSepFile, TRUE)
- &&PyWinObject_AsTCHAR(obPrintProcessor, &pi2->pPrintProcessor, TRUE)
- &&PyWinObject_AsTCHAR(obDatatype, &pi2->pDatatype, TRUE)
- &&PyWinObject_AsTCHAR(obParameters, &pi2->pParameters, TRUE)
- &&PyWinObject_AsSECURITY_DESCRIPTOR(obSecurityDescriptor, &pi2->pSecurityDescriptor, TRUE);
- break;
- }
- case 3:{
- 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;
- ret=PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi3_format, pi3_keys, &obSecurityDescriptor)
- &&PyWinObject_AsSECURITY_DESCRIPTOR(obSecurityDescriptor, &pi3->pSecurityDescriptor, FALSE);
- break;
- }
- case 4:{
- 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;
- ret=PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi4_format, pi4_keys,
- &obPrinterName, &obServerName, &pi4->Attributes)
- &&PyWinObject_AsTCHAR(obPrinterName, &pi4->pPrinterName, TRUE)
- &&PyWinObject_AsTCHAR(obServerName, &pi4->pServerName, TRUE);
- break;
- }
- case 5:{
- static char *pi5_keys[]={"pPrinterName","pPortName","Attributes",
- "DeviceNotSelectedTimeout","TransmissionRetryTimeout", 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;
- ret=PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi5_format, pi5_keys,
- &obPrinterName, &obPortName, &pi5->Attributes,
- &pi5->DeviceNotSelectedTimeout, &pi5->TransmissionRetryTimeout)
- &&PyWinObject_AsTCHAR(obPrinterName, &pi5->pPrinterName, TRUE)
- &&PyWinObject_AsTCHAR(obPortName, &pi5->pPortName, TRUE);
- 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;
- ret=PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi7_format, pi7_keys,
- &obObjectGUID, &pi7->dwAction)
- &&PyWinObject_AsTCHAR(obObjectGUID, &pi7->pszObjectGUID, TRUE);
- break;
- }
- case 8:
- case 9:{ //identical structs, 8 is for global defaults and 9 is for user defaults
- 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;
- ret=PyArg_ParseTupleAndKeywords(dummy_tuple, obinfo, pi8_format, pi8_keys, &obDevMode)
- &&PyWinObject_AsDEVMODE(obDevMode,&pi8->pDevMode,FALSE);
- break;
- }
- default:
- PyErr_Format(PyExc_NotImplementedError,"Information level %d is not supported", level);
- }
- if (!ret){
- if ((*pbuf!=NULL) && (level!=0))
- free(*pbuf);
- *pbuf=NULL;
- }
- return ret;
- }
- // @pymethod |win32print|SetPrinter|Change printer configuration and status
- static PyObject *PySetPrinter(PyObject *self, PyObject *args)
- {
- HANDLE hprinter;
- LPBYTE buf=NULL;
- DWORD level, command;
- PyObject *obinfo=NULL, *ret=NULL;
- // @pyparm <o PyPrinterHANDLE>|hPrinter||Printer handle as returned by <om win32print.OpenPrinter>
- // @pyparm int|Level||Level of data contained in pPrinter
- // @pyparm dict|pPrinter||PRINTER_INFO_* dict as returned by <om win32print.GetPrinter>, can be None if level is 0
- // @pyparm int|Command||Command to send to printer - one of the PRINTER_CONTROL_* constants, or 0
- // @comm If Level is 0 and Command is PRINTER_CONTROL_SET_STATUS, pPrinter should be an integer,
- // and is interpreted as the new printer status to set (one of the PRINTER_STATUS_* constants).
- if (!PyArg_ParseTuple(args, "O&kOk:SetPrinter",
- PyWinObject_AsPrinterHANDLE, &hprinter, &level, &obinfo, &command))
- return NULL;
- if (!PyWinObject_AsPRINTER_INFO(level, obinfo, &buf))
- return NULL;
- if (!SetPrinter(hprinter, level, buf, command))
- PyWin_SetAPIError("SetPrinter");
- else{
- Py_INCREF(Py_None);
- ret=Py_None;
- }
- PyWinObject_FreePRINTER_INFO(level, buf);
- return ret;
- }
- // @pymethod None|win32print|AddPrinterConnection|Connects to remote printer
- static PyObject *PyAddPrinterConnection(PyObject *self, PyObject *args)
- {
- TCHAR *printer;
- PyObject *obprinter;
- if (!PyArg_ParseTuple(args, "O:AddPrinterConnection",
- &obprinter)) // @pyparm string|printer||printer to connect to (eg: \\server\printer).
- return NULL;
- if (!PyWinObject_AsTCHAR(obprinter, &printer, FALSE))
- return NULL;
- BOOL bsuccess=AddPrinterConnection(printer);
- PyWinObject_FreeTCHAR(printer);
- if (!bsuccess)
- return PyWin_SetAPIError("AddPrinterConnection");
- Py_INCREF(Py_None);
- return Py_None;
- }
- // @pymethod None|win32print|DeletePrinterConnection|Removes connection to remote printer
- static PyObject *PyDeletePrinterConnection(PyObject *self, PyObject *args)
- {
- TCHAR *printer;
- PyObject *obprinter;
- if (!PyArg_ParseTuple(args, "O:DeletePrinterConnection",
- &obprinter)) // @pyparm string|printer||printer to disconnect from (eg: \\server\printer).
- return NULL;
- if (!PyWinObject_AsTCHAR(obprinter, &printer, FALSE))
- return NULL;
- BOOL bsuccess=DeletePrinterConnection(printer);
- PyWinObject_FreeTCHAR(printer);
- if (!bsuccess)
- return PyWin_SetAPIError("DeletePrinterConnection");
- Py_INCREF(Py_None);
- return Py_None;
- }
- // @pymethod string|win32print|GetDefaultPrinter|Returns the default printer.
- static PyObject *PyGetDefaultPrinter(PyObject *self, PyObject *args)
- {
- TCHAR *printer, *s;
- int printer_size= 100;
- /* Windows < 2000 does not have a GetDefaultPrinter so the default printer
- must be retrieved from registry */
- if (NULL == (printer= (TCHAR *)malloc(printer_size * sizeof(TCHAR))))
- {
- PyErr_SetString(PyExc_MemoryError, "Malloc failed.");
- return NULL;
- }
- if (0 == GetProfileString(TEXT("Windows"), TEXT("Device"), TEXT(""), printer, printer_size))
- {
- PyErr_SetString(PyExc_RuntimeError, "The default printer was not found.");
- return NULL;
- }
- if (NULL == (s= _tcschr(printer, TEXT(','))))
- {
- PyErr_SetString(PyExc_RuntimeError, "The returned printer is malformed.");
- return NULL;
- }
- *s= 0;
- PyObject *ret= PyWinObject_FromTCHAR(printer);
- free(printer);
- return ret;
- }
- // @pymethod <o PyUnicode>|win32print|GetDefaultPrinterW|Returns the default printer.
- // @comm Unlike <om win32print.GetDefaultPrinter>, this method calls the GetDefaultPrinter API function.
- static PyObject *PyGetDefaultPrinterW(PyObject *self, PyObject *args)
- {
- CHECK_PFN(GetDefaultPrinter);
- WCHAR *printer=NULL;
- DWORD err, printer_size=100;
- PyObject *ret=NULL;
- printer= (WCHAR *)malloc(printer_size*sizeof(WCHAR));
- if (printer==NULL)
- return PyErr_Format(PyExc_MemoryError, "Unable to allocate %d bytes", printer_size*sizeof(WCHAR));
- if (!(*pfnGetDefaultPrinter)(printer, &printer_size)){
- err=GetLastError();
- if (err!=ERROR_INSUFFICIENT_BUFFER){
- PyWin_SetAPIError("GetDefaultPrinter");
- goto done;
- }
- free(printer);
- printer=(WCHAR *)malloc(printer_size*sizeof(WCHAR));
- if (printer==NULL)
- return PyErr_Format(PyExc_MemoryError, "Unable to allocate %d bytes", printer_size*sizeof(WCHAR));
- if (!(*pfnGetDefaultPrinter)(printer, &printer_size)){
- PyWin_SetAPIError("GetDefaultPrinter");
- goto done;
- }
- }
- ret=PyWinObject_FromWCHAR(printer);
- done:
- if (printer)
- free(printer);
- return ret;
- }
- // @pymethod None|win32print|SetDefaultPrinter|Sets the default printer.
- // @comm This function uses the pre-win2k method of WriteProfileString rather than the SetDefaultPrinter API function
- static PyObject *PySetDefaultPrinter(PyObject *self, PyObject *args)
- {
- TCHAR *printer=NULL, *info=NULL, *dprinter=NULL;
- int info_size= 100;
- PyObject *obprinter;
- /* Windows < 2000 does not have a SetDefaultPrinter so the default printer
- must be set in the registry */
- if (!PyArg_ParseTuple(args, "O:SetDefaultPrinter",
- &obprinter)) // @pyparm string|printer||printer to set as default
- return NULL;
- if (!PyWinObject_AsTCHAR(obprinter, &printer, FALSE))
- return NULL;
- if (NULL == (info= (TCHAR *)malloc(info_size *sizeof(TCHAR))))
- PyErr_NoMemory();
- else if (0 == GetProfileString(TEXT("Devices"), printer, TEXT(""), info, info_size))
- PyErr_SetString(PyExc_RuntimeError, "The printer was not found.");
- else if (NULL == (dprinter= (TCHAR *)malloc((_tcslen(printer) + _tcslen(info) + 3) * sizeof(TCHAR))))
- PyErr_NoMemory();
- else{
- _tcscpy(dprinter, printer);
- _tcscat(dprinter, TEXT(","));
- _tcscat(dprinter, info);
- WriteProfileString(TEXT("Windows"), TEXT("device"), dprinter);
- SendNotifyMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,0);
- }
- if (dprinter)
- free(dprinter);
- if (info)
- free(info);
- PyWinObject_FreeTCHAR(printer);
- Py_INCREF(Py_None);
- return Py_None;
- }
- // @pymethod None|win32print|SetDefaultPrinterW|Sets the default printer
- // @comm Unlike <om win32print.SetDefaultPrinter>, this method calls the SetDefaultPrinter API function.
- static PyObject *PySetDefaultPrinterW(PyObject *self, PyObject *args)
- {
- CHECK_PFN(SetDefaultPrinter);
- WCHAR *printer=NULL;
- PyObject *obprinter, *ret=NULL;
- // @pyparm <o PyUnicode>|Printer||Name of printer, can be None to use first available printer
- if (!PyArg_ParseTuple(args, "O:SetDefaultPrinter", &obprinter))
- return NULL;
- if (!PyWinObject_AsWCHAR(obprinter, &printer, TRUE))
- return NULL;
- if (!(*pfnSetDefaultPrinter)(printer))
- PyWin_SetAPIError("SetDefaultPrinter");
- else{
- Py_INCREF(Py_None);
- ret = Py_None;
- }
- PyWinObject_FreeWCHAR(printer);
- return ret;
- }
- // @pymethod tuple|win32print|EnumPrinters|Enumerates printers, print servers, domains and print providers.
- // @comm Use Flags=PRINTER_ENUM_NAME, Name=None, Level=1 to enumerate print providers.<nl>
- // Use Flags=PRINTER_ENUM_NAME, Name=\\servername, Level=2 or 5 to list printers on another server.<nl>
- // See MSDN docs for EnumPrinters for other specific combinations
- static PyObject *PyEnumPrinters(PyObject *self, PyObject *args)
- {
- DWORD flags;
- DWORD level= 1;
- BYTE *buf=NULL;
- DWORD bufsize;
- DWORD bufneeded;
- DWORD printersreturned;
- TCHAR *name= NULL;
- PyObject *obname=Py_None;
- DWORD i;
- PyObject *ret=NULL, *obprinter_info;
- static size_t printer_info_offset[]={
- sizeof(PRINTER_INFO_1),sizeof(PRINTER_INFO_2),sizeof(PRINTER_INFO_3),
- sizeof(PRINTER_INFO_4),sizeof(PRINTER_INFO_5),sizeof(PRINTER_INFO_6),
- sizeof(PRINTER_INFO_7),sizeof(PRINTER_INFO_8),sizeof(PRINTER_INFO_9)
- };
- if (!PyArg_ParseTuple(args, "k|Ok:EnumPrinters",
- &flags, // @pyparm int|flags||types of printer objects to enumerate (combination of PRINTER_ENUM_* constants).
- &obname, // @pyparm string|name|None|name of printer object.
- &level)) // @pyparm int|level|1|type of printer info structure (Levels 1,2,4,5 supported)
- return NULL;
- if (level<1 || level>9)
- return PyErr_Format(PyExc_ValueError,"Level %d is not supported", level);
- if (!PyWinObject_AsTCHAR(obname, &name, TRUE))
- return NULL; // last exit without cleanup
- // if call with NULL buffer succeeds, there's nothing to enumerate
- if (EnumPrinters(flags, name, level, NULL, 0, &bufneeded, &printersreturned)){
- ret = PyTuple_New(0);
- goto done;
- }
- if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER){
- PyWin_SetAPIError("EnumPrinters");
- goto done;
- }
- bufsize= bufneeded;
- if (NULL == (buf= (BYTE *)malloc(bufsize))){
- PyErr_Format(PyExc_MemoryError,"EnumPrinters: unable to allocate %d bytes", bufsize);
- goto done;
- }
- // @rdesc Level 1 returns a tuple of tuples for backward compatibility.
- // Each individual element is a tuple of (flags, description, name, comment)<nl>
- // All other levels return a tuple of dictionaries representing PRINTER_INFO_* structures
- if (!EnumPrinters(flags, name, level, buf, bufsize, &bufneeded, &printersreturned))
- PyWin_SetAPIError("EnumPrinters");
- else{
- ret=PyTuple_New(printersreturned);
- if (ret!=NULL)
- for (i= 0; i < printersreturned; i++){
- if (level==1){
- PRINTER_INFO_1 *info;
- info= (PRINTER_INFO_1 *)(buf + i * sizeof(PRINTER_INFO_1));
- obprinter_info=Py_BuildValue("kNNN",
- info->Flags,
- PyWinObject_FromTCHAR(info->pDescription),
- PyWinObject_FromTCHAR(info->pName),
- PyWinObject_FromTCHAR(info->pComment));
- }
- else
- obprinter_info=PyWinObject_FromPRINTER_INFO(buf + i * printer_info_offset[level-1], level);
- if (obprinter_info==NULL){
- Py_DECREF(ret);
- ret=NULL;
- break;
- }
- PyTuple_SET_ITEM(ret, i, obprinter_info);
- }
- }
- done:
- PyWinObject_FreeTCHAR(name);
- if (buf)
- free(buf);
- return ret;
- }
- // @pymethod int|win32print|StartDocPrinter|Notifies the print spooler that a document is to be spooled for printing. To be used before using WritePrinter. Returns the Jobid of the started job.
- static PyObject *PyStartDocPrinter(PyObject *self, PyObject *args)
- {
- HANDLE hprinter;
- DWORD level= 1;
- TCHAR *pDocName=NULL, *pOutputFile=NULL, *pDatatype=NULL;
- PyObject *obDocName, *obOutputFile, *obDatatype, *ret=NULL;
- DOC_INFO_1 info;
- DWORD JobID;
- if (!PyArg_ParseTuple(args, "O&k(OOO):StartDocPrinter",
- PyWinObject_AsPrinterHANDLE, &hprinter, // @pyparm <o PyPrinterHANDLE>|hprinter||handle to printer (from <om win32print.OpenPrinter>)
- &level, // @pyparm int|level|1|type of docinfo structure (only docinfo level 1 supported)
- &obDocName, &obOutputFile, &obDatatype // @pyparm data|tuple||A tuple corresponding to the level parameter.
- ))
- return NULL;
- if (level != 1)
- {
- PyErr_SetString(PyExc_ValueError, "This information level is not supported");
- return NULL;
- }
- // @comm For level 1, the tuple is:
- // @tupleitem 0|string|docName|Specifies the name of the document.
- // @tupleitem 1|string|outputFile|Specifies the name of an output file. To print to a printer, set this to None.
- // @tupleitem 2|string|dataType|Identifies the type of data used to record the document, such
- // as "raw" or "emf", used to record the print job. This member can be None. If it is not None,
- // the StartDoc function passes it to the printer driver. Note that the printer driver might
- // ignore the requested data type.
- if (PyWinObject_AsTCHAR(obDocName, &pDocName, FALSE)
- &&PyWinObject_AsTCHAR(obOutputFile, &pOutputFile, TRUE)
- &&PyWinObject_AsTCHAR(obDatatype, &pDatatype, TRUE)){
- info.pDocName= pDocName;
- info.pOutputFile= pOutputFile;
- info.pDatatype= pDatatype;
- Py_BEGIN_ALLOW_THREADS
- JobID= StartDocPrinter(hprinter, level, (LPBYTE)&info);
- Py_END_ALLOW_THREADS
- if (0 == JobID)
- PyWin_SetAPIError("StartDocPrinter");
- else
- ret = PyLong_FromUnsignedLong(JobID);
- }
- PyWinObject_FreeTCHAR(pDocName);
- PyWinObject_FreeTCHAR(pOutputFile);
- PyWinObject_FreeTCHAR(pDatatype);
- return ret;
- }
- // @pymethod None|win32print|EndDocPrinter|The EndDocPrinter function ends a print job for the specified printer. To be used after using WritePrinter.
- static PyObject *PyEndDocPrinter(PyObject *self, PyObject *args)
- {
- HANDLE hprinter;
- if (!PyArg_ParseTuple(args, "O&:EndDocPrinter",
- PyWinObject_AsPrinterHANDLE, &hprinter)) // @pyparm <o PyPrinterHANDLE>|hPrinter||handle to printer (from <om win32print.OpenPrinter>)
- return NULL;
- if (!EndDocPrinter(hprinter))
- return PyWin_SetAPIError("EndDocPrinter");
- Py_INCREF(Py_None);
- return Py_None;
- }
- // @pymethod |win32print|AbortPrinter|Deletes spool file for a printer
- static PyObject *PyAbortPrinter(PyObject *self, PyObject *args)
- {
- // @pyparm <o PyPrinterHANDLE>|hPrinter||Handle to printer as returned by <om win32print.OpenPrinter>
- HANDLE hprinter;
- if (!PyArg_ParseTuple(args, "O&:AbortPrinter", PyWinObject_AsPrinterHANDLE, &hprinter))
- return NULL;
- if (!AbortPrinter(hprinter))
- return PyWin_SetAPIError("AbortPrinter");
- Py_INCREF(Py_None);
- return Py_None;
- }
- // @pymethod |win32print|StartPagePrinter|Notifies the print spooler that a page is to be printed on specified printer
- static PyObject *PyStartPagePrinter(PyObject *self, PyObject *args)
- {
- // @pyparm <o PyPrinterHANDLE>|hprinter||Printer handle as returned by <om win32print.OpenPrinter>
- HANDLE hprinter;
- if (!PyArg_ParseTuple(args, "O&:StartPagePrinter", PyWinObject_AsPrinterHANDLE, &hprinter))
- return NULL;
- if (!StartPagePrinter(hprinter))
- return PyWin_SetAPIError("StartPagePrinter");
- Py_INCREF(Py_None);
- return Py_None;
- }
- // @pymethod |win32print|EndPagePrinter|Ends a page in a print job
- static PyObject *PyEndPagePrinter(PyObject *self, PyObject *args)
- {
- // @pyparm <o PyPrinterHANDLE>|hprinter||Printer handle as returned by <om win32print.OpenPrinter>
- HANDLE hprinter;
- if (!PyArg_ParseTuple(args, "O&:EndPagePrinter", PyWinObject_AsPrinterHANDLE, &hprinter))
- return NULL;
- if (!EndPagePrinter(hprinter))
- return PyWin_SetAPIError("EndPagePrinter");
- Py_INCREF(Py_None);
- return Py_None;
- }
- void PyWinObject_FreeDOCINFO(DOCINFO *di)
- {
- PyWinObject_FreeTCHAR((TCHAR *)di->lpszDocName);
- PyWinObject_FreeTCHAR((TCHAR *)di->lpszOutput);
- PyWinObject_FreeTCHAR((TCHAR *)di->lpszDatatype);
- }
- // @object DOCINFO|A tuple of information representing a DOCINFO struct
- // @prop string/<o PyUnicode>|DocName|Name of document
- // @prop string/<o PyUnicode>|Output|Name of output file when printing to file. Use None for normal printing.
- // @prop string/<o PyUnicode>|DataType|Type of data to be sent to printer, eg RAW, EMF, TEXT. Use None for printer default.
- // @prop int|Type|Flag specifying mode of operation. Can be DI_APPBANDING, DI_ROPS_READ_DESTINATION, or 0
- BOOL PyWinObject_AsDOCINFO(PyObject *obdocinfo, DOCINFO *di)
- {
- PyObject *obDocName, *obOutput, *obDataType;
- ZeroMemory(di, sizeof(*di));
- if (!PyTuple_Check(obdocinfo)){
- PyErr_SetString(PyExc_TypeError,"DOCINFO must be a tuple");
- return FALSE;
- }
- di->cbSize=sizeof(DOCINFO);
- return PyArg_ParseTuple(obdocinfo, "OOOk", &obDocName, &obOutput, &obDataType, &di->fwType)
- &&PyWinObject_AsTCHAR(obDocName, (TCHAR **)&di->lpszDocName, TRUE)
- &&PyWinObject_AsTCHAR(obOutput, (TCHAR **)&di->lpszOutput, TRUE)
- &&PyWinObject_AsTCHAR(obDataType, (TCHAR **)&di->lpszDatatype, TRUE);
- }
- // @pymethod int|win32print|StartDoc|Starts spooling a print job on a printer device context
- static PyObject *PyStartDoc(PyObject *self, PyObject *args)
- {
- // @pyparm <o PyHANDLE>|hdc||Printer device context handle as returned by <om win32gui.CreateDC>
- // @pyparm tuple|docinfo||<o DOCINFO> tuple specifying print job parameters
- // @rdesc On success, returns the job id of the print job
- HDC hdc;
- DOCINFO docinfo={0};
- int jobid;
- PyObject *obdocinfo;
- if (!PyArg_ParseTuple(args, "O&O:StartDoc", PyWinObject_AsPrinterHANDLE, &hdc, &obdocinfo))
- return NULL;
- if (!PyWinObject_AsDOCINFO(obdocinfo, &docinfo))
- return NULL;
- jobid=StartDoc(hdc, &docinfo);
- PyWinObject_FreeDOCINFO(&docinfo);
- if (jobid > 0)
- return PyLong_FromUnsignedLong(jobid);
- return PyWin_SetAPIError("StartDoc");
- }
- // @pymethod |win32print|EndDoc|Stops spooling a print job on a printer device context
- static PyObject *PyEndDoc(PyObject *self, PyObject *args)
- {
- // @pyparm <o PyHANDLE>|hdc||Printer device context handle as returned by <om win32gui.CreateDC>
- HDC hdc;
- int err;
- if (!PyArg_ParseTuple(args, "O&:EndDoc", PyWinObject_AsPrinterHANDLE, &hdc))
- return NULL;
- err=EndDoc(hdc);
- if (err > 0){
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyWin_SetAPIError("EndDoc");
- }
- // @pymethod |win32print|AbortDoc|Cancels a print job
- static PyObject *PyAbortDoc(PyObject *self, PyObject *args)
- {
- // @pyparm <o PyHANDLE>|hdc||Printer device context handle as returned by <om win32gui.CreateDC>
- HDC hdc;
- int err;
- if (!PyArg_ParseTuple(args, "O&:AbortDoc", PyWinObject_AsPrinterHANDLE, &hdc))
- return NULL;
- err=AbortDoc(hdc);
- if (err > 0){
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyWin_SetAPIError("AbortDoc");
- }
- // @pymethod |win32print|StartPage|Starts a page on a printer device context
- static PyObject *PyStartPage(PyObject *self, PyObject *args)
- {
- // @pyparm <o PyHANDLE>|hdc||Printer device context handle as returned by <om win32gui.CreateDC>
- HDC hdc;
- int err;
- if (!PyArg_ParseTuple(args, "O&:StartPage", PyWinObject_AsPrinterHANDLE, &hdc))
- return NULL;
- err=StartPage(hdc);
- if (err > 0){
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyWin_SetAPIError("StartPage");
- }
- // @pymethod |win32print|EndPage|Ends a page on a printer device context
- static PyObject *PyEndPage(PyObject *self, PyObject *args)
- {
- // @pyparm <o PyHANDLE>|hdc||Printer device context handle as returned by <om win32gui.CreateDC>
- HDC hdc;
- int err;
- if (!PyArg_ParseTuple(args, "O&:EndPage", PyWinObject_AsPrinterHANDLE, &hdc))
- return NULL;
- err=EndPage(hdc);
- if (err > 0){
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyWin_SetAPIError("EndPage");
- }
- // @pymethod int|win32print|WritePrinter|Copies the specified bytes to the specified printer.
- // Suitable for copying raw Postscript or HPGL files to a printer.
- // StartDocPrinter and EndDocPrinter should be called before and after.
- // @rdesc Returns number of bytes written to printer.
- static PyObject *PyWritePrinter(PyObject *self, PyObject *args)
- {
- HANDLE hprinter;
- LPVOID buf;
- DWORD buf_size;
- DWORD bufwritten_size;
- PyObject *obbuf;
- if (!PyArg_ParseTuple(args, "O&O:WritePrinter",
- PyWinObject_AsPrinterHANDLE, &hprinter, // @pyparm <o PyPrinterHANDLE>|hprinter||Handle to printer as returned by <om win32print.OpenPrinter>.
- &obbuf)) // @pyparm string|buf||String or buffer containing data to send to printer. Embedded NULL bytes are allowed.
- return NULL;
- if (!PyWinObject_AsReadBuffer(obbuf, &buf, &buf_size, FALSE))
- return NULL;
- if (!WritePrinter(hprinter, buf, buf_size, &bufwritten_size))
- return PyWin_SetAPIError("WritePrinter");
- return PyLong_FromUnsignedLong(bufwritten_size);
- }
- // convert a job structure to python. only works for level 1
- PyObject *JobtoPy(DWORD level, LPBYTE buf)
- {
- JOB_INFO_1 *job1;
- JOB_INFO_2 *job2;
- JOB_INFO_3 *job3;
- PyObject *ret;
- switch (level){
- case 1:{
- job1= (JOB_INFO_1 *)buf;
- ret= Py_BuildValue("{s:k, s:N, s:N, s:N, s:N, s:N, s:N, s:k, s:k, s:k, s:k, s:k, s:N}",
- "JobId", job1->JobId,
- "pPrinterName", PyWinObject_FromTCHAR(job1->pPrinterName),
- "pMachineName", PyWinObject_FromTCHAR(job1->pMachineName),
- "pUserName", PyWinObject_FromTCHAR(job1->pUserName),
- "pDocument", PyWinObject_FromTCHAR(job1->pDocument),
- "pDatatype", PyWinObject_FromTCHAR(job1->pDatatype),
- "pStatus", PyWinObject_FromTCHAR(job1->pStatus),
- "Status", job1->Status,
- "Priority", job1->Priority,
- "Position", job1->Position,
- "TotalPages", job1->TotalPages,
- "PagesPrinted", job1->PagesPrinted,
- "Submitted", PyWinObject_FromSYSTEMTIME(job1->Submitted));
- return ret;
- }
- case 2:{
- job2=(JOB_INFO_2 *)buf;
- ret= Py_BuildValue("{s:k, s:N, s:N, s:N, s:N, s:N, s:N, s:N, s:N, s:N, s:N, s:N, s:N, s:k, s:k, s:k, s:k, s:k, s:k, s:k, s:N, s:k, s:k}",
- "JobId", job2->JobId,
- "pPrinterName", PyWinObject_FromTCHAR(job2->pPrinterName),
- "pMachineName", PyWinObject_FromTCHAR(job2->pMachineName),
- "pUserName", PyWinObject_FromTCHAR(job2->pUserName),
- "pDocument", PyWinObject_FromTCHAR(job2->pDocument),
- "pNotifyName", PyWinObject_FromTCHAR(job2->pNotifyName),
- "pDatatype", PyWinObject_FromTCHAR(job2->pDatatype),
- "pPrintProcessor", PyWinObject_FromTCHAR(job2->pPrintProcessor),
- "pParameters", PyWinObject_FromTCHAR(job2->pParameters),
- "pDriverName", PyWinObject_FromTCHAR(job2->pDriverName),
- "pDevMode", PyWinObject_FromDEVMODE(job2->pDevMode),
- "pStatus", PyWinObject_FromTCHAR(job2->pStatus),
- "pSecurityDescriptor", PyWinObject_FromSECURITY_DESCRIPTOR(job2->pSecurityDescriptor),
- "Status", job2->Status,
- "Priority", job2->Priority,
- "Position", job2->Position,
- "StartTime", job2->StartTime,
- "UntilTime", job2->UntilTime,
- "TotalPages", job2->TotalPages,
- "Size", job2->Size,
- "Submitted", PyWinObject_FromSYSTEMTIME(job2->Submitted),
- "Time", job2->Time,
- "PagesPrinted", job2->PagesPrinted);
- return ret;
- }
- case 3:{
- job3=(JOB_INFO_3 *)buf;
- ret=Py_BuildValue("{s:k, s:k, s:k}",
- "JobId", job3->JobId,
- "NextJobId",job3->NextJobId,
- "Reserved",job3->Reserved);
- return ret;
- }
- default:
- return PyErr_Format(PyExc_NotImplementedError,"Job info level %d is not yet supported", level);
- }
- }
- // @pymethod tuple|win32print|EnumJobs|Enumerates print jobs on specified printer.
- // @rdesc Returns a sequence of dictionaries representing JOB_INFO_* structures, depending on level
- static PyObject *PyEnumJobs(PyObject *self, PyObject *args)
- {
- HANDLE hprinter;
- DWORD firstjob;
- DWORD nojobs;
- DWORD level= 1;
- LPBYTE buf;
- DWORD buf_size;
- DWORD bufneeded_size;
- DWORD jobsreturned;
- size_t job_info_offset[]={sizeof(JOB_INFO_1),sizeof(JOB_INFO_2),sizeof(JOB_INFO_3)};
- if (!PyArg_ParseTuple(args, "O&kk|k:EnumJobs",
- PyWinObject_AsPrinterHANDLE, &hprinter, // @pyparm <o PyPrinterHANDLE>|hPrinter||Handle of printer.
- &firstjob, // @pyparm int|FirstJob||location of first job in print queue to enumerate.
- &nojobs, // @pyparm int|NoJobs||Number of jobs to enumerate.
- &level // @pyparm int|Level|1|Level of information to return (JOB_INFO_1, JOB_INFO_2, JOB_INFO_3 supported).
- ))
- return NULL;
- if ((level < 1)||(level > 3))
- return PyErr_Format(PyExc_ValueError, "Information level %d is not supported", level);
- if (EnumJobs(hprinter, firstjob, nojobs, level, NULL, 0, &bufneeded_size, &jobsreturned))
- return PyTuple_New(0);
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- return PyWin_SetAPIError("EnumJobs");
- buf_size= bufneeded_size;
- if (NULL == (buf= (LPBYTE)malloc(buf_size)))
- return PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", buf_size);
- if (!EnumJobs(hprinter, firstjob, nojobs, level, buf, buf_size, &bufneeded_size, &jobsreturned))
- {
- free(buf);
- return PyWin_SetAPIError("EnumJobs");
- }
- DWORD i;
- PyObject *job_info;
- PyObject *ret = PyTuple_New(jobsreturned);
- if (ret!=NULL)
- for (i= 0; i < jobsreturned; i++)
- {
- job_info=JobtoPy(level, (buf + i * job_info_offset[level-1]));
- if (job_info == NULL){
- Py_DECREF(ret);
- ret=NULL;
- break;
- }
- PyTuple_SetItem(ret, i, job_info);
- }
- free(buf);
- return ret;
- }
- // @pymethod dictionary|win32print|GetJob|Returns dictionary of information about a specified print job.
- // @rdesc Returns a dict representing a JOB_INFO_* struct, depending on level
- static PyObject *PyGetJob(PyObject *self, PyObject *args)
- {
- HANDLE hprinter;
- DWORD jobid;
- DWORD level= 1;
- LPBYTE buf;
- DWORD buf_size;
- DWORD bufneeded_size;
- if (!PyArg_ParseTuple(args, "O&k|k:GetJob",
- PyWinObject_AsPrinterHANDLE, &hprinter, // @pyparm <o PyPrinterHANDLE>|hPrinter||Handle to a printer as returned by <om win32print.OpenPrinter>.
- &jobid, // @pyparm int|JobID||Job Identifier.
- &level // @pyparm int|Level|1|Level of information to return (JOB_INFO_1, JOB_INFO_2, JOB_INFO_3 supported).
- ))
- return NULL;
- if ((level < 1)||(level > 3))
- return PyErr_Format(PyExc_ValueError, "Information level %d is not supported", level);
- GetJob(hprinter, jobid, level, NULL, 0, &bufneeded_size);
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- return PyWin_SetAPIError("GetJob");
- buf_size= bufneeded_size;
- if (NULL == (buf= (LPBYTE)malloc(buf_size)))
- {
- PyErr_SetString(PyExc_MemoryError, "Malloc failed.");
- return NULL;
- }
- if (!GetJob(hprinter, jobid, level, buf, buf_size, &bufneeded_size))
- {
- free(buf);
- return PyWin_SetAPIError("GetJob");
- }
- PyObject *ret= JobtoPy(level, buf);
- free(buf);
- return ret;
- }
- // Convert a python dictionary to a JOB_INFO_* structure.
- // Returned buffer must be freed.
- BOOL PytoJob(DWORD level, PyObject *pyjobinfo, LPBYTE *pbuf)
- {
- static char *job1_keys[]={"JobId","pPrinterName","pMachineName","pUserName","pDocument","pDatatype",
- "pStatus","Status","Priority","Position","TotalPages","PagesPrinted","Submitted", NULL};
- static char *job1_format="kzzzzzzkkkkk|O:JOB_INFO_1";
- static char *job2_keys[]={"JobId","pPrinterName","pMachineName","pUserName","pDocument","pNotifyName",
- "pDatatype","pPrintProcessor","pParameters","pDriverName","pDevMode","pStatus","pSecurityDescriptor",
- "Status","Priority","Position","StartTime","UntilTime","TotalPages","Size",
- "Submitted","Time","PagesPrinted", NULL};
- static char *job2_format="kzzzzzzzzzOzOkkkkkkkOkk:JOB_INFO_2";
- static char *job3_keys[]={"JobId","NextJobId","Reserved", NULL};
- static char *job3_format="kk|k:JOB_INFO_3";
- PyObject *obdevmode, *obsecurity_descriptor, *obsubmitted=Py_None;
- BOOL ret=FALSE;
- *pbuf=NULL;
- switch(level){
- case 0:
- if (pyjobinfo==Py_None)
- ret=TRUE;
- else
- PyErr_SetString(PyExc_TypeError,"Info must be None when level is 0.");
- break;
- case 1:
- if (!PyDict_Check (pyjobinfo)){
- PyErr_SetString(PyExc_TypeError, "JOB_INFO_1 must be a dictionary");
- break;
- }
- JOB_INFO_1 *job1;
- if (NULL == (*pbuf= (LPBYTE)malloc(sizeof(JOB_INFO_1)))){
- PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", sizeof(JOB_INFO_1));
- break;
- }
- job1=(JOB_INFO_1 *)*pbuf;
- ZeroMemory(job1,sizeof(JOB_INFO_1));
- if (PyArg_ParseTupleAndKeywords(dummy_tuple, pyjobinfo, job1_format, job1_keys,
- &job1->JobId, &job1->pPrinterName, &job1->pMachineName, &job1->pUserName, &job1->pDocument,
- &job1->pDatatype, &job1->pStatus, &job1->Status, &job1->Priority, &job1->Position,
- &job1->TotalPages, &job1->PagesPrinted, &obsubmitted)
- &&((obsubmitted==Py_None)||PyWinObject_AsSYSTEMTIME(obsubmitted, &job1->Submitted)))
- ret=TRUE;
- break;
- case 2:
- if (!PyDict_Check (pyjobinfo)){
- PyErr_SetString(PyExc_TypeError, "JOB_INFO_2 must be a dictionary");
- break;
- }
- JOB_INFO_2 *job2;
- if (NULL == (*pbuf=(LPBYTE)malloc(sizeof(JOB_INFO_2)))){
- PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", sizeof(JOB_INFO_2));
- break;
- }
- job2=(JOB_INFO_2 *)*pbuf;
- ZeroMemory(job2,sizeof(JOB_INFO_2));
- if (PyArg_ParseTupleAndKeywords(dummy_tuple, pyjobinfo, job2_format, job2_keys,
- &job2->JobId, &job2->pPrinterName, &job2->pMachineName, &job2->pUserName, &job2->pDocument,
- &job2->pNotifyName, &job2->pDatatype, &job2->pPrintProcessor, &job2->pParameters,
- &job2->pDriverName, &obdevmode, &job2->pStatus, &obsecurity_descriptor, &job2->Status,
- &job2->Priority, &job2->Position, &job2->StartTime, &job2->UntilTime,
- &job2->TotalPages, &job2->Size, &obsubmitted, &job2->Time, &job2->PagesPrinted)
- &&PyWinObject_AsDEVMODE(obdevmode, &job2->pDevMode, TRUE)
- &&PyWinObject_AsSECURITY_DESCRIPTOR(obsecurity_descriptor, &job2->pSecurityDescriptor, TRUE)
- &&((obsubmitted==Py_None)||PyWinObject_AsSYSTEMTIME(obsubmitted, &job2->Submitted)))
- ret=TRUE;
- break;
- case 3:
- if (!PyDict_Check (pyjobinfo)){
- PyErr_SetString(PyExc_TypeError, "JOB_INFO_3 must be a dictionary");
- break;
- }
- JOB_INFO_3 *job3;
- if (NULL == (*pbuf=(LPBYTE)malloc(sizeof(JOB_INFO_3)))){
- PyErr_Format(PyExc_MemoryError, "Malloc failed for %d bytes", sizeof(JOB_INFO_3));
- break;
- }
- job3=(JOB_INFO_3 *)*pbuf;
- ZeroMemory(job3,sizeof(JOB_INFO_3));
- ret=PyArg_ParseTupleAndKeywords(dummy_tuple, pyjobinfo, job3_format, job3_keys,
- &job3->JobId, &job3->NextJobId, &job3->Reserved);
- break;
- default:
- PyErr_Format(PyExc_NotImplementedError,"Information level %d is not supported", level);
- }
- if (!ret)
- if (*pbuf!=NULL)
- free(*pbuf);
- return ret;
- }
- // @pymethod None|win32print|SetJob|Pause, cancel, resume, set priority levels on a print job.
- // @comm If printer is not opened with at least PRINTER_ACCESS_ADMINISTER access, 'Position' member of
- // JOB_INFO_1 and JOB_INFO_2 must be set to JOB_POSITION_UNSPECIFIED
- static PyObject *PySetJob(PyObject *self, PyObject *args)
- {
- HANDLE hprinter;
- DWORD jobid;
- DWORD level= 1;
- PyObject *pyjobinfo;
- DWORD command;
- LPBYTE buf;
- if (!PyArg_ParseTuple(args, "O&kkOk:SetJob",
- PyWinObject_AsPrinterHANDLE, &hprinter, // @pyparm <o PyPrinterHANDLE>|hPrinter||Handle of printer.
- &jobid, // @pyparm int|JobID||Job Identifier.
- &level, // @pyparm int|Level||Level of information in JobInfo dict (0, 1, 2, and 3 are supported).
- &pyjobinfo, // @pyparm dict|JobInfo||JOB_INFO_* Dictionary as returned by <om win32print.GetJob> or <om win32print.EnumJobs> (can be None if Level is 0).
- &command // @pyparm int|Command||Job command value (JOB_CONTROL_*).
- ))
- return NULL;
- if (!PytoJob(level, pyjobinfo, &buf))
- return NULL;
- if (!SetJob(hprinter, jobid, level, buf, command))
- {
- if (buf)
- free(buf);
- return PyWin_SetAPI…