Esempio n. 1
0
DWORD
OpenLocalPrinterName(
    LPCWSTR pPrinterName,
    const PINISPOOLER pIniSpooler,
    PDWORD pTypeofHandle,
    PINIPRINTER* ppIniPrinter,
    PINIPORT* ppIniPort,
    PINIPORT* ppIniNetPort,
    PHANDLE phPort,
    PDWORD pOpenPortError,
    const LPPRINTER_DEFAULTS pDefaults
    )
{
    PINIPRINTER pIniPrinter;
    PINIPORT pIniPort;
    PINIPORT pIniNetPort = NULL;
    BOOL bOpenPrinterPort;
    LPWSTR pDatatype;

    //
    // If the printer name is the name of a local printer:
    //
    //    Find the first port the printer's attached to.
    //
    //    If the port has a monitor (e.g. LPT1:, COM1 etc.),
    //       we're OK,
    //    Otherwise
    //       try to open the port - this may be a network printer
    //

    if( ( pIniPrinter = FindPrinter( pPrinterName )) ||
        ( pIniPrinter = FindPrinterShare( pPrinterName, pIniSpooler ))) {


        pIniPort = FindIniPortFromIniPrinter( pIniPrinter );

        if( pIniPort && ( pIniPort->Status & PP_MONITOR )){

            //
            // A Printer that has a Port with a Monitor is not a
            // DownLevel Connection (or LocalPrinter acting as a
            // remote printer - "Masquarade" case).
            //
            pIniPort = NULL;
        }

        pDatatype = (pDefaults && pDefaults->pDatatype) ?
                        pDefaults->pDatatype :
                        NULL;

        //
        // Validate datatypes for both masq and local.
        //
        if( pDatatype && !FindDatatype( NULL, pDatatype )){
            goto BadDatatype;
        }

        if( pIniPort ){

            //
            // DownLevel Connection Printer; save it in pIniNetPort.
            // SetPrinterPorts checks this value.
            //
            pIniNetPort = pIniPort;

            //
            // Validate datatype.  We only send RAW across the net
            // to masq printers.
            //
            if( pDatatype && !ValidRawDatatype( pDatatype )){
                goto BadDatatype;
            }

            //
            // There is a network port associated with this printer.
            // Make sure we can open it, and get the handle to use on
            // future API calls:
            //
            LeaveSplSem();
            bOpenPrinterPort = OpenPrinterPortW( pIniPort->pName, phPort, NULL );
            EnterSplSem();

            if( !bOpenPrinterPort ){

                *phPort = INVALID_PORT_HANDLE;
                *pOpenPortError = GetLastError();

                //
                // Must be non-zero otherwise it looks like success.
                //
                SPLASSERT( *pOpenPortError );

                if( *pOpenPortError == ERROR_INVALID_PASSWORD ) {

                    //
                    // This call should fail if it's because the password
                    // is invalid, then winspool or printman can prompt
                    // for the password.
                    //
                    DBGMSG(DBG_WARNING, ("OpenPrinterPort1( %ws ) failed with ERROR_INVALID_PASSWORD .  OpenPrinter returning FALSE\n", pIniPort->pName ));
                    return ROUTER_STOP_ROUTING;
                }

                DBGMSG(DBG_WARNING, ("OpenPrinterPort1( %ws ) failed: Error %d.  OpenPrinter returning TRUE\n", pIniPort->pName, *pOpenPortError));
            }
        } else {

            //
            // Not a masq case.  If it's direct, it must be raw.
            //
            // Note: we will use the default if no datatype is specified.
            // However, if the default datatype is non-RAW and the
            // printer is direct, the open will succeed using a
            // non-RAW datatype!
            //
            if(( pIniPrinter->Attributes & PRINTER_ATTRIBUTE_DIRECT ) &&
                pDatatype &&
                !ValidRawDatatype( pDatatype )) {

                goto BadDatatype;
            }
        }

        *pTypeofHandle |= ( pIniPort ?
                                PRINTER_HANDLE_PORT :
                                PRINTER_HANDLE_PRINTER );

        *ppIniPort = pIniPort;
        *ppIniNetPort = pIniNetPort;
        *ppIniPrinter = pIniPrinter;

        return ROUTER_SUCCESS;
    }

    return ROUTER_UNKNOWN;

BadDatatype:

    SetLastError( ERROR_INVALID_DATATYPE );
    return ROUTER_STOP_ROUTING;
}
Esempio n. 2
0
static DWORD
_LocalSetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PJOB_INFO_2W pJobInfo)
{
    DWORD dwErrorCode;
    PLOCAL_PRINT_PROCESSOR pPrintProcessor;

    // First check the validity of the input before changing anything.
    pPrintProcessor = FindPrintProcessor(pJobInfo->pPrintProcessor);
    if (!pPrintProcessor)
    {
        dwErrorCode = ERROR_UNKNOWN_PRINTPROCESSOR;
        goto Cleanup;
    }

    if (!FindDatatype(pPrintProcessor, pJobInfo->pDatatype))
    {
        dwErrorCode = ERROR_INVALID_DATATYPE;
        goto Cleanup;
    }

    // Check if the datatype has changed.
    if (!_EqualStrings(pJob->pwszDatatype, pJobInfo->pDatatype))
    {
        // Use the new value.
        if (!ReallocSplStr(&pJob->pwszDatatype, pJobInfo->pDatatype))
        {
            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
            ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
            goto Cleanup;
        }
    }

    // Check if the document name has changed. An empty string is permitted here!
    if (!_EqualStrings(pJob->pwszDocumentName, pJobInfo->pDocument))
    {
        // Use the new value.
        if (!ReallocSplStr(&pJob->pwszDocumentName, pJobInfo->pDocument))
        {
            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
            ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
            goto Cleanup;
        }
    }

    // Check if the notify name has changed. An empty string is permitted here!
    if (!_EqualStrings(pJob->pwszNotifyName, pJobInfo->pNotifyName))
    {
        // The new notify name doesn't need to exist, so no additional verification is required.

        // Use the new value.
        if (!ReallocSplStr(&pJob->pwszNotifyName, pJobInfo->pNotifyName))
        {
            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
            ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
            goto Cleanup;
        }
    }

    // Check if the Print Processor Parameters have changed. An empty string is permitted here!
    if (!_EqualStrings(pJob->pwszPrintProcessorParameters, pJobInfo->pParameters))
    {
        // Use the new value.
        if (!ReallocSplStr(&pJob->pwszPrintProcessorParameters, pJobInfo->pParameters))
        {
            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
            ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
            goto Cleanup;
        }
    }

    // Check if the Status Message has changed. An empty string is permitted here!
    if (!_EqualStrings(pJob->pwszStatus, pJobInfo->pStatus))
    {
        // Use the new value.
        if (!ReallocSplStr(&pJob->pwszStatus, pJobInfo->pStatus))
        {
            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
            ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
            goto Cleanup;
        }
    }

    // Check if the user name has changed. An empty string is permitted here!
    if (!_EqualStrings(pJob->pwszUserName, pJobInfo->pUserName))
    {
        // The new user name doesn't need to exist, so no additional verification is required.

        // Use the new value.
        if (!ReallocSplStr(&pJob->pwszUserName, pJobInfo->pUserName))
        {
            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
            ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
            goto Cleanup;
        }
    }

    // Check if the priority has changed.
    if (pJob->dwPriority != pJobInfo->Priority && IS_VALID_PRIORITY(pJobInfo->Priority))
    {
        // Set the new priority.
        pJob->dwPriority = pJobInfo->Priority;

        // Remove and reinsert the job in the Printer's Job List.
        // The Compare function will be used to find the right position now considering the new priority.
        DeleteElementSkiplist(&pJob->pPrinter->JobList, pJob);
        InsertElementSkiplist(&pJob->pPrinter->JobList, pJob);
    }

    // Check if the status flags have changed.
    if (pJob->dwStatus != pJobInfo->Status)
    {
        // Only add status flags that make sense.
        if (pJobInfo->Status & JOB_STATUS_PAUSED)
            pJob->dwStatus |= JOB_STATUS_PAUSED;

        if (pJobInfo->Status & JOB_STATUS_ERROR)
            pJob->dwStatus |= JOB_STATUS_ERROR;

        if (pJobInfo->Status & JOB_STATUS_OFFLINE)
            pJob->dwStatus |= JOB_STATUS_OFFLINE;

        if (pJobInfo->Status & JOB_STATUS_PAPEROUT)
            pJob->dwStatus |= JOB_STATUS_PAPEROUT;
    }

    dwErrorCode = ERROR_SUCCESS;

Cleanup:
    return dwErrorCode;
}
Esempio n. 3
0
HANDLE
CreatePrinterHandle(
    LPWSTR      pPrinterName,
    PINIPRINTER pIniPrinter,
    PINIPORT    pIniPort,
    PINIPORT    pIniNetPort,
    PINIJOB     pIniJob,
    DWORD       TypeofHandle,
    HANDLE      hPort,
    PPRINTER_DEFAULTS pDefaults,
    PINISPOOLER pIniSpooler,
    DWORD       AccessRequested,
    LPBYTE      pSplClientInfo,
    DWORD   dwLevel,
    HANDLE  hReadFile
    )
{
    PSPOOL              pSpool = NULL;
    BOOL                bStatus = FALSE;
    HANDLE              hReturnHandle = NULL;
    LPDEVMODE           pDevMode = NULL;
    PSPLCLIENT_INFO_1   pSplClientInfo1 = (PSPLCLIENT_INFO_1)pSplClientInfo;

    SPLASSERT( pIniSpooler->signature == ISP_SIGNATURE );

    if ( dwLevel && ( dwLevel != 1 || !pSplClientInfo) ) {

        DBGMSG(DBG_ERROR,
               ("CreatePrintHandle: Invalid client info %x - %d\n",
                pSplClientInfo, dwLevel));
        pSplClientInfo = NULL;
    }

 try {

    pSpool = (PSPOOL)AllocSplMem( SPOOL_SIZE );

    if ( pSpool == NULL ) {
        DBGMSG( DBG_WARNING, ("CreatePrinterHandle failed to allocate SPOOL %d\n", GetLastError() ));
        leave;
    }

    pSpool->signature = SJ_SIGNATURE;
    pSpool->pIniPrinter = pIniPrinter;
    pSpool->hReadFile = hReadFile;

    //
    // We get other useful info like build #, client architecture
    // we do not need this info now -- so we do not put it in PSPOOL
    //
    if ( (TypeofHandle & PRINTER_HANDLE_REMOTE) ) {

        if ( !pSplClientInfo ) {

            TypeofHandle |= PRINTER_HANDLE_3XCLIENT;
        } else if ( dwLevel == 1 ) {
            SPLASSERT(pSplClientInfo1->pUserName && pSplClientInfo1->pMachineName);
            pSpool->pUserName = AllocSplStr(pSplClientInfo1->pUserName);
            pSpool->pMachineName = AllocSplStr(pSplClientInfo1->pMachineName);
            if ( !pSpool->pUserName || !pSpool->pMachineName ) {

                DBGMSG(DBG_WARNING, ("CreatePrinterHandle: could not allocate memory for user name or machine name\n"));
            }
        }
    }

    if ( TypeofHandle & PRINTER_HANDLE_SERVER ) {

        bStatus = ValidateObjectAccess( SPOOLER_OBJECT_SERVER,
                                        AccessRequested,
                                        pSpool, pIniSpooler );
    } else {

        bStatus = ValidateObjectAccess( SPOOLER_OBJECT_PRINTER,
                                        AccessRequested,
                                        pSpool, pIniSpooler );
    }

    if ( !bStatus ) {

        SetLastError(ERROR_ACCESS_DENIED);
        leave;
    }

    MapGenericToSpecificAccess(SPOOLER_OBJECT_PRINTER,
                                   pSpool->GrantedAccess,
                                   &pSpool->GrantedAccess);


    pSpool->pIniPort     = pIniPort;
    pSpool->pIniNetPort  = pIniNetPort;
    pSpool->pIniJob      = pIniJob;
    pSpool->TypeofHandle = TypeofHandle;
    pSpool->hPort        = hPort;
    pSpool->Status       = 0;
    pSpool->pDevMode     = NULL;
    pSpool->pName        = AllocSplStr( pPrinterName );

    if ( pSpool->pName == NULL ) {
        leave;
    }

    pSpool->pIniSpooler = pIniSpooler;

    if ( pIniPrinter ) {

        if ( pDefaults ) {

            //
            // Allocate DevMode
            //


            if ( pDefaults->pDevMode ) {

                pDevMode = pDefaults->pDevMode;

            } else {

                pDevMode = pIniPrinter->pDevMode;
            }

            if ( pDevMode != NULL  ) {

                pSpool->pDevMode = AllocSplMem( pDevMode->dmSize + pDevMode->dmDriverExtra );

                if ( pSpool->pDevMode == NULL ) {

                    DBGMSG(DBG_WARNING, ("CreatePrinterHandle failed allocation for devmode %d\n", GetLastError() ));
                    leave;
                }
                memcpy( pSpool->pDevMode, pDevMode, pDevMode->dmSize + pDevMode->dmDriverExtra );
            }
        }

        //
        //  Allocate Datype and Print Processor
        //

        if ( pDefaults && pDefaults->pDatatype ) {

                pSpool->pDatatype = AllocSplStr( pDefaults->pDatatype );
                pSpool->pIniPrintProc = FindDatatype( pIniPrinter->pIniPrintProc, pSpool->pDatatype );

        } else {

            pSpool->pDatatype = AllocSplStr( pIniPrinter->pDatatype );
            pSpool->pIniPrintProc = pIniPrinter->pIniPrintProc;
        }


        if ( pSpool->pIniPrintProc == NULL ) {
            DBGMSG( DBG_WARNING,("CreatePrinterHandle failed to PrintProcessor for datatype %ws %d\n",
                    pSpool->pDatatype, GetLastError() ));
            leave;
        }

        SPLASSERT( pSpool->pIniPrintProc->signature == IPP_SIGNATURE );

        pSpool->pIniPrintProc->cRef++;

        if ( pSpool->pDatatype == NULL ) {
            DBGMSG( DBG_WARNING,("CreatePrinterHandle failed to allocate DataType %x\n", GetLastError() ));
            leave;
        }

    }

    // Add us to the linked list of handles for this printer.
    // This will be scanned when a change occurs on the printer,
    // and will be updated with a flag indicating what type of
    // change it was.
    // There is a flag for each handle, because we cannot guarantee
    // that all threads will have time to reference a flag in the
    // INIPRINTER before it is updated.

    if ( TypeofHandle & PRINTER_HANDLE_PRINTER ) {

        pSpool->pNext = pSpool->pIniPrinter->pSpool;
        pSpool->pIniPrinter->pSpool = pSpool;

    } else if ( TypeofHandle & PRINTER_HANDLE_SERVER ) {

        //
        // For server handles, hang them off the global IniSpooler:
        //

        pSpool->pNext = pIniSpooler->pSpool;
        pIniSpooler->pSpool = pSpool;

        INCSPOOLERREF( pIniSpooler );

    }

    //  Note Only PRINTER_HANDLE_PRINTER are attatched to the
    //  pIniPrinter, since those are the handle which will require
    //  change notifications.

    if ( pSpool->pIniPrinter != NULL ) {

        INCPRINTERREF( pSpool->pIniPrinter );
    }

    hReturnHandle = (HANDLE)pSpool;

 } finally {

    if ( hReturnHandle == NULL ) {

        // Failure CleanUP

        if ( pSpool != NULL ) {

            FreeSplStr(pSpool->pUserName);
            FreeSplStr(pSpool->pMachineName);
            FreeSplStr( pSpool->pName ) ;
            FreeSplStr( pSpool->pDatatype );

            if ( pSpool->pIniPrintProc != NULL )
                pSpool->pIniPrintProc->cRef--;

            if ( pSpool->pDevMode )
                FreeSplMem( pSpool->pDevMode );

            FreeSplMem( pSpool );
            pSpool = NULL;

        }
    }
}
    return hReturnHandle;
}