BOOL LocalPlayGdiScriptOnPrinterIC( HANDLE hPrinterIC, LPBYTE pIn, DWORD cIn, LPBYTE pOut, DWORD cOut, DWORD ul ) { INT nBufferSize,iRet; PUNIVERSAL_FONT_ID pufi; LARGE_INTEGER TimeStamp; if( cOut == sizeof(INT) ) { pufi = NULL; nBufferSize = 0; } else { pufi = (PUNIVERSAL_FONT_ID) (pOut + sizeof(INT)); nBufferSize = (cOut - sizeof(INT)) / sizeof(UNIVERSAL_FONT_ID); } iRet = GdiQueryFonts( pufi, nBufferSize, &TimeStamp ); if( iRet == -1 ) { SPLASSERT( GetLastError() != 0 ); return(FALSE); // BUGUBG WHAT IS LAST ERROR ?, its real important.... } else { *((INT*)pOut) = iRet; return(TRUE); } }
VOID FreeIniJob( __inout PINIJOB pIniJob ) /*++ Routine Description: Deletes a job entry. Arguments: pIniJob : Pointer to the IniJob structure to be deleted Return Value: None --*/ { SPLASSERT(pIniJob); if ( pIniJob->hPrinter ) ClosePrinter(pIniJob->hPrinter); FreeSplMem(pIniJob); }
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 PJLMonStartDocPort( IN HANDLE hPort, IN LPTSTR pszPrinterName, IN DWORD dwJobId, IN DWORD dwLevel, IN LPBYTE pDocInfo ) /*++ Routine Description: Language monitor StartDocPort Arguments: hPort : Port handle pszPrinterName : Printer name dwJobId : Job identifier dwLevel : Level of Doc info strucuture pDocInfo : Pointer to doc info structure Return Value: TRUE on success, FALSE on error --*/ { 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; } WaitForSingleObject(pIniPort->DoneWriting, INFINITE); 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) ) { if ( IsPJL(pIniPort) ) pIniPort->status |= PP_IS_PJL; else pIniPort->status &= ~PP_IS_PJL; } // // 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; if ( pIniPort->status & PP_IS_PJL ) pIniJob->status |= PP_SEND_PJL; EnterSplSem(); if ( !pIniPort->pIniJob ) { pIniPort->pIniJob = pIniJob; } else { pIniJob->pNext = pIniPort->pIniJob; pIniPort->pIniJob = pIniJob; } LeaveSplSem(); if ( (pIniPort->status & PP_IS_PJL) && !(pIniPort->status & PP_RUN_THREAD) ) { // // only create the read thread if printer is PJL capable // CreateUstatusThread(pIniPort); } Cleanup: if ( !bRet ) { SetEvent(pIniPort->DoneWriting); if ( pIniJob ) FreeIniJob(pIniJob); } return bRet; }
DWORD UstatusThread( HANDLE hPort ) /*++ Routine Description: Unsolicited status information thread. This thread will continue to read unsolicited until it's asked to terminate, which will happen under one of these conditions: 1) Receive EOJ confirmation from the printer. 2) Timeout waiting for EOJ confirmation. 3) The port is been closed. Arguments: hPort : IniPort structure for the port Return Value: --*/ { PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort); HANDLE hToken; SPLASSERT(pIniPort && pIniPort->signature == PJ_SIGNATURE); pIniPort->PrinterStatus = 0; pIniPort->status &= ~PP_PRINTER_OFFLINE; pIniPort->dwLastReadTime = 0; for ( ; ; ) { // // check if PP_RUN_THREAD has been cleared to terminate // if ( !(pIniPort->status & PP_RUN_THREAD) ) { if ( pIniPort->status & PP_INSTARTDOC ) { // // there's an active job, can't end the thread // pIniPort->status |= PP_RUN_THREAD; } else { DBGMSG(DBG_INFO, ("PJLMon Read Thread for Port %ws Closing Down.\n", pIniPort->pszPortName)); pIniPort->status &= ~PP_THREAD_RUNNING; ClearPrinterStatusAndIniJobs(pIniPort); CloseHandle(pIniPort->WakeUp); CloseHandle(pIniPort->DoneReading); // // wake up ClosePort if it's waiting // pIniPort->WakeUp = NULL; return 0; } } // // check if the printer is bi-di // if (pIniPort->status & PP_IS_PJL) { (VOID)ReadCommand(hPort); // // If we are under error condition or if we have jobs pending // read status back from printer more frequently // if ( pIniPort->pIniJob || (pIniPort->status & PP_PRINTER_OFFLINE) || (pIniPort->status & PP_WRITE_ERROR) ) { WaitForSingleObject(pIniPort->WakeUp, dwReadThreadErrorTimeout); } else { WaitForSingleObject(pIniPort->WakeUp, dwReadThreadIdleTimeoutOther); } if ( pIniPort->pIniJob && !(pIniPort->status & PP_PRINTER_OFFLINE) && !(pIniPort->status & PP_WRITE_ERROR) ) { // // Some printers are PJL bi-di, but do not send // EOJ. We want jobs to disappear from printman // SendJobLastPageEjected(pIniPort, GetTickCount() - dwReadThreadEOJTimeout, TRUE); } // // If we did not read from printer for more than a minute // and no more jobs talk to printer again // if ( !(pIniPort->status & PP_INSTARTDOC) && (GetTickCount() - pIniPort->dwLastReadTime) > 240000 ) RefreshPrinterInfo(pIniPort); } else { // // exit the thread if printer is not PJL bi-di capable // Sleep(2000); pIniPort->status &= ~PP_RUN_THREAD; #ifdef DEBUG OutputDebugStringA("Set ~PP_RUN_THREAD because printer is not bi-di\n"); #endif } } }
BOOL InternalCopyFile( HANDLE hSourceFile, PWIN32_FIND_DATA pSourceFileData, LPWSTR lpNewFileName, BOOL bFailIfExists ) /*++ Routine Description: Arguments: hSourceFile - SourceFile Handle pSourceFileData - Pointer to WIN32_FIND_DATA for the source file lpNewFileName - Supplies the name where a copy of the existing files data and attributes are to be stored. bFailIfExists - Supplies a flag that indicates how this operation is to proceed if the specified new file already exists. A value of TRUE specifies that this call is to fail. A value of FALSE causes the call to the function to succeed whether or not the specified new file exists. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { DWORD dwSourceFileAttributes; BOOL bReturnValue = FALSE; HANDLE hTargetFile = INVALID_HANDLE_VALUE; DWORD dwLowFileSize, dwHighFileSize; LPVOID pBuffer; DWORD cbBufferSize = BUFFER_SIZE; DWORD cbBytesRead; DWORD cbBytesWritten; DWORD dwSourceFilePointer; SPLASSERT( hSourceFile != NULL && hSourceFile != INVALID_HANDLE_VALUE && pSourceFileData != NULL && lpNewFileName != NULL ); #if DBG // <<<<< DEBUG ONLY >>>>>> // // ASSERTION Check Source File Pointer is Zero. // dwSourceFilePointer = SetFilePointer( hSourceFile, 0, NULL, FILE_CURRENT ); if ( dwSourceFilePointer != 0xffffffff ) { SPLASSERT( dwSourceFilePointer == 0 ); } #endif // DBG // // Alloc I/O Buffer // pBuffer = AllocSplMem( BUFFER_SIZE ); if ( pBuffer == NULL ) goto InternalCopyFileExit; // // Create TagetFile with same File Attributes // hTargetFile = CreateFile( lpNewFileName, GENERIC_WRITE, FILE_SHARE_EXCLUSIVE, NULL, bFailIfExists ? CREATE_NEW : CREATE_ALWAYS, pSourceFileData->dwFileAttributes | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if ( hTargetFile != INVALID_HANDLE_VALUE ) { // // Copy The Data // while (( bReturnValue = ReadFile( hSourceFile, pBuffer, cbBufferSize, &cbBytesRead, NULL )) && cbBytesRead != 0 ) { // // Add Code to Build CheckSum Here // bReturnValue = WriteFile( hTargetFile, pBuffer, cbBytesRead, &cbBytesWritten, NULL ); if ( bReturnValue == FALSE || cbBytesWritten != cbBytesRead ) { bReturnValue = FALSE; break; } } if ( bReturnValue ) { // // Set TargetFile Times to be the same as the Source File // bReturnValue = SetFileTime( hTargetFile, &pSourceFileData->ftCreationTime, &pSourceFileData->ftLastAccessTime, &pSourceFileData->ftLastWriteTime ); // // Verify that the file size is correct. // if ( bReturnValue ) { dwLowFileSize = GetFileSize( hTargetFile, &dwHighFileSize ); if ( dwLowFileSize != pSourceFileData->nFileSizeLow || dwHighFileSize != pSourceFileData->nFileSizeHigh ) { DBGMSG(DBG_ERROR, ("InternalCopyFile: sizes do not match for %ws: (%d %d) and (%d %d)", lpNewFileName, pSourceFileData->nFileSizeHigh, pSourceFileData->nFileSizeLow, dwHighFileSize, dwLowFileSize)); bReturnValue = FALSE; SetLastError(ERROR_FILE_INVALID); } } // // Add Code here to Verify the CheckSum is correct. // } CloseHandle( hTargetFile ); } FreeSplMem( pBuffer ); InternalCopyFileExit: if ( !bReturnValue ) { DBGMSG( DBG_WARN, ("InternalCopyFile hSourceFile %x %ws error %d\n", hSourceFile, lpNewFileName, GetLastError() )); SPLASSERT( GetLastError() != ERROR_SUCCESS ); } return bReturnValue; }
BOOL SpoolerGetSpoolMessage() { DWORD dwResult; PSPOOLESC pInput; // Input buffer that receives messages from Kernel BYTE *pOutput; // Output buffer that receives data from KMxxx() spooler calls BYTE *pMem; DWORD cbOut = 0; // Size of pOutput DWORD cbIn = IN_BUF_SIZE; // Size of pInput buffer in bytes DWORD cbOutSize; if(!(pInput = (PSPOOLESC) AllocSplMem(cbIn))) { DBGMSG(DBG_WARNING, ("Error allocating pInput in SpoolerGetSpoolMessage\n")); return FALSE; } if(!(pOutput = AllocSplMem(OUT_BUF_SIZE))) { DBGMSG(DBG_WARNING, ("Error allocating pInput in SpoolerGetSpoolMessage\n")); return FALSE; } cbOutSize = OUT_BUF_SIZE; EnterCriticalSection(&ThreadCriticalSection); ++nThreads; LeaveCriticalSection(&ThreadCriticalSection); while(1) { EnterCriticalSection(&ThreadCriticalSection); ++nIdleThreads; LeaveCriticalSection(&ThreadCriticalSection); dwResult = GdiGetSpoolMessage(pInput,cbIn,(PDWORD)pOutput,cbOut); EnterCriticalSection(&ThreadCriticalSection); --nIdleThreads; LeaveCriticalSection(&ThreadCriticalSection); if(dwResult) { if( (pInput->iMsg != GDISPOOL_TERMINATETHREAD) && (pInput->iMsg != GDISPOOL_INPUT2SMALL)) { EnterCriticalSection(&ThreadCriticalSection); if(nIdleThreads == 0) { AddThread(); DBGMSG(DBG_TRACE, ("Thread Added: nIdle = %d nThreads = %d\n", nIdleThreads, nThreads)); } LeaveCriticalSection(&ThreadCriticalSection); } // check if the out buffer needs to be grown or shrunk. if ((pInput->cjOut + MAX_GRE_STRUCT_SIZE) > cbOutSize) { FreeSplMem(pOutput); pOutput = AllocSplMem(cbOutSize = pInput->cjOut + MAX_GRE_STRUCT_SIZE); if (!pOutput) { DBGMSG(DBG_WARNING, ("Error allocating pInput in SpoolerGetSpoolMessage\n")); pInput->ulRet = 0; cbOut = 0; cbOutSize = 0; continue; } } else if ((pInput->cjOut < OUT_BUF_SIZE) && (cbOutSize > OUT_BUF_SIZE)) { // we want to shrink the buffer PBYTE pbTmp = AllocSplMem(OUT_BUF_SIZE); if (pbTmp) { FreeSplMem(pOutput); pOutput = pbTmp; cbOutSize = OUT_BUF_SIZE; } } if (pInput->iMsg & GDISPOOL_API) { SPLASSERT(pInput->hSpool || pInput->iMsg == GDISPOOL_OPENPRINTER); if (pInput->iMsg != GDISPOOL_OPENPRINTER || pInput->hSpool) { if (InterlockedIncrement(&((PSPOOL)pInput->hSpool)->cThreads) > 0) { // We are already processing a message & have now gotten a ClosePrinter // We should not get here on any other API SPLASSERT(pInput->iMsg == GDISPOOL_CLOSEPRINTER); pInput->ulRet = TRUE; // Let Client terminate continue; } } } switch (pInput->iMsg) { case GDISPOOL_INPUT2SMALL: DBGMSG(DBG_TRACE,(" - buffer not big enough\n")); pMem = ReallocSplMem(pInput, cbIn, pInput->cjOut); if (!pMem) { DBGMSG(DBG_WARNING, ("Error reallocating pInput in SpoolerGetSpoolMessage\n")); pInput->ulRet = 0; } else { pInput = (PSPOOLESC) pMem; cbIn = pInput->cjOut; pInput->ulRet = 1; } break; case GDISPOOL_TERMINATETHREAD: EnterCriticalSection(&ThreadCriticalSection); // There is 1 way to get here: from a 10 minute Kernel Event timeout if(nIdleThreads > 1) { --nThreads; if (nThreads == 0) { DBGMSG(DBG_WARNING, ("SpoolerGetSpoolMessage nThreads is now ZERO\n")); } DBGMSG(DBG_TRACE, ("Thread Deleted: nIdle = %d nThreads = %d\n", nIdleThreads, nThreads)); LeaveCriticalSection(&ThreadCriticalSection); FreeSplMem(pInput); FreeSplMem(pOutput); return TRUE; } LeaveCriticalSection(&ThreadCriticalSection); break; case GDISPOOL_WRITE: DBGMSG(DBG_TRACE,(" - GDISPOOL_WRITE\n")); pInput->ulRet = DoWritePrinter( pInput, (DWORD*) pOutput ); cbOut = sizeof(DWORD); break; case GDISPOOL_OPENPRINTER: DBGMSG(DBG_TRACE,(" - GDISPOOL_OPENPRINTER\n")); DoOpenPrinter(pInput,(HANDLE*)pOutput,&cbOut); break; case GDISPOOL_STARTDOCPRINTER: DBGMSG(DBG_TRACE,(" - GDISPOOL_STARTDOCPRINTER\n")); DoStartDocPrinter(pInput); break; case GDISPOOL_STARTPAGEPRINTER: DBGMSG(DBG_TRACE,(" - GDISPOOL_STARTPAGEPRINTER\n")); pInput->ulRet = KMStartPagePrinter( pInput->hSpool ); break; case GDISPOOL_ENDPAGEPRINTER: DBGMSG(DBG_TRACE,(" - GDISPOOL_ENDPAGEPRINTER\n")); pInput->ulRet = KMEndPagePrinter( pInput->hSpool ); break; case GDISPOOL_ENDDOCPRINTER: DBGMSG(DBG_TRACE,(" - GDISPOOL_ENDDOCPRINTER\n")); pInput->ulRet = KMEndDocPrinter( pInput->hSpool ); break; case GDISPOOL_ENUMFORMS: DBGMSG(DBG_TRACE,(" - GDISPOOL_ENUMFORMS\n")); DoEnumForms(pInput, (GREENUMFORMS *) pOutput, &cbOut); break; case GDISPOOL_GETPRINTER: DBGMSG(DBG_TRACE,(" - GDISPOOL_GETPRINTER\n")); DoGetPrinter(pInput, (GREGETPRINTER *) pOutput, &cbOut); break; case GDISPOOL_GETFORM: DBGMSG(DBG_TRACE,(" - GDISPOOL_GETFORM\n")); DoGetForm(pInput, (GREGETFORM *) pOutput, &cbOut); break; case GDISPOOL_GETPRINTERDRIVER: DBGMSG(DBG_TRACE,(" - GDISPOOL_GETPRINTERDRIVER\n")); DoGetPrinterDriver(pInput,(GREGETPRINTERDRIVER*)pOutput,&cbOut); break; case GDISPOOL_GETPRINTERDATA: DBGMSG(DBG_TRACE,(" - GDISPOOL_GETPRINTERDATA\n")); DoGetPrinterData(pInput,(GREGETPRINTERDATA *) pOutput,&cbOut); break; case GDISPOOL_SETPRINTERDATA: DBGMSG(DBG_TRACE,(" - GDISPOOL_SETPRINTERDATA\n")); DoSetPrinterData(pInput,(GRESETPRINTERDATA *) pOutput,&cbOut); break; case GDISPOOL_ABORTPRINTER: DBGMSG(DBG_TRACE,(" - GDISPOOL_ABORTPRINTER\n")); pInput->ulRet = KMAbortPrinter( pInput->hSpool ); break; case GDISPOOL_CLOSEPRINTER: DBGMSG(DBG_TRACE,(" - GDISPOOL_CLOSEPRINTER\n")); pInput->ulRet = KMClosePrinter( pInput->hSpool ); break; case GDISPOOL_GETPATHNAME: DBGMSG(DBG_TRACE,(" - GDISPOOL_GETPATHNAME\n")); pInput->ulRet = DoGetPathName((WCHAR*)pInput->ajData, (WCHAR*)pOutput, &cbOut); break; default: DBGMSG(DBG_ERROR,(" - invalid message\n")); break; } if ((pInput->iMsg & GDISPOOL_API) && pInput->iMsg != GDISPOOL_CLOSEPRINTER && pInput->iMsg != GDISPOOL_OPENPRINTER && pInput->hSpool) { if (InterlockedDecrement(&((PSPOOL)pInput->hSpool)->cThreads) == 0) { DBGMSG(DBG_TRACE,(" - GDISPOOL_CLOSEPRINTER\n")); pInput->ulRet = KMClosePrinter( pInput->hSpool ); } } } } }
BOOL ReadCommand( HANDLE hPort ) /*++ Routine Description: Read a command from the port Arguments: hPort : Port handle Return Value: TRUE on successfully reading one or more commands, FALSE on error --*/ { PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort); DWORD cbRead, cbToRead, cbProcessed, cbPrevious; char string[CBSTRING]; DWORD status; BOOL bRet=FALSE; cbPrevious = 0; ResetEvent(pIniPort->DoneReading); cbToRead = CBSTRING - 1; for ( ; ; ) { if ( !PJLMonReadPort(hPort, &string[cbPrevious], cbToRead, &cbRead) ) break; if ( cbRead ) { string[cbPrevious + cbRead] = '\0'; status = ProcessPJLString(pIniPort, string, &cbProcessed); if ( cbProcessed ) bRet = TRUE; if (status == STATUS_END_OF_STRING ) { if ( cbProcessed ) strcpy(string, string+cbProcessed); cbPrevious = cbRead + cbPrevious - cbProcessed; } } else { SPLASSERT(!cbPrevious); } if ( status != STATUS_END_OF_STRING && cbRead != cbToRead ) break; cbToRead = CBSTRING - cbPrevious - 1; if ( cbToRead == 0 ) DBGMSG(DBG_ERROR, ("ReadCommand cbToRead is 0 (buffer too small)\n")); Sleep(WAIT_FOR_DATA_TIMEOUT); } SetEvent(pIniPort->DoneReading); // // Update the time we last read from printer // if ( bRet ) pIniPort->dwLastReadTime = GetTickCount(); return bRet; }
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, TRUE); 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; }
static struct ipsecrequest * ipsec_nextisr( struct mbuf *m, struct ipsecrequest *isr, int af, struct secasindex *saidx, int *error ) { #define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \ isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++) struct secasvar *sav; SPLASSERT(net, "ipsec_nextisr"); KASSERT(af == AF_INET || af == AF_INET6, ("ipsec_nextisr: invalid address family %u", af)); again: /* * Craft SA index to search for proper SA. Note that * we only fillin unspecified SA peers for transport * mode; for tunnel mode they must already be filled in. */ *saidx = isr->saidx; if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) { /* Fillin unspecified SA peers only for transport mode */ if (af == AF_INET) { struct sockaddr_in *sin; struct ip *ip = mtod(m, struct ip *); if (saidx->src.sa.sa_len == 0) { sin = &saidx->src.sin; sin->sin_len = sizeof(*sin); sin->sin_family = AF_INET; sin->sin_port = IPSEC_PORT_ANY; sin->sin_addr = ip->ip_src; } if (saidx->dst.sa.sa_len == 0) { sin = &saidx->dst.sin; sin->sin_len = sizeof(*sin); sin->sin_family = AF_INET; sin->sin_port = IPSEC_PORT_ANY; sin->sin_addr = ip->ip_dst; } } else { struct sockaddr_in6 *sin6; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); if (saidx->src.sin6.sin6_len == 0) { sin6 = (struct sockaddr_in6 *)&saidx->src; sin6->sin6_len = sizeof(*sin6); sin6->sin6_family = AF_INET6; sin6->sin6_port = IPSEC_PORT_ANY; sin6->sin6_addr = ip6->ip6_src; if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { /* fix scope id for comparing SPD */ sin6->sin6_addr.s6_addr16[1] = 0; sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); } } if (saidx->dst.sin6.sin6_len == 0) { sin6 = (struct sockaddr_in6 *)&saidx->dst; sin6->sin6_len = sizeof(*sin6); sin6->sin6_family = AF_INET6; sin6->sin6_port = IPSEC_PORT_ANY; sin6->sin6_addr = ip6->ip6_dst; if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { /* fix scope id for comparing SPD */ sin6->sin6_addr.s6_addr16[1] = 0; sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); } } } }
BOOL SplOpenPrinter( LPWSTR pPrinterName, LPHANDLE pPrinterHandle, LPPRINTER_DEFAULTS pDefaults, PINISPOOLER pIniSpooler, LPBYTE pSplClientInfo, DWORD dwLevel ) /*++ Routine Description: OpenPrinter can open any of the following by specifying a string in pPrinterName:- Server \\MachineName NULL Job PrinterName, Job xxxx Port PortName, Port Printer PrinterName ShareName \\MachineName\PrinterName \\MachineName\ShareName PrinterName, UpgradeToken ShareName, UpgradeToken Note for Printer there are two Types 1 - Regular LocalPrinter 2 - DownLevel Connection Printer For type 2 a LocalPrinter exists ( pIniPrinter ) but its port does not have a monitor associated with it. In this case we also open the port ( typically \\share\printer of a remote machine ) before we return success. GUI Applications usually use Server and Printer Type Job and Port are used by Print Processors:- A print processor will Open a Job then read the job using ReadPrinter. A print processor will output to a Port by opening the PortName, Port and using WritePrinter. Usually these strings "PrinterName, Job xxx" "PortName, Port" are passed to the print processor by the spooler and are currently not documented. We do know that some OEMs have figured out the extentions and we might break someone if we change them. Type UpgradeToken is used by a Printer Driver:- Used when we need to upgrade a printer's settings from an older version of the driver to a newer one (see drvupgrd.c for details). This was added in NT 3.51. Arguments: pPrinterName - PrinterName ( see above for different types of PrinterName ) pPrinterHandle - Address to put hPrinter on Success pDefaults - Optional, allows user to specify Datatype, DevMode, DesiredAccess. pIniSpooler - handle of spooler on which the open should occur. ( see SDK Online Help for full explanation ) Return Value: TRUE - *pPrinterHandle will have a PrinterHandle FALSE - use GetLastError --*/ { PINIPRINTER pIniPrinter = NULL; PINIPORT pIniPort = NULL; PINIPORT pIniNetPort = NULL; DWORD LastError = 0; LPWSTR pName = pPrinterName+2; WCHAR string[MAX_UNC_PRINTER_NAME + PRINTER_NAME_SUFFIX_MAX]; PINIJOB pIniJob = NULL; HANDLE hReadFile = INVALID_HANDLE_VALUE; DWORD TypeofHandle = 0; LPWSTR pSecondPart = NULL; HANDLE hPort = INVALID_PORT_HANDLE; DWORD OpenPortError = NO_ERROR; BOOL bRemoteUserPrinterNotShared = FALSE; DWORD MachineNameLength; DWORD RouterReturnValue = ROUTER_UNKNOWN; DWORD AccessRequested; #if DBG // // On DBG builds, force last error to zero so we can catch people // that don't set it when they should. // SetLastError( ERROR_SUCCESS ); #endif // // Reject "" - pointer to a NULL string. // if ( pPrinterName && !pPrinterName[0] ) { SetLastError(ERROR_INVALID_NAME); return ROUTER_UNKNOWN; } // // Check for SERVER Opens. // // If the printer name was NULL or our own MachineName, then // the caller wants a handle to the server. // if( MyName( pPrinterName, pIniSpooler )){ return CreateServerHandle( pPrinterName, pPrinterHandle, pDefaults, pIniSpooler ); } DBGMSG( DBG_TRACE, ( "OpenPrinter(%ws)\n", pPrinterName )); EnterSplSem(); // // For the Mars folks who will come in with the same printer // connection, do a DeletePrinterCheck; this will allow // Mars connections that have been deleted to be proceed // to the Mars print providor // if (( pIniPrinter = FindPrinter( pPrinterName )) || ( pIniPrinter = FindPrinterShare( pPrinterName, pIniSpooler ))) { DeletePrinterCheck( pIniPrinter ); pIniPrinter = NULL; } // // The strategy for the rest of this code is to walk through each // different printer handle type, searching for a match. // // RouterReturnValue will be set to the current state of routing. // If a section recognizes and "owns" a printer and successfully // opens it, it sets RouterReturnValue to ROUTER_SUCCESS and // jumps to DoneRouting which allocs the handle. // // If it recoginzes the printer but fails to open it, and // guarentees that no one else (localspl code or other providers) // will recognize it, it should set RouterReturnValue to // ROUTER_STOP_ROUTING. We will quit at this point. // // If it doesn't recognize the printer, set RouterReturnValue // to ROUTER_UNKNOWN and we will keep looking. // // // Try regular printer name: "My Printer" "TestPrinter." // RouterReturnValue = OpenLocalPrinterName( pPrinterName, pIniSpooler, &TypeofHandle, &pIniPrinter, &pIniPort, &pIniNetPort, &hPort, &OpenPortError, pDefaults ); // // Note: Don't check for interactive users, since anyone using the // name without the server prefix must be local anyway. // The server does this and must not be marked as remote, since // its AddJob calls will fail. // if( RouterReturnValue != ROUTER_UNKNOWN ){ goto DoneRouting; } SPLASSERT( !TypeofHandle && !pIniPrinter && !pIniPort && !pIniNetPort && !pIniJob && !hPort ); // // Try LocalPrinter with an extention e.g. // // PortName, Port // PrinterName, Job xxxx // PrinterName, UpgradeToken // // See if the name includes a comma. Look for qualifiers: // Port Job LocalOnly UpgradeToken // wcscpy( string, pPrinterName ); if( pSecondPart = wcschr( string, L',' )){ // // Turn into 2 strings // First PrintName // pSecondPart points to the rest. // *pSecondPart++ = 0; // // Get rid of Leading Spaces // while ( *pSecondPart == L' ' && *pSecondPart != 0 ) { pSecondPart++; } SPLASSERT( *pSecondPart ); // // PrintName, UpgradeToken // RouterReturnValue = CheckPrinterUpgradeToken( string, pSecondPart, &TypeofHandle, &pIniPrinter, pIniSpooler ); if( RouterReturnValue != ROUTER_UNKNOWN ){ goto DoneRouting; } SPLASSERT( !TypeofHandle && !pIniPrinter && !pIniPort && !pIniNetPort && !pIniJob && !hPort ); // // PortName, Port // RouterReturnValue = CheckPrinterPortToken( string, pSecondPart, &TypeofHandle, &pIniPrinter, &pIniPort, &pIniJob, pDefaults, pIniSpooler ); if( RouterReturnValue != ROUTER_UNKNOWN ){ goto DoneRouting; } SPLASSERT( !TypeofHandle && !pIniPrinter && !pIniPort && !pIniNetPort && !pIniJob && !hPort ); // // PrinterName, Job ### // RouterReturnValue = CheckPrinterJobToken( string, pSecondPart, &TypeofHandle, &pIniPrinter, &pIniJob, &hReadFile, pIniSpooler ); if( RouterReturnValue != ROUTER_UNKNOWN ){ goto DoneRouting; } SPLASSERT( !TypeofHandle && !pIniPrinter && !pIniPort && !pIniNetPort && !pIniJob && !hPort ); } // // Try local printer qualified by \\ServerName: // "\\ServerName\PrinterName" "\\ServerName\ShareName." // wcscpy( string, pPrinterName ); if( string[0] == L'\\' && string[1] == L'\\' && ( pName = wcschr( &string[2], L'\\')) ) { *pName = L'\0'; pName++; if ( MyName(string, pIniSpooler) ) { // // Check local printer. // RouterReturnValue = OpenLocalPrinterName( pName, pIniSpooler, &TypeofHandle, &pIniPrinter, &pIniPort, &pIniNetPort, &hPort, &OpenPortError, pDefaults ); if( RouterReturnValue == ROUTER_SUCCESS ){ // // On success, determine whether the user is remote or local. // Note: we only do this for fully qualified names // (\\server\share), since using just the share or printer // name can only succeed locally. // if( ( pIniSpooler->SpoolerFlags & SPL_REMOTE_HANDLE_CHECK ) && !IsInteractiveUser() ) { TypeofHandle |= PRINTER_HANDLE_REMOTE; } // // This is a remote open. // // If the printer is not shared, ensure the caller // has Administer access to the printer. // // bugbug! // // The following seems to belong to the inside of the above "if" clause. As it is, if // an interactive user calls in with UNC name, we require him to have ADMIN access if the // printer is not shared; but if he uses the printer friendly name, we let him go. // if( !( pIniPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED )){ bRemoteUserPrinterNotShared = TRUE; } } else { // // Since we matched the server but didn't find the printer, // we should stop routing. // RouterReturnValue = ROUTER_STOP_ROUTING; SetLastError( ERROR_INVALID_PRINTER_NAME ); } // // Both cases we are done routing since we found our // server name prefix. // goto DoneRouting; } } // // We have completed all routing. Anything other than success // should exit now. // DoneRouting: if( RouterReturnValue == ROUTER_SUCCESS) { // // It's an error if the printer is pending deletion or pending creation. // SPLASSERT( pIniPrinter ); if ( (( pIniPrinter->Status & PRINTER_PENDING_DELETION ) && ( pIniSpooler->SpoolerFlags & SPL_FAIL_OPEN_PRINTERS_PENDING_DELETION ) && ( pIniPrinter->cJobs == 0 )) || ( pIniPrinter->Status & PRINTER_PENDING_CREATION ) ) { RouterReturnValue = ROUTER_STOP_ROUTING; SetLastError( ERROR_INVALID_PRINTER_NAME ); goto DoneRouting; } // // When the printer is opened, access type may be specified in // pDefaults. If no defaults are supplied (or request access // is unspecified), we use PRINTER_ACCESS_USE. // // Future calls with the handle will check against both the // current user privileges on this printer but also this initial // access. (Even if the user is an admin of the printer, unless // they open the printer with PRINTER_ALL_ACCESS, they can't // administer it. // // If the user requires more access, the printer must be reopened. // AccessRequested = ( !pDefaults || !pDefaults->DesiredAccess ) ? PRINTER_READ : pDefaults->DesiredAccess; // // If the user is remote and the printer is not shared, only allow // administrators succeed. // // This allows administrators to admin printers even if they // are not shared, and prevents non-admins from opening non-shared // printers. // if( bRemoteUserPrinterNotShared && !(AccessRequested & PRINTER_ACCESS_ADMINISTER )) { PSPOOL pSpool; // Get a quick and dirty pSpool to pass in pSpool = (PSPOOL)AllocSplMem( SPOOL_SIZE ); if( pSpool == NULL ) { DBGMSG( DBG_WARNING, ("SplOpenPrinter failed to allocate memory %d\n", GetLastError() )); RouterReturnValue = ROUTER_STOP_ROUTING; goto WrapUp; } pSpool->signature = SJ_SIGNATURE; pSpool->pIniPrinter = pIniPrinter; // Add admin request, and see if user has the right. AccessRequested |= PRINTER_ACCESS_ADMINISTER; if( !ValidateObjectAccess( SPOOLER_OBJECT_PRINTER, AccessRequested, pSpool, pIniSpooler )) { SetLastError(ERROR_ACCESS_DENIED); RouterReturnValue = ROUTER_STOP_ROUTING; } AccessRequested &= ~PRINTER_ACCESS_ADMINISTER; // clean up FreeSplMem( pSpool ); // If the user had no ADMIN privilege, fail the open call. if( RouterReturnValue == ROUTER_STOP_ROUTING ) goto WrapUp; } // // Create the printer handle that we will return to the user. // *pPrinterHandle = CreatePrinterHandle( pPrinterName, pIniPrinter, pIniPort, pIniNetPort, pIniJob, TypeofHandle, hPort, pDefaults, pIniSpooler, AccessRequested, pSplClientInfo, dwLevel, hReadFile ); if( *pPrinterHandle ){ // // Update the OpenPortError. // ((PSPOOL)*pPrinterHandle)->OpenPortError = OpenPortError; } else { SPLASSERT( GetLastError( )); RouterReturnValue = ROUTER_STOP_ROUTING; } } WrapUp: LeaveSplSem(); // // Don't have an SplOutSem as we could be called recursively. // switch( RouterReturnValue ){ case ROUTER_SUCCESS: DBGMSG( DBG_TRACE, ("OpenPrinter returned handle %x\n", *pPrinterHandle)); SPLASSERT( *pPrinterHandle ); break; case ROUTER_UNKNOWN: SPLASSERT( !TypeofHandle && !pIniPrinter && !pIniPort && !pIniNetPort && !pIniJob && !hPort ); // // hPort should not be valid. If it is, we have leaked a handle. // SPLASSERT( !hPort ); SPLASSERT( hReadFile == INVALID_HANDLE_VALUE ); DBGMSG( DBG_TRACE, ( "OpenPrinter failed, invalid name %s\n", pPrinterName )); SetLastError( ERROR_INVALID_NAME ); break; case ROUTER_STOP_ROUTING: LastError = GetLastError(); SPLASSERT( LastError ); // // On failure, we may have opened a port or file handle. We need // to close it since we won't return a valid handle, and // so ClosePrinter will never get called. // if( hPort != INVALID_PORT_HANDLE ) { ClosePrinter( hPort ); } if ( hReadFile != INVALID_HANDLE_VALUE ) { CloseHandle( hReadFile ); } DBGMSG( DBG_TRACE, ("OpenPrinter %s failed: Error %d\n", pPrinterName, GetLastError())); SetLastError( LastError ); break; } return RouterReturnValue; }
DWORD CheckPrinterJobToken( LPCWSTR string, LPCWSTR pSecondPart, PDWORD pTypeofHandle, PINIPRINTER* ppIniPrinter, PINIJOB* ppIniJob, PHANDLE phReadFile, const PINISPOOLER pIniSpooler ) { HANDLE hImpersonationToken; DWORD Position; DWORD JobId; PINIPRINTER pIniPrinter; PINIJOB pIniJob, pCurrentIniJob; if( wcsncmp( pSecondPart, L"Job ", 4 ) != STRINGS_ARE_EQUAL || !( pIniPrinter = FindPrinter( string ))){ return ROUTER_UNKNOWN; } // // Get the Job ID ",Job xxxx" // pSecondPart += 4; JobId = Myatol( (LPWSTR)pSecondPart ); pIniJob = FindJob( pIniPrinter, JobId, &Position ); if( pIniJob == NULL ) { DBGMSG( DBG_WARN, ("OpenPrinter failed to find Job %d\n", JobId )); return ROUTER_UNKNOWN; } DBGMSG( DBG_TRACE, ("OpenPrinter: pIniJob->cRef = %d\n", pIniJob->cRef)); if( pIniJob->Status & JOB_DIRECT ) { SplInSem(); INCJOBREF( pIniJob ); *pTypeofHandle |= PRINTER_HANDLE_JOB | PRINTER_HANDLE_DIRECT; goto Success; } // // If this job is assigned to a port // Then pick up the correct chained jobid file instead of the master // JobId. // if ( pIniJob->pCurrentIniJob != NULL ) { SPLASSERT( pIniJob->pCurrentIniJob->signature == IJ_SIGNATURE ); DBGMSG( DBG_TRACE,("CheckPrinterJobToken pIniJob %x JobId %d using chain JobId %d\n", pIniJob, pIniJob->JobId, pIniJob->pCurrentIniJob->JobId )); pCurrentIniJob = pIniJob->pCurrentIniJob; SPLASSERT( pCurrentIniJob->signature == IJ_SIGNATURE ); } else { pCurrentIniJob = pIniJob; } GetFullNameFromId( pCurrentIniJob->pIniPrinter, pCurrentIniJob->JobId, TRUE, (LPWSTR)string, FALSE ); // !! BUGBUG !! // Even a user without previledge can open a ", JOB #" // if he is physically running on the machine. hImpersonationToken = RevertToPrinterSelf(); *phReadFile = CreateFile( string, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); ImpersonatePrinterClient( hImpersonationToken ); if( *phReadFile != INVALID_HANDLE_VALUE ) { DBGMSG( DBG_TRACE, ("OpenPrinter JobID %d pIniJob %x CreateFile( %ws ), hReadFile %x success", JobId, pIniJob, string, *phReadFile )); SplInSem(); INCJOBREF( pIniJob ); *pTypeofHandle |= PRINTER_HANDLE_JOB; goto Success; } DBGMSG( DBG_WARNING, ("LocalOpenPrinter CreateFile(%ws) GENERIC_READ failed : %d\n", string, GetLastError())); SPLASSERT( GetLastError( )); return ROUTER_STOP_ROUTING; Success: *ppIniJob = pIniJob; *ppIniPrinter = pIniPrinter; return ROUTER_SUCCESS; }
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; }
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; }
BOOL SplClosePrinter( HANDLE hPrinter ) { PSPOOL pSpool=(PSPOOL)hPrinter; PSPOOL *ppIniSpool = NULL; DBGMSG(DBG_TRACE, ("ClosePrinter( %08x )\n", hPrinter)); if (!ValidateSpoolHandle(pSpool, 0)) { return(FALSE); } if (!(pSpool->TypeofHandle & PRINTER_HANDLE_JOB) && pSpool->pIniJob && (pSpool->Status & SPOOL_STATUS_ADDJOB)) { LocalScheduleJob(hPrinter, pSpool->pIniJob->JobId); } if (pSpool->Status & SPOOL_STATUS_STARTDOC) { // BUGBUG - it looks as though this might cause a double // decrement of pIniJob->cRef once inside LocalEndDocPrinter // and the other later in this routine. LocalEndDocPrinter(hPrinter); } if (pSpool->TypeofHandle & PRINTER_HANDLE_JOB) { if (pSpool->TypeofHandle & PRINTER_HANDLE_DIRECT) { // // If EndDoc is still waiting for a final ReadPrinter // if (pSpool->pIniJob->cbBuffer) { // Amount last transmitted // // Wake up the EndDoc Thread // SetEvent(pSpool->pIniJob->WaitForRead); SplOutSem(); // // Wait until he is finished // WaitForSingleObject(pSpool->pIniJob->WaitForWrite, INFINITE); EnterSplSem(); // // Now it is ok to close the handles // if (!CloseHandle(pSpool->pIniJob->WaitForWrite)) { DBGMSG(DBG_WARNING, ("CloseHandle failed %d %d\n", pSpool->pIniJob->WaitForWrite, GetLastError())); } if (!CloseHandle(pSpool->pIniJob->WaitForRead)) { DBGMSG(DBG_WARNING, ("CloseHandle failed %d %d\n", pSpool->pIniJob->WaitForRead, GetLastError())); } pSpool->pIniJob->WaitForRead = INVALID_HANDLE_VALUE; pSpool->pIniJob->WaitForWrite = INVALID_HANDLE_VALUE; LeaveSplSem(); } DBGMSG(DBG_TRACE, ("ClosePrinter(DIRECT):cRef = %d\n", pSpool->pIniJob->cRef)); } EnterSplSem(); DBGMSG(DBG_TRACE, ("ClosePrinter:cRef = %d\n", pSpool->pIniJob->cRef)); DECJOBREF(pSpool->pIniJob); DeleteJobCheck(pSpool->pIniJob); LeaveSplSem(); } if ( pSpool->hReadFile != INVALID_HANDLE_VALUE ) { if ( !CloseHandle( pSpool->hReadFile ) ) { DBGMSG(DBG_WARNING, ("ClosePrinter CloseHandle(%d) failed %d\n", pSpool->hReadFile, GetLastError())); } } // // Close the handle that was opened via OpenPrinterPort: // if (pSpool->hPort) { if (pSpool->hPort != INVALID_PORT_HANDLE) { ClosePrinter(pSpool->hPort); } else { DBGMSG(DBG_WARNING, ("ClosePrinter ignoring bad port handle.\n")); } } EnterSplSem(); // // Remove us from the linked list of handles: // if (pSpool->TypeofHandle & PRINTER_HANDLE_PRINTER) { SPLASSERT( pSpool->pIniPrinter->signature == IP_SIGNATURE ); ppIniSpool = &pSpool->pIniPrinter->pSpool; } else if (pSpool->TypeofHandle & PRINTER_HANDLE_SERVER) { SPLASSERT( pSpool->pIniSpooler->signature == ISP_SIGNATURE ); DECSPOOLERREF( pSpool->pIniSpooler ); ppIniSpool = &pSpool->pIniSpooler->pSpool; } if (ppIniSpool) { while (*ppIniSpool && *ppIniSpool != pSpool) ppIniSpool = &(*ppIniSpool)->pNext; if (*ppIniSpool) *ppIniSpool = pSpool->pNext; else { DBGMSG( DBG_WARNING, ( "Didn't find pSpool %08x in linked list\n", pSpool ) ); } } if (pSpool->pIniPrinter) { DECPRINTERREF( pSpool->pIniPrinter ); DeletePrinterCheck(pSpool->pIniPrinter); } DeletePrinterHandle(pSpool); LeaveSplSem(); // // Don't call SplOutSem() since SplAddPrinter calls // use from inside the critical section. // return TRUE; }
int ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr) { struct tdb_ident *tdbi; struct m_tag *mtag; struct secasvar *sav; struct secasindex *saidx; int error; SPLASSERT(net, "ipsec_process_done"); KASSERT(m != NULL, ("ipsec_process_done: null mbuf")); KASSERT(isr != NULL, ("ipsec_process_done: null ISR")); sav = isr->sav; KASSERT(sav != NULL, ("ipsec_process_done: null SA")); KASSERT(sav->sah != NULL, ("ipsec_process_done: null SAH")); saidx = &sav->sah->saidx; switch (saidx->dst.sa.sa_family) { #ifdef INET case AF_INET: /* Fix the header length, for AH processing. */ mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len); break; #endif /* INET */ #ifdef INET6 case AF_INET6: /* Fix the header length, for AH processing. */ if (m->m_pkthdr.len < sizeof (struct ip6_hdr)) { error = ENXIO; goto bad; } if (m->m_pkthdr.len - sizeof (struct ip6_hdr) > IPV6_MAXPACKET) { /* No jumbogram support. */ error = ENXIO; /*?*/ goto bad; } mtod(m, struct ip6_hdr *)->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); break; #endif /* INET6 */ default: DPRINTF(("ipsec_process_done: unknown protocol family %u\n", saidx->dst.sa.sa_family)); error = ENXIO; goto bad; } /* * Add a record of what we've done or what needs to be done to the * packet. */ mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, sizeof(struct tdb_ident), M_NOWAIT); if (mtag == NULL) { DPRINTF(("ipsec_process_done: could not get packet tag\n")); error = ENOMEM; goto bad; } tdbi = (struct tdb_ident *)(mtag + 1); tdbi->dst = saidx->dst; tdbi->proto = saidx->proto; tdbi->spi = sav->spi; m_tag_prepend(m, mtag); /* * If there's another (bundled) SA to apply, do so. * Note that this puts a burden on the kernel stack size. * If this is a problem we'll need to introduce a queue * to set the packet on so we can unwind the stack before * doing further processing. */ if (isr->next) { newipsecstat.ips_out_bundlesa++; return ipsec4_process_packet(m, isr->next, 0, 0); } /* * We're done with IPsec processing, transmit the packet using the * appropriate network protocol (IP or IPv6). SPD lookup will be * performed again there. */ switch (saidx->dst.sa.sa_family) { #ifdef INET struct ip *ip; case AF_INET: ip = mtod(m, struct ip *); ip->ip_len = ntohs(ip->ip_len); ip->ip_off = ntohs(ip->ip_off); return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL); #endif /* INET */ #ifdef INET6 case AF_INET6: /* * We don't need massage, IPv6 header fields are always in * net endian. */ return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); #endif /* INET6 */ } panic("ipsec_process_done"); bad: m_freem(m); KEY_FREESAV(&sav); return (error); }
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", TRUE) ) { 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, TRUE); 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", TRUE); } // // 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; }
/* * ESP input processing, called (eventually) through the protocol switch. */ static int esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff) { struct auth_hash *esph; struct enc_xform *espx; struct tdb_ident *tdbi; struct tdb_crypto *tc; int plen, alen, hlen; struct m_tag *mtag; struct newesp *esp; struct cryptodesc *crde; struct cryptop *crp; SPLASSERT(net, "esp_input"); KASSERT(sav != NULL, ("esp_input: null SA")); KASSERT(sav->tdb_encalgxform != NULL, ("esp_input: null encoding xform")); KASSERT((skip&3) == 0 && (m->m_pkthdr.len&3) == 0, ("esp_input: misaligned packet, skip %u pkt len %u", skip, m->m_pkthdr.len)); /* XXX don't pullup, just copy header */ IP6_EXTHDR_GET(esp, struct newesp *, m, skip, sizeof (struct newesp)); esph = sav->tdb_authalgxform; espx = sav->tdb_encalgxform; /* Determine the ESP header length */ if (sav->flags & SADB_X_EXT_OLD) hlen = sizeof (struct esp) + sav->ivlen; else hlen = sizeof (struct newesp) + sav->ivlen; /* Authenticator hash size */ alen = esph ? AH_HMAC_HASHLEN : 0; /* * Verify payload length is multiple of encryption algorithm * block size. * * NB: This works for the null algorithm because the blocksize * is 4 and all packets must be 4-byte aligned regardless * of the algorithm. */ plen = m->m_pkthdr.len - (skip + hlen + alen); if ((plen & (espx->blocksize - 1)) || (plen <= 0)) { DPRINTF(("esp_input: " "payload of %d octets not a multiple of %d octets," " SA %s/%08lx\n", plen, espx->blocksize, ipsec_address(&sav->sah->saidx.dst), (u_long) ntohl(sav->spi))); espstat.esps_badilen++; m_freem(m); return EINVAL; } /* * Check sequence number. */ if (esph && sav->replay && !ipsec_chkreplay(ntohl(esp->esp_seq), sav)) { DPRINTF(("esp_input: packet replay check for %s\n", ipsec_logsastr(sav))); /*XXX*/ espstat.esps_replay++; m_freem(m); return ENOBUFS; /*XXX*/ } /* Update the counters */ espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen; /* Find out if we've already done crypto */ for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); mtag != NULL; mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { tdbi = (struct tdb_ident *) (mtag + 1); if (tdbi->proto == sav->sah->saidx.proto && tdbi->spi == sav->spi && !bcmp(&tdbi->dst, &sav->sah->saidx.dst, sizeof(union sockaddr_union))) break; } /* Get crypto descriptors */ crp = crypto_getreq(esph && espx ? 2 : 1); if (crp == NULL) { DPRINTF(("esp_input: failed to acquire crypto descriptors\n")); espstat.esps_crypto++; m_freem(m); return ENOBUFS; } /* Get IPsec-specific opaque pointer */ if (esph == NULL || mtag != NULL) tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), M_XDATA, M_NOWAIT|M_ZERO); else tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto) + alen, M_XDATA, M_NOWAIT|M_ZERO); if (tc == NULL) { crypto_freereq(crp); DPRINTF(("esp_input: failed to allocate tdb_crypto\n")); espstat.esps_crypto++; m_freem(m); return ENOBUFS; } tc->tc_ptr = (caddr_t) mtag; if (esph) { struct cryptodesc *crda = crp->crp_desc; KASSERT(crda != NULL, ("esp_input: null ah crypto descriptor")); /* Authentication descriptor */ crda->crd_skip = skip; crda->crd_len = m->m_pkthdr.len - (skip + alen); crda->crd_inject = m->m_pkthdr.len - alen; crda->crd_alg = esph->type; crda->crd_key = _KEYBUF(sav->key_auth); crda->crd_klen = _KEYBITS(sav->key_auth); /* Copy the authenticator */ if (mtag == NULL) m_copydata(m, m->m_pkthdr.len - alen, alen, (caddr_t) (tc + 1)); /* Chain authentication request */ crde = crda->crd_next; } else { crde = crp->crp_desc; } /* Crypto operation descriptor */ crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ crp->crp_flags = CRYPTO_F_IMBUF; crp->crp_buf = (caddr_t) m; crp->crp_callback = esp_input_cb; crp->crp_sid = sav->tdb_cryptoid; crp->crp_opaque = (caddr_t) tc; /* These are passed as-is to the callback */ tc->tc_spi = sav->spi; tc->tc_dst = sav->sah->saidx.dst; tc->tc_proto = sav->sah->saidx.proto; tc->tc_protoff = protoff; tc->tc_skip = skip; /* Decryption descriptor */ if (espx) { KASSERT(crde != NULL, ("esp_input: null esp crypto descriptor")); crde->crd_skip = skip + hlen; crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); crde->crd_inject = skip + hlen - sav->ivlen; crde->crd_alg = espx->type; crde->crd_key = _KEYBUF(sav->key_enc); crde->crd_klen = _KEYBITS(sav->key_enc); /* XXX Rounds ? */ } if (mtag == NULL) return crypto_dispatch(crp); else return esp_input_cb(crp); }
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_THREAD_RUNNING) { 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; }
/* * ESP output routine, called by ipsec[46]_process_packet(). */ static int esp_output( struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp, int skip, int protoff ) { struct enc_xform *espx; struct auth_hash *esph; int hlen, rlen, plen, padding, blks, alen, i, roff; struct mbuf *mo = (struct mbuf *) NULL; struct tdb_crypto *tc; struct secasvar *sav; struct secasindex *saidx; unsigned char *pad; u_int8_t prot; int error, maxpacketsize; struct cryptodesc *crde = NULL, *crda = NULL; struct cryptop *crp; SPLASSERT(net, "esp_output"); sav = isr->sav; KASSERT(sav != NULL, ("esp_output: null SA")); esph = sav->tdb_authalgxform; espx = sav->tdb_encalgxform; KASSERT(espx != NULL, ("esp_output: null encoding xform")); if (sav->flags & SADB_X_EXT_OLD) hlen = sizeof (struct esp) + sav->ivlen; else hlen = sizeof (struct newesp) + sav->ivlen; rlen = m->m_pkthdr.len - skip; /* Raw payload length. */ /* * NB: The null encoding transform has a blocksize of 4 * so that headers are properly aligned. */ blks = espx->blocksize; /* IV blocksize */ /* XXX clamp padding length a la KAME??? */ padding = ((blks - ((rlen + 2) % blks)) % blks) + 2; plen = rlen + padding; /* Padded payload length. */ if (esph) alen = AH_HMAC_HASHLEN; else alen = 0; espstat.esps_output++; saidx = &sav->sah->saidx; /* Check for maximum packet size violations. */ switch (saidx->dst.sa.sa_family) { #ifdef INET case AF_INET: maxpacketsize = IP_MAXPACKET; break; #endif /* INET */ #ifdef INET6 case AF_INET6: maxpacketsize = IPV6_MAXPACKET; break; #endif /* INET6 */ default: DPRINTF(("esp_output: unknown/unsupported protocol " "family %d, SA %s/%08lx\n", saidx->dst.sa.sa_family, ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); espstat.esps_nopf++; error = EPFNOSUPPORT; goto bad; } if (skip + hlen + rlen + padding + alen > maxpacketsize) { DPRINTF(("esp_output: packet in SA %s/%08lx got too big " "(len %u, max len %u)\n", ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi), skip + hlen + rlen + padding + alen, maxpacketsize)); espstat.esps_toobig++; error = EMSGSIZE; goto bad; } /* Update the counters. */ espstat.esps_obytes += m->m_pkthdr.len - skip; m = m_clone(m); if (m == NULL) { DPRINTF(("esp_output: cannot clone mbuf chain, SA %s/%08lx\n", ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); espstat.esps_hdrops++; error = ENOBUFS; goto bad; } /* Inject ESP header. */ mo = m_makespace(m, skip, hlen, &roff); if (mo == NULL) { DPRINTF(("esp_output: failed to inject %u byte ESP hdr for SA " "%s/%08lx\n", hlen, ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); espstat.esps_hdrops++; /* XXX diffs from openbsd */ error = ENOBUFS; goto bad; } /* Initialize ESP header. */ bcopy((caddr_t) &sav->spi, mtod(mo, caddr_t) + roff, sizeof(u_int32_t)); if (sav->replay) { u_int32_t replay = htonl(++(sav->replay->count)); bcopy((caddr_t) &replay, mtod(mo, caddr_t) + roff + sizeof(u_int32_t), sizeof(u_int32_t)); } /* * Add padding -- better to do it ourselves than use the crypto engine, * although if/when we support compression, we'd have to do that. */ pad = (u_char *) m_pad(m, padding + alen); if (pad == NULL) { DPRINTF(("esp_output: m_pad failed for SA %s/%08lx\n", ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); m = NULL; /* NB: free'd by m_pad */ error = ENOBUFS; goto bad; } /* * Add padding: random, zero, or self-describing. * XXX catch unexpected setting */ switch (sav->flags & SADB_X_EXT_PMASK) { case SADB_X_EXT_PRAND: (void) read_random(pad, padding - 2); break; case SADB_X_EXT_PZERO: bzero(pad, padding - 2); break; case SADB_X_EXT_PSEQ: for (i = 0; i < padding - 2; i++) pad[i] = i+1; break; } /* Fix padding length and Next Protocol in padding itself. */ pad[padding - 2] = padding - 2; m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1); /* Fix Next Protocol in IPv4/IPv6 header. */ prot = IPPROTO_ESP; m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot); /* Get crypto descriptors. */ crp = crypto_getreq(esph && espx ? 2 : 1); if (crp == NULL) { DPRINTF(("esp_output: failed to acquire crypto descriptors\n")); espstat.esps_crypto++; error = ENOBUFS; goto bad; } if (espx) { crde = crp->crp_desc; crda = crde->crd_next; /* Encryption descriptor. */ crde->crd_skip = skip + hlen; crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); crde->crd_flags = CRD_F_ENCRYPT; crde->crd_inject = skip + hlen - sav->ivlen; /* Encryption operation. */ crde->crd_alg = espx->type; crde->crd_key = _KEYBUF(sav->key_enc); crde->crd_klen = _KEYBITS(sav->key_enc); /* XXX Rounds ? */ } else crda = crp->crp_desc; /* IPsec-specific opaque crypto info. */ tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), M_XDATA, M_NOWAIT|M_ZERO); if (tc == NULL) { crypto_freereq(crp); DPRINTF(("esp_output: failed to allocate tdb_crypto\n")); espstat.esps_crypto++; error = ENOBUFS; goto bad; } /* Callback parameters */ tc->tc_isr = isr; tc->tc_spi = sav->spi; tc->tc_dst = saidx->dst; tc->tc_proto = saidx->proto; /* Crypto operation descriptor. */ crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ crp->crp_flags = CRYPTO_F_IMBUF; crp->crp_buf = (caddr_t) m; crp->crp_callback = esp_output_cb; crp->crp_opaque = (caddr_t) tc; crp->crp_sid = sav->tdb_cryptoid; if (esph) { /* Authentication descriptor. */ crda->crd_skip = skip; crda->crd_len = m->m_pkthdr.len - (skip + alen); crda->crd_inject = m->m_pkthdr.len - alen; /* Authentication operation. */ crda->crd_alg = esph->type; crda->crd_key = _KEYBUF(sav->key_auth); crda->crd_klen = _KEYBITS(sav->key_auth); } return crypto_dispatch(crp); bad: if (m) m_freem(m); return (error); }
BOOL WINAPI PJLMonGetPrinterDataFromPort( HANDLE hPort, DWORD ControlID, LPTSTR pValueName, LPTSTR lpInBuffer, DWORD cbInBuffer, LPTSTR lpOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbReturned ) /*++ Routine Description: GetPrinter data from port. Supports predefined commands/valuenames. When we support Value name commands (not supported by DeviceIoControl) we should check for startdoc -- MuhuntS This monitor function supports the following two functionalities, 1. Allow spooler or language monitor to call DeviceIoControl to get information from the port driver vxd, i.e. ControlID != 0. And only port monitor support this functionality, language monitor doesn't, so language monitor just pass this kind of calls down to port monitor. 2. Allow app or printer driver query language monitor for some device information by specifying some key names that both parties understand, i.e. ControlID == 0 && pValueName != 0. So when printer driver call DrvGetPrinterData DDI, gdi will call spooler -> language monitor to get specific device information, for example, UNIDRV does this to get installed printer memory from PJL printers thru PJLMON. Only language monitor support this functionality, port monitor doesn't. Arguments: hPort : Port handle ControId : Control id pValueName : Value name lpInBuffer : Input buffer for the command cbinBuffer : Input buffer size lpOutBuffer : Output buffer cbOutBuffer : Output buffer size lpcbReturned : Set to the amount of data in output buffer on success Return Value: TRUE on success, FALSE on error --*/ { PINIPORT pIniPort = (PINIPORT)((INIPORT *)hPort); BOOL bRet = FALSE, bStopUstatusThread; SPLASSERT(pIniPort && pIniPort->signature == PJ_SIGNATURE); if ( ControlID ) { if ( !pIniPort->fn.pfnGetPrinterDataFromPort ) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } return (*pIniPort->fn.pfnGetPrinterDataFromPort)( pIniPort->hPort, ControlID, pValueName, lpInBuffer, cbInBuffer, lpOutBuffer, cbOutBuffer, lpcbReturned); } // // Only 2 keys supported // if ( lstrcmpi(pValueName, cszInstalledMemory) && lstrcmpi(pValueName, cszAvailableMemory) ) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } // // Wait for crrent job to print since we can't send a PJL command // in the middle of job // WaitForSingleObject(pIniPort->DoneWriting, INFINITE); // make sure the first write succeeds // WIN95C BUG 14299, ccteng, 5/18/95 // // The multi-language printers (4M, 4ML, 4MP, 4V, 4SI), if you print a // PS print job, the memory resources claimed by the PS processor are not // release until you enter PCL or reset the printer with "EscE". // // So if we had just printed a PS job, the available memory will be // incorrect if we don't have the "EscE" here. if ( (pIniPort->status & PP_IS_PJL) && WriteCommand(hPort, "\033E\033%-12345X@PJL INFO CONFIG\015\012", FALSE) ) { if ( !(pIniPort->status & PP_RUN_THREAD) ) { bStopUstatusThread = TRUE; CreateUstatusThread(pIniPort); } // PJLMON currently only supports the following pValueName // 1. installed printer memory // 2. available printer memory if ( !lstrcmpi(pValueName, cszInstalledMemory) ) pIniPort->dwInstalledMemory = 0; else if (!lstrcmpi(pValueName, cszAvailableMemory)) pIniPort->dwAvailableMemory = 0; ResetEvent(pIniPort->DoneReading); SetEvent(pIniPort->WakeUp); WaitForSingleObject(pIniPort->DoneReading, READTHREADTIMEOUT); WriteCommand(hPort, "@PJL INFO MEMORY\015\012@PJL INFO STATUS\015\012", FALSE); ResetEvent(pIniPort->DoneReading); SetEvent(pIniPort->WakeUp); WaitForSingleObject(pIniPort->DoneReading, READTHREADTIMEOUT); if ( bStopUstatusThread ) { pIniPort->status &= ~PP_RUN_THREAD; SetEvent(pIniPort->WakeUp); } if ( !lstrcmpi(pValueName, cszInstalledMemory) ) { *lpcbReturned = sizeof(DWORD); if ( lpOutBuffer && cbOutBuffer >= sizeof(DWORD) && pIniPort->dwInstalledMemory ) { *((LPDWORD)lpOutBuffer) = pIniPort->dwInstalledMemory; bRet = TRUE; } } else if ( !lstrcmpi(pValueName, cszAvailableMemory) ) { *lpcbReturned = sizeof(DWORD); if ( lpOutBuffer && cbOutBuffer >= sizeof(DWORD) && pIniPort->dwAvailableMemory) { *((LPDWORD)lpOutBuffer) = pIniPort->dwAvailableMemory; bRet = TRUE; } } if ( bStopUstatusThread ) { while (pIniPort->WakeUp) Sleep(WAIT_FOR_USTATUS_THREAD_TIMEOUT); } } if ( !bRet ) SetLastError(ERROR_INVALID_PARAMETER); SetEvent(pIniPort->DoneWriting); return bRet; }
DWORD IrdaConnect( _In_ PLCMINIPORT pIniPort ) { BOOL bRet = FALSE; WORD WSAVerReq = MAKEWORD(1,1); DWORD dwIndex = 0, dwNeeded = BUF_SIZE, dwEnableIrLPT = TRUE, dwLastError = ERROR_SUCCESS, dwSendPduLen = 0; LPSTR pBuf = NULL; WSADATA WSAData = {0}; SOCKET Socket = INVALID_SOCKET; PIRDA_INFO pIrda = NULL; PDEVICELIST pDevList = NULL; SOCKADDR_IRDA PrinterAddr = { AF_IRDA, 0, 0, 0, 0, "IrLPT" }; SPLASSERT(pIniPort->hFile == (HANDLE)INVALID_SOCKET && pIniPort->pExtra == NULL); dwLastError = WSAStartup(WSAVerReq, &WSAData); if ( dwLastError ) goto Done; pBuf = (LPSTR)AllocSplMem(dwNeeded); if ( !pBuf ) { dwLastError = GetLastError(); goto Done; } if ( (Socket = WSASocket(AF_IRDA, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET || getsockopt(Socket, SOL_IRLMP, IRLMP_ENUMDEVICES, (LPSTR)pBuf, (int *)&dwNeeded) == SOCKET_ERROR ) { dwLastError = WSAGetLastError(); goto Done; } if ( dwNeeded > BUF_SIZE ) { FreeSplMem(pBuf); pBuf = (LPSTR)AllocSplMem(dwNeeded); if ( !pBuf ) { dwLastError = GetLastError(); goto Done; } if ( getsockopt(Socket, SOL_IRLMP, IRLMP_ENUMDEVICES, (LPSTR)pBuf, (int *)&dwNeeded) == SOCKET_ERROR ) { dwLastError = WSAGetLastError(); goto Done; } } pDevList = (PDEVICELIST) pBuf; // // Any of the devices a printer? // for ( dwIndex = 0 ; dwIndex < pDevList->numDevice ; ++dwIndex ) { if ( (pDevList->Device[dwIndex].irdaDeviceHints1 & PRINTER_HINT_BIT) || (pDevList->Device[dwIndex].irdaDeviceHints2 & PRINTER_HINT_BIT) ) break; } // // Any printers found? // if ( dwIndex == pDevList->numDevice ) { dwLastError = ERROR_PRINTER_NOT_FOUND; goto Done; } // // Move printer's address into the socket address // memcpy(PrinterAddr.irdaDeviceID, pDevList->Device[dwIndex].irdaDeviceID, sizeof(PrinterAddr.irdaDeviceID)); dwIndex = 0; dwNeeded = sizeof(dwSendPduLen); bRet = SOCKET_ERROR != setsockopt(Socket, SOL_IRLMP, IRLMP_IRLPT_MODE, (LPCSTR)&dwEnableIrLPT, sizeof(dwEnableIrLPT)) && SOCKET_ERROR != connect(Socket, (const struct sockaddr *)&PrinterAddr, sizeof(PrinterAddr)) && SOCKET_ERROR != getsockopt(Socket, SOL_IRLMP, IRLMP_SEND_PDU_LEN, (char *)&dwSendPduLen, (int *)&dwNeeded) && SOCKET_ERROR != setsockopt(Socket, SOL_SOCKET, SO_SNDBUF, (LPCSTR)&dwIndex, sizeof(dwIndex)); if ( bRet ) { SPLASSERT(pIniPort->pExtra == NULL); dwNeeded = sizeof(IRDA_INFO) + dwSendPduLen; pIrda = (PIRDA_INFO) AllocSplMem(dwNeeded); if ( !pIrda ) { bRet = FALSE; dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto Done; } pIniPort->hFile = (HANDLE)Socket; pIniPort->pExtra = (LPBYTE)pIrda; pIrda->dwSendPduLen = dwSendPduLen; pIrda->pBuf = ((LPBYTE) pIrda) + sizeof(IRDA_INFO); } else dwLastError = WSAGetLastError(); Done: FreeSplMem(pBuf); if ( !bRet ) { if ( Socket != INVALID_SOCKET ) closesocket(Socket); FreeSplMem(pIniPort->pExtra); pIniPort->pExtra = NULL; } return bRet ? ERROR_SUCCESS : dwLastError; }