670 lines
15 KiB
C++
670 lines
15 KiB
C++
/*++
|
|
|
|
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;
|
|
|
|
}
|