windows-nt/Source/XPSP1/NT/printscan/print/spooler/spoolss/client/prnprst.cxx

670 lines
15 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (C) Microsoft Corporation, 1998 - 1999
All rights reserved.
Module Name:
PrnPrst.cxx
Abstract:
TPrinterPersist member definitions.
This class implements methods for storing , restoring printer settings into a file
Also , implements read, write , seek methods to operate a file likewise a stream
Author:
Adina Trufinescu (AdinaTru) 4-Nov-1998
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include "prnprst.hxx"
/*++
Title:
TPrinterPersist
Routine Description:
Initialise m_pPrnStream to NULL.
TPrinterPersist functionality is implemented through this object methods call.
m_pPrnStream is created when BindPrinterAndFile is called. If this function fails,
any subsequent method call will fail too.
Arguments:
None
Return Value:
Nothing
--*/
TPrinterPersist::
TPrinterPersist()
{
m_pPrnStream = NULL;
}
/*++
Title:
~TPrinterPersist
Routine Description:
destructor: if created , deletes PrnStream object
Arguments:
None
Return Value:
Nothing
--*/
TPrinterPersist::
~TPrinterPersist()
{
if(m_pPrnStream)
{
delete m_pPrnStream;
}
}
/*++
Title:
BindPrinterAndFile
Routine Description:
Create a TPrnStream object and if succeeded , bind it to a printer and a file
Arguments:
pszPrinter - printer to bind to
pszFile - file to bind to
Return Value:
BindPrinterAndFile could return E_OUTOFMEMORY if failed to allocate memory,
an error code mapped to HRESULT with storage facility set if failed to open printer in TPrnStream::BindPrnStream
or S_OK if suceeded
--*/
HRESULT
TPrinterPersist::
BindPrinterAndFile(
IN LPCTSTR pszPrinter,
IN LPCTSTR pszFile
)
{
TStatusB bStatus;
TStatusH hr;
//
// Create a TPrnStream obj ant initialise it with printer name and file name
//
m_pPrnStream = new TPrnStream(pszPrinter, pszFile);
bStatus DBGCHK = (m_pPrnStream != NULL);
if(bStatus)
{
DBGMSG(DBG_TRACE , ("BindPrinterAndFile to : " TSTR " \n" , pszPrinter));
//
// calls TPrnStream bind method; it will open the printer with maximum access rights
// and will create a TStream object that will open the file
//
hr DBGCHK = m_pPrnStream->BindPrnStream();
//
// if failed to bind TPrnStream to printer and file , delete it!!!
//
if(FAILED(hr))
{
delete m_pPrnStream;
m_pPrnStream = NULL;
}
}
else
{
hr DBGCHK = E_OUTOFMEMORY;
}
return hr;
}
/*++
Title:
UnBindPrinterAndFile
Routine Description:
Call UnBindPrnStream method of m_pPrnStream.After this function is called , any subsequent method call will fail.
Arguments:
None
Return Value:
S_OK if succeeded
PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
--*/
HRESULT
TPrinterPersist::
UnBindPrinterAndFile(
)
{
TStatusH hr;
DBGMSG(DBG_TRACE , ("UnBindPrinterAndFile!!! \n"));
hr DBGNOCHK = E_FAIL;
//
// if BindPrinterAndFile wasn't called or failed , this funct will fail also
//
if(m_pPrnStream != NULL)
{
hr DBGCHK = m_pPrnStream->UnBindPrnStream();
}
return hr;
}
/*++
Title:
bGetPrinterAndFile
Routine Description:
Query m_pPrnStream for printer and file it is binded
Arguments:
pszPrinter - outs printer name
pszFile - outs file name
Return Value:
TRUE if m_pPrnStream is initialized
FALSE otherwise
--*/
BOOL
TPrinterPersist::
bGetPrinterAndFile(
OUT LPCTSTR& pszPrinter,
OUT LPCTSTR& pszFile
)
{
TStatusB bStatus;
if(m_pPrnStream != NULL)
{
pszPrinter = m_pPrnStream->GetPrinterName();
pszFile = m_pPrnStream->GetFileName();
bStatus DBGNOCHK = TRUE;
}
else
{
bStatus DBGCHK = FALSE;
}
return bStatus;
}
/*++
Title:
Read
Routine Description:
Indirects call to PrnStream which , in turns , idirects it to TStream
Eventually , this function will be called through IStream interface
Arguments the same as IStream::Read
Arguments:
pv - The buffer that the bytes are read into
cb - The offset in the stream to begin reading from.
pcbRead - The number of bytes to read
Return Value:
S_OK if succeeded
ReadFile Win32 error mapped to HRESULT(FACILITY_STORAGE) if failed
--*/
HRESULT
TPrinterPersist::
Read(
IN VOID * pv,
IN ULONG cb,
IN ULONG * pcbRead
)
{
if(m_pPrnStream)
{
return m_pPrnStream->GetIStream()->Read(pv, cb, pcbRead);
}
else
{
return STG_E_NOMOREFILES;
}
}
/*++
Title:
Write
Routine Description:
Indirects call to PrnStream which , in turns , idirects it to TStream
Eventually , this function will be called through IStream interface
Arguments the same as IStream::Write
Arguments:
pv - The buffer to write from.
cb - The offset in the array to begin writing from
pcbRead - The number of bytes to write
Return Value:
S_OK if succeeded
WriteFile Win32 error mapped to HRESULT(FACILITY_STORAGE) if failed
--*/
HRESULT
TPrinterPersist::
Write(
IN VOID const* pv,
IN ULONG cb,
IN ULONG* pcbWritten
)
{
if(m_pPrnStream)
{
return m_pPrnStream->GetIStream()->Write(pv, cb, pcbWritten);
}
else
{
return STG_E_NOMOREFILES;
}
}
/*++
Title:
Seek
Routine Description:
Indirects call to PrnStream which , in turns , idirects it to TStream
Arguments the same as IStream::Seek
Eventually , this function will be called through IStream interface
Arguments:
dlibMove - The offset relative to dwOrigin
dwOrigin - The origin of the offset
plibNewPosition - Pointer to value of the new seek pointer from the beginning of the stream
Return Value:
S_OK if succeeded
SetFilePointer Win32 error mapped to HRESULT(FACILITY_STORAGE) if failed
--*/
HRESULT
TPrinterPersist::
Seek(
IN LARGE_INTEGER dlibMove,
IN DWORD dwOrigin,
IN ULARGE_INTEGER * plibNewPosition
)
{
if(m_pPrnStream)
{
return m_pPrnStream->GetIStream()->Seek(dlibMove, dwOrigin, plibNewPosition);
}
else
{
return STG_E_NOMOREFILES;
}
}
/*++
Title:
bStorePrinterInfo
Routine Description:
Writes the printer settings into file.
Depending on specified flags, call TPrnStream methods to store printer data
This function must be called after calling BindPrinterAndFile which bind the object to
a printer and to a file.For that fnct to succeed, current user must have PRINTER_READ rights
on specified printer.
Arguments:
Flags - specifies what settings should be stored
StoredFlags - specifies what settings were actually stored
Return Value:
S_OK if succeeded
PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
--*/
HRESULT
TPrinterPersist::
StorePrinterInfo(
IN DWORD Flags,
OUT DWORD& StoredFlags
)
{
TStatusH hr;
DBGMSG(DBG_TRACE , ("Store Printer Flag %x \n" , Flags));
hr DBGNOCHK = E_FAIL;
//
// if BindPrinterAndFile wasn't called or failed , this funct will fail also
//
if(m_pPrnStream != NULL)
{
hr DBGCHK = m_pPrnStream->StorePrinterInfo(Flags, StoredFlags);
}
DBGMSG( DBG_TRACE, ( "Store Completed :: %x \n" ,hr));
return hr;
}
/*++
Title:
RestorePrinterInfo
Routine Description:
Depending on specified flags, call TPrnStream methods to restore printer data
This function must be called after calling BindPrinterAndFile which bind the object to
a printer and to a file.For that fnct to succeed, current user has to have PRINTER_ALL_ACCESS rights.
If he don't , BindPrinterAndFile will bind to printer with PRINTER_READ which will lead to
SetPrinter failure.
Arguments:
Flags - specifies what settings should be restored
RestoredFlags - specifies what settings were actually restored
Return Value:
S_OK if succeeded
PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
--*/
HRESULT
TPrinterPersist::
RestorePrinterInfo(
IN DWORD Flags,
OUT DWORD& RestoredFlags
)
{
TStatusH hr;
TStatusB bStatus;
hr DBGNOCHK = E_FAIL;
RestoredFlags = 0;
DBGMSG(DBG_TRACE , ("Restore Printer info %x \n" , Flags));
//
// if BindPrinterAndFile wasn't called or failed , this funct will fail also
//
if(m_pPrnStream != NULL)
{
hr DBGCHK = m_pPrnStream->CheckPrinterNameIntegrity(Flags);
if(SUCCEEDED(hr))
{
DBGMSG( DBG_TRACE, ( "CheckPrinterNameIntegrity OK!!! %x \n" , hr));
hr DBGCHK = m_pPrnStream->RestorePrinterInfo(Flags, RestoredFlags);
}
}
DBGMSG( DBG_TRACE, ( "RESTORE END!!! %x \n" , hr));
return hr;
}
/*++
Title:
SafeRestorePrinterInfo
Routine Description:
Before restoring ant flags, create a new temporary persistent object binded to also to printer which stores current printer settings.
If something fails at the restoring, we are able to roll back all the changes made and we will leave printer in the
initial state.
A temporary file which holds initial printer settings are created by invoking StorePrinterInfo for temporary object.
This file will be deleted by calling UnBindPrinterAndFile for temporary object.
Arguments:
Flags - specifies what settings should be restored
Return Value:
S_OK if succeeded
PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
--*/
HRESULT
TPrinterPersist::
SafeRestorePrinterInfo(
IN DWORD Flags
)
{
LPTSTR pszPrinterTemp;
LPTSTR pszFile;
TString strFileTempPrefix(_T("Prst"));
TCHAR szTempFileName[MAX_PATH];
TCHAR szTempPath[MAX_PATH];
TStatusH hr;
TStatusH hrBkp;
DWORD StoredFlags;
DWORD RestoredFlags;
//
// initialize hr to Backup error; if something wrong happens when trying to build backup version of file,
// fnct will return Back-up Error
//
hr DBGNOCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_BACKUP);
hrBkp DBGNOCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_BACKUP);
//
// Create temporary object for storing current settings
// In case the main restoring fails , current settings can be restored
//
TPrinterPersist* pPrnPersistTemp = new TPrinterPersist;
if(pPrnPersistTemp != NULL)
{
if(bGetPrinterAndFile(pszPrinterTemp, pszFile))
{
TStatus Status;
//
// create a temp file for saving current settings
//
Status DBGNOCHK = GetTempPathW(MAX_PATH, szTempPath);
if (Status > 0 && Status <= MAX_PATH) {
GetTempFileName(szTempPath, strFileTempPrefix, 0, szTempFileName);
}
else {
GetTempFileName(_T("."), strFileTempPrefix, 0, szTempFileName);
}
hrBkp DBGCHK = pPrnPersistTemp->BindPrinterAndFile(pszPrinterTemp, szTempFileName);
if(SUCCEEDED(hrBkp))
{
hrBkp DBGCHK = pPrnPersistTemp->StorePrinterInfo(Flags, StoredFlags);
if(SUCCEEDED(hrBkp))
{
hr DBGCHK = RestorePrinterInfo(Flags, RestoredFlags);
if(FAILED(hr))
{
//
// if main restoring failed , try backup restoring with flags set to:
// flags successfully restored
// &
// flags that were successfully stored in backup file
// fct will still return hr = reason for main restoring failure
//
// PRST_FORCE_NAME must be always set on force for a scenario like this:
// restore settings from file ( printer P1 stored) on top of printer P2 with f flag set
// restoring fails (printer P2 could become P1 at this point) and back-up is needed;
// in back-up file , printer name is P2 . This means we have to force printer name from back-up file,
// in order to become P2 again
// If it's not the case then printer was renamed and the restoring failed,f flag is harmless
//
hrBkp DBGCHK = pPrnPersistTemp->RestorePrinterInfo((StoredFlags & RestoredFlags) | PRST_FORCE_NAME , RestoredFlags);
if(FAILED(hrBkp))
{
// if backup restoring failed also,
// set hr to FATAL Error
//
hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_FATAL);
}
}
}
}
pPrnPersistTemp->UnBindPrinterAndFile();
}
delete pPrnPersistTemp;
}
return hr;
}
/*++
Title:
QueryPrinterInfo
Routine Description:
Read from
Arguments:
Flags - specifies what settings should be restored
pPrstInfo - pointer to union that holds a pointer to read item
Return Value:
S_OK if succeeded;
ERROR_INVALID_PARAMETER maped to HRESULT if more than one flag specified;
PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed;
--*/
HRESULT
TPrinterPersist::
QueryPrinterInfo(
IN PrinterPersistentQueryFlag Flag,
OUT PersistentInfo *pPrstInfo
)
{
TStatusH hr;
TStatusB bStatus;
hr DBGNOCHK = E_FAIL;
DBGMSG(DBG_TRACE , ("Restore Printer info %x \n" , Flag));
//
// if BindPrinterAndFile wasn't called or failed , this funct will fail also
//
if(m_pPrnStream != NULL)
{
hr DBGCHK = m_pPrnStream->QueryPrinterInfo(Flag, pPrstInfo);
}
DBGMSG( DBG_TRACE, ( "QueryPrinterInfo END!!! %x \n" , hr));
return hr;
}