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

📄 pjlmon.c

📁 A language monitor provides a full duplex communications path between the print spooler and bi-direc
💻 C
📖 第 1 页 / 共 4 页
字号:
    msg[0]  = '\0';
#endif

    OldStatus = pIniPort->PrinterStatus;
    pIniPort->PrinterStatus = 0;

    for (i = 0; i < nTokenParsed; i++) {

        // DBGMSG(DBG_INFO, ("pjlmon!Token=0x%x, Value=%d\n",
        //                   tokenPairs[i].token, tokenPairs[i].value));

        switch(tokenPairs[i].token) {

        case TOKEN_INFO_STATUS_CODE:
        case TOKEN_USTATUS_DEVICE_CODE:

            for (pMap = PJLToStatus; pMap->pjl; pMap++) {

                if (pMap->pjl == tokenPairs[i].value) {

                    pIniPort->PrinterStatus = pMap->status;
                    dwSeverity = SeverityFromPjlStatus(pMap->pjl);
                    if ( dwSeverity == PORT_STATUS_TYPE_ERROR )
                        pIniPort->status |= PP_PRINTER_OFFLINE;
                    else
                        pIniPort->status &= ~PP_PRINTER_OFFLINE;
                    break;
                }
            }

            if ( pMap->pjl && pMap->pjl == tokenPairs[i].value )
                break;

            //
            // some printers use this to signal online/ready
            //
            if ( tokenPairs[i].value == 10001  ||
                 tokenPairs[i].value == 10002  ||
                 tokenPairs[i].value == 11002 ) {

                pIniPort->status       &= ~PP_PRINTER_OFFLINE;
                pIniPort->PrinterStatus = 0;
                dwSeverity              = 0;
            }


            //
            // background or foreground paper out
            //
            if ( tokenPairs[i].value > 11101 && tokenPairs[i].value < 12000  ||
                 tokenPairs[i].value > 41101 && tokenPairs[i].value < 42000 ) {

                pIniPort->PrinterStatus  = PORT_STATUS_PAPER_OUT;

                if ( tokenPairs[i].value > 4000 ) {

                    dwSeverity           = PORT_STATUS_TYPE_ERROR;
                    pIniPort->status    |= PP_PRINTER_OFFLINE;
                } else {

                    dwSeverity = PORT_STATUS_TYPE_WARNING;
                }
            } else if (tokenPairs[i].value > 40000) {

                pIniPort->PrinterStatus = PORT_STATUS_USER_INTERVENTION;
                pIniPort->status       |= PP_PRINTER_OFFLINE;
                dwSeverity              = PORT_STATUS_TYPE_ERROR;
            }

            break;

        case TOKEN_INFO_STATUS_ONLINE:
        case TOKEN_USTATUS_DEVICE_ONLINE:

            // DBGMSG(DBG_INFO, ("PJLMON:ONLINE = %d\n", tokenPairs[i].value));

            if (tokenPairs[i].value) {

                pIniPort->status        &= ~PP_PRINTER_OFFLINE;
                dwSeverity = pIniPort->PrinterStatus ? PORT_STATUS_TYPE_WARNING :
                                                       0;
            } else {

                if ( !pIniPort->PrinterStatus )
                    pIniPort->PrinterStatus = PORT_STATUS_OFFLINE;
                pIniPort->status       |= PP_PRINTER_OFFLINE;
                dwSeverity              = PORT_STATUS_TYPE_ERROR;
            }
            break;

        case TOKEN_USTATUS_JOB_NAME_MSJOB:

#ifdef DEBUG
            sprintf(msg, "EOJ for %d\n", tokenPairs[i].value);
            OutputDebugStringA(msg);
#endif
            SendJobLastPageEjected(pIniPort, (DWORD)tokenPairs[i].value, FALSE);
            break;

        case TOKEN_INFO_CONFIG_MEMORY:
        case TOKEN_INFO_CONFIG_MEMORY_SPACE:

            // IMPORTANT NOTE:
            //
            // Use SetPrinterData to cache the information in printer's registry.
            // GDI's DrvGetPrinterData will check the printer's registry first,
            // and if cache data is available, it will use it and not call
            // GetPrinterData (which calls language monitor's
            // GetPrinterDataFromPort).

#ifdef DEBUG
            sprintf(msg, "PJLMON installed memory %d\n", tokenPairs[i].value);
            OutputDebugStringA(msg);
#endif
            pIniPort->dwInstalledMemory = (DWORD)tokenPairs[i].value;
            break;

        case TOKEN_INFO_MEMORY_TOTAL:

            // IMPORTANT NOTE:
            //
            // Use SetPrinterData to cache the information in printer's registry.
            // GDI's DrvGetPrinterData will check the printer's registry first,
            // and if cache data is available, it will use it and not call
            // GetPrinterData (which calls language monitor's
            // GetPrinterDataFromPort).

#ifdef DEBUG
            sprintf(msg, "PJLMON available memory %d\n", tokenPairs[i].value);
            OutputDebugStringA(msg);
#endif
            pIniPort->dwAvailableMemory = (DWORD)tokenPairs[i].value;
            break;

        default:
            break;
        }
    }

    if ( OldStatus != pIniPort->PrinterStatus ) {

        ZeroMemory(&PortInfo3, sizeof(PortInfo3));
        PortInfo3.dwStatus      = pIniPort->PrinterStatus;
        PortInfo3.dwSeverity    = dwSeverity;

        if ( !SetPort(NULL,
                      pIniPort->pszPortName,
                      3,
                      (LPBYTE)&PortInfo3) ) {

            DBGMSG(DBG_WARNING,
                   ("pjlmon: SetPort failed %d (LE: %d)\n",
                    pIniPort->PrinterStatus, GetLastError()));

            pIniPort->PrinterStatus = OldStatus;
        }
    }
}


VOID
ProcessParserError(
    DWORD status
)
/*++

Routine Description:
    Print error messages on parsing error

Arguments:
    status  : status

Return Value:
    None

--*/
{
#ifdef DEBUG
    LPSTR pString;

    switch (status)
    {
    case STATUS_REACHED_END_OF_COMMAND_OK:
        pString = "STATUS_REACHED_END_OF_COMMAND_OK\n";
        break;

    case STATUS_CONTINUE:
        pString = "STATUS_CONTINUE\n";
        break;

    case STATUS_REACHED_FF:
        pString = "STATUS_REACHED_FF\n";
        break;

    case STATUS_END_OF_STRING:
        pString = "STATUS_END_OF_STRING\n";
        break;

    case STATUS_SYNTAX_ERROR:
        pString = "STATUS_SYNTAX_ERROR\n";
        break;

    case STATUS_ATPJL_NOT_FOUND:
        pString = "STATUS_ATPJL_NOT_FOUND\n";
        break;

    case STATUS_NOT_ENOUGH_ROOM_FOR_TOKENS:
        pString = "STATUS_NOT_ENOUGH_ROOM_FOR_TOKENS\n";
        break;

    default:
        pString = "INVALID STATUS RETURNED!!!!!!\n";
        break;
    };

    OutputDebugStringA(pString);
#endif
}


#define MODEL                       "MODEL:"
#define MDL                         "MDL:"
#define COMMAND                     "COMMAND SET:"
#define CMD                         "CMD:"
#define COLON                       ':'
#define SEMICOLON                   ';'


LPSTR
FindP1284Key(
    PINIPORT    pIniPort,
    LPSTR   lpKey
    )
/*++

Routine Description:
    Find the 1284 key identifying the device id

Arguments:
    status  : status

Return Value:
    Pointer to the command string, NULL if not found.

--*/
{
    LPSTR   lpValue;                // Pointer to the Key's value
    WORD    wKeyLength;             // Length for the Key (for stringcmps)
    LPSTR   ret = NULL;

    // While there are still keys to look at.
#ifdef DEBUG
    OutputDebugStringA("PJLMon!DeviceId : <");
    OutputDebugStringA(lpKey);
    OutputDebugStringA(">\n");
#endif

    while (lpKey && *lpKey) {

        //
        // Is there a terminating COLON character for the current key?
        //
        if (!(lpValue = mystrchr(lpKey, COLON)) ) {

            //
            // N: OOPS, somthing wrong with the Device ID
            //
            return ret;
        }

        //
        // The actual start of the Key value is one past the COLON
        //
        ++lpValue;

        //
        // Compute the Key length for Comparison, including the COLON
        // which will serve as a terminator
        //
        wKeyLength = (WORD)(lpValue - lpKey);

        //
        // Compare the Key to the Know quantities.  To speed up the comparison
        // a Check is made on the first character first, to reduce the number
        // of strings to compare against.
        // If a match is found, the appropriate lpp parameter is set to the
        // key's value, and the terminating SEMICOLON is converted to a NULL
        // In all cases lpKey is advanced to the next key if there is one.
        //
        if ( *lpKey == 'C' ) {

            //
            // Look for COMMAND SET or CMD
            //
            if ( !mystrncmp(lpKey, COMMAND, wKeyLength) ||
                 !mystrncmp(lpKey, CMD, wKeyLength) ) {

                ret = lpValue;
            }
        }

        // Go to the next Key

        if ( lpKey = mystrchr(lpValue, SEMICOLON) ) {

            *lpKey = '\0';
            ++lpKey;
        }
    }

    return ret;
}


BOOL
IsPJL(
    PINIPORT pIniPort
    )
/*++

Routine Description:
    Finds out if the printer is a PJL bi-di printer

Arguments:
    pIniPort  : Points to an INIPORT

Return Value:
    TRUE if printer is PJL bi-di, else FALSE

    On failure PP_DONT_TRY_PJL is set

--*/
{
    char        szID[MAX_DEVID];
    DWORD       cbRet;
    LPSTR       lpCMD;
    HANDLE      hPort = (HANDLE)pIniPort;
    BOOL        bRet = FALSE;

    //
    // for printers that supports P1284 plug and play like LJ 4L, DJ540.
    // we parse the COMMAND string and see if PJL is supported
    //
    if (pIniPort->fn.pfnGetPrinterDataFromPort) {

        //
        // Only try P1284 if port monitor supports DeviceIOCtl
        //
        memset((LPBYTE)szID, 0, sizeof(szID));
        cbRet = 0;
        if ((*pIniPort->fn.pfnGetPrinterDataFromPort)
                (pIniPort->hPort, GETDEVICEID, NULL, NULL,
                    0, (LPWSTR)szID, sizeof(szID), &cbRet)
            && cbRet) {

            //
            // succeeded the P1284 plug and play protocol
            //
            szID[cbRet] = '\0';

            if ( lpCMD = FindP1284Key(pIniPort, szID) ) {

                // found the COMMAND string

                while (*lpCMD) {

                    //
                    // look for "PJL"
                    //
                    if ( lpCMD[0] == 'P' && lpCMD[1] == 'J' && lpCMD[2] == 'L' ){

                        pIniPort->status &= ~PP_DONT_TRY_PJL;
                        bRet = TRUE;
                        goto Cleanup;
                    }

                    lpCMD++;
                }

                pIniPort->status |= PP_DONT_TRY_PJL;
                goto Cleanup;
            }
        }

        //
        // fall thru to try PJL bi-di if we failed the P1284 communication
        // or P1284 didn't return a COMMAND string
        //
    }

    //
    // for printers that don't support P1284 plug and play, but support PJL
    // language command, like LJ 4 and 4M. we try to write/read PJL
    // command and see if it succeeds.
    // if we can't set the time outs we don't want to try to read, just fail.
    //
    if ( pIniPort->fn.pfnSetPortTimeOuts &&
         !(pIniPort->status & PP_DONT_TRY_PJL)) {

        COMMTIMEOUTS CTO;

        memset((LPSTR)&CTO, 0, sizeof(CTO));
        CTO.ReadTotalTimeoutConstant = 5000;
        CTO.ReadIntervalTimeout = 200;
        if ( !(*pIniPort->fn.pfnSetPortTimeOuts)(pIniPort->hPort, &CTO, 0) ) {

            goto Cleanup;
        }

        // This <ESC>*s1M is a PCL5 command to determine the amount of memory
        // in a PCL5 printer, and if the printer is PCL5 and bi-di capable,
        // it will return "PCL\015\012INFO MEMORY".
        // See PJL Tech Ref Manual page 7-21.

        pIniPort->status &= ~PP_IS_PJL;

        if ( !WriteCommand(hPort, "\033*s1M") )
            goto Cleanup;

        // ReadCommand->ProcessPJLString will set PP_IS_PJL
        // if we read any valid PJL command back from the printer

        if ( !ReadCommand(hPort) ) {

            //
            // We have jumped through the hoop to determin if this printer can
            // understand PJL.  It DOES NOT.  We are not going to try again.
            // until there is a printer change.
            //
            pIniPort->status |= PP_DONT_TRY_PJL;
        }

        if (pIniPort->status & PP_IS_PJL) {

            bRet = TRUE;
            goto Cleanup;
        }
    }

Cleanup:
    if ( bRet ) {

        WriteCommand(hPort, "\033%-12345X@PJL \015\012@PJL USTATUS TIMED 30 \015\012\033%-12345X");
        pIniPort->dwLastReadTime = GetTickCount();
    }

    return bRet;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -