The following information is provided as is, and the authors take no responsibility for the correctness.
Try executing “rundll32 printui.dll,PrintUIEntry /?“, and you will discover all sorts of tasty managment functions.
Microsoft has included some nifty spooler stress test tools in their Windows Server System Reference Architecture (WSSRA).
The complete WSSRA including the tools can be download here: http://go.microsoft.com/fwlink/?LinkId=32645&clcid=0x409
On Windows 2000 the only upper limit in theory is due to the dmDriverExtra field (short) in public devmode. But in practice, there are legacy applications that assumed their own “big enough” devmode size. From our testing experience, we recommend the full DEVMODE size to be no more than 10K.
Windows 98 has a 2K limit.
Our testing showed that some legacy apps will crash if the full DEVMODE size is over 12K. That's why we recommended the 10K size (For Windows NT/2000/XP...). //Printer Drivers -- Ask the Experts Online, November 2002
When specifying Level 2 for GetPrinter, you might always receive an ERROR_ACCESS_DENIED, even if you provided PRINTER_ACCESS_ADMINISTER, READ_CONTROL or ACCESS_SYSTEM_SECURITY in the access mask used for OpenPrinter.
To sucessfully call GetPrinter for level 2, you should:
The status of printers and print jobs are updated by the Win32 Spooler during the despool of a print job. At all other times, when that printer is not despooling and reports no state information, the printer is considered to be ready and idle.
There is one fundamental premise that must be true to determine the state of a physical printer: the Spooler must be attempting to send a print job to the physical printer. This is the only time the state of the printer is reported by the port monitor.
For information on how to get status informations se the Microsoft Knowledge Base article Q160129.
Just read in a post from Jeffrey Tan that BIDI communication with the printer is actually possible.
I always thought that this was impossible, as Windows restrics the read access to any ports to language monitors only.
But now it turns out, you can work around this, by creating a dummy job, and then opening a handle to that job with OpenPrinter. You ofcourse still need the port monitor to support bidi.
#define BUFSIZE 256
BOOL TestReadPrinterWithJob(LPSTR szPrinterName)
{
HANDLE hPrinter = NULL;
HANDLE hPrinterJob = NULL;
DWORD dwBytesRead;
LPVOID lpBytes = NULL;
DOC_INFO_1 dc;
DWORD jobid;
TCHAR jobStr[100];
// Open a handle to the printer.
if (!OpenPrinter(szPrinterName, &hPrinter, NULL))
{
PrintError(GetLastError(), "OpenPrinter");
return FALSE;
}
// We can't read from a printer handle, but we can read from
// a printer job handle, So the trick is to create a Job using
// StartDocPrinter, then open a handle to the printer job...
ZeroMemory(&dc, sizeof(DOC_INFO_1));
dc.pDocName="Dummy job";
jobid = StartDocPrinter(hPrinter,1,(LPSTR)&dc); // start a Doc
if (jobid == 0)
{
ClosePrinter(hPrinter);
PrintError(GetLastError(), "OpenPrinter");
return FALSE;
}
// Open handle to the printer job...
wsprintf(jobStr, "%s,Job %i", szPrinterName, jobid);
if (!OpenPrinter(jobStr, &hPrinterJob, NULL))
{
ClosePrinter(hPrinter);
PrintError(GetLastError(), "OpenPrinter Job");
return FALSE;
}
// Allocate a buffer to read printer data into...
lpBytes = (LPVOID)malloc(BUFSIZE);
if (!lpBytes)
{
PrintError(GetLastError(), "malloc");
ClosePrinter(hPrinter);
ClosePrinter(hPrinterJob);
return FALSE;
}
// Try ReadPrinter...
SetLastError(0);
if (!ReadPrinter(hPrinterJob, lpBytes, BUFSIZE, &dwBytesRead))
{
PrintError(GetLastError(), "ReadPrinter");
ClosePrinter(hPrinter);
ClosePrinter(hPrinterJob);
if (lpBytes)
free(lpBytes);
return FALSE;
}
else
{
printf("%i bytes successfully read by ReadPrinter (%i attempted)\n",
dwBytesRead, BUFSIZE);
}
// Clean up...
ClosePrinter(hPrinterJob);
EndDocPrinter(hPrinter); // end the doc
ClosePrinter(hPrinter);
if (lpBytes)
free(lpBytes);
return TRUE;
}
void PrintError( DWORD dwError, LPCSTR lpString )
{
#define MAX_MSG_BUF_SIZE 512
char *msgBuf;
DWORD cMsgLen;
cMsgLen = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | 40,
NULL, dwError, MAKELANGID(0, SUBLANG_ENGLISH_US),
(LPTSTR) &msgBuf, MAX_MSG_BUF_SIZE, NULL);
printf( "%s Error [%d]:: %s\n", lpString, dwError, msgBuf );
LocalFree( msgBuf );
#undef MAX_MSG_BUF_SIZE
}