Beispiel #1
0
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);
    }


}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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;
}
Beispiel #5
0
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
        }
    }
}
Beispiel #6
0
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;
}
Beispiel #7
0
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 );
                }
            }
        }
    }
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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]);
				}
			}
		}
	}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
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;
}
Beispiel #14
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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);
}
Beispiel #17
0
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;
}
Beispiel #18
0
/*
 * 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);
}
Beispiel #19
0
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;
}
Beispiel #20
0
/*
 * 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);
}
Beispiel #21
0
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;
}
Beispiel #22
0
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;
}