|
|
/*****************************************************************************\
* 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; }
}
|