Ejemplo n.º 1
0
DWORD
GetPortSize(
    __in    PLCMINIPORT pIniPort,
            DWORD   Level
)
{
    DWORD   cb  = 0;


    switch (Level) {

    case 1:

        cb = (DWORD) (sizeof(PORT_INFO_1) + wcslen(pIniPort->pName)*sizeof(WCHAR) + sizeof(WCHAR));
        break;

    case 2:
        {
            LPWSTR  pszLocalMonitor = NULL;
            LPWSTR  pszPortDesc     = NULL;

            pszLocalMonitor = (LPWSTR)AllocSplMem((MAX_PATH + 1) * sizeof(WCHAR));
            pszPortDesc = (LPWSTR)AllocSplMem((MAX_PATH + 1) * sizeof(WCHAR));

            if (pszLocalMonitor && pszPortDesc)
            {
                LoadString(LcmhInst, IDS_LOCALMONITORNAME, pszLocalMonitor, MAX_PATH);
                LoadString(LcmhInst, IDS_LOCALMONITOR, pszPortDesc, MAX_PATH);
                cb = (DWORD) (wcslen(pIniPort->pName) + 1 +
                              wcslen(pszLocalMonitor) + 1 +
                              wcslen(pszPortDesc) + 1);
                cb *= sizeof(WCHAR);
                cb += sizeof(PORT_INFO_2);
            }

            if (pszLocalMonitor)
            {
                FreeSplMem(pszLocalMonitor);
                pszLocalMonitor = NULL;
            }

            if (pszPortDesc)
            {
                FreeSplMem(pszPortDesc);
                pszPortDesc = NULL;
            }
        }

        break;

    default:
        cb = 0;
        break;
    }

    return cb;
}
Ejemplo n.º 2
0
LPWSTR
AllocSplStr(
    LPCWSTR pszSource
)
{
    PWSTR pszRet = NULL;

    if (pszSource)
    {
        size_t  len = 0;
        HRESULT hr = StringCchLength(pszSource, STRSAFE_MAX_CCH, &len);

        if (SUCCEEDED(hr))
        {
            pszRet = (PWSTR)AllocSplMem((len + 1) * sizeof(WCHAR));

            if (pszRet)
            {
                hr = StringCchCopy(pszRet, len + 1, pszSource);

                if (FAILED(hr))
                {
                    FreeSplMem(pszRet);

                    pszRet = NULL;
                }
            }
        }
    }

    return pszRet;
}
Ejemplo n.º 3
0
PINIPORT
CreatePortEntry(
    LPWSTR   pPortName
)
{
    DWORD       cb;
    PINIPORT    pIniPort, pPort;

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

    if (pIniPort = AllocSplMem(cb)) {

        pIniPort->pName = wcscpy((LPWSTR)(pIniPort+1), pPortName);
        pIniPort->cb = cb;
        pIniPort->pNext = 0;
        pIniPort->signature = IPO_SIGNATURE;

        if (pPort = pIniFirstPort) {

            while (pPort->pNext)
                pPort = pPort->pNext;

            pPort->pNext = pIniPort;

        } else

            pIniFirstPort = pIniPort;
    }

    return pIniPort;
}
Ejemplo n.º 4
0
LPTSTR
AllocSplStr(
    LPTSTR lpStr
)
/*++

Routine Description:

    This function will allocate enough local memory to store the specified
    string, and copy that string to the allocated memory

Arguments:

    lpStr - Pointer to the string that needs to be allocated and stored

Return Value:

    NON-NULL - A pointer to the allocated memory containing the string

    FALSE/NULL - The operation failed. Extended error status is available
        using GetLastError.

--*/
{
   LPTSTR lpMem;

   if (!lpStr)
      return 0;

   if (lpMem = AllocSplMem( (_tcslen(lpStr) + 1 )*sizeof(TCHAR)))
      _tcscpy(lpMem, lpStr);

   return lpMem;
}
Ejemplo n.º 5
0
__user_driver

PLCMINIPORT
LcmCreatePortEntry(
    __inout PINILOCALMON pIniLocalMon,
    __in    PWSTR pPortName
    )
{
    DWORD       cb          = 0;
    PLCMINIPORT pIniPort    = NULL;
    PLCMINIPORT pPort       = NULL;
    size_t      cchPortName = wcslen (pPortName) + 1;


    if (!pPortName || wcslen(pPortName) > 247)
    {
        SetLastError(ERROR_INVALID_NAME);
        return NULL;
    }

    cb = (DWORD) (sizeof(LCMINIPORT) + cchPortName * sizeof (WCHAR));

    pIniPort = (PLCMINIPORT)AllocSplMem(cb);

    if( pIniPort )
    {
        ZeroMemory(pIniPort, cb);

        pIniPort->pName = (LPWSTR)(pIniPort+1);
        (VOID) StringCchCopy (pIniPort->pName, cchPortName, pPortName);
        pIniPort->cb = cb;
        pIniPort->cRef = 0;
        pIniPort->pNext = 0;
        pIniPort->pIniLocalMon = pIniLocalMon;
        pIniPort->signature = IPO_SIGNATURE;


        pIniPort->hFile = INVALID_HANDLE_VALUE;

        LcmEnterSplSem();

        pPort = pIniLocalMon->pIniPort;
        if (pPort) {

            while (pPort->pNext)
                pPort = pPort->pNext;

            pPort->pNext = pIniPort;

        } else
            pIniLocalMon->pIniPort = pIniPort;

        LcmLeaveSplSem();
    }

    return pIniPort;
}
Ejemplo n.º 6
0
LPVOID
ReallocSplMem(
    LPVOID lpOldMem,
    DWORD cbNew)
{
    if (lpOldMem)
        return LocalReAlloc(lpOldMem, cbNew, LMEM_MOVEABLE);
    else
        return AllocSplMem(cbNew);
}
Ejemplo n.º 7
0
/* PortExists
 *
 * Calls EnumPorts to check whether the port name already exists.
 * This asks every monitor, rather than just this one.
 * The function will return TRUE if the specified port is in the list.
 * If an error occurs, the return is FALSE and the variable pointed
 * to by pError contains the return from GetLastError().
 * The caller must therefore always check that *pError == NO_ERROR.
 */
BOOL
PortExists(
    _In_opt_ LPWSTR pName,
    _In_     LPWSTR pPortName,
    _Out_    PDWORD pError
)
{
    DWORD           cbNeeded    = 0;
    DWORD           cReturned   = 0;
    DWORD           cbPorts     = 0;
    LPPORT_INFO_1   pPorts      = NULL;
    DWORD           i           = 0;
    BOOL            Found       = TRUE;


    *pError = NO_ERROR;

    if (!EnumPortsW(pName, 1, NULL, 0, &cbNeeded, &cReturned))
    {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
            cbPorts = cbNeeded;

            pPorts = (LPPORT_INFO_1)AllocSplMem(cbPorts);

            if (pPorts)
            {
                if (EnumPortsW(pName, 1, (LPBYTE)pPorts, cbPorts, &cbNeeded, &cReturned))
                {
                    Found = FALSE;

                    for (i = 0; i < cReturned; i++)
                    {
                        if (!lstrcmpi(pPorts[i].pName, pPortName))
                        {
                            Found = TRUE;
                            break;
                        }
                    }
                }
            }

            FreeSplMem(pPorts);
        }
    }
    else
    {
        Found = FALSE;
    }

    return Found;
}
Ejemplo n.º 8
0
/*++

Title:

    vsntprintf

Routine Description:

    Formats a string and returns a heap allocated string with the
    formated data.  This routine can be used to for extremely
    long format strings.  Note:  If a valid pointer is returned
    the callng functions must release the data with a call to delete.


Arguments:

    psFmt - format string
    pArgs - pointer to a argument list.

Return Value:

    Pointer to formated string.  NULL if error.

--*/
LPSTR
vsntprintf(
    IN LPCSTR      szFmt,
    IN va_list     pArgs
    )
{
    LPSTR  pszBuff;
    UINT   uSize   = 256;

    for( ; ; )
    {
        pszBuff = (LPSTR)AllocSplMem(sizeof(char) * uSize);

        if (!pszBuff)
        {
            break;
        }

        //
        // Attempt to format the string.  If format succeeds, get out
        // of the loop. If it fails, increase buffer size and continue.
        // (assuming failure is due to less buffer size).
        //
        if (SUCCEEDED ( StringCchVPrintfA(pszBuff, uSize, szFmt, pArgs) ) )
        {
            break;
        }

        FreeSplMem(pszBuff);

        pszBuff = NULL;

        //
        // Double the buffer size after each failure.
        //
        uSize *= 2;

        //
        // If the size is greater than 100k exit without formatting a string.
        //
        if (uSize > 100*1024)
        {
            break;
        }
    }
    return pszBuff;
}
Ejemplo n.º 9
0
/* GetUnicodeString
 *
 * Easy way to get a pointer to a resource string.
 * (Remember to free it.)
 */
LPWSTR GetUnicodeString(int id)
{
    WCHAR ResString[RESOURCE_STRING_LENGTH];
    DWORD length = 0;
    LPWSTR pUnicode;
    DWORD  cbUnicode;

    length = LoadStringW(hInst, id, ResString, sizeof(ResString)/sizeof(TCHAR));

    cbUnicode = ( length * sizeof ( WCHAR ) + sizeof ( WCHAR ) );
    pUnicode = AllocSplMem( cbUnicode );

    if( pUnicode )
        memcpy( pUnicode, ResString, cbUnicode );

    return pUnicode;
}
Ejemplo n.º 10
0
PINIXCVPORT
CreateXcvPortEntry(
    __inout PINILOCALMON pIniLocalMon,
            LPCWSTR pszName,
            ACCESS_MASK GrantedAccess
)
{
    DWORD       cb          = 0;
    PINIXCVPORT pIniXcvPort = NULL;
    PINIXCVPORT pPort       = NULL;
    size_t      cchName     = wcslen (pszName) + 1;


    cb = (DWORD) (sizeof(INIXCVPORT) + cchName*sizeof(WCHAR));

    pIniXcvPort = (PINIXCVPORT)AllocSplMem(cb);

    if( pIniXcvPort )
    {
        pIniXcvPort->pszName = (LPWSTR)(pIniXcvPort+1);
        (VOID) StringCchCopy (pIniXcvPort->pszName, cchName, pszName);
        pIniXcvPort->dwMethod = 0;
        pIniXcvPort->cb = cb;
        pIniXcvPort->pNext = 0;
        pIniXcvPort->signature = XCV_SIGNATURE;
        pIniXcvPort->GrantedAccess = GrantedAccess;
        pIniXcvPort->pIniLocalMon = pIniLocalMon;


        pPort = pIniLocalMon->pIniXcvPort;
        if (pPort) {

            while (pPort->pNext)
                pPort = pPort->pNext;

            pPort->pNext = pIniXcvPort;

        } else
            pIniLocalMon->pIniXcvPort = pIniXcvPort;
    }

    return pIniXcvPort;
}
Ejemplo n.º 11
0
LPVOID
ReallocSplMem(
    LPVOID pOldMem,
    DWORD cbOld,
    DWORD cbNew
    )
{
    LPVOID pNewMem;

    pNewMem=AllocSplMem(cbNew);

    if (pOldMem && pNewMem) {

        if (cbOld) {
            CopyMemory( pNewMem, pOldMem, min(cbNew, cbOld));
        }
        FreeSplMem(pOldMem);
    }
    return pNewMem;
}
Ejemplo n.º 12
0
LPWSTR
AllocSplStr(
    __in    LPWSTR pStr
    )

/*++

Routine Description:

    This function will allocate enough local memory to store the specified
    string, and copy that string to the allocated memory

Arguments:

    pStr - Pointer to the string that needs to be allocated and stored

Return Value:

    NON-NULL - A pointer to the allocated memory containing the string

    FALSE/NULL - The operation failed. Extended error status is available
    using GetLastError.

--*/

{
    LPWSTR pMem;
    DWORD  cbStr;

    if (!pStr) {
        return NULL;
    }

    cbStr = wcslen(pStr)*sizeof(WCHAR) + sizeof(WCHAR);

    pMem = AllocSplMem( cbStr );
    if (pMem) {
        CopyMemory( pMem, pStr, cbStr );
    }
    return pMem;
}
Ejemplo n.º 13
0
PINIPORT
CreatePortEntry(
    LPWSTR   pPortName
)
{
    DWORD       cb;
    PINIPORT    pIniPort, pPort;

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

    pIniPort=AllocSplMem(cb);

    if( pIniPort )
    {
        pIniPort->pName = wcscpy((LPWSTR)(pIniPort+1), pPortName);
        pIniPort->cb = cb;
        pIniPort->pNext = 0;
        pIniPort->signature = IPO_SIGNATURE;

        //
        // KrishnaG -- initialized the hFile value; it will be set to
        // a legal value in the StartDocPort call
        //

        pIniPort->hFile = INVALID_HANDLE_VALUE;


        if (pPort = pIniFirstPort) {

            while (pPort->pNext)
                pPort = pPort->pNext;

            pPort->pNext = pIniPort;

        } else

            pIniFirstPort = pIniPort;
    }

    return pIniPort;
}
Ejemplo n.º 14
0
BOOL
AbortThisJob(
    _In_    PLCMINIPORT    pIniPort
    )
/*++
        Tells if the job should be aborted. A job should be aborted if it has
        been deleted or it needs to be restarted.

--*/
{
    BOOL            bRet        = FALSE;
    DWORD           dwNeeded    = 0;
    LPJOB_INFO_1    pJobInfo    = NULL;


    dwNeeded = 0;

    GetJob(pIniPort->hPrinter, pIniPort->JobId, 1, NULL, 0, &dwNeeded);

    if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
        goto Done;

    pJobInfo = (LPJOB_INFO_1) AllocSplMem(dwNeeded);
    if ( !pJobInfo     ||
         !GetJob(pIniPort->hPrinter, pIniPort->JobId,
                 1, (LPBYTE)pJobInfo, dwNeeded, &dwNeeded))

        goto Done;

    bRet = (pJobInfo->Status & JOB_STATUS_DELETING) ||
           (pJobInfo->Status & JOB_STATUS_DELETED)  ||
           (pJobInfo->Status & JOB_STATUS_RESTART);
Done:
    if ( pJobInfo )
        FreeSplMem(pJobInfo);

    return bRet;
}
Ejemplo n.º 15
0
DWORD
GetDriverMajorVersion(
    LPWSTR pFileName
    )
{
     DWORD dwSize = 0;
     LPVOID pFileVersion;
     UINT  uLen = 0;
     LPVOID pMem;
     DWORD dwFileOS;
     DWORD dwFileVersionMS;
     DWORD dwFileVersionLS;
     DWORD dwProductVersionMS;
     DWORD dwProductVersionLS;


     if (!(dwSize = GetFileVersionInfoSize(pFileName, 0))) {
         DBGMSG(DBG_TRACE, ("Error: GetFileVersionInfoSize failed with %d\n", GetLastError()));
         DBGMSG(DBG_TRACE, ("Returning back a version # 0\n"));
         return(0);
     }
     if (!(pMem = AllocSplMem(dwSize))) {
         DBGMSG(DBG_TRACE, ("AllocMem  failed \n"));
         DBGMSG(DBG_TRACE, ("Returning back a version # 0\n"));
         return(0);
     }
     if (!GetFileVersionInfo(pFileName, 0, dwSize, pMem)) {
         FreeSplMem(pMem);
         DBGMSG(DBG_TRACE, ("GetFileVersionInfo failed\n"));
         DBGMSG(DBG_TRACE, ("Returning back a version # 0\n"));
         return(0);
     }
     if (!VerQueryValue(pMem, L"\\",
                            &pFileVersion, &uLen)) {
        FreeSplMem(pMem);
        DBGMSG(DBG_TRACE, ("VerQueryValue failed \n"));
        DBGMSG(DBG_TRACE, ("Returning back a version # 0\n"));
        return(0);
     }

     //
     // We could determine the Version Information
     //

     DBGMSG(DBG_TRACE, ("dwFileVersionMS =  %d\n", ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionMS));
     DBGMSG(DBG_TRACE, ("dwFileVersionLS = %d\n", ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionLS));

     DBGMSG(DBG_TRACE, ("dwProductVersionMS = %d\n", ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionMS));
     DBGMSG(DBG_TRACE, ("dwProductVersionLS =  %d\n", ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionLS));

     dwFileOS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileOS;
     dwFileVersionMS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionMS;
     dwFileVersionLS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwFileVersionLS;

     dwProductVersionMS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionMS;
     dwProductVersionLS = ((VS_FIXEDFILEINFO *)pFileVersion)->dwProductVersionLS;

     FreeSplMem(pMem);

     if (dwFileOS != VOS_NT_WINDOWS32) {
         DBGMSG(DBG_TRACE,("Returning back a version # 0\n"));
         return(0);
     }

     if (dwProductVersionMS == dwFileVersionMS) {

         //
         // This means this hold for all dlls Pre-Daytona
         // after Daytona, printer driver writers must support
         // version control or we'll dump them as Version 0
         // drivers


         DBGMSG(DBG_TRACE,("Returning back a version # 0\n"));
         return(0);
     }

     //
     // Bug-Bug: suppose a third-party vendor uses a different system
     // methinks we should use the lower dword to have  specific value
     // which implies he/she supports spooler version -- check with MattFe

     DBGMSG(DBG_TRACE,("Returning back a version # %d\n", dwFileVersionMS));

     return(dwFileVersionMS);
}
Ejemplo n.º 16
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;
}
Ejemplo n.º 17
0
BOOL
PrintRawJob(
         IN PPRINTPROCESSORDATA pData,
    _In_ IN LPWSTR pPrinterName)
{
    DOC_INFO_1  DocInfo;
    DWORD       Copies;
    DWORD       NoRead, NoWritten;
    BOOL        rc;
    HANDLE      hPrinter;
    BYTE        *ReadBuffer = NULL;
    BOOL        bRet        = FALSE;
    BOOL        bStartDoc   = FALSE;

    DocInfo.pDocName    = pData->pDocument;     /* Document name */
    DocInfo.pOutputFile = pData->pOutputFile;   /* Output file */
    DocInfo.pDatatype   = pData->pDatatype;     /* Document data type */

    /** Let the printer know we are starting a new document **/

    if (!StartDocPrinter(pData->hPrinter, 1, (LPBYTE)&DocInfo)) {
        goto Done;
    }

    bStartDoc = TRUE;


    /** Allocate the read buffer, dynamically allocated to conserve stack space **/

    ReadBuffer = (BYTE *)AllocSplMem(READ_BUFFER_SIZE);

    if (!ReadBuffer) {
        goto Done;
    }

    /** Print the data pData->Copies times **/

    Copies = pData->Copies;

    while (Copies--) {

        /**
            Open the printer.  If it fails, return.  This also sets up the
            pointer for the ReadPrinter calls.
        **/

        if (!OpenPrinter(pPrinterName, &hPrinter, NULL)) {   
            goto Done;
        }

        /**
            Loop, getting data and sending it to the printer.  This also
            takes care of pausing and cancelling print jobs by checking
            the processor's status flags while printing.
        **/

        while (
            ((rc = ReadPrinter(hPrinter, ReadBuffer, READ_BUFFER_SIZE, &NoRead)) != 0) &&
            NoRead
            ) {


            /** If the print processor is paused, wait for it to be resumed **/

            if (pData->fsStatus & PRINTPROCESSOR_PAUSED) {
                WaitForSingleObject(pData->semPaused, INFINITE);
            }

            /** If the job has been aborted, don't write anymore **/

            if (pData->fsStatus & PRINTPROCESSOR_ABORTED) {
                break;
            }

            /** Write the data to the printer **/

            WritePrinter(pData->hPrinter, ReadBuffer, NoRead, &NoWritten);
        }


        /**
            Close the printer - we open/close the printer for each
            copy so the data pointer will rewind.
        **/

        ClosePrinter(hPrinter);

    } /* While copies to print */

    bRet = TRUE;

Done:    
    
    /** Close the buffer we allocated **/

    if (ReadBuffer) {
        FreeSplMem(ReadBuffer);
    }
    
    /** Let the printer know that we are done printing **/

    if (bStartDoc) {
        EndDocPrinter(pData->hPrinter);
    }
    
    return bRet;
}
Ejemplo n.º 18
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 );
                }
            }
        }
    }
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
0
PUCHAR
GetPrinterInfo(IN  HANDLE   hPrinter,
               IN  ULONG    StructLevel,
               OUT PULONG   pErrorCode)
{
    ULONG   reqbytes, alloc_size;
    PUCHAR  ptr_info, pTempPtr_info = NULL;
    USHORT  retry = 2;

    alloc_size = BASE_PRINTER_BUFFER_SIZE;

    ptr_info = (PUCHAR)AllocSplMem(alloc_size);

    if (!ptr_info) {
        *pErrorCode = ERROR_NOT_ENOUGH_MEMORY;
        return NULL;
    }

    while (retry--) {

        if (GetPrinter(
              hPrinter,
              StructLevel,
              (PUCHAR)ptr_info,
              alloc_size,
              &reqbytes) == TRUE) {

            *pErrorCode = 0;
            return (PUCHAR)ptr_info;
        }

        //
        // GetPrinter failed - if not because of insufficient buffer, fail
        // the call.  Otherwise, up our hint, re-allocate and try again.
        //

        *pErrorCode = GetLastError();

        if (*pErrorCode != ERROR_INSUFFICIENT_BUFFER) {
            FreeSplMem(ptr_info);
            return NULL;
        }

        //
        // Reallocate the buffer and re-try (note that, because we
        // allocated the buffer as LMEM_FIXED, the LMEM_MOVABLE does
        // not return a movable allocation, it just allows realloc
        // to return a different pointer.
        //

        FreeSplMem(ptr_info);
        ptr_info      = NULL;
        pTempPtr_info = (PUCHAR)AllocSplMem(reqbytes);
        alloc_size    = reqbytes;

        if (pTempPtr_info) {

            ptr_info = pTempPtr_info;
            pTempPtr_info = NULL;
        } else {
            //
            // If the realloc failed we break out of the loop so that we
            // can cleanup and return error code.
            //
            break;
        }

    }

    if (ptr_info) {
        FreeSplMem(ptr_info);
    }

    *pErrorCode = ERROR_NOT_ENOUGH_MEMORY;
    return NULL;
}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
/*++
*******************************************************************
    O p e n P r i n t P r o c e s s o r

    Routine Description:

    Arguments:
        pPrinterName            => name of printer we are
                                    opening for
        pPrintProcessorOpenData => information used for opening
                                    the print processor

    Return Value:
        PPRINTPROCESSORDATA => processor data of opened
                                processor if successful
        NULL if failed - caller uses GetLastError for reason

    NOTE: OpenPrinter will be called iff this returns a valid handle
          (and we're not journal)

*******************************************************************
--*/
HANDLE
OpenPrintProcessor(
    _In_ LPWSTR                  pPrinterName,
    _In_ PPRINTPROCESSOROPENDATA pPrintProcessorOpenData
)
{
    PPRINTPROCESSORDATA pData;
    LPWSTR              *pMyDatatypes    = Datatypes;
    DWORD               uDatatype        = 0;
    HANDLE              hPrinter         = 0;
    HDC                 hDC              = 0;
    PDEVMODEW           pDevmode         = NULL;
    DWORD               dwNewDevmodeSize = 0;


    /** If the caller passed a NULL for the open data, fail the call.
        pPrintProcessorOpenData->pDevMode can be NULL **/

    if (!pPrintProcessorOpenData ||
        !pPrintProcessorOpenData->pDatatype ||
        !*pPrintProcessorOpenData->pDatatype) {

        SetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }

    /** Search for the data type index we are opening for **/

    while (*pMyDatatypes) {

        if (!_wcsicmp(*pMyDatatypes,pPrintProcessorOpenData->pDatatype)) {
            break;
        }
        pMyDatatypes++;
        uDatatype++;
    }

    /** Allocate a buffer for the print processor data to return **/

    pData = (PPRINTPROCESSORDATA)AllocSplMem(sizeof(PRINTPROCESSORDATA));

    if (!pData) {
        ODS(("Alloc failed in OpenPrintProcessor, while printing on %ws\n", pPrinterName));
        return NULL;
    }

    ZeroMemory ( pData, sizeof (PRINTPROCESSORDATA) );

    /** Open the processor accordingly **/

    switch (uDatatype) {

    case PRINTPROCESSOR_TYPE_RAW:
        if (!OpenPrinter(pPrinterName, &hPrinter, NULL))
            goto Fail;
        break;

    case PRINTPROCESSOR_TYPE_EMF_50_1:
    case PRINTPROCESSOR_TYPE_EMF_50_2:
    case PRINTPROCESSOR_TYPE_EMF_50_3:

        if(pPrintProcessorOpenData->pDevMode)
        {
            if ( ! SUCCEEDED ( DWordAdd(pPrintProcessorOpenData->pDevMode->dmSize,
                                        pPrintProcessorOpenData->pDevMode->dmDriverExtra,
                                        &dwNewDevmodeSize) )
                 ||

                 (NULL == (pDevmode=(PDEVMODE)AllocSplMem( dwNewDevmodeSize ) ) )
               )
            {
                goto Fail;
            }
            memcpy(pDevmode,
                   pPrintProcessorOpenData->pDevMode,
                   pPrintProcessorOpenData->pDevMode->dmSize+
                   pPrintProcessorOpenData->pDevMode->dmDriverExtra);
        }
        break;

    case PRINTPROCESSOR_TYPE_TEXT:
        if ((hDC = CreateDC(
                 L"", pPrinterName, L"",
                 pPrintProcessorOpenData->pDevMode))
            == NULL)
            goto Fail;
        break;

    default:
        SetLastError(ERROR_INVALID_DATATYPE);
        goto Fail;
    }

    /** Fill in the print processors information **/

    pData->cb          = sizeof(PRINTPROCESSORDATA);
    pData->signature   = PRINTPROCESSORDATA_SIGNATURE;
    pData->JobId       = pPrintProcessorOpenData->JobId;
    pData->hPrinter    = hPrinter;
    pData->semPaused   = CreateEvent(NULL, TRUE, TRUE,NULL);
    pData->uDatatype   = uDatatype;
    pData->hDC         = hDC;
    pData->Copies      = 1;
    pData->TabSize     = BASE_TAB_SIZE;

    /** Allocate and fill in the processors strings **/

    pData->pPrinterName = AllocSplStr(pPrinterName);
    pData->pDatatype    = AllocSplStr(pPrintProcessorOpenData->pDatatype);
    pData->pDocument    = AllocSplStr(pPrintProcessorOpenData->pDocumentName);
    pData->pOutputFile  = AllocSplStr(pPrintProcessorOpenData->pOutputFile);
    pData->pParameters  = AllocSplStr(pPrintProcessorOpenData->pParameters);
    pData->pDevmode     = pDevmode;
    pData->pPrinterNameFromOpenData = AllocSplStr(pPrintProcessorOpenData->pPrinterName);

    //
    // Check for validity of pData. In the AllocSplStr above, if RHS is non-null, then LHS
    // should be non-null.
    //
    if ( NULL == pData->semPaused ||
        ( NULL != pPrinterName                           && NULL == pData->pPrinterName )  ||
        ( NULL != pPrintProcessorOpenData->pDatatype     && NULL == pData->pDatatype    )  ||
        ( NULL != pPrintProcessorOpenData->pDocumentName && NULL == pData->pDocument    )  ||
        ( NULL != pPrintProcessorOpenData->pOutputFile   && NULL == pData->pOutputFile  )  ||
        ( NULL != pPrintProcessorOpenData->pParameters   && NULL == pData->pParameters  )  ||
        ( NULL != pPrintProcessorOpenData->pPrinterName  && NULL == pData->pPrinterNameFromOpenData)
      )
    {
        goto Fail;
    }


    /** Parse the parameters string **/
    if (pData->pParameters) {
        ULONG   value;
        USHORT  length = sizeof(ULONG);

        /**
            Look to see if there is a COPIES=n key/value in the
            Parameters field of this job.  This tells us the number
            of times to play the data.
        **/

        if (pData->pParameters) {

            GetKeyValue(pData->pParameters,
                        pCopiesKey,
                        VALUE_ULONG,
                        &length,
                        &value);

            if (length == sizeof(ULONG)) {
                pData->Copies = value;
            }
        }

        /** If this is a text job, see if the tab size is in there **/

        if (uDatatype == PRINTPROCESSOR_TYPE_TEXT) {
            length = sizeof(ULONG);

            GetKeyValue(pData->pParameters,
                        pTabsKey,
                        VALUE_ULONG,
                        &length,
                        &value);

            if ((length == sizeof(ULONG)) && value) {
                pData->TabSize = value;
            }
        }
    } /* If we have a parameter string */

    /**
        If we are doing copies, we need to check to see if
        this is a direct or spooled job.  If it is direct, then
        we can't do copies because we can't rewind the data stream.
    **/

    if (pData->Copies > 1) {
        ULONG           Error;
        PPRINTER_INFO_2 pPrinterInfo2;

        /** If we don't already have the printer open, open it **/

        if (uDatatype != PRINTPROCESSOR_TYPE_RAW
            ) {

            OpenPrinter(pPrinterName, &hPrinter, NULL);
        }
        if (hPrinter && hPrinter != INVALID_HANDLE_VALUE) {

            /** Get the printer info - this returns an allocated buffer **/

            pPrinterInfo2 = (PPRINTER_INFO_2)GetPrinterInfo(hPrinter, 2, &Error);

            /** If we couldn't get the info, be safe and don't do copies **/

            if (!pPrinterInfo2) {
                ODS(("GetPrinter failed - falling back to 1 copy\n"));
                pData->Copies = 1;
            }
            else {
                if (pPrinterInfo2->Attributes & PRINTER_ATTRIBUTE_DIRECT) {
                    pData->Copies = 1;
                }
                FreeSplMem((PUCHAR)pPrinterInfo2);
            }

            /** If we just opened the printer, close it **/

            if (uDatatype != PRINTPROCESSOR_TYPE_RAW
                ) {

                ClosePrinter(hPrinter);
            }
        }
        else {
            pData->Copies = 1;
        }
    }

    return (HANDLE)pData;

Fail:
    BReleasePPData(&pData);

    return FALSE;
}
Ejemplo n.º 24
0
LPBYTE
CopyIniPortToPort(
    __in    PLCMINIPORT pIniPort,
            DWORD       Level,
    __out   LPBYTE      pPortInfo,
    __inout LPBYTE      pEnd
)
{
    LPWSTR          *SourceStrings              = NULL;
    LPWSTR          *pSourceStrings             = NULL;
    PPORT_INFO_2    pPort2                      = (PPORT_INFO_2)pPortInfo;
    LPWSTR          pszLocalMonitor             = NULL;
    LPWSTR          pszPortDesc                 = NULL;
    DWORD           *pOffsets                   = NULL;
    DWORD           Count                       = 0;
    LPBYTE          pReturnPointer              = NULL;


    switch (Level) {

    case 1:
        pOffsets = LcmPortInfo1Strings;
        break;

    case 2:
        pOffsets = LcmPortInfo2Strings;
        break;

    default:

        goto Done;
    }

    for ( Count = 0 ; pOffsets[Count] != -1 ; ++Count ) {
    }

    SourceStrings = pSourceStrings = (LPWSTR *)AllocSplMem(Count * sizeof(LPWSTR));

    if ( !SourceStrings ) {


        goto Done;
    }

    switch (Level) {

    case 1:
        *pSourceStrings++=pIniPort->pName;

        break;

    case 2:
        {
            pszLocalMonitor = (LPWSTR)AllocSplMem((MAX_PATH + 1) * sizeof(WCHAR));
            pszPortDesc = (LPWSTR)AllocSplMem((MAX_PATH + 1) * sizeof(WCHAR));

            if (pszLocalMonitor && pszPortDesc)
            {
                *pSourceStrings++=pIniPort->pName;

                LoadString(LcmhInst, IDS_LOCALMONITORNAME, pszLocalMonitor, MAX_PATH);
                LoadString(LcmhInst, IDS_LOCALMONITOR, pszPortDesc, MAX_PATH);
                *pSourceStrings++ = pszLocalMonitor;
                *pSourceStrings++ = pszPortDesc;

                pPort2->fPortType = PORT_TYPE_WRITE | PORT_TYPE_READ;

                // Reserved
                pPort2->Reserved = 0;
            }
            else
            {
                goto Done;
            }
        }

        break;

    default:
        goto Done;
    }

    pEnd = LcmPackStrings(Count, SourceStrings, pPortInfo, pOffsets, pEnd);

    pReturnPointer = pEnd;

Done:
    if (SourceStrings)
    {
        FreeSplMem(SourceStrings);
        SourceStrings = NULL;
    }

    if (pszLocalMonitor)
    {
        FreeSplMem(pszLocalMonitor);
        pszLocalMonitor = NULL;
    }

    if (pszPortDesc)
    {
        FreeSplMem(pszPortDesc);
        pszPortDesc = NULL;
    }

    return pReturnPointer;
}
Ejemplo n.º 25
0
/*++
*******************************************************************
    P r i n t T e x t J o b

    Routine Description:
        Prints a text data job.

    Arguments:
        pData           => Data structure for this job
        pDocumentName   => Name of this document

    Return Value:
        TRUE  if successful
        FALSE if failed - GetLastError() will return reason.
*******************************************************************
--*/
BOOL
PrintTextJob(
         IN PPRINTPROCESSORDATA pData,
    __in IN LPWSTR pDocumentName)
{
    DOCINFO     DocInfo;
    LOGFONT     LogFont;
    CHARSETINFO CharSetInfo;
    HFONT       hOldFont, hFont = NULL;
    DWORD       Copies;
    BOOL        rc;
    DWORD       NoRead;
    DWORD       CurrentLine;
    DWORD       CurrentCol;
    HANDLE      hPrinter = NULL;
    BYTE        *ReadBufferStart = NULL;
    PBYTE       pLineBuffer = NULL;
    PBYTE       pReadBuffer = NULL;
    PBYTE       pReadBufferEnd = NULL;
    ULONG       CharHeight, CharWidth, CharsPerLine, LinesPerPage;
    ULONG       PageWidth, PageHeight;
    ULONG       Length, TabBase;
    BOOL        ReadAll;
    TEXTMETRIC  tm;
    DWORD       fdwFlags;
    DWORD       Encoding;
    DWORD       SplitSize;
    BOOL        ReturnValue = FALSE;
    BOOL        bAbortDoc   = FALSE;

    DWORD       dwNeeded;
    DWORD       dwNoTranslate = 0;
    DWORD       dwNoTranslateCR = 0;
    DWORD       dwTransparent = 0;
    INT         iBkMode = OPAQUE;

    DocInfo.lpszDocName = pData->pDocument;  /* Document name */
    DocInfo.lpszOutput  = NULL;              /* Output file */
    DocInfo.lpszDatatype = NULL;             /* Datatype */
    DocInfo.cbSize = sizeof(DOCINFO);        /* Size of the structure */



    //
    // Go figure out the size of the form on the printer.  We do this
    // by calling GetTextMetrics, which gives us the font size of the
    // printer font, then getting the form size and calculating the
    // number of characters that will fit. In other cases we treat it as ANSI text.
    // Currently the codepage context is fixed to the system default codepage.
    //

    Encoding = GetACP();

    //
    // Create FIXED PITCH font and select
    //

    hOldFont = 0;
    ZeroMemory(&CharSetInfo, sizeof(CHARSETINFO));
    if (TranslateCharsetInfo((PDWORD)UIntToPtr(Encoding), &CharSetInfo, TCI_SRCCODEPAGE))
    {
        ZeroMemory(&LogFont, sizeof(LOGFONT));

        LogFont.lfWeight = 400;
        LogFont.lfCharSet = (BYTE)CharSetInfo.ciCharset;
        LogFont.lfPitchAndFamily = FIXED_PITCH;

        hFont = CreateFontIndirect(&LogFont);
        hOldFont = (HFONT) SelectObject(pData->hDC, hFont);
    }

    if (!GetTextMetrics(pData->hDC, &tm)) {
        // Essential text processing computation failed
        goto Done;
    }

    CharHeight = tm.tmHeight + tm.tmExternalLeading;
    CharWidth  = tm.tmAveCharWidth;

    if (!CharWidth || !CharHeight) {
        // Essential text processing computation failed
        goto Done;
    }

    //
    // Calculate most fittable characters' number to one line.
    //

    PageWidth = GetDeviceCaps(pData->hDC, DESKTOPHORZRES);
    PageHeight = GetDeviceCaps(pData->hDC, DESKTOPVERTRES);

    CharsPerLine = PageWidth / CharWidth;
    LinesPerPage = PageHeight / CharHeight;

    if (!CharsPerLine || !LinesPerPage) {
        // Essential text processing computation failed
        goto Done;
    }

    /** Allocate a buffer for one line of text **/

    pLineBuffer = (PBYTE)AllocSplMem(CharsPerLine + 5);

    if (!pLineBuffer) {
        goto Done;
    }

    /** Let the printer know we are starting a new document **/

    if (!StartDoc(pData->hDC, (LPDOCINFO)&DocInfo)) {

        goto Done;
    }

    ReadBufferStart = (BYTE *)AllocSplMem(READ_BUFFER_SIZE);

    if (!ReadBufferStart) {

        goto Done;
    }

    /** Print the data pData->Copies times **/

    Copies = pData->Copies;

    while (Copies--) {

        /**
            Loop, getting data and sending it to the printer.  This also
            takes care of pausing and cancelling print jobs by checking
            the processor's status flags while printing.  The way we do
            this is to read in some data from the printer.  We will then
            pull data, one tabbed line at a time from there and print
            it.  If the last bit of data in the buffer does not make up
            a whole line, we call GetTabbedLineFromBuffer() with a non-
            zero Length, which indicates that there are chars left
            from the previous read.
        **/

        TabBase = 0;
        Length = 0;
        fdwFlags = FLAG_TRANSLATE_CR | FLAG_TRANSLATE_LF;

        CurrentLine = 0;
        CurrentCol = 0;

        /**
            Open the printer.  If it fails, return.  This also sets up the
            pointer for the ReadPrinter calls.
        **/

        if (!OpenPrinter(pDocumentName, &hPrinter, NULL)) {

            hPrinter = NULL;
            bAbortDoc = TRUE;
            goto Done;
        }

        //
        // Call GetPrinterData to see if the queue wants no LF/CR processing.
        //
        if( GetPrinterData( hPrinter,
                            (LPWSTR)gszNoTranslateCRLF,
                            NULL,
                            (PBYTE)&dwNoTranslate,
                            sizeof( dwNoTranslate ),
                            &dwNeeded ) == ERROR_SUCCESS ){

            if( dwNoTranslate ){
                fdwFlags &= ~( FLAG_TRANSLATE_CR | FLAG_TRANSLATE_LF );
            }
        }

        //
        // Call GetPrinterData to see if the queue wants no CR processing.
        //
        if( GetPrinterData( hPrinter,
                            (LPWSTR)gszNoTranslateCR,
                            NULL,
                            (PBYTE)&dwNoTranslateCR,
                            sizeof( dwNoTranslateCR ),
                            &dwNeeded ) == ERROR_SUCCESS ){

            if( dwNoTranslateCR ){

                fdwFlags &= ~FLAG_TRANSLATE_CR;

                if( GetPrinterData( hPrinter,
                                (LPWSTR)gszTransparency,
                                NULL,
                                (PBYTE)&dwTransparent,
                                sizeof( dwTransparent ),
                                &dwNeeded ) == ERROR_SUCCESS ){

                    if( dwTransparent ){
                        iBkMode = SetBkMode( pData->hDC, TRANSPARENT );
                    }
                }
            }
        }

        if (StartPage(pData->hDC) == SP_ERROR) {

            bAbortDoc = TRUE;
            goto Done;
        }

        /** ReadAll indicates if we are on the last line of the file **/

        ReadAll = FALSE;

        /**
            This next do loop continues until we have read all of the
            data for the print job.
        **/

        do {

            if (fdwFlags & FLAG_DBCS_SPLIT) {
                SplitSize = (DWORD)(pReadBufferEnd - pReadBuffer);
                memcpy(ReadBufferStart, pReadBuffer, SplitSize);
                fdwFlags &= ~FLAG_DBCS_SPLIT;
            }
            else {
                SplitSize = 0;
            }

            rc = ReadPrinter(hPrinter,
                             (ReadBufferStart + SplitSize),
                             (READ_BUFFER_SIZE - SplitSize),
                             &NoRead);

            if (!rc || !NoRead) {

                ReadAll = TRUE;

            } else {

                /** Pick up a pointer to the end of the data **/

                pReadBuffer    = ReadBufferStart;
                pReadBufferEnd = ReadBufferStart + SplitSize + NoRead;
            }

            /**
                This loop will process all the data that we have
                just read from the printer.
            **/

            do {

                if (!ReadAll) {

                    /**
                        Length on entry holds the length of any
                        residual chars from the last line that we couldn't
                        print out because we ran out of characters on
                        the ReadPrinter buffer.
                    **/

                    pReadBuffer = GetTabbedLineFromBuffer(
                                      pReadBuffer,
                                      pReadBufferEnd,
                                      pLineBuffer,
                                      CharsPerLine - CurrentCol,
                                      pData->TabSize,
                                      Encoding,
                                      &Length,
                                      &TabBase,
                                      &fdwFlags );

                    /**

                        If pReadBuffer == NULL, then we have
                        exhausted the read buffer and we need to ReadPrinter
                        again and save the last line chars.  Length holds
                        the number of characters on this partial line,
                        so the next time we call ReadPrinter we will
                        pickup where we left off.

                        The only time we'll get residual chars is if:

                        1. The last line ends w/o ff/lf/cr ("Hello\EOF")
                           In this case we should TextOutA the last line
                           and then quit.

                           (In this case, don't break here; go ahead and
                           print, then we'll break out below in the do..while.)


                        2. The ReadPrinter last byte is in the middle of a line.
                           Here we should read the next chunk and add the
                           new characters at the end of the chars we just read.

                           (In this case, we should break and leave Length
                           as it is so we will read again and append to the
                           buffer, beginning at Length.)
                    **/

                    if (!pReadBuffer || (fdwFlags & FLAG_DBCS_SPLIT))
                        break;
                }


                /** If the print processor is paused, wait for it to be resumed **/

                if (pData->fsStatus & PRINTPROCESSOR_PAUSED) {
                    WaitForSingleObject(pData->semPaused, INFINITE);
                }

                /** If the job has been aborted, clean up and leave **/

                if (pData->fsStatus & PRINTPROCESSOR_ABORTED) {

                    ReturnValue = TRUE;

                    bAbortDoc = TRUE;
                    goto Done;
                }

                /** Write the data to the printer **/

                /** Make sure Length is not zero  **/
                /** TextOut will fail if Length == 0 **/

                if (Length) {

                    /**
                        We may have a number of newlines pending, that
                        may push us to the next page (or even next-next
                        page).
                    **/

                    while (CurrentLine >= LinesPerPage) {

                        /**
                            We need a new page; always defer this to the
                            last second to prevent extra pages from coming out.
                        **/

                        if (EndPage(pData->hDC) == SP_ERROR ||
                            StartPage(pData->hDC) == SP_ERROR) {

                            bAbortDoc = TRUE;
                            goto Done;
                        }

                        CurrentLine -= LinesPerPage;
                    }

#pragma prefast(suppress:__WARNING_ANSI_APICALL, "By design. This function is inherently handling only ANSI text print jobs.")
                    if (TextOutA(pData->hDC,
                                 CurrentCol * CharWidth,
                                 CurrentLine * CharHeight,
                                 (LPCSTR)pLineBuffer,
                                 Length) == FALSE) {

                        ODS(("TextOut() failed\n"));

                        bAbortDoc = TRUE;
                        goto Done;
                    }

                    CurrentCol += Length;
                }

                /**
                    Even if the length is zero, increment the line.
                    Should happen when the character is only 0x0D or 0x0A.
                **/

                if (fdwFlags & FLAG_CR) {
                    CurrentCol=0;
                    fdwFlags &= ~FLAG_CR;
                }

                if (fdwFlags & FLAG_LF) {
                    CurrentLine++;
                    fdwFlags &= ~FLAG_LF;
                }

                /**
                    We need a new page.  Set the current line to the
                    end of the page.  We could do a End/StartPage
                    sequence, but this may cause a blank page to get
                    ejected.

                    Note: this code will avoid printing out pages that
                    consist of formfeeds only (if you have a page with a
                    space in it, that counts as text).
                **/

                if (fdwFlags & FLAG_FF) {

                    CurrentLine = LinesPerPage;
                    CurrentCol = 0;
                    fdwFlags &= ~FLAG_FF;
                }

                /**
                    We have done the text out, so these characters have
                    been successfully printed.  Zero out Length
                    so these characters won't be printed again
                **/

                Length = 0;

                /**
                    We only terminate this loop if we run out of chars
                    or we run out of read buffer.
                **/

            } while (pReadBuffer && pReadBuffer != pReadBufferEnd);

            /** Keep going until we get the last line **/

        } while (!ReadAll);

        if (EndPage(pData->hDC) == SP_ERROR) {

            bAbortDoc = TRUE;
            goto Done;
        }

        /**
            Close the printer - we open/close the printer for each
            copy so the data pointer will rewind.
        **/

        ClosePrinter(hPrinter);
        hPrinter = NULL;

    } /* While copies to print */

    /** Let the printer know that we are done printing **/

    EndDoc(pData->hDC);

    ReturnValue = TRUE;

Done:

    if (dwTransparent)
        SetBkMode( pData->hDC, iBkMode  );

    if (hPrinter)
        ClosePrinter(hPrinter);

    if (bAbortDoc)
        AbortDoc(pData->hDC);

    if (pLineBuffer)
        FreeSplMem(pLineBuffer);

    if (hOldFont)
    {
        SelectObject(pData->hDC, hOldFont);
        DeleteObject(hFont);
    }

    if (ReadBufferStart) 
    {
        FreeSplMem(ReadBufferStart);
    }

    return ReturnValue;
}
Ejemplo n.º 26
0
BOOL
EnumGeneric(
    IN  PROC    fnEnum,
    IN  DWORD   Level,
    IN  PBYTE   *ppEnumData,
    IN  DWORD   cbBuf,
    OUT LPDWORD pcbReturned,
    OUT LPDWORD pcReturned,
    IN  PVOID   Arg1,
    IN  PVOID   Arg2,
    IN  PVOID   Arg3 )
{
    BOOL   rc;
    BOOL   UnknownFunction = FALSE;
    DWORD  cbRealloc;

    if( fnEnum == (PROC)EnumPrinters )
        rc = EnumPrinters( (DWORD)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
                           // Flags        Name
    else if( fnEnum == (PROC)EnumJobs )
        rc = EnumJobs( (HANDLE)Arg1, (DWORD)Arg2, (DWORD)Arg3, COMMON_ARGS );
                       // hPrinter      FirstJob     NoJobs
    else if( fnEnum == (PROC)EnumPrinterDrivers )
        rc = EnumPrinterDrivers( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
                                 // pName        pEnvironment
    else if( fnEnum == (PROC)EnumForms )
        rc = EnumForms( (HANDLE)Arg1, COMMON_ARGS );
                        // hPrinter
    else if( fnEnum == (PROC)EnumMonitors )
        rc = EnumMonitors( (LPTSTR)Arg1, COMMON_ARGS );
                           // pName
    else if( fnEnum == (PROC)EnumPorts )
        rc = EnumPorts( (LPTSTR)Arg1, COMMON_ARGS );
                        // pName
    else if( fnEnum == (PROC)EnumPrintProcessors )
        rc = EnumPrintProcessors( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
                                  // pName        pEnvironment
    else if( fnEnum == (PROC)EnumPrintProcessorDatatypes )
        rc = EnumPrintProcessorDatatypes( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
                                          // pName        pPrintProcessorName
    else
    {
        *ppEnumData = NULL;
        UnknownFunction = TRUE;

        DBGMSG( DBG_ERROR, ( "EnumGeneric called with unknown function\n" ) );

        rc = FALSE;
    }


    if( ( rc == FALSE ) && ( UnknownFunction == FALSE ) )
    {
        if( GetLastError( ) == ERROR_INSUFFICIENT_BUFFER )
        {
            cbRealloc = *pcbReturned;

            DBGMSG( DBG_TRACE, ( "EnumGeneric: Reallocating %d (0x%x) bytes @%08x\n",
                                 cbBuf, cbBuf, *ppEnumData ) );

            if( cbBuf == 0 )
                *ppEnumData = AllocSplMem( cbRealloc );
            else
                *ppEnumData = ReallocSplMem( *ppEnumData, cbRealloc );

            cbBuf = cbRealloc;

            if( *ppEnumData )
            {
                DBGMSG( DBG_TRACE, ( "EnumGeneric: %d (0x%x) bytes reallocated @%08x\n",
                                     cbBuf, cbBuf, *ppEnumData ) );

             if( fnEnum == (PROC)EnumPrinters )
                    rc = EnumPrinters( (DWORD)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
                                       // Flags        Name
             else if( fnEnum == (PROC)EnumJobs )
                    rc = EnumJobs( (HANDLE)Arg1, (DWORD)Arg2, (DWORD)Arg3, COMMON_ARGS );
                                   // hPrinter      FirstJob     NoJobs
                else if( fnEnum == (PROC)EnumPrinterDrivers )
                    rc = EnumPrinterDrivers( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
                                             // pName        pEnvironment
                else if( fnEnum == (PROC)EnumForms )
                    rc = EnumForms( (HANDLE)Arg1, COMMON_ARGS );
                                    // hPrinter
                else if( fnEnum == (PROC)EnumMonitors )
                    rc = EnumMonitors( (LPTSTR)Arg1, COMMON_ARGS );
                                       // pName
                else if( fnEnum == (PROC)EnumPorts )
                    rc = EnumPorts( (LPTSTR)Arg1, COMMON_ARGS );
                                    // pName
                else if( fnEnum == (PROC)EnumPrintProcessors )
                    rc = EnumPrintProcessors( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
                                              // pName        pEnvironment
                else if( fnEnum == (PROC)EnumPrintProcessorDatatypes )
                    rc = EnumPrintProcessorDatatypes( (LPTSTR)Arg1, (LPTSTR)Arg2, COMMON_ARGS );
                                                      // pName        pPrintProcessorName

                /* If things haven't worked out, free up the buffer.
                 * We do this because otherwise the caller will not know
                 * whether the pointer is valid any more,
                 * since ReallocSplMem might have failed.
                 */
                if( rc == FALSE )
                {
                    if( *ppEnumData )
                        FreeSplMem( *ppEnumData );
                    *ppEnumData = NULL;
                    *pcbReturned = 0;
                    *pcReturned = 0;
                }

                /* Don't rely on pcbReturned having the same value
                 * that was passed in:
                 */
                else
                    *pcbReturned = cbRealloc;
            }
        }

        else
        {
            if( *ppEnumData )
                FreeSplMem( *ppEnumData );
            *ppEnumData = NULL;
            *pcbReturned = 0;
            *pcReturned = 0;
            rc = FALSE;
        }
    }

    else
        *pcbReturned = cbBuf;

    return rc;
}
Ejemplo n.º 27
0
PINIPORT
CreatePortEntry(
    __in    LPTSTR  pszPortName
    )
/*++

Routine Description:
    Creates a IniPort entry for a port. Needs to be called inside monitor
    critical section.

Arguments:
    pszPortName       : Name of the port

Return Value:
      On success pointer to the IniPort stucture.
      On failure NULL

--*/
{
    PINIPORT    pIniPort    = NULL;
    HANDLE      DoneWriting = NULL;
    HANDLE      DoneReading = NULL;
    HANDLE      WakeUp      = NULL;
    LPWSTR      pszString   = NULL;

    SplInSem();


    DoneWriting = CreateEvent(NULL, FALSE, TRUE, NULL);
    if (!DoneWriting)
    {
        goto Fail;
    }

    WakeUp = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!WakeUp)
    {
        goto Fail;
    }
    //
    // manual-reset event, initially signal state
    //
    DoneReading = CreateEvent(NULL, TRUE, TRUE, NULL);
    if (!DoneReading)
    {
        goto Fail;
    }
    pIniPort = (PINIPORT) AllocSplMem(sizeof(*pIniPort));
    if (!pIniPort)
    {
        goto Fail;
    }
    pszString = AllocSplStr(pszPortName);
    if (!pszString)
    {
        goto Fail;
    }
    pIniPort->pNext         = NULL;
    pIniPort->signature     = PJ_SIGNATURE;
    pIniPort->DoneWriting   = DoneWriting;
    pIniPort->DoneReading   = DoneReading;
    pIniPort->WakeUp        = WakeUp;
    pIniPort->hUstatusThread= NULL;
    pIniPort->pszPortName   = pszString;

    pIniPort->pNext         = pIniFirstPort;
    pIniFirstPort           = pIniPort;
    return pIniPort;

Fail:
    if (DoneWriting)
    {
        CloseHandle (DoneWriting);
    }
    if (DoneReading)
    {
        CloseHandle (DoneReading);
    }
    if (WakeUp)
    {
        CloseHandle (WakeUp);
    }
    FreeSplMem (pszString);
    FreeSplMem (pIniPort);
    return NULL;
}
Ejemplo n.º 28
0
LPBYTE
CopyIniPortToPort(
    PINIPORT pIniPort,
    DWORD   Level,
    LPBYTE  pPortInfo,
    LPBYTE   pEnd
)
{
    LPWSTR         *SourceStrings,  *pSourceStrings;
    PPORT_INFO_2    pPort2 = (PPORT_INFO_2)pPortInfo;
    WCHAR           szLocalMonitor[MAX_PATH+1], szPortDesc[MAX_PATH+1];
    DWORD          *pOffsets;
    DWORD           Count;

    switch (Level) {

    case 1:
        pOffsets = PortInfo1Strings;
        break;

    case 2:
        pOffsets = PortInfo2Strings;
        break;

    default:
        DBGMSG(DBG_ERROR,
               ("CopyIniPortToPort: invalid level %d", Level));
        return NULL;
    }

    for ( Count = 0 ; pOffsets[Count] != -1 ; ++Count ) {
    }

    SourceStrings = pSourceStrings = AllocSplMem(Count * sizeof(LPWSTR));

    if ( !SourceStrings ) {

        DBGMSG( DBG_WARNING, ("Failed to alloc port source strings.\n"));
        return NULL;
    }

    switch (Level) {

    case 1:
        *pSourceStrings++=pIniPort->pName;

        break;

    case 2:
        *pSourceStrings++=pIniPort->pName;

        LoadString(hInst, IDS_LOCALMONITORNAME, szLocalMonitor, sizeof(szLocalMonitor)-1);
        LoadString(hInst, IDS_LOCALMONITOR, szPortDesc, sizeof(szPortDesc)-1);
        *pSourceStrings++ = szLocalMonitor;
        *pSourceStrings++ = szPortDesc;

        // How do i findout other types ???
        pPort2->fPortType = PORT_TYPE_WRITE;

        // Reserved
        pPort2->Reserved = 0;



        break;

    default:
        DBGMSG(DBG_ERROR,
               ("CopyIniPortToPort: invalid level %d", Level));
        return NULL;
    }

    pEnd = PackStrings(SourceStrings, pPortInfo, pOffsets, pEnd);
    FreeSplMem(SourceStrings);

    return pEnd;
}
Ejemplo n.º 29
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;
}