📄 pjlmon.c
字号:
--*/
{
PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort);
PINIJOB pIniJob = NULL;
DWORD cbJob;
BOOL bRet = FALSE;
//
// Validate parameters
//
if ( !pIniPort ||
pIniPort->signature != PJ_SIGNATURE ||
!pDocInfo ||
!pszPrinterName ||
!*pszPrinterName ) {
SPLASSERT(pIniPort &&
pIniPort->signature == PJ_SIGNATURE &&
pDocInfo);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if ( dwLevel != 1 ) {
SPLASSERT(dwLevel == 1);
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
//
// Serialize access to the port
//
if ( pIniPort->status & PP_INSTARTDOC ) {
SetLastError(ERROR_BUSY);
return FALSE;
}
cbJob = sizeof(*pIniJob) + lstrlen(pszPrinterName) * sizeof(TCHAR)
+ sizeof(TCHAR);
pIniJob = (PINIJOB) AllocSplMem(cbJob);
if ( !pIniJob ) {
goto Cleanup;
}
pIniJob->pszPrinterName = wcscpy((LPTSTR)(pIniJob+1), pszPrinterName);
if ( !OpenPrinter(pIniJob->pszPrinterName, &pIniJob->hPrinter, NULL) ) {
DBGMSG(DBG_WARNING,
("pjlmon: OpenPrinter failed for %s, last error %d\n",
pIniJob->pszPrinterName, GetLastError()));
goto Cleanup;
}
pIniPort->status |= PP_INSTARTDOC;
bRet = (*pIniPort->fn.pfnStartDocPort)(pIniPort->hPort,
pszPrinterName,
dwJobId,
dwLevel,
pDocInfo);
if ( !bRet ) {
pIniPort->status &= ~PP_INSTARTDOC;
goto Cleanup;
}
//
// If Ustatus thread is not running then check if printer understands
// PJL, unless we determined that printer does not understand PJL earlier
//
if ( !(pIniPort->status & PP_RUN_THREAD) &&
!(pIniPort->status & PP_DONT_TRY_PJL) ) {
CreateUstatusThread(pIniPort);
}
//
// set PP_SEND_PJL flag here so the first write of the job
// will try to send PJL command to initiate the job control
//
pIniJob->JobId = dwJobId;
pIniJob->status |= PP_INSTARTDOC;
EnterSplSem();
if ( !pIniPort->pIniJob ) {
pIniPort->pIniJob = pIniJob;
} else {
pIniJob->pNext = pIniPort->pIniJob;
pIniPort->pIniJob = pIniJob;
}
LeaveSplSem();
if ( pIniPort->status & PP_IS_PJL )
pIniJob->status |= PP_SEND_PJL;
WaitForSingleObject(pIniPort->DoneWriting, INFINITE);
Cleanup:
if ( !bRet ) {
if ( pIniJob )
FreeIniJob(pIniJob);
}
return bRet;
}
BOOL
WINAPI
PJLMonReadPort(
IN HANDLE hPort,
OUT LPBYTE pBuffer,
IN DWORD cbBuf,
OUT LPDWORD pcbRead
)
/*++
Routine Description:
Language monitor ReadPort
Arguments:
hPort : Port handle
pBuffer : Buffer to read data to
cbBuf : Buffer size
pcbRead : Pointer to the variable to return read count
Return Value:
TRUE on success, FALSE on error
--*/
{
PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort);
if ( !pIniPort ||
pIniPort->signature != PJ_SIGNATURE ) {
SPLASSERT(pIniPort && pIniPort->signature == PJ_SIGNATURE);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return (*pIniPort->fn.pfnReadPort)(pIniPort->hPort, pBuffer, cbBuf, pcbRead);
}
BOOL
WINAPI
PJLMonWritePort(
IN HANDLE hPort,
IN LPBYTE pBuffer,
IN DWORD cbBuf,
IN LPDWORD pcbWritten
)
/*++
Routine Description:
Language monitor WritePort
Arguments:
hPort : Port handle
pBuffer : Data Buffer
cbBuf : Buffer size
pcbRead : Pointer to the variable to return written count
Return Value:
TRUE on success, FALSE on error
--*/
{
PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort);
BOOL ret;
if ( !pIniPort ||
pIniPort->signature != PJ_SIGNATURE ) {
SPLASSERT(pIniPort && pIniPort->signature == PJ_SIGNATURE);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// check if it's the fist write of the job
//
if ( pIniPort->pIniJob &&
(pIniPort->pIniJob->status & PP_SEND_PJL) ) {
// PP_SEND_PJL is set if it's the first write of the job
char string[256];
if ( !WriteCommand(hPort, "\033%-12345X@PJL \015\012") ) {
return FALSE;
}
//
// clear PP_SEND_PJL here if we have successfully send a PJL command.
//
pIniPort->pIniJob->status &= ~PP_SEND_PJL;
//
// set PP_PJL_SENT meaning that we have successfully sent a
// PJL command to the printer, though it doesn't mean that
// we will get a successfully read. PP_PJL_SENT gets cleared in
// StartDocPort.
//
pIniPort->pIniJob->status |= PP_PJL_SENT;
sprintf(string, "@PJL JOB NAME = \"MSJOB %d\"\015\012",
pIniPort->pIniJob->JobId);
WriteCommand(hPort, string);
WriteCommand(hPort, "@PJL USTATUS JOB = ON \015\012@PJL USTATUS PAGE = OFF \015\012@PJL USTATUS DEVICE = ON \015\012@PJL USTATUS TIMED = 30 \015\012\033%-12345X");
}
//
// writing to port monitor
//
ret = (*pIniPort->fn.pfnWritePort)(pIniPort->hPort, pBuffer,
cbBuf, pcbWritten);
if ( ret ) {
pIniPort->status &= ~PP_WRITE_ERROR;
} else {
pIniPort->status |= PP_WRITE_ERROR;
}
if ( (!ret || pIniPort->PrinterStatus) &&
(pIniPort->status & PP_THREAD_RUNNING) ) {
//
// By waiting for the UStatus thread to finish reading if there
// is an error and printer sends unsolicited status
// and user gets status on queue view before the win32 popup
//
ResetEvent(pIniPort->DoneReading);
SetEvent(pIniPort->WakeUp);
WaitForSingleObject(pIniPort->DoneReading, INFINITE);
}
return ret;
}
BOOL
WINAPI
PJLMonEndDocPort(
HANDLE hPort
)
/*++
Routine Description:
Language monitor EndDocPort
Arguments:
hPort : Port handle
Return Value:
TRUE on success, FALSE on error
--*/
{
PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort);
PINIJOB pIniJob;
if ( !pIniPort ||
pIniPort->signature != PJ_SIGNATURE ) {
SPLASSERT(pIniPort && pIniPort->signature == PJ_SIGNATURE);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//
// Find the job (which is the last)
//
pIniJob = pIniPort->pIniJob;
if ( !pIniJob )
DBGMSG(DBG_ERROR, ("No jobs?\n"));
//
// check if we had sent PJL command, i.e. if the printer is bi-di
//
if ( pIniJob && (pIniJob->status & PP_PJL_SENT) ) {
//
// if the printer is bi-di, tell printer to let us know when the job
// is don't in the printer and we'll really EndDoc then. this is so
// that we can continue to monitor the job status until the job is
// really done in case there's an error occurs.
// but some cheap printers like 4L, doesn't handle this EOJ command
// reliably, so we time out if printer doesn't tell us EOJ after a
// while so that we don't end up having the port open forever in this
// case.
//
char string[256];
sprintf(string,
"\033%%-12345X@PJL EOJ NAME = \"MSJOB %d\"\015\012\033%%-12345X",
pIniPort->pIniJob->JobId);
WriteCommand(hPort, string);
pIniJob->TimeoutCount = GetTickCount();
pIniJob->status &= ~PP_INSTARTDOC;
}
(*pIniPort->fn.pfnEndDocPort)(pIniPort->hPort);
if ( pIniJob && !(pIniJob->status & PP_PJL_SENT) ) {
//
// This is not bi-di printer send EOJ so that spooler deletes it
//
SendJobLastPageEjected(pIniPort, pIniJob->JobId, FALSE);
}
pIniPort->status &= ~PP_INSTARTDOC;
// wake up the UStatus read thread if printer is bi-di
if ( pIniPort->status & PP_THREAD_RUNNING )
SetEvent(pIniPort->WakeUp);
SetEvent(pIniPort->DoneWriting);
return TRUE;
}
BOOL
WINAPI
PJLMonClosePort(
HANDLE hPort
)
/*++
Routine Description:
Language monitor ClosePort
Arguments:
hPort : Port handle
Return Value:
TRUE on success, FALSE on error
--*/
{
PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort);
if ( !pIniPort ||
pIniPort->signature != PJ_SIGNATURE ) {
SPLASSERT(pIniPort && pIniPort->signature == PJ_SIGNATURE);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
pIniPort->status &= ~PP_INSTARTDOC;
//
// Kill Ustatus thread if it is running
//
if (pIniPort->status & PP_RUN_THREAD) {
pIniPort->status &= ~PP_RUN_THREAD;
#ifdef DEBUG
OutputDebugStringA("Set ~PP_RUN_THREAD from close port\n");
#endif
SetEvent(pIniPort->WakeUp);
//
// if UStatusThread is still running at this point,
// wait utill it terminates, because we can't DeletePortEntry
// until it terminates.
//
while (pIniPort->WakeUp)
Sleep(WAIT_FOR_USTATUS_THREAD_TIMEOUT);
}
if ( pIniPort->fn.pfnClosePort )
(*pIniPort->fn.pfnClosePort)(pIniPort->hPort);
EnterSplSem();
DeletePortEntry(pIniPort);
LeaveSplSem();
return TRUE;
}
BOOL
WriteCommand(
HANDLE hPort,
LPSTR cmd
)
/*++
Routine Description:
Write a command to the port
Arguments:
hPort : Port handle
cmd : Command buffer
Return Value:
TRUE on success, FALSE on error
--*/
{
DWORD cbWrite, cbWritten, dwRet;
PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort);
cbWrite = strlen(cmd);
dwRet = (*pIniPort->fn.pfnWritePort)(pIniPort->hPort, cmd, cbWrite, &cbWritten);
if ( dwRet ) {
pIniPort->status &= ~PP_WRITE_ERROR;
} else {
pIniPort->status |= PP_WRITE_ERROR;
DBGMSG(DBG_INFO, ("PJLMON!No data Written\n"));
if ( pIniPort->status & PP_THREAD_RUNNING )
SetEvent(pIniPort->WakeUp);
}
return dwRet;
}
#define CBSTRING 1024
BOOL
ReadCommand(
HANDLE hPort
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -