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; }
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; }
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; }