windows-nt/Source/XPSP1/NT/printscan/print/spooler/inetpp2/server/splpjm.cxx
2020-09-26 16:20:57 +08:00

717 lines
16 KiB
C++

/*****************************************************************************\
* MODULE: splpjm.c
*
* This module contains the routines to deal with job-mapping list.
*
*
* Copyright (C) 1996-1997 Microsoft Corporation
* Copyright (C) 1996-1997 Hewlett Packard
*
* History:
* 13-Jan-1997 ChrisWil Created.
*
\*****************************************************************************/
#include "precomp.h"
#include "priv.h"
/*****************************************************************************\
* pjm_OldEntry (Local Routine)
*
*
\*****************************************************************************/
_inline BOOL pjm_IsOldEntry(
PJOBMAP pjm)
{
return !pjm->bRemoteJob && !pjmChkState(pjm, PJM_SPOOLING);
}
/*****************************************************************************\
* pjm_IsLocalJob (Local Routine)
*
*
\*****************************************************************************/
_inline BOOL pjm_IsLocalJob(
PJOBMAP pjm)
{
return !pjm->bRemoteJob && pjmChkState(pjm, PJM_SPOOLING);
}
/*****************************************************************************\
* pjm_DelEntry (Local Routine)
*
*
\*****************************************************************************/
_inline VOID pjm_DelEntry(
PJOBMAP pjm)
{
if (pjm->hSplFile)
SplFree(pjm->hSplFile);
if (pjm->lpszUri)
memFreeStr(pjm->lpszUri);
if (pjm->lpszUser)
memFreeStr(pjm->lpszUser);
memFree(pjm, sizeof(JOBMAP));
}
/*****************************************************************************\
* pjmAdd
*
* Add a job-mapping to the list. Access to this list needs ownership of the
* crit-sect.
*
\*****************************************************************************/
PJOBMAP pjmAdd(
PJOBMAP *pjmList,
PCINETMONPORT pIniPort,
LPCTSTR lpszUser,
LPCTSTR lpszDocName)
{
PJOBMAP pjm = NULL;
static DWORD s_idJobLocal = 0;
semCheckCrit();
if (pjmList) {
// Add the new job-entry to the list.
//
if (pjm = (PJOBMAP)memAlloc(sizeof(JOBMAP))) {
// Initialize our job-entry.
//
GetSystemTime (&pjm->SubmitTime);
pjm->dwState = 0;
pjm->pIniPort = pIniPort;
pjm->idJobLocal = ++s_idJobLocal;
pjm->idJobRemote = 0;
pjm->lpszUri = NULL;
pjm->lpszUser = memAllocStr(lpszUser);
pjm->lpszDocName = memAllocStr(lpszDocName);
pjm->hSplFile = NULL;
pjm->dwLocalJobSize = 0;
pjm->dwStatus = JOB_STATUS_SPOOLING;
pjm->pNext = NULL;
// Place it at the end of the list.
//
if (! *pjmList) {
*pjmList = pjm;
}
else {
for (PJOBMAP pjPtr = *pjmList; pjPtr->pNext; pjPtr = pjPtr->pNext);
pjPtr->pNext = pjm;
}
}
}
return pjm;
}
/*****************************************************************************\
* pjmDel
*
* Delete a job-mapping from the list. Access to this list needs owenership
* of the crit-sect.
*
\*****************************************************************************/
VOID pjmDel(
PJOBMAP* pjmList,
PJOBMAP pjm)
{
PJOBMAP pjPtr;
PJOBMAP pjPrv;
DWORD idx;
semCheckCrit();
if (pjmList) {
for (pjPtr = *pjmList, idx = 0; pjPtr && (pjm != pjPtr); ) {
// Reposition.
//
pjPrv = pjPtr;
pjPtr = pjPtr->pNext;
// If we've iterated 1000 jobs in this list, then we've
// either got a very heavily taxed print-system, or we
// may have an infinite loop.
//
if (idx++ >= g_dwJobLimit) {
DBG_MSG(DBG_LEV_ERROR, (TEXT("Error: pjmDel : Looped 1000 jobs, possible infinite loop")));
return;
}
}
// If we found the entry, then delete it.
//
if (pjPtr) {
if (pjPtr == *pjmList) {
*pjmList = pjPtr->pNext;
} else {
pjPrv->pNext = pjPtr->pNext;
}
pjm_DelEntry(pjPtr);
}
}
}
/*****************************************************************************\
* pjmCleanRemoteFlag
*
* Cleanup remote jobid from list. Access to this list needs ownership of the
* crit-sect.
*
\*****************************************************************************/
VOID pjmCleanRemoteFlag(
PJOBMAP* pjmList)
{
PJOBMAP pjPtr = NULL;
semCheckCrit();
if (pjmList) {
for (pjPtr = *pjmList; pjPtr; ) {
pjPtr->bRemoteJob = FALSE;
// Next item.
//
pjPtr = pjPtr->pNext;
}
}
}
/*****************************************************************************\
* pjmGetLocalJobCount
*
* Locate number of job-entries from list. Access to this list needs ownership of the
* crit-sect.
*
\*****************************************************************************/
DWORD pjmGetLocalJobCount(
PJOBMAP* pjmList,
DWORD* pcbItems)
{
PJOBMAP pjPtr = NULL;
DWORD idx = 0;
semCheckCrit();
*pcbItems = 0;
if (pjmList) {
for (pjPtr = *pjmList; pjPtr; ) {
if (pjm_IsLocalJob (pjPtr)) {
idx++;
*pcbItems += sizeof (JOB_INFO_2) +
utlStrSize (pjPtr->lpszDocName) +
utlStrSize (pjPtr->lpszUser);
}
// Next item.
//
pjPtr = pjPtr->pNext;
}
}
return idx;
}
/*****************************************************************************\
* pjmFind
*
* Locate job-entry from list. Access to this list needs ownership of the
* crit-sect. This will lookup either Local/Remote id's and return its
* position.
*
\*****************************************************************************/
PJOBMAP pjmFind(
PJOBMAP* pjmList,
DWORD fType,
DWORD idJob)
{
PJOBMAP pjPtr = NULL;
DWORD idx;
semCheckCrit();
if (pjmList) {
// Search.
//
for (pjPtr = *pjmList, idx = 0; pjPtr && (pjmJobId(pjPtr, fType) != idJob); ) {
// Next item.
//
pjPtr = pjPtr->pNext;
// If we've iterated 1000 jobs in this list, then we've
// either got a very heavily taxed print-system, or we
// may have an infinite loop.
//
if (idx++ >= g_dwJobLimit) {
DBG_MSG(DBG_LEV_ERROR, (TEXT("Error: pjmFind : Looped 1000 jobs, possible infinite loop")));
return NULL;
}
}
if (pjPtr && fType == PJM_REMOTEID) {
pjPtr->bRemoteJob = TRUE;
}
}
return pjPtr;
}
/*****************************************************************************\
* pjmNextLocalJob
*
* Walk the list and look for any expired entries. Access to this list needs
* ownership of the crit-sect.
*
\*****************************************************************************/
PJOBMAP pjmNextLocalJob(
PJOBMAP* pjmList,
PJOB_INFO_2 pJobInfo2,
PBOOL pbFound)
{
PJOBMAP pjPtr = NULL;
DWORD idx;
BOOL bFound = FALSE;
semCheckCrit();
if (pjmList) {
for (pjPtr = *pjmList, idx = 0; pjPtr && !bFound; ) {
// If we're spooling, then we can't be an old-job.
//
if (pjm_IsLocalJob (pjPtr)) {
// It is a new entry
//
ZeroMemory (pJobInfo2, sizeof (JOB_INFO_2));
pJobInfo2->JobId = pjPtr->idJobLocal;
pJobInfo2->pDocument = pjPtr->lpszDocName;
pJobInfo2->pUserName = pjPtr->lpszUser;
pJobInfo2->Size = pjPtr->dwLocalJobSize;
pJobInfo2->Submitted = pjPtr->SubmitTime;
pJobInfo2->Status = pjPtr->dwStatus;
if (pjmChkState (pjPtr, PJM_CANCEL)) {
pJobInfo2->Status |= JOB_STATUS_DELETING;
}
bFound = TRUE;
}
// Next item.
//
pjPtr = pjPtr->pNext;
}
}
*pbFound = bFound;
return pjPtr;
}
/*****************************************************************************\
* pjmRmoveOldEntries
*
* Walk the list and look for any expired entries. Access to this list needs
* ownership of the crit-sect.
*
\*****************************************************************************/
VOID pjmRemoveOldEntries(
PJOBMAP *pjmList)
{
PJOBMAP pjPtr;
PJOBMAP pjDel;
PJOBMAP pjPrv;
DWORD idx;
semCheckCrit();
for (pjPtr = *pjmList, pjPrv = *pjmList, idx = 0; pjPtr; ) {
// If we're an old entry, then delete it.
//
if (pjm_IsOldEntry (pjPtr)) {
// No remote job ID and the state is not spooling
// It is an old entry, delete it
pjDel = pjPtr;
if (pjPtr == *pjmList) {
*pjmList = pjPtr->pNext;
pjPtr = *pjmList;
pjPrv = *pjmList;
} else {
pjPrv->pNext = pjPtr->pNext;
pjPtr = pjPrv->pNext;
}
pjm_DelEntry(pjDel);
} else {
pjPrv = pjPtr;
pjPtr = pjPtr->pNext;
}
// If we've iterated 1000 jobs in this list, then we've
// either got a very heavily taxed print-system, or we
// may have an infinite loop.
//
if (idx++ >= g_dwJobLimit) {
DBG_MSG(DBG_LEV_ERROR, (TEXT("Warn : pjmWalk : Looped 1000 jobs, possible infinite loop")));
return;
}
}
}
/*****************************************************************************\
* pjmDelList
*
*
\*****************************************************************************/
VOID pjmDelList(
PJOBMAP pjmList)
{
PJOBMAP pjPtr;
semCheckCrit();
for (pjPtr = pjmList; pjPtr; ) {
pjmList = pjPtr->pNext;
pjm_DelEntry(pjPtr);
pjPtr = pjmList;
}
}
/*****************************************************************************\
* pjmSetState
*
* Set the state of the job-entry. If we're setting this to spooling-state,
* then we go through the extra-trouble of setting up a spool-file entry as
* well.
*
\*****************************************************************************/
BOOL pjmSetState(
PJOBMAP pjm,
DWORD dwState)
{
DWORD fType;
BOOL bSet = FALSE;
semCheckCrit();
if (pjm) {
// If the caller is setting the job into spooling-state, then
// we need to create a spool-file. If this state is already
// set, then ignore this particular call.
//
if ((dwState & PJM_SPOOLING) && !pjmChkState(pjm, PJM_SPOOLING)) {
// Determine the type of spl-file to open. If PJM_NOOPEN
// is specified, then we will close the file-handle so that
// other processes can obtain exclusive access (i.e. AddJob,
// and ScheduleJob require this).
//
fType = (dwState & PJM_NOOPEN ? SPLFILE_TMP : SPLFILE_SPL);
// Allocate the spool-file, and close if necessary.
//
if (pjm->hSplFile = SplCreate(pjm->idJobLocal, fType)) {
if (dwState & PJM_NOOPEN)
SplClose(pjm->hSplFile);
bSet = TRUE;
} else {
goto EndSet;
}
} else {
bSet = TRUE;
}
// Set the state.
//
pjm->dwState |= dwState;
}
EndSet:
return bSet;
}
/*****************************************************************************\
* pjmClrState
*
* Clear the state specified in the job-entry. If we're turning of spooling,
* then we need to free up the spool-file-object.
*
\*****************************************************************************/
VOID pjmClrState(
PJOBMAP pjm,
DWORD dwState)
{
semCheckCrit();
if (pjm) {
// If the caller is turning off spooling, then we need to
// clean our spool-file resources. If there is no spooling
// going on, then ignore.
//
if ((dwState & PJM_SPOOLING) && pjmChkState(pjm, PJM_SPOOLING)) {
// Clean our spooling-file resources.
//
SplFree(pjm->hSplFile);
pjm->hSplFile = NULL;
}
// Clear the state.
//
pjm->dwState &= ~dwState;
}
}
/*****************************************************************************\
* pjmSetJobRemote
*
* Set the remote-job-id into the job-entry. This is usually called once
* the job-id is obtained from the print-server. We will maintain this for
* local/remote job-mapping.
*
\*****************************************************************************/
VOID pjmSetJobRemote(
PJOBMAP pjm,
DWORD idJobRemote,
LPCTSTR lpszUri)
{
semCheckCrit();
if (pjm) {
// If we had a previous job-url, then we need to free it
// before reseting it with the new.
//
if (pjm->lpszUri)
memFreeStr(pjm->lpszUri);
// Store remote-job information.
//
pjm->idJobRemote = idJobRemote;
pjm->lpszUri = memAllocStr(lpszUri);
pjm->bRemoteJob = TRUE;
}
}
/*****************************************************************************\
* pjmAddJobSize
*
* Add the job size to the local job info. This is usually called by
* PPWritePrinter
*
\*****************************************************************************/
VOID pjmAddJobSize(
PJOBMAP pjm,
DWORD dwSize)
{
semCheckCrit();
if (pjm) {
pjm->dwLocalJobSize += dwSize;
}
}
/*****************************************************************************\
* pjmSplLock
*
* Lock the spool-file for reading. This returns a file-map pointer to the
* caller.
*
\*****************************************************************************/
CFileStream* pjmSplLock(
PJOBMAP pjm)
{
CFileStream *pStream = NULL;
semCheckCrit();
if (pjm) {
// If the state of our spool-object requires that we not
// keep open-handles on the file, then we need to open
// it here. This is closed at pjmSplUnlock().
//
if (pjmChkState(pjm, PJM_NOOPEN))
SplOpen(pjm->hSplFile);
pStream = SplLock(pjm->hSplFile);
}
return pStream;
}
/*****************************************************************************\
* pjmSplUnlock
*
* This unlocks our file-mapped-pointer on the spool-file.
*
\*****************************************************************************/
BOOL pjmSplUnlock(
PJOBMAP pjm)
{
BOOL bRet = FALSE;
semCheckCrit();
// The spool-file must have already been locked in order to proceed
// with this call.
//
if (pjm) {
// Unlock the spool-file.
//
bRet = SplUnlock(pjm->hSplFile);
// If the state of our spool-object requires that
// we keep no open-handles, then we need to close
// the spool-handle.
//
if (pjmChkState(pjm, PJM_NOOPEN))
SplClose(pjm->hSplFile);
}
return bRet;
}
/*****************************************************************************\
* pjmSplWrite
*
* Write out data to the spool-file.
*
\*****************************************************************************/
BOOL pjmSplWrite(
PJOBMAP pjm,
LPVOID lpMem,
DWORD cbMem,
LPDWORD lpcbWr)
{
BOOL bRet = FALSE;
semCheckCrit();
if (pjm) {
if (pjmChkState(pjm, PJM_NOOPEN))
SplOpen(pjm->hSplFile);
bRet = SplWrite(pjm->hSplFile, (LPBYTE) lpMem, cbMem, lpcbWr);
if (pjmChkState(pjm, PJM_NOOPEN))
SplClose(pjm->hSplFile);
}
return bRet;
}
/*****************************************************************************\
* pjmSetState
*
* Set the status of the local job-entry.
*
\*****************************************************************************/
VOID pjmUpdateLocalJobStatus(
PJOBMAP pjm,
DWORD dwStatus)
{
semCheckCrit();
if (pjm) {
pjm->dwStatus = dwStatus;
}
}