⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pjlmon.c

📁 A language monitor provides a full duplex communications path between the print spooler and bi-direc
💻 C
📖 第 1 页 / 共 4 页
字号:
--*/
{

    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 + -