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

📄 printqueue.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    for(it = PrintJobList.begin(); it != itEnd; ++it) {
        (*it)->ShutDown();
    }   
}


HRESULT 
SMBPrintQueue::FindPrintJob(USHORT Fid, PrintJob **pPrintJob)
{
    CCritSection csLock(&csJobListLock);
    csLock.Lock();
    
    //
    // Loop through all active jobs
    ce::list<PrintJob *, PRINTJOB_LIST_ALLOC >::iterator it;
    ce::list<PrintJob *, PRINTJOB_LIST_ALLOC >::iterator itEnd = PrintJobList.end();
        
    *pPrintJob = NULL;
    for(it = PrintJobList.begin(); it != itEnd; ++it) {
        if(Fid == (*it)->JobID()) {
            *pPrintJob = *it;
        }
    } 
    
    if(NULL != *pPrintJob) {
        (*pPrintJob)->AddRef();
        return S_OK;
    }    
    else
        return E_FAIL;
}


//
// NOTE: THIS IS ONLY TO BE CALLED BY THE PrintJob DESTRUCTOR!!!
//
HRESULT 
SMBPrintQueue::RemovePrintJob(PrintJob *pPrintJob)
{
    CCritSection csLock(&csJobListLock);
    csLock.Lock();
    HRESULT hr = E_FAIL;
    
    //
    // Loop through all active jobs
    ce::list<PrintJob *, PRINTJOB_LIST_ALLOC >::iterator it;
    ce::list<PrintJob *, PRINTJOB_LIST_ALLOC >::iterator itEnd = PrintJobList.end();
       
    for(it = PrintJobList.begin(); it != itEnd; ++it) {
        if(pPrintJob == (*it)) {
            PrintJobList.erase(it++);
            hr = S_OK;
            break;
        }
    } 
    return hr;
}




HRESULT 
SMBPrintQueue::JobsFinished(PrintJob *pPrintJob)
{   
    TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV: printqueue -- closing spool for job %d", pPrintJob->JobID()));

    //
    // Here we set its status to finished... 
    if(pPrintJob) {
        pPrintJob->SetInternalStatus(pPrintJob->GetInternalStatus() | JOB_STATUS_FINISHED);
    }
    return S_OK;    
}


/*
 *
 *  Print Job class information
 *
 */ 
PrintJob::PrintJob(Share *_pMyShare, USHORT usFID) : 
    m_pMyShare(_pMyShare)
{    
    m_fShutDown = FALSE;
    m_lRefCnt = 1;
    m_uiBytesWritten = 0;
    m_WakeUpThereIsData = CreateEvent(NULL, FALSE, FALSE, NULL);
    
    
    InitializeCriticalSection(&m_csRingBuffer);
    InitializeCriticalSection(&m_csMainLock);

    m_usJobID = usFID;
    
    this->SetInternalStatus(JOB_STATUS_UNKNOWN);
        
    //
    // Write down the start time (format per spec in cirsprt.doc)
    m_ulStartTime = SecSinceJan1970_0_0_0();
    
    //
    // Add ourselves to our print queue
    SMBPrintQueue *pMyQueue = NULL;
    if(m_pMyShare) {
        pMyQueue = m_pMyShare->GetPrintQueue();
    }
    ASSERT(NULL != pMyQueue);
    
    if(pMyQueue) {
        pMyQueue->AddJobToSpool(this);
    }       
}



PrintJob::~PrintJob()
{
    TRACEMSG(ZONE_PRINTQUEUE, (L"SMB-PRINT: Job:%d finished", JobID()));
    
    //
    // Remove the print job from our queue
    SMBPrintQueue *pMyQueue = NULL;
    if(m_pMyShare) {
        pMyQueue = m_pMyShare->GetPrintQueue();
    }
    ASSERT(NULL != pMyQueue);
    
    if(pMyQueue) {
        pMyQueue->RemovePrintJob(this);
    }    
    
    DeleteCriticalSection(&m_csRingBuffer);
    DeleteCriticalSection(&m_csMainLock);
    CloseHandle(m_WakeUpThereIsData);
}



VOID
PrintJob::SetInternalStatus(USHORT s)
{
    CCritSection csLock(&m_csMainLock);
    csLock.Lock();
    
    m_usJobInternalStatus = s; 
    TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV: PrintQUEUE -- setting internal status on job %d -- status=(0x%x)!", JobID(), s));
        
    IFDBG(if(s&JOB_STATUS_UNKNOWN)TRACEMSG(ZONE_PRINTQUEUE, (L"      Unknown")));
    IFDBG(if(s&JOB_STATUS_HAS_DATA)TRACEMSG(JOB_STATUS_HAS_DATA, (L"      Has Data")));
    IFDBG(if(s&JOB_STATUS_FINISHED)TRACEMSG(JOB_STATUS_FINISHED, (L"      Finished")));
    IFDBG(if(s&JOB_STATUS_FINISHED)TRACEMSG(JOB_STATUS_FINISHED, (L"      In Print Queue")));
    IFDBG(if(s&JOB_STATUS_ABORTED)TRACEMSG(JOB_STATUS_ABORTED, (L"      Aborted")));
    IFDBG(if(s&JOB_STATUS_PAUSED)TRACEMSG(JOB_STATUS_PAUSED, (L"      Paused")));

    //
    // If we have been aborted, purge out the ringbuffer (this will happen on delete etc)
    if(0 != (s&JOB_STATUS_ABORTED)) {
        CCritSection csRingLock(&m_csRingBuffer);
        csRingLock.Lock();
        m_QueuedData.Purge();
    }

    //if they set the finished bit, wake up the writer
    if(0 != (s & JOB_STATUS_FINISHED)) {
        TRACEMSG(ZONE_PRINTQUEUE, (L"....setting finished bit!"));
        SetEvent(m_WakeUpThereIsData);       
    }    
}

HRESULT 
PrintJob::SetComment(const WCHAR *_pComment)
{
    HRESULT hr;
    CCritSection csLock(&m_csMainLock);
    csLock.Lock();    
    
    if(FAILED(hr = m_Comment.Clear())) {
        return hr;
    }
    return m_Comment.append(_pComment);    
}

HRESULT
PrintJob::SetQueueName(const WCHAR *pName)
{
    HRESULT hr;
    CCritSection csLock(&m_csMainLock);
    csLock.Lock(); 
    
    if(FAILED(hr = m_QueueName.Clear())) {
        return hr;
    }
    return m_QueueName.append(pName);    
}

HRESULT
PrintJob::SetOwnerName(const WCHAR * pName)
{
    HRESULT hr;
    CCritSection csLock(&m_csMainLock);
    csLock.Lock();
    
    if(FAILED(hr = m_OwnerName.Clear())) {
        return hr;
    }
    return m_OwnerName.append(pName);
}


HRESULT 
PrintJob::Read(BYTE *pDest, UINT uiSize, UINT *pRead)
{
    HRESULT hr;
    BOOL fNeedToBlock = FALSE;
    
    CCritSection csLock(&m_csRingBuffer);
    csLock.Lock();
    *pRead = 0;
        
    //
    // if there isnt any data to read, we need to block until there is data
    if(0 == m_QueuedData.BytesReadyToRead() && 
       0 == (this->GetInternalStatus() & JOB_STATUS_FINISHED)) {
        csLock.UnLock();
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: print spool read()  going to block (queue size %d)", m_QueuedData.BytesReadyToRead()));  
        if(WAIT_FAILED == WaitForSingleObject(m_WakeUpThereIsData, INFINITE)) {
            TRACEMSG(ZONE_ERROR, (L"SMBSRV-PRINTQUEUE: error waiting for read event!!")); 
            ASSERT(FALSE);
            hr = E_UNEXPECTED;
            goto Done;
        }
        csLock.Lock();
    }
    ASSERT(csLock.IsLocked());
    TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: print spool read() has %d bytes in queue", m_QueuedData.BytesReadyToRead()));
    
    if(TRUE == this->m_fShutDown) {
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: we have been told to shut down... canceling the request"));
        return E_FAIL;
    }

    //
    // Do the actual Read()
    hr = m_QueuedData.Read(pDest, uiSize, pRead);
   
    Done:
        ASSERT(SUCCEEDED(hr));
        ASSERT(uiSize >= *pRead);
        return hr;
}

HRESULT
PrintJob::Write(const BYTE *pData, UINT uiSize, ULONG ulOffset, UINT *uiWritten)
{ 
    HRESULT hr = E_FAIL;
    BOOL fWakeupThreadOnExit = ((0==m_uiBytesWritten) && uiSize)?TRUE:FALSE;
#ifdef DEBUG
    UINT uiBytesBefore = 0;
    BOOL fBypassCountCheck = FALSE;
#endif  
    CCritSection csLock(&m_csRingBuffer);
    UINT uiWrittenInPass;
    if(NULL == pData || NULL == uiWritten) {
        hr = E_INVALIDARG;
        goto Done;
    }  
    *uiWritten = 0;    
    csLock.Lock();
    
    //
    // If the job has been ended, this means it was removed 
    //   by someone OTHER than the person writing!  this is okay, but we
    //   have to do something -- tell them its okay
    if(GetInternalStatus() & (JOB_STATUS_FINISHED | JOB_STATUS_ABORTED)) {
        TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINT: Job:%d has been closed, but TID is still valid (unclosed). -- just pretend that we wrote", JobID()));
        *uiWritten = uiSize;
        hr = S_OK;
#ifdef DEBUG
        fBypassCountCheck = TRUE;
#endif
        goto Done;
    }   
    
#ifdef DEBUG
    uiBytesBefore = this->BytesLeftInQueue();
#endif
    
    //
    // Loop writing data into the spool
    //
    // If this job ISNT in the queue and our buffer is less than a quarter full always return 0 bytes written
    //
    //
    // Here is the buffer layout
    // [JOBS NOT ON QUEUE %25][Job In Queue 55%][Job In Queue Delay buffer   20%]
    //     the delay buffer is to help compensate for slow/jammed printers (and only given to the job thats activly printing)
    //
    //
    // NOTE: this will make 9x clients quit their job, but the problem is if we dont do it
    // jobs not on the queue will starve the job trying to print (causing deadlock)
    if(FALSE == (GetInternalStatus() & JOB_STATUS_PRINTING) && 
        m_QueuedData.BytesRemaining() * 4 <= m_QueuedData.TotalBufferSize()) {
        TRACEMSG(ZONE_ERROR, (L"SMB_SRV: Buffer for job *NOT PRINTING* has gotten to %d of %d -- not writing!", m_QueuedData.BytesRemaining(), m_QueuedData.TotalBufferSize()));
        uiWrittenInPass = 0;
        hr = S_OK;
    } else {
        do {
            if(SUCCEEDED(hr = m_QueuedData.Write(pData, uiSize, &uiWrittenInPass))) {
                ASSERT(uiSize >= uiWrittenInPass);
                pData += uiWrittenInPass;
                uiSize -= uiWrittenInPass;
                *uiWritten = (*uiWritten) + uiWrittenInPass;  
                m_uiBytesWritten += uiWrittenInPass;
            } else {
                uiWrittenInPass = 0;
                hr = S_OK; //its okay if we didnt write,  this just means buffers were full
            }            
        } while(uiSize && uiWrittenInPass && SUCCEEDED(hr));
    }    
    Done:
        //
        // If we wrote data, wake up the reader
        if(0 != *uiWritten) {    
            TRACEMSG(ZONE_PRINTQUEUE, (L"SMBSRV-PRINTQUEUE: PRINTQUEUE -- writer() waking up reader() for JobID: %d", JobID()));
            TRACEMSG(ZONE_PRINTQUEUE, (L"   ...queue size is %d -- total written %d -- this pass %d\n", m_QueuedData.BytesReadyToRead(), m_uiBytesWritten, *uiWritten));
#ifdef PRINTQUEUE_BLOCK_WRITES            
            Sleep(PRINTQUEUE_MS_PER_KILOBYTE * (*uiWritten)  / 1024);            
#endif            
            SetEvent(m_WakeUpThereIsData);   
            
#ifdef DEBUG
        if(FALSE == fBypassCountCheck) {
            ASSERT(uiBytesBefore + *uiWritten == this->BytesLeftInQueue());
        }
#endif
        }   
        if(m_QueuedData.TotalBufferSize() - m_QueuedData.BytesReadyToRead() <= 1024*1024 ||
           (100 * m_QueuedData.BytesReadyToRead() / m_QueuedData.TotalBufferSize()) >= 80) {
                TRACEMSG(ZONE_ERROR, (L"SMB_SRV: Buffer size has gotten to %d of %d -- delaying packets", m_QueuedData.BytesReadyToRead(), m_QueuedData.TotalBufferSize()));

                // Free up the cracker
                Sleep(1000);
        }        
        return hr;
}


USHORT 
PrintJob::JobID() {
    CCritSection csLock(&m_csMainLock);
    csLock.Lock();
    return m_usJobID;
}

USHORT 
PrintJob::GetInternalStatus() {             
    CCritSection csLock(&m_csMainLock);
    csLock.Lock();
    return m_usJobInternalStatus; 
}

USHORT 
PrintJob::GetStatus() { //this function converts status code to be good for network 
    USHORT Status = GetInternalStatus();
    USHORT usRetStatus = 0;
    
    
    if( Status & JOB_STATUS_PAUSED)
       usRetStatus |= PRJ_QS_PAUSED;
    if( Status & JOB_STATUS_PRINTING)
       usRetStatus |= PRJ_QS_PRINTING;
    else   
       usRetStatus |= PRJ_QS_SPOOLING;
       
    return usRetStatus;
}

UINT 
PrintJob::BytesLeftInQueue() {
    CCritSection csLock(&m_csMainLock);
    csLock.Lock();
    return m_QueuedData.BytesReadyToRead();
}

const WCHAR *
PrintJob::GetQueueName() {
       return m_QueueName.GetString();
}

const WCHAR *
PrintJob::GetComment() {           
    return m_Comment.GetString(); 
}

const WCHAR *
PrintJob::GetOwnerName() {
    return m_OwnerName.GetString();
}


Share *
PrintJob::MyShare() {
    return m_pMyShare;
}

VOID 
PrintJob::Release() {
    if(0 == InterlockedDecrement(&m_lRefCnt)) {   
        delete this;
    }   
#ifdef DEBUG
    TRACEMSG(ZONE_PRINTQUEUE, (L"SMB_SRV: Release() for job %d to cnt %d", m_usJobID, m_lRefCnt));
#endif
}

VOID 
PrintJob::AddRef() {
    InterlockedIncrement(&m_lRefCnt);
    TRACEMSG(ZONE_PRINTQUEUE, (L"SMB_SRV: AddRef() for job %d to cnt %d", m_usJobID, m_lRefCnt));
}

VOID 
PrintJob::ShutDown() {
    ASSERT(!m_fShutDown);
    m_fShutDown = TRUE;
    SetEvent(m_WakeUpThereIsData);
}
    
UINT 
PrintJob::TotalBytesWritten() {
    return m_uiBytesWritten;
}

⌨️ 快捷键说明

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