📄 printqueue.cpp
字号:
ULONG
PrintJob::GetStartTime()
{
return m_ulStartTime;
}
DWORD PrintQueue::SMB_Com_Open_Spool(SMB_PACKET *pSMB,
SMB_PROCESS_CMD *_pRawRequest,
SMB_PROCESS_CMD *_pRawResponse,
UINT *puiUsed)
{
DWORD dwRet = 0;
SMB_OPEN_PRINT_SPOOL_CLIENT_REQUEST *pRequest =
(SMB_OPEN_PRINT_SPOOL_CLIENT_REQUEST *)_pRawRequest->pDataPortion;
SMB_OPEN_PRINT_SPOOL_SERVER_RESPONSE *pResponse =
(SMB_OPEN_PRINT_SPOOL_SERVER_RESPONSE *)_pRawResponse->pDataPortion;
StringTokenizer RequestTokenizer;
ce::smart_ptr<TIDState> pTIDState = NULL;
SMBPrintQueue *pPrintQueue;
USHORT usQueueID;
PrintJob *pNewJob = NULL;
SMBFileStream *pPrintStream = NULL;
ce::smart_ptr<ActiveConnection> pMyConnection = NULL;
//
// Find our connection state
if(!(pMyConnection = SMB_Globals::g_pConnectionManager->FindConnection(pSMB))) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV: SMB_INFO_ALLOCATION: -- cant find connection 0x%x!", pSMB->ulConnectionID));
ASSERT(FALSE);
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Verify that we have enough memory
if(_pRawRequest->uiDataSize < sizeof(SMB_OPEN_PRINT_SPOOL_CLIENT_REQUEST)) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool -- not enough memory for request!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
if(_pRawResponse->uiDataSize < sizeof(SMB_OPEN_PRINT_SPOOL_SERVER_RESPONSE)) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool -- not enough memory for response!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
if(pRequest->SpoolMode != 1) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool -- we dont support TextMode"));
ASSERT(FALSE);
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Find a share state
if(FAILED(pMyConnection->FindTIDState(_pRawRequest->pSMBHeader->Tid, pTIDState, SEC_READ)) || !pTIDState) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool -- couldnt find share state!!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Make sure this is actually a print queue
if(!pTIDState ||
!pTIDState->GetShare () ||
!pTIDState->GetShare()->GetPrintQueue()) {
ASSERT(FALSE);
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool -- the Tid is for a file -- we only do print!!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Fetch the queue
if(NULL == (pPrintQueue = pTIDState->GetShare()->GetPrintQueue())) {
ASSERT(FALSE);
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool -- we didnt get a print queue back!!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Create a file stream
if(NULL == (pPrintStream = pTIDState->CreateFileStream(pMyConnection))) {
TRACEMSG(ZONE_FILES, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool-- error getting Print Stream"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Create a new print job
if(NULL == (pNewJob = new PrintJob(pTIDState->GetShare(), pPrintStream->FID()))) {
TRACEMSG(ZONE_FILES, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool-- error getting creating print job"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Set our username
if(FAILED(pNewJob->SetOwnerName(pMyConnection->UserName()))) {
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Create a new PrintStream and then add the job to TIDState
if(NULL == (pPrintStream = new PrintStream(pNewJob,pTIDState))) {
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
if(FAILED(pTIDState->AddFileStream(pPrintStream))) {
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Init then fetch the file name from the request tokenizer
RequestTokenizer.Reset((BYTE*)(pRequest+1), _pRawRequest->uiDataSize - sizeof(SMB_OPEN_PRINT_SPOOL_CLIENT_REQUEST));
if(FALSE == pMyConnection->SupportsUnicode(pSMB->pInSMB)) {
CHAR *pRequestedFile;
if(FAILED(RequestTokenizer.GetString(&pRequestedFile)) || 0x04 != pRequestedFile[0]) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool -- error getting file name"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
// the +1 on field is to advance beyond the string id
if(FAILED(pNewJob->SetQueueName(StringConverter(pRequestedFile+1).GetString()))) {
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
} else {
WCHAR *pRequestedFile;
if(FAILED(RequestTokenizer.GetUnicodeString(&pRequestedFile))) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Open_Spool -- error getting file name"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
// the +1 on field is to advance beyond the string id
if(FAILED(pNewJob->SetQueueName(pRequestedFile))) {
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
}
//
// Set the job ID
if(0xFFFF == (usQueueID = pNewJob->JobID())) {
ASSERT(FALSE);
TRACEMSG(ZONE_ERROR, (L"PRINT QUEUE ERROR!: got an invalid job ID!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Fill out return params and send back the data
pResponse->ByteCount = 0;
pResponse->FileID = usQueueID;
pResponse->WordCount = (sizeof(SMB_OPEN_PRINT_SPOOL_SERVER_RESPONSE) - 1) / sizeof(WORD);
*puiUsed = sizeof(SMB_OPEN_PRINT_SPOOL_SERVER_RESPONSE);
Done:
//
// Give back our handle
if(pNewJob) {
pNewJob->Release();
pNewJob = 0;
}
if(0 != dwRet) {
if(pPrintStream) {
delete pPrintStream;
}
}
return dwRet;
}
DWORD PrintQueue::SMB_Com_Close_Spool(SMB_PROCESS_CMD *_pRawRequest,
SMB_PROCESS_CMD *_pRawResponse,
UINT *puiUsed,
SMB_PACKET *pSMB)
{
DWORD dwRet = 0;
SMB_CLOSE_PRINT_SPOOL_CLIENT_REQUEST *pRequest =
(SMB_CLOSE_PRINT_SPOOL_CLIENT_REQUEST *)_pRawRequest->pDataPortion;
SMB_CLOSE_PRINT_SPOOL_SERVER_RESPONSE *pResponse =
(SMB_CLOSE_PRINT_SPOOL_SERVER_RESPONSE *)_pRawResponse->pDataPortion;
StringTokenizer RequestTokenizer;
ce::smart_ptr<TIDState> pTIDState = NULL;
ce::smart_ptr<ActiveConnection> pMyConnection = NULL;
//
// Verify that we have enough memory
if(_pRawRequest->uiDataSize < sizeof(SMB_CLOSE_PRINT_SPOOL_CLIENT_REQUEST)) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Close_Spool -- not enough memory for request!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
if(_pRawResponse->uiDataSize < sizeof(SMB_CLOSE_PRINT_SPOOL_SERVER_RESPONSE)) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Close_Spool -- not enough memory for response!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Find our connection state
if(!(pMyConnection = SMB_Globals::g_pConnectionManager->FindConnection(pSMB))) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV: SMB_INFO_ALLOCATION: -- cant find connection 0x%x!", pSMB->ulConnectionID));
ASSERT(FALSE);
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Find a TID state
if(FAILED(pMyConnection->FindTIDState(_pRawRequest->pSMBHeader->Tid, pTIDState, SEC_READ)) || !pTIDState) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Close_Spool -- couldnt find share state!!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Close it up
if(FAILED(pTIDState->Close(pRequest->FileID))) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Close_Spool -- closing the job failed!!!"));
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Remove the share from the TIDState (to prevent it from being aborted
// if the connection goes down)
if(FAILED(pTIDState->RemoveFileStream(pRequest->FileID))) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_Com_Close -- couldnt find filestream for FID(%d) to remove from share state!", pRequest->FileID));
ASSERT(FALSE);
dwRet = ERROR_CODE(STATUS_INTERNAL_ERROR);
goto Done;
}
//
// Fill out return params and send back the data
pResponse->ByteCount = 0;
pResponse->WordCount = 0;
*puiUsed = sizeof(SMB_CLOSE_PRINT_SPOOL_SERVER_RESPONSE);
Done:
return dwRet;
}
PrintStream::PrintStream(PrintJob *_pJob,
TIDState *_pMyState) : SMBFileStream(PRINT_STREAM, _pMyState)
{
//
// For a print stream, the FID is the same as the JobID (see the code
// for PrintJob to see that it uses the global FID list for its JobID)
this->SetFID(_pJob->JobID());
//
// PrintJob is something thats ref counted (the print queue owns a copy
// too). So Addref it. it will be released in the deconstructor
pPrintJob = _pJob;
if(pPrintJob)
pPrintJob->AddRef();
}
PrintStream::~PrintStream()
{
//
// Destroy the print job if it hasnt already been aborted or hasnt finished
if(pPrintJob &&
(0 == (pPrintJob->GetInternalStatus() & (JOB_STATUS_FINISHED | JOB_STATUS_ABORTED)))) {
PrintJob *pFoundPrintJob = NULL;
SMBPrintQueue *pPrintQueue = NULL;
TRACEMSG(ZONE_ERROR, (L"remove printjob %d to TIDState:0x%x because of delete of holder\n", pPrintJob->JobID(), (UINT)this));
if(FAILED(SMB_Globals::g_pShareManager->SearchForPrintJob(pPrintJob->JobID(), &pFoundPrintJob, &pPrintQueue)) ||
NULL == pFoundPrintJob ||
NULL == pPrintQueue)
{
TRACEMSG(ZONE_ERROR, (L"SMBSRV: ~TIDState -- couldnt find print job %d, maybe the job was deleted?", pPrintJob->JobID()));
goto Done;
}
ASSERT(pFoundPrintJob == pPrintJob);
//
// Set its abort logic
// NOTE: I dont set finished here because JobsFinished does
// and thats the proper way to get the FINISHED bit set
pFoundPrintJob->SetInternalStatus(pFoundPrintJob->GetInternalStatus() |
JOB_STATUS_ABORTED);
//
// Kill off the job
pFoundPrintJob->ShutDown();
//
// Remove it from the spool
if(FAILED(pPrintQueue->JobsFinished(pFoundPrintJob))) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV: ~TIDState -- delete the print job from the queue FID(%d)!", pPrintJob->JobID()));
ASSERT(FALSE);
}
if(NULL != pFoundPrintJob) {
pPrintJob->Release();
}
}
Done:
//
// Release our ref count on the job
if(pPrintJob)
pPrintJob->Release();
}
HRESULT
PrintStream::Read(BYTE *pDest, DWORD dwOffset, DWORD dwReqSize, DWORD *pdwRead)
{
ASSERT(FALSE);
return E_NOTIMPL;
}
HRESULT
PrintStream::Write(BYTE *pSrc, DWORD dwOffset, DWORD dwReqSize, DWORD *pdwWritten)
{
//BUGBUG: make these line up (DWORD and UINT)
UINT uiWritten;
//
// If the job hasnt been sent to the queue, send it now
if(0 == (pPrintJob->GetInternalStatus() & JOB_STATUS_HAS_DATA)) {
SMBPrintQueue *pMyQueue = NULL;
pPrintJob->SetInternalStatus(pPrintJob->GetInternalStatus() | JOB_STATUS_HAS_DATA);
if(pPrintJob->MyShare()) {
pMyQueue = pPrintJob->MyShare()->GetPrintQueue();
pMyQueue->JobReadyForPrint(pPrintJob);
} else {
ASSERT(FALSE);
}
}
HRESULT hr = pPrintJob->Write(pSrc, dwReqSize, dwOffset, &uiWritten);
*pdwWritten = uiWritten;
return hr;
}
HRESULT
PrintStream::Open(const WCHAR *pFileName,
DWORD dwAccess,
DWORD dwDisposition,
DWORD dwAttributes,
DWORD dwShareMode,
DWORD *pdwActionTaken,
SMBFile_OpLock_PassStruct *pdwOpLock)
{
HRESULT hr = E_FAIL;
SMBPrintQueue *pPrintQueue = NULL;
//
// If the request is for anything but NULL, fail it
if(NULL == pFileName || NULL != pFileName[0]) {
TRACEMSG(ZONE_ERROR, (L"SMBSRV-CRACKER: SMB_OpenX Printer -- error filename!"));
hr = E_ACCESSDENIED;
goto Done;
}
if(NULL == pPrintJob->MyShare() || NULL == (pPrintQueue = pPrintJob->MyShare()->GetPrintQueue())) {
hr = E_ACCESSDENIED;
goto Done;
}
if(FAILED(pPrintJob->SetQueueName(pFileName))) {
hr = E_FAIL;
goto Done;
}
hr = S_OK;
//
// if we were able to open the file, always say its 2 (2=file didnt exist and was created)
if(NULL != pdwActionTaken) {
*pdwActionTaken = 2;
}
Done:
return hr;
}
HRESULT
PrintStream::Close()
{
SMBPrintQueue *pPrintQueue = NULL;
HRESULT hr = E_FAIL;
//
// We always should have a print job!!
if(NULL == pPrintJob) {
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Done;
}
//
// Get the print queue for this guy
if(NULL == pPrintJob->MyShare() || NULL == (pPrintQueue = pPrintJob->MyShare()->GetPrintQueue())) {
hr = E_UNEXPECTED;
goto Done;
}
//
// Close the spool
if(FAILED(pPrintQueue->JobsFinished(pPrintJob))){
TRACEMSG(ZONE_ERROR, (L"SMB_PrintStream: Close() -- error setting Jobs Finished on print queue!"));
hr = E_UNEXPECTED;
goto Done;
}
//nobody should set hr to success yet
ASSERT(FAILED(hr));
hr = S_OK;
Done:
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -