Code:
#pragma comment(lib, "winspool.lib")
#pragma comment(lib, "user32.lib")
#include <windows.h>
#include <stdio.h>
struct userdata{
char szUserid[32];
char szPort[32];
}users[3] = {"BSmith", "Port1", "DJones", "Port2", "FPorter", "Port3"};
VOID DisplayError(CHAR* pMessage)
{
DWORD dwErrorNum;
CHAR szSysMsg[256] = {0};
CHAR* pPos;
dwErrorNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwErrorNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
szSysMsg, 256, NULL );
// Trim the end of the line and terminate it with a null
pPos = szSysMsg;
while((*pPos > 31) || (*pPos == 9))
++pPos;
do { *pPos-- = 0; } while((pPos >= szSysMsg) &&
((*pPos == '.') || (*pPos < 33) ));
printf( "\n%s, error %d (%s)", pMessage, dwErrorNum, szSysMsg );
}
BOOL PauseOrResumePrinter(CHAR *pPrinter, DWORD dwOperation)
{
HANDLE hPrinter;
PRINTER_DEFAULTS pd;
pd.pDatatype = NULL;
pd.pDevMode = NULL;
pd.DesiredAccess = PRINTER_ALL_ACCESS;
if(!OpenPrinter(pPrinter,&hPrinter,&pd))
{
DisplayError("OpenPrinter Failed");
return FALSE;
}
else if(!SetPrinter(hPrinter, 0, NULL, dwOperation))
{
DisplayError("SetPrinter failed");
return FALSE;
}
else if(!ClosePrinter(hPrinter))
{
DisplayError("ClosePrinter failed");
return FALSE;
}
else return TRUE;
}
BOOL ChangePrinterPort(LPTSTR pPrinterName, LPTSTR pPortName)
{
HANDLE hPrinter = NULL;
DWORD dwSizeNeeded = 0;
DEVMODE *pDevMode = NULL;
PRINTER_DEFAULTS pd;
BOOL bFlag;
LONG lFlag;
PPRINTER_INFO_2 pi2 = NULL;
ZeroMemory(&pd, sizeof(pd));
pd.DesiredAccess = PRINTER_ALL_ACCESS;
if(!OpenPrinter(pPrinterName, &hPrinter, &pd))
{
DisplayError("OpenPrinter failed");
return FALSE;
}
SetLastError(0);
bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwSizeNeeded);
if ((!bFlag) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwSizeNeeded == 0))
{
DisplayError("First GetPrinter failed");
ClosePrinter(hPrinter);
return FALSE;
}
if((pi2 = (PPRINTER_INFO_2) malloc(dwSizeNeeded)) == NULL)
{
DisplayError("pi2 malloc failed");
ClosePrinter(hPrinter);
return FALSE;
}
if(!GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwSizeNeeded, &dwSizeNeeded))
{
DisplayError("Second GetPrinter failed");
free(pi2);
pi2 = NULL;
ClosePrinter(hPrinter);
return FALSE;
}
// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
// DocumentProperties...
if (pi2->pDevMode == NULL)
{
dwSizeNeeded = DocumentProperties(NULL, hPrinter, pPrinterName, NULL, NULL, 0);
if (dwSizeNeeded <= 0)
{
DisplayError("First DocumentProperties failed");
free(pi2);
pi2 = NULL;
ClosePrinter(hPrinter);
return FALSE;
}
if((pDevMode = (DEVMODE *) malloc(dwSizeNeeded)) == NULL)
{
DisplayError("pDeviceMode malloc failed");
free(pi2);
pi2 = NULL;
ClosePrinter(hPrinter);
return FALSE;
}
lFlag = DocumentProperties(NULL, hPrinter, pPrinterName, pDevMode, NULL, DM_OUT_BUFFER | DM_IN_PROMPT);
if (lFlag != IDOK || pDevMode == NULL)
{
DisplayError("Second DocumentProperties failed");
free(pDevMode);
pDevMode = NULL;
free(pi2);
pi2 = NULL;
ClosePrinter(hPrinter);
return FALSE;
}
pi2->pDevMode = pDevMode;
}
// Do not attempt to set security descriptor...
pi2->pSecurityDescriptor = NULL;
printf("Printer name: %s\n", pi2->pPrinterName );
printf("Port name: %s\n", pi2->pPortName);
printf("Server name: %s\n", pi2->pServerName);
printf("Share name: %s\n", pi2->pShareName );
printf("Driver name: %s\n", pi2->pDriverName);
strcpy(pi2->pPortName, pPortName);
bFlag = SetPrinter(hPrinter, 2, (LPBYTE)pi2, 0);
if (!bFlag)
{
DisplayError("SetPrinter failed");
free(pi2);
pi2 = NULL;
ClosePrinter(hPrinter);
if (pDevMode != NULL)
{
free(pDevMode);
pDevMode = NULL;
}
return FALSE;
}
// Tell other apps that there was a change...
SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE, 0L, (LPARAM)(LPCSTR)pPrinterName, SMTO_NORMAL, 1000, NULL);
if (pi2)
{
free(pi2);
pi2 = NULL;
}
if (hPrinter)
ClosePrinter(hPrinter);
if (pDevMode)
{
free(pDevMode);
pDevMode = NULL;
}
return TRUE;
}
BOOL GetJobs(HANDLE hPrinter,
JOB_INFO_2 **ppJobInfo,
int *pcJobs,
DWORD *pStatus)
{
DWORD dwBytesNeeded, dwReturned, dwBytesUsed;
JOB_INFO_2 *pJobStorage = NULL;
PRINTER_INFO_2 *pPrinterInfo = NULL;
if (!GetPrinter(hPrinter, 2, NULL, 0, &dwBytesNeeded))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
DisplayError("First GetPrinter error");
return FALSE;
}
}
if((pPrinterInfo = (PRINTER_INFO_2 *)malloc(dwBytesNeeded)) == NULL)
{
DisplayError("pPrinterInfo malloc failed");
return FALSE;
}
if (!GetPrinter(hPrinter,
2,
(unsigned char *) pPrinterInfo,
dwBytesNeeded,
&dwBytesUsed))
{
DisplayError("Second GetPrinter error");
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
NULL,
0,
(LPDWORD)&dwBytesNeeded,
(LPDWORD)&dwReturned))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
DisplayError("First EnumJobs failed");
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
}
if((pJobStorage = (JOB_INFO_2 *)malloc(dwBytesNeeded)) == NULL)
{
DisplayError("pJobStorage malloc failed");
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
ZeroMemory(pJobStorage, dwBytesNeeded);
if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
(LPBYTE)pJobStorage,
dwBytesNeeded,
(LPDWORD)&dwBytesUsed,
(LPDWORD)&dwReturned))
{
DisplayError("Second EnumJobs failed");
free(pPrinterInfo);
free(pJobStorage);
pJobStorage = NULL;
pPrinterInfo = NULL;
return FALSE;
}
*pcJobs = dwReturned;
*pStatus = pPrinterInfo->Status;
*ppJobInfo = pJobStorage;
free(pPrinterInfo);
return TRUE;
}
BOOL PrintTheJobs(char *pPrinter, char *pOriginalPort)
{
char szTempError[128] = {0};
JOB_INFO_2 *pJobInfo = NULL;
DWORD dwNeeded, dwRet, dwPrinterStatus;
HANDLE hPrinter;
PRINTER_DEFAULTS pd;
JOB_INFO_2 *pJobs;
int iJobs, iIndex, iTempIndex;
pd.pDatatype = NULL;
pd.pDevMode = NULL;
pd.DesiredAccess = PRINTER_ALL_ACCESS;
if(!OpenPrinter(pPrinter,&hPrinter,&pd))
{
DisplayError("OpenPrinter Failed");
return FALSE;
}
else
GetJobs(hPrinter,
&pJobs, /* Pointer to be filled. */
&iJobs, /* Count of jobs filled. */
&dwPrinterStatus); /* Print Queue status. */
for (iIndex = 0; iIndex < iJobs; iIndex++)
{
printf("%s\n", pJobs[iIndex].pUserName);
printf("%s\n", pJobs[iIndex].pMachineName);
printf("%s\n", pJobs[iIndex].pPrinterName);
if (pJobs[iIndex].Status & JOB_STATUS_PAUSED)
{
printf("Job %d is paused\n", pJobs[iIndex].JobId);
GetJob( hPrinter,pJobs[iIndex].JobId , 2, (LPBYTE)pJobInfo , NULL, &dwNeeded);
if((pJobInfo = (JOB_INFO_2 *)malloc(dwNeeded)) == NULL)
{
DisplayError("pJobInfo malloc failed");
return FALSE;
}
GetJob( hPrinter, pJobs[iIndex].JobId, 2, (LPBYTE)pJobInfo , dwNeeded , &dwRet);
pJobInfo->Status = JOB_STATUS_RESTART;
if(!SetJob(hPrinter, pJobs[iIndex].JobId, 2, (LPBYTE)pJobInfo,0))
DisplayError("SetJob failed");
else
{
// Change this port per your requirements.
// Possibly based on userid of job
char szNewPrinterPort[128] = {0};
for(iTempIndex = 0; iTempIndex < sizeof(users) / sizeof(userdata); iTempIndex++)
{
printf("%s %s\n", users[iTempIndex].szUserid,users[iTempIndex].szPort);
if(stricmp(users[iTempIndex].szUserid, pJobs[iIndex].pUserName) == 0)
{
printf("Processing job for: %s\n",users[iTempIndex].szUserid);
strcpy(szNewPrinterPort,users[iTempIndex].szPort );
break;
}
}
if(ChangePrinterPort(pPrinter, szNewPrinterPort) == TRUE)
{
PauseOrResumePrinter(pPrinter, PRINTER_CONTROL_RESUME);
GetJob( hPrinter,pJobs[iIndex].JobId , 2, (LPBYTE)pJobInfo , NULL, &dwNeeded);
// This is where you'll have to refine the code to continuously
// query the printer and print the jobs
// The following while loop is very primitive. You'll need something a
// lot more elegant.
while(pJobs[iIndex].Status & JOB_STATUS_PRINTING)
{
GetJob( hPrinter,pJobs[iIndex].JobId , 2, (LPBYTE)pJobInfo , NULL, &dwNeeded);
printf("Job printing\n");
Sleep(2000);
}
if(ChangePrinterPort(pPrinter, pOriginalPort) == FALSE)
{
sprintf(szTempError, "Cannot change back to original printer port %s from %s\n",pOriginalPort, szNewPrinterPort);
DisplayError(szTempError);
}
}
else
{
sprintf(szTempError, "Could not print job id: %d User Name: %s Machine name: %s",
pJobs[iIndex].JobId,pJobs[iIndex].pUserName,pJobs[iIndex].pMachineName);
DisplayError(szTempError);
}
}
free(pJobInfo);
}
}
return TRUE;
}
INT main(VOID)
{
char szOriginalPrinterPort[] = {"Port4"};
char szPrinter[] = {"\\\\MyServer\\MyPrinter"};
PrintTheJobs(szPrinter, szOriginalPrinterPort);
return 0;
}