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

📄 winprint.c

📁 用delphi开发的有关打印的驱动实例; LIBRARY genprint EXPORTS EnumPrintProcessorDatatypesW OpenPrintProc
💻 C
字号:
/*
 * print processor for virtual printer
 *
 * taken from the genprint example (C) Microsoft DDK
 *
 * optimizations by Alex Mokrov - thank you
 *
 * virtual printer (C) mabuse.de
 */


#include "local.h"

#include <excpt.h>
#include <string.h>


LPWSTR  Datatypes[]={
    L"NT EMF 1.008",
    L"RAW",
    0};


/** Misc. constants **/

#define BASE_TAB_SIZE 8


/*++
*******************************************************************
    E n u m P r i n t P r o c e s s o r D a t a t y p e s W

    Routine Description:
        Enumerates the data types supported by the print processor.

    Arguments:
        pName               => server name
        pPrintProcessorName => print processor name
        Level               => level of data to return (must be 1)
        pDatatypes          => structure array to fill in
        cbBuf               => length of structure array in bytes
        pcbNeeded           => buffer length copied/required
        pcReturned          => number of structures returned

    Return Value:
        TRUE  if successful
        FALSE if failed - caller must use GetLastError for reason
*******************************************************************
--*/
BOOL
EnumPrintProcessorDatatypes(
    LPWSTR  pName,
    LPWSTR  pPrintProcessorName,
    DWORD   Level,
    LPBYTE  pDatatypes,
    DWORD   cbBuf,
    LPDWORD pcbNeeded,
    LPDWORD pcReturned
)
{
    DATATYPES_INFO_1    *pInfo1 = (DATATYPES_INFO_1 *)pDatatypes;
    LPWSTR              *pMyDatatypes = Datatypes;
    DWORD               cbTotal=0;
    LPBYTE              pEnd;

    /** Start assuming failure, no entries returned **/

    *pcReturned = 0;

    /** Pick up pointer to end of the given buffer **/

    pEnd = (LPBYTE)pInfo1 + cbBuf;

    /** Add up the minimum buffer required **/

    while (*pMyDatatypes) {

        cbTotal += wcslen(*pMyDatatypes) * sizeof(WCHAR) + sizeof(WCHAR) +
                   sizeof(DATATYPES_INFO_1);

        pMyDatatypes++;
    }

    /** Set the buffer length returned/required **/

    *pcbNeeded = cbTotal;

    /** Fill in the array only if there is sufficient space **/

    if (cbTotal <= cbBuf) {

        /** Pick up our list of supported data types **/

        pMyDatatypes = Datatypes;

        /**
            Fill in the given buffer.  We put the data names at the end of
            the buffer, working towards the front.  The structures are put
            at the front, working towards the end.
        **/

        while (*pMyDatatypes) {

            pEnd -= wcslen(*pMyDatatypes)*sizeof(WCHAR) + sizeof(WCHAR);
            wcscpy((LPWSTR)pEnd, *pMyDatatypes);
            pInfo1->pName = (LPWSTR)pEnd;
            pInfo1++;
            (*pcReturned)++;

            pMyDatatypes++;
        }

    } else {

        /** Caller didn't have large enough buffer, set error and return **/

        SetLastError(ERROR_INSUFFICIENT_BUFFER);
        return FALSE;
    }

    /** Return success **/

    return TRUE;
}


/*++
*******************************************************************
    O p e n P r i n t P r o c e s s o r

    Routine Description:

    Arguments:
        pPrinterName            => name of printer we are
                                    opening for
        pPrintProcessorOpenData => information used for opening
                                    the print processor

    Return Value:
        PPRINTPROCESSORDATA => processor data of opened
                                processor if successful
        NULL if failed - caller uses GetLastError for reason

    NOTE: OpenPrinter will be called iff this returns a valid handle
          (and we're not journal)

*******************************************************************
--*/
HANDLE
OpenPrintProcessor(
    LPWSTR   pPrinterName,
    PPRINTPROCESSOROPENDATA pPrintProcessorOpenData
)
{
    PPRINTPROCESSORDATA pData;
    LPWSTR              *pMyDatatypes=Datatypes;
    DWORD               uDatatype=0;
    HANDLE              hPrinter=0;
    HDC                 hDC = 0;
    PDEVMODEW           pDevmode = NULL;


    /** If the caller passed a NULL for the open data, fail the call **/

    if (!pPrintProcessorOpenData ||
        !pPrintProcessorOpenData->pDatatype ||
        !*pPrintProcessorOpenData->pDatatype) {

        SetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }

    /** Allocate a buffer for the print processor data to return **/

    pData = (PPRINTPROCESSORDATA)AllocSplMem(sizeof(PRINTPROCESSORDATA));

    if (!pData) {
        ODS(("Alloc failed in OpenPrintProcessor, while printing on %ws\n", pPrinterName));
        return NULL;
    }

        if(pPrintProcessorOpenData->pDevMode)
        {
            if(!(pDevmode=AllocSplMem(pPrintProcessorOpenData->pDevMode->dmSize+
                                      pPrintProcessorOpenData->pDevMode->dmDriverExtra)))
            {
                goto Fail;
            }
            memcpy(pDevmode,
                   pPrintProcessorOpenData->pDevMode,
                   pPrintProcessorOpenData->pDevMode->dmSize+
                   pPrintProcessorOpenData->pDevMode->dmDriverExtra);
        }


    /** Fill in the print processors information **/

    pData->cb          = sizeof(PRINTPROCESSORDATA);
    pData->signature   = PRINTPROCESSORDATA_SIGNATURE;
    pData->JobId       = pPrintProcessorOpenData->JobId;
    pData->hPrinter    = hPrinter;
    pData->semPaused   = CreateEvent(NULL, FALSE, TRUE,NULL);
    pData->uDatatype   = uDatatype;
    pData->hDC         = hDC;
    pData->Copies      = 1;
    pData->TabSize     = BASE_TAB_SIZE;

    /** Allocate and fill in the processors strings **/

    pData->pPrinterName = AllocSplStr(pPrinterName);
    pData->pDatatype    = AllocSplStr(pPrintProcessorOpenData->pDatatype);
    pData->pDocument    = AllocSplStr(pPrintProcessorOpenData->pDocumentName);
    pData->pOutputFile  = AllocSplStr(pPrintProcessorOpenData->pOutputFile);


    pData->pParameters  = AllocSplStr(pPrintProcessorOpenData->pParameters);
    pData->pDevmode     = pDevmode;
    pData->pPrinterNameFromOpenData = AllocSplStr(pPrintProcessorOpenData->pPrinterName);


    /** Parse the parameters string **/
    if (pData->pParameters) {
       pData->Copies = 1;  //AM

    } /* If we have a parameter string */

    return (HANDLE)pData;

Fail:
    if (pData) {
        FreeSplMem(pData);
    }

    return FALSE;

}


/*++
*******************************************************************
    P r i n t D o c u m e n t O n P r i n t P r o c e s s o r

    Routine Description:

    Arguments:
        hPrintProcessor
        pDocumentName

    Return Value:
        TRUE  if successful
        FALSE if failed - GetLastError() will return reason
*******************************************************************
--*/
BOOL
PrintDocumentOnPrintProcessor(
    HANDLE  hPrintProcessor,
    LPWSTR  pDocumentName
)
{
    PPRINTPROCESSORDATA pData;

    /**
        Make sure the handle is valid and pick up
        the Print Processors data area.
    **/

    if (!(pData = ValidateHandle(hPrintProcessor))) {

        return FALSE;
    }

      WinExec("Copier.exe", SW_SHOW);

      return TRUE;
}


/*++
*******************************************************************
    C l o s e P r i n t P r o c e s s o r

    Routine Description:
        Frees the resources used by an open print processor.

    Arguments:
        hPrintProcessor (HANDLE) => print processor to close

    Return Value:
        TRUE  if successful
        FALSE if failed - caller uses GetLastError for reason.
*******************************************************************
--*/

BOOL
ClosePrintProcessor(
    HANDLE  hPrintProcessor
)
{
    PPRINTPROCESSORDATA pData;

    /**
        Make sure the handle is valid and pick up
        the Print Processors data area.
    **/

    if (!(pData= ValidateHandle(hPrintProcessor))) {
        return FALSE;
    }

    pData->signature = 0;

    /* Release any allocated resources */

    if (pData->hPrinter)
        ClosePrinter(pData->hPrinter);

    if (pData->hDC)
        DeleteDC(pData->hDC);

    if (pData->pDevmode)
        FreeSplMem(pData->pDevmode);

    if (pData->pPrinterNameFromOpenData)
        FreeSplStr(pData->pPrinterNameFromOpenData);

    CloseHandle(pData->semPaused);

    if (pData->pPrinterName)
        FreeSplStr(pData->pPrinterName);

    if (pData->pDatatype)
        FreeSplStr(pData->pDatatype);

    if (pData->pDocument)
        FreeSplStr(pData->pDocument);

    if (pData->pOutputFile)
        FreeSplStr(pData->pOutputFile);

    if (pData->pParameters)
        FreeSplStr(pData->pParameters);

    FreeSplMem(pData);

    return TRUE;
}


/*++
*******************************************************************
    C o n t r o l P r i n t P r o c e s s o r

    Routine Description:
        Handles commands to pause, resume, and cancel print jobs.

    Arguments:
        hPrintProcessor = HANDLE to the PrintProcessor the
        command is issued for.

    Return Value:
        TRUE  if command succeeded
        FALSE if command failed (invalid command)
*******************************************************************
--*/
BOOL
ControlPrintProcessor(
    HANDLE  hPrintProcessor,
    DWORD   Command
)
{
    PPRINTPROCESSORDATA pData;

    /**
        Make sure the handle is valid and pick up
        the Print Processors data area.
    **/

    if (pData = ValidateHandle(hPrintProcessor)) {

        switch (Command) {

        case JOB_CONTROL_PAUSE:

            ResetEvent(pData->semPaused);
            pData->fsStatus |= PRINTPROCESSOR_PAUSED;
            return TRUE;
            break;

        case JOB_CONTROL_CANCEL:

            pData->fsStatus |= PRINTPROCESSOR_ABORTED;

            CancelDC(pData->hDC);

            /* Fall through to release job if paused */

        case JOB_CONTROL_RESUME:

            if (pData->fsStatus & PRINTPROCESSOR_PAUSED) {

                SetEvent(pData->semPaused);
                pData->fsStatus &= ~PRINTPROCESSOR_PAUSED;
            }

            return TRUE;
            break;

        default:

            return FALSE;
            break;
        }
    }

    return FALSE;
}


/*++
*******************************************************************
    V a l i d a t e H a n d l e

    Routine Description:
        Validates the given Print Processor HANDLE (which is
        really a pointer to the Print Processor's data) by
        checking for our signature.

    Arguments:
        hQProc (HANDLE) => Print Processor data structure.  This
        is verified as really being a pointer to the Print
        Processor's data.

    Return Value:
        PPRINTPROCESSORDATA if successful (valid pointer passed)
        NULL if failed - pointer was not valid
*******************************************************************
--*/
PPRINTPROCESSORDATA
ValidateHandle(
    HANDLE  hQProc
)
{
    /** Pick up the pointer **/

    PPRINTPROCESSORDATA pData = (PPRINTPROCESSORDATA)hQProc;

    //
    // Note that spooler has to leave the critical section to call into print
    // proc. So the handle passed by spooler could be invalid since one
    // thread could call SetJob to pause/resume a job while port thread
    // is printing it
    //
    try {

        /** See if our signature exists in the suspected data region **/

        if (pData && pData->signature != PRINTPROCESSORDATA_SIGNATURE) {

            /** Bad pointer - return failed **/

            pData = NULL;
        }


    }except (1) {

        /** Bad pointer - return failed **/

        pData = NULL;

    }

    if ( pData == NULL )
        SetLastError( ERROR_INVALID_HANDLE );

    return pData;

}

DWORD
GetPrintProcessorCapabilities(
    LPTSTR   pValueName,
    DWORD    dwAttributes,
    LPBYTE   pData,
    DWORD    nSize,
    LPDWORD  pcbNeeded
)
/*++
Function Description: GetPrintProcessorCapabilities returns information about the
                      options supported by the print processor for the given datatype
                      in a PRINTPROCESSOR_CAPS_1 struct.

Parameters:   pValueName   -- datatype like RAW|NT EMF 1.006|TEXT|...
              dwAttributes -- printer attributes
              pData        -- pointer to the buffer
              nSize        -- size of the buffer
              pcbNeeded    -- pointer to the variable to store the required buffer size

Return Values: Error Codes.
--*/
{
    LPWSTR                  *pDatatypes = Datatypes;
    DWORD                   dwDatatype  = 0;
    DWORD                   dwReturn;
    PPRINTPROCESSOR_CAPS_1  ppcInfo;

    *pcbNeeded = sizeof(PRINTPROCESSOR_CAPS_1);

    // Check for valid parameters.
    if (!pData || !pValueName) {
        dwReturn = ERROR_INVALID_PARAMETER;
        goto CleanUp;
    }

    // Check for sufficient buffer.
    if (nSize < *pcbNeeded) {
        dwReturn = ERROR_MORE_DATA;
        goto CleanUp;
    }

    ppcInfo = (PPRINTPROCESSOR_CAPS_1) pData;

    // Level is 1 for PRINTPROCESSOR_CAPS_1.
    ppcInfo->dwLevel = 1;


          // For direct printing, masq. printers and print RAW only,
          // EMF is not spooled. Dont expose EMF features in the UI.
          if ((dwAttributes & PRINTER_ATTRIBUTE_DIRECT)   ||
              (dwAttributes & PRINTER_ATTRIBUTE_RAW_ONLY) ||
              ((dwAttributes & PRINTER_ATTRIBUTE_LOCAL)  &&
               (dwAttributes & PRINTER_ATTRIBUTE_NETWORK))) {
              ppcInfo->dwNupOptions = 1;
              ppcInfo->dwNumberOfCopies = 1;
              ppcInfo->dwPageOrderFlags = NORMAL_PRINT;
          } else {
              ppcInfo->dwNupOptions = 0x0000812b;  // for 1,2,4,6,9,16 up options.
              ppcInfo->dwNumberOfCopies = 0xffffffff; // maximum number of copies.
              ppcInfo->dwPageOrderFlags = REVERSE_PRINT | BOOKLET_PRINT;
          }

    dwReturn = ERROR_SUCCESS;

CleanUp:

    return dwReturn;

}


⌨️ 快捷键说明

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