Example #1
0
BOOL
EnumPortsW(
    LPWSTR   pName,
    DWORD   Level,
    LPBYTE  pPorts,
    DWORD   cbBuf,
    LPDWORD pcbNeeded,
    LPDWORD pcReturned
)
{
    PINIPORT pIniPort;
    DWORD   cb;
    LPBYTE  pEnd;
    DWORD   LastError=0;

   EnterSplSem();

    cb=0;

    pIniPort=pIniFirstPort;

    while (pIniPort) {
        cb+=GetPortSize(pIniPort, Level);
        pIniPort=pIniPort->pNext;
    }

    *pcbNeeded=cb;

    if (cb <= cbBuf) {

        pEnd=pPorts+cbBuf;
        *pcReturned=0;

        pIniPort=pIniFirstPort;
        while (pIniPort) {
            pEnd = CopyIniPortToPort(pIniPort, Level, pPorts, pEnd);
            switch (Level) {
            case 1:
                pPorts+=sizeof(PORT_INFO_1);
                break;
            }
            pIniPort=pIniPort->pNext;
            (*pcReturned)++;
        }

    } else

        LastError = ERROR_INSUFFICIENT_BUFFER;

   LeaveSplSem();

    if (LastError) {

        SetLastError(LastError);
        return FALSE;

    } else

        return TRUE;
}
Example #2
0
VOID
FreeIniJobs(
    __inout PINIPORT pIniPort
    )
/*++

Routine Description:
    Free all the InJob structures assigned to this port

Arguments:
    pIniPort    : IniPort for the port for which all jobs need to be freed

--*/
{
    PINIJOB pIniJob, pIniNextJob;

    EnterSplSem();
    pIniJob = pIniPort->pIniJob;
    while ( pIniJob ) {

        pIniNextJob = pIniJob->pNext;
        FreeIniJob(pIniJob);
        pIniJob = pIniNextJob;
    }

    pIniPort->pIniJob = NULL;
    LeaveSplSem();
}
Example #3
0
BOOL
AddPortW(
    LPWSTR   pName,
    HWND    hWnd,
    LPWSTR   pMonitorName
)
{
    WCHAR   PortName[MAX_PATH];
    DWORD   Status;

    UNREFERENCED_PARAMETER(pName); /* Possible future enhancements:
                                      this will be the server name,
                                      so that the monitor can update
                                      remote servers. */

    Status = WNetBrowsePrinterDialog( hWnd,
                                      PortName,
                                      ( sizeof PortName / sizeof *PortName ),
                                      L"Printman.hlp",
                                      0 /* help context */,
                                      (PFUNC_VALIDATION_CALLBACK)IsPortValid );

    if (Status == NO_ERROR) {

        EnterSplSem();

        if (FindName((PINIENTRY)pIniFirstPort, PortName)) {

           LeaveSplSem();
            Message(hWnd, MSG_ERROR, IDS_ERROR,
                     IDS_PORT_ALREADY_EXISTS_S, PortName);

            return FALSE;
        }

        if( CreatePortEntry( PortName ) )
            SetRegistryValue( szRegPortNames, PortName, REG_SZ, L"", 0 );
        else
            ; /* Message box to say can't create port */

        LeaveSplSem();
    }

    return TRUE;
}
Example #4
0
BOOL
InitializeMonitor(
    VOID
)
{
    InitializeCriticalSection(&SpoolerSection);

    hHeap=HeapCreate(0, 10240, 204800);

    EnterSplSem();

    EnumRegistryValues( szRegPortNames, (ENUMREGPROC)CreatePortEntry );

    LeaveSplSem();

    return TRUE;
}
Example #5
0
BOOL
OpenPort(
    LPWSTR   pName,
    PHANDLE pHandle
)
{
    PINIPORT    pIniPort;

   EnterSplSem();
    pIniPort = FindPort(pName);
   LeaveSplSem();

    if (pIniPort) {
        *pHandle = pIniPort;
        return TRUE;
    } else {
//     DbgPrint("localmon!OpenPort %s : Failed\n", pName);
        return FALSE;
    }
}
Example #6
0
BOOL
EndDocPort(
   HANDLE   hPort
)
{
    PINIPORT    pIniPort = (PINIPORT)hPort;

    CloseHandle(pIniPort->hFile);

    SetJob(pIniPort->hPrinter, pIniPort->JobId, 0, NULL, JOB_CONTROL_CANCEL);

    ClosePrinter(pIniPort->hPrinter);

   EnterSplSem();

    FreeSplStr(pIniPort->pPrinterName);

   LeaveSplSem();

    return TRUE;
}
Example #7
0
BOOL
CreateServerHandle(
    LPWSTR   pPrinterName,
    LPHANDLE pPrinterHandle,
    LPPRINTER_DEFAULTS pDefaults,
    PINISPOOLER pIniSpooler
    )
{
    DWORD AccessRequested;
    DWORD ReturnValue = ROUTER_STOP_ROUTING;

    DBGMSG(DBG_TRACE, ("OpenPrinter(%ws)\n",
                       pPrinterName ? pPrinterName : L"NULL"));

    EnterSplSem();

    if (!pDefaults || !pDefaults->DesiredAccess)
        AccessRequested = SERVER_READ;
    else
        AccessRequested = pDefaults->DesiredAccess;

    if (*pPrinterHandle = CreatePrinterHandle( pIniSpooler->pMachineName,
                                               NULL, NULL, NULL, NULL,
                                               PRINTER_HANDLE_SERVER,
                                               NULL,
                                               pDefaults,
                                               pIniSpooler,
                                               AccessRequested,
                                               NULL,
                           0,
                           INVALID_HANDLE_VALUE )){
        ReturnValue = ROUTER_SUCCESS;

    }
    LeaveSplSem();

    DBGMSG(DBG_TRACE, ("OpenPrinter returned handle %08x\n", *pPrinterHandle));

    return ReturnValue;
}
Example #8
0
BOOL
StartDocPort(
    HANDLE  hPort,
    LPWSTR   pPrinterName,
    DWORD   JobId,
    DWORD   Level,
    LPBYTE  pDocInfo
)
{
    PINIPORT    pIniPort = (PINIPORT)hPort;
    LPWSTR       pFileName;

    pIniPort->hFile = INVALID_HANDLE_VALUE;

   EnterSplSem();

    if (pIniPort->pPrinterName = AllocSplStr(pPrinterName)) {
        if (OpenPrinter(pPrinterName, &pIniPort->hPrinter, NULL)) {

            pIniPort->JobId = JobId;

            pFileName = pIniPort->pName;

            pIniPort->hFile = CreateFile(pFileName, GENERIC_WRITE,
                                         FILE_SHARE_READ, NULL, OPEN_ALWAYS,
                                         FILE_ATTRIBUTE_NORMAL, NULL);
        } else
            FreeSplStr(pIniPort->pPrinterName);

    }

   LeaveSplSem();

    if (pIniPort->hFile == INVALID_HANDLE_VALUE) {
//     DbgPrint("localmon!StartDocPort FAILED %x\n", GetLastError());
        return FALSE;
    } else {
        return TRUE;
    }
}
Example #9
0
BOOL
DeletePort(
    LPWSTR   pName,
    HWND    hWnd,
    LPWSTR   pPortName
)
{
    BOOL rc;

    if( !hWnd )
        hWnd = GetDesktopWindow( );

    EnterSplSem();

    if (rc = DeletePortEntry( pPortName ))
        WriteProfileString(szPorts, pPortName, NULL);

    LeaveSplSem();

    return rc;

    UNREFERENCED_PARAMETER( pName );
}
Example #10
0
BOOL
DeletePortEntry(
    LPWSTR   pPortName
)
{
    DWORD       cb;
    BOOL        rc;
    PINIPORT    pPort, pPrevPort;

    cb = sizeof(INIPORT) + wcslen(pPortName)*sizeof(WCHAR) + sizeof(WCHAR);

   EnterSplSem();

    pPort = pIniFirstPort;
    while (pPort && wcscmp(pPort->pName, pPortName)) {
        pPrevPort = pPort;
        pPort = pPort->pNext;
    }

    if (pPort) {
        if (pPort == pIniFirstPort) {
            pIniFirstPort = pPort->pNext;
        } else {
            pPrevPort->pNext = pPort->pNext;
        }
        FreeSplMem (pPort, cb);

        rc = TRUE;
    }
    else
        rc = FALSE;

   LeaveSplSem();

   return rc;
}
Example #11
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;
}
Example #12
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;
}
Example #13
0
BOOL
WINAPI
PJLMonOpenPortEx(
    IN     LPTSTR       pszPortName,
    IN     LPTSTR       pszPrinterName,
    IN OUT LPHANDLE     pHandle,
    IN OUT LPMONITOR    pMonitor
)
/*++

Routine Description:
    Opens the port

Arguments:
    pszPortName     : Port name
    pszPrinterName  : Printer name
    pHandle         : Pointer to the handle to return
    pMonitor        : Port monitor function table

Return Value:
    TRUE on success, FALSE on error

--*/
{
    PINIPORT    pIniPort;
    BOOL        bRet = FALSE;
    BOOL        bInSem = FALSE;

    //
    // Validate port monitor
    //
    if ( !pMonitor                  ||
         !pMonitor->pfnOpenPort     ||
         !pMonitor->pfnStartDocPort ||
         !pMonitor->pfnWritePort    ||
         !pMonitor->pfnReadPort     ||
         !pMonitor->pfnClosePort ) {


        DBGMSG(DBG_WARNING,
               ("PjlMon: Invalid port monitors passed to OpenPortEx\n"));
        SetLastError(ERROR_INVALID_PRINT_MONITOR);
        goto Cleanup;
    }

    EnterSplSem();
    bInSem = TRUE;

    //
    // Is the port open already?
    //
    if ( pIniPort = FindIniPort(pszPortName) ) {

        SetLastError(ERROR_BUSY);
        goto Cleanup;
    }

    pIniPort = CreatePortEntry(pszPortName);
    LeaveSplSem();
    bInSem = FALSE;

    if ( pIniPort &&
         (*pMonitor->pfnOpenPort)(pszPortName, &pIniPort->hPort) ) {

        *pHandle = pIniPort;
        CopyMemory((LPBYTE)&pIniPort->fn, (LPBYTE)pMonitor, sizeof(*pMonitor));

        if ( IsPJL(pIniPort) ) {

            pIniPort->status |= PP_IS_PJL;
            CreateUstatusThread(pIniPort);
        }

        bRet = TRUE;
    } else {

        DBGMSG(DBG_WARNING, ("PjlMon: OpenPort %s : Failed\n", pszPortName));
    }

Cleanup:
    if ( bInSem ) {

        LeaveSplSem();
    }
    SplOutSem();

    return bRet;
}
Example #14
0
VOID
SendJobLastPageEjected(
    __in    PINIPORT    pIniPort,
            __int64     nValue,
            BOOL        bTime
    )
/*++

Routine Description:
    Send LastPageEjected notification for 1 or more jobs to spooler

Arguments:
    pIniPort    : IniPort for the port for which all jobs need to be freed
    nValue      : if bTime is TRUE send EOJ to any jobs rcvd before nValue
                  else nValue is JobId -- ALL_JOBS is for all jobs
    bTime       : Tells how to interpret nValue (FALSE means it is a DWORD JobId)

--*/
{
    PINIJOB pIniJob;

    EnterSplSem();
    //
    // JobId == ALL_JOBS is a special case where we want to send LastPage
    // ejected for all jobs pending
    //
    if ( (!bTime) && (ALL_JOBS == nValue) ) {

        pIniJob = pIniPort->pIniJob;
        pIniPort->pIniJob = NULL;

        while ( pIniJob ) {

            PINIJOB pTempJob = pIniJob;

            SendLastPageEjectedForIniJob(pIniPort, pIniJob);
            pIniJob = pIniJob->pNext;
            FreeIniJob(pTempJob);
        }

    } else {

        PINIJOB pPrevIniJob = NULL;

        pIniJob = pIniPort->pIniJob;

        //
        // If bTime we want to send LastPageEjected for all jobs timedout
        //
        if ( bTime )  {

            pIniJob = FindFirstIniJobTimedOut(pIniPort, nValue, &pPrevIniJob);
        } else {

            pIniJob = FindIniJobFromJobId(pIniPort, (DWORD)nValue, &pPrevIniJob);
        }

        if ( pIniJob ) {

            //
            // Send notifications for any previous jobs too
            //
            if ( pIniPort->pIniJob == pIniJob )
                pIniPort->pIniJob = NULL;
            else
                pPrevIniJob->pNext = NULL;

            do {

                SendLastPageEjectedForIniJob(pIniPort, pIniJob);

                pPrevIniJob = pIniJob;
                pIniJob = pIniJob->pNext;
                FreeIniJob(pPrevIniJob);
            } while ( pIniJob );
        }
    }

    LeaveSplSem();
}
Example #15
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;
}
Example #16
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;
}
Example #17
0
BOOL
EnumPorts(
    LPWSTR   pName,
    DWORD   Level,
    LPBYTE  pPorts,
    DWORD   cbBuf,
    LPDWORD pcbNeeded,
    LPDWORD pcReturned
)
{
    PINIPORT pIniPort;
    DWORD   cb;
    LPBYTE  pEnd;
    DWORD   LastError=0;

   EnterSplSem();

    cb=0;

    pIniPort=pIniFirstPort;

    while (pIniPort) {
        cb+=GetPortSize(pIniPort, Level);
        pIniPort=pIniPort->pNext;
    }

    *pcbNeeded=cb;

    if (cb <= cbBuf) {

        pEnd=pPorts+cbBuf;
        *pcReturned=0;

        pIniPort=pIniFirstPort;
        while (pIniPort) {

            if (!(pIniPort->Status & PP_FILEPORT)) {

                pEnd = CopyIniPortToPort(pIniPort, Level, pPorts, pEnd);

                switch (Level) {
                case 1:
                    pPorts+=sizeof(PORT_INFO_1);
                    break;
                case 2:
                    pPorts+=sizeof(PORT_INFO_2);
                    break;
                default:
                    DBGMSG(DBG_ERROR,
                           ("EnumPorts: invalid level %d", Level));
                    LastError = ERROR_INVALID_LEVEL;
                    goto Cleanup;
                }
                (*pcReturned)++;
            }
            pIniPort=pIniPort->pNext;
        }

    } else

        LastError = ERROR_INSUFFICIENT_BUFFER;

Cleanup:
   LeaveSplSem();

    if (LastError) {

        SetLastError(LastError);
        return FALSE;

    } else

        return TRUE;
}
Example #18
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;
}