⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printqueue.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include <windows.h>
#include <Winbase.h>
#include <CReg.hxx>

#include "SMB_Globals.h"
#include "PrintQueue.h"
#include "ShareInfo.h"
#include "SMBPackets.h"
#include "SMBErrors.h"
#include "ConnectionManager.h"
#include "Cracker.h"
#include "SMBCommands.h"




BOOL PrintQueue::fIsRunning = FALSE;

//blocking writes simulates a stalled printer (to test queue managment)
//#define PRINTQUEUE_BLOCK_WRITES // <-- uses PRINTQUEUE_MS_PER_BYTE (this slows the SMB)
//#define PRINTQUEUE_BLOCK_READS  // <-- uses PRINTQUEUE_MS_PER_BYTE (this slows the printing)
//#define PRINTQUEUE_USE_FILE 
//#define PRINTQUEUE_MS_SLEEP_TO_START_QUEUE 5000
//#define PRINTQUEUE_MS_PER_KILOBYTE 100

#define DEFAULT_SWAP_FILE L"\\Printer.swap"
#define DEFAULT_SWAP_MAX 2000000
#define DEFAULT_SWAP_INC 10000

ce::fixed_block_allocator<10>    SMB_Globals::g_PrintJobAllocator;



//
// Forward declare functions here
VOID FileTimeToDosDateTime(FILETIME * ft,WORD *ddate,WORD *dtime);
DWORD DosToNetTime(WORD time, WORD date);

DWORD 
PrintQueue::SMBSRV_SpoolThread(LPVOID lpvPrintQueue)
{
   UINT uiToBeWrittenSize = 20000;
   BYTE *pToBeWritten = new BYTE[uiToBeWrittenSize]; //BUGBUG: make this a const (and = to the block size)
   SMBPrintQueue *pPrintQueue = (SMBPrintQueue *)lpvPrintQueue;
   
   if(NULL == pPrintQueue) { 
        ASSERT(FALSE);
        goto Done;
   }   
   if(NULL == pToBeWritten) {
        goto Done;
   }
   for(;;)
   {        
        PrintJob *pPrintJob = NULL;
        HANDLE hPrinter = INVALID_HANDLE_VALUE;            
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: Waiting for new print job to enter the queue... ZZZzzzz"));
        
        if(pPrintQueue->ShuttingDown()) {
             TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: Shutting down -- stopping spool thread"));
             break;
        }   
    
        //
        // Get the next job (remember to Release() it!)   
        if(NULL == (pPrintJob = pPrintQueue->WaitForJobThatIsReady())) {            
            TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: we woke up but there isnt anything to print... maybe we were removing a dead job"));
            continue;
        }  
        
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: I'm up... I'm up... Got a job to start printing!"));
        
        
        //
        // See if the job has been aborted, if so kill it off
        if(pPrintJob->GetInternalStatus() & JOB_STATUS_ABORTED) {
            TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: this job was aborted... kill it off"));
             
            //
            //  Release our job, if there are no more refs to it, it will go away
            pPrintJob->Release();
            continue;
        }
        
#if defined (PRINTQUEUE_MS_SLEEP_TO_START_QUEUE)
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: going to sleep for %d ms to simulate slow printer?",PRINTQUEUE_MS_SLEEP_TO_START_QUEUE));
        Sleep(PRINTQUEUE_MS_SLEEP_TO_START_QUEUE);
#endif
        
#if !defined(PRINTQUEUE_USE_FILE) 
        //
        // Open up the parallel port       
        if(NULL == pPrintJob->MyShare()) 
        {
            TRACEMSG(ZONE_ERROR, (L"SMBSRV-PRINTQUEUE:  Error opening opening up share"));         
            goto Done;
        }
        if(INVALID_HANDLE_VALUE == (hPrinter = CreateFile(pPrintQueue->GetPortName(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,NULL)))
        //if(INVALID_HANDLE_VALUE == (hPrinter = CreateFile(L"myprinter.file", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,NULL)))
        {
            TRACEMSG(ZONE_ERROR, (L"SMBSRV-PRINTQUEUE:  Error opening printer on %s (err=%d)", pPrintQueue->GetPortName(), GetLastError()));           
            Sleep(5000); //BUGBUG: sleep for some reg configurable amount of time here
            
            //
            // Thump the queue 
            pPrintQueue->JobReadyForPrint(NULL);
            continue;
        }
#else        
        
        WCHAR TempFileName[MAX_PATH];
        GetTempFileName(L"\\", L"SMBSpool", 0, TempFileName);
        if(INVALID_HANDLE_VALUE == (hPrinter = CreateFile(TempFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL)))
        {
            TRACEMSG(ZONE_ERROR, (L"SMBSRV-PRINTQUEUE: Error opening printer on %s (err=%d)", pPrintQueue->GetPortName(), GetLastError()));           
            Sleep(5000); //BUGBUG: sleep for some reg configurable amount of time here
            
            //
            // Thump the queue 
            pPrintQueue->JobReadyForPrint(NULL);            
            continue;
        }
#endif      
        
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: Job:%d has started printing", pPrintJob->JobID()));
        
        //
        // Mark bit saying the job is printing
        pPrintJob->SetInternalStatus(pPrintJob->GetInternalStatus() | JOB_STATUS_PRINTING);        
        
        //
        // Loop while there is data
        UINT uiRead;
        UINT uiTotalRead = 0;
        BOOL fDontWrite = FALSE;
        HRESULT hr;
        while(SUCCEEDED(hr = pPrintJob->Read(pToBeWritten, uiToBeWrittenSize, &uiRead))) {
        
            if(0 == uiRead && 
               0 == pPrintJob->BytesLeftInQueue() && 
               (pPrintJob->GetInternalStatus() & JOB_STATUS_FINISHED)) {
                TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: nothing left to read -- we are done, close up"));
                break;
            }
            uiTotalRead += uiRead;
            
            //
            // Write back to printer
            BYTE *pToWrite = pToBeWritten;
            while(uiRead) {
                DWORD dwWritten;
                if(FALSE == fDontWrite && 0 == WriteFile(hPrinter, pToWrite, uiRead, &dwWritten, NULL)) 
                {
                    TRACEMSG(ZONE_ERROR, (L"SMBSRV-PRINTQUEUE:  Error writing to printer! (err=%d)", GetLastError()));
                    ASSERT(FALSE);
                    fDontWrite = TRUE;
                } else if(TRUE == fDontWrite) {
                    TRACEMSG(ZONE_ERROR, (L"SMBSRV-PRINTQUEUE:  MAJOR Error writing to printer! (err=%d) - lying to flush buffers!", GetLastError()));
                    dwWritten = uiRead;
                }
#if defined(PRINTQUEUE_BLOCK_READS) && defined(DEBUG)  
                Sleep(PRINTQUEUE_MS_PER_KILOBYTE * dwWritten / 1024);
#endif

                TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: Just Sent %d bytes to printer", dwWritten));
                pToWrite += dwWritten;
                uiRead -= dwWritten;
           }
        }
        

        //
        // Mark the job saying we are done with it
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: Finished print job... closing handle and going to sleep (%d bytes read/written for job)", uiTotalRead));  
        pPrintJob->SetInternalStatus(pPrintJob->GetInternalStatus() | JOB_STATUS_PRINTED);
        pPrintJob->SetInternalStatus(pPrintJob->GetInternalStatus() & (~JOB_STATUS_PRINTING));
        pPrintJob->Release();
        //
        // Close up shop
        CloseHandle(hPrinter);
        hPrinter = INVALID_HANDLE_VALUE;        
        
#if defined (PRINTQUEUE_USE_FILE)
        //
        // If we are spooling to file, delete the file
        DeleteFile(TempFileName);
#endif
   }
   
 
#if !defined(PRINTQUEUE_USE_FILE)       
   Done:    
#endif   
   
    //
    // We need to go and release all jobs that are ours. do this by marking them
    //   invalid, and releasing them
    {  
        PrintJob *pPrintJob = NULL;        
        while(NULL != (pPrintJob = pPrintQueue->GetJobNextJobThatIsReady())) { 
            pPrintJob->SetInternalStatus(pPrintJob->GetInternalStatus() | JOB_STATUS_PRINTED);
            pPrintJob->SetInternalStatus(pPrintJob->GetInternalStatus() & (~JOB_STATUS_PRINTING));        
            pPrintJob->Release(); 
        }  
    }

    if(NULL != pToBeWritten) {
        delete [] pToBeWritten;
    }
    return 0;
}




HRESULT StartPrintSpool()
{
    CReg RegPrinter;
    HRESULT hr = E_FAIL;
    WCHAR SwapFile[MAX_PATH];
    UINT uiMax, uiInc;


    //
    // Load the CName from the registry
    if(FALSE == RegPrinter.Open(HKEY_LOCAL_MACHINE, L"Services\\SMBServer")) {  
        swprintf(SwapFile, DEFAULT_SWAP_FILE);
        uiMax = DEFAULT_SWAP_MAX;
        uiInc = DEFAULT_SWAP_INC;
    } else {
        if(FALSE == RegPrinter.ValueSZ(L"PrintSwapFile", SwapFile, MAX_PATH/sizeof(WCHAR))) {
            swprintf(SwapFile, DEFAULT_SWAP_FILE);
        }
        uiMax = RegPrinter.ValueDW(L"PrintSwapMax", DEFAULT_SWAP_MAX);
        uiInc = RegPrinter.ValueDW(L"PrintSwapInc", DEFAULT_SWAP_INC);
    }

    TRACEMSG(ZONE_PRINTQUEUE, (L"SMB_PRINT:  Configuring swap file."));
    TRACEMSG(ZONE_PRINTQUEUE, (L"            File: %s", SwapFile));
    TRACEMSG(ZONE_PRINTQUEUE, (L"            Max : %d", uiMax));
    TRACEMSG(ZONE_PRINTQUEUE, (L"            Inc : %d", uiInc));


    //
    // Fire up our swap memory
    if(FAILED(hr = SMB_Globals::g_PrinterMemMapBuffers.Open(SwapFile, uiMax, uiInc))) {
        TRACEMSG(ZONE_ERROR, (L"SMB_PRINT: Error Opening memory map! -- cant continue"));
        goto Done;
    }
    ASSERT(FALSE == PrintQueue::fIsRunning);   
    PrintQueue::fIsRunning = TRUE;

    Done:
        return hr;
}


HRESULT StopPrintSpool()
{
    HRESULT hr = E_FAIL;   
    UINT i, uiNumShares; 
    //
    // Verify incoming params
    if(FALSE == PrintQueue::fIsRunning) {        
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE:  stopping print spool not required since it never started!"));
        hr = S_OK;
        goto Done;
    }
        
    //
    // At this point we know that no new shares are going to be ENTERED
    //   so its okay to enumerate through them killing off jobs  
    uiNumShares = SMB_Globals::g_pShareManager->NumShares();
    for(i=0; i<uiNumShares; i++) {
        Share         *pShare = SMB_Globals::g_pShareManager->SearchForShare(i);
        SMBPrintQueue *pQueue;
        if(NULL != pShare && NULL!=(pQueue = pShare->GetPrintQueue())){
            //    
            // Tap the event saying there is a job ready (this is a lie, but 
            //   the thread will check to see if its supposed to shutdown so its 
            //   okay (it saves an event)
            pQueue->SetShutDown(TRUE);
            pQueue->StopAllJobs();
            pQueue->JobReadyForPrint(NULL);
        }
    }    
           
    hr = S_OK;
    ASSERT(TRUE == PrintQueue::fIsRunning);  

    Done:
        if(SUCCEEDED(hr)) {              
             PrintQueue::fIsRunning = FALSE;
        }    
        return hr;
}


HRESULT SetString(CHAR **pOldString, const CHAR *pNewString)
{
    HRESULT hr;
    UINT uiLen;
    CHAR *pTemp;
    
    //verify incoming params
    if(NULL == pNewString) {
        hr = E_INVALIDARG;
        goto Done;
    }
    
    //make a new memory buffer for the name
    uiLen = strlen(pNewString) + 1;
    pTemp = new CHAR[uiLen];
    
    //if we are out of memory return
    if(NULL == pTemp) {
        hr = E_OUTOFMEMORY;
        goto Done;
    }
 
    //delete old memory and replace with new
    if(*pOldString)
        delete [] *pOldString;
    *pOldString = pTemp;
    
    //do the copy
    memcpy(*pOldString, pNewString, uiLen);  
    hr = S_OK;
    Done:
        return hr;
}



SMBPrintQueue::SMBPrintQueue()
{
    Priority = 0;
    StartTime = 0;
    UntilTime = 0;
    Pad1 = 0;
    pSepFile = 0;
    pPrProc = 0;
    pParams = 0;
    pComment = 0;
    Status = 0;
    cJobs = 0;
    pPrinters = 0;
    pDriverName = 0;
    pDriverData = 0;
    pName = 0;  
    wPortName = 0;
    fShutDown = FALSE;
    
    ReadyToPrintSemaphore = NULL;
   
    InitializeCriticalSection(&csJobListLock);
    
    //
    // Fire up the spool semaphore
    ReadyToPrintSemaphore = CreateSemaphore(NULL, 0, SMB_Globals::g_uiMaxJobsInPrintQueue ,NULL);
    
    //
    // Spin the print spool thread (this thread does the actual printing 
    //   MUST Be last for error handling
    if(NULL == (PrintThreadHandle = CreateThread(NULL, 0, PrintQueue::SMBSRV_SpoolThread, (VOID*)this, 0, NULL))) {
        TRACEMSG(ZONE_ERROR, (L"SSMBSRV-PRINTQUEUE: cant make spool thread"));
    }
}

SMBPrintQueue::~SMBPrintQueue()
{      
    //    
    // Tap the event saying there is a job ready (this is a lie, but 
    //   the thread will check to see if its supposed to shutdown so its 
    //   okay (it saves an event)
    this->SetShutDown(TRUE);
    this->StopAllJobs();
    this->JobReadyForPrint(NULL);
    
    
    //
    // Now block for the print thread to stop
    if(WAIT_FAILED == WaitForSingleObject(PrintThreadHandle, INFINITE)) {
        TRACEMSG(ZONE_INIT, (L"SMBSRV-PRINTQUEUE: Waiting for spool thread FAILED!"));
        ASSERT(FALSE);
    } 

    //
    // Destroy all members
    if(pName)
        delete [] pName;
    if(pSepFile)
        delete [] pSepFile;
    if(pPrProc)
        delete [] pPrProc;
    if(pParams)
        delete [] pParams;
    if(pComment)
        delete [] pComment;
    if(pPrinters)
        delete [] pPrinters;
    if(pDriverName)
        delete [] pDriverName;
    if(pDriverData)
        delete [] pDriverData;
    if(wPortName)
        delete [] wPortName;
 
    //
    // Clean up memory    
    DeleteCriticalSection(&csJobListLock);   
    CloseHandle(ReadyToPrintSemaphore);
    CloseHandle(PrintThreadHandle);
    ReadyToPrintSemaphore = INVALID_HANDLE_VALUE;
    PrintThreadHandle = INVALID_HANDLE_VALUE;

    ASSERT(INVALID_HANDLE_VALUE == PrintThreadHandle);
    ASSERT(0 == PrintJobList.size());
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -