Files
admin
base
com
developer
drivers
ds
enduser
inetcore
inetsrv
loc
mergedcomponents
multimedia
net
printscan
ddk
dload
fax
faxsrv
inc
lib
print
drivers
embedded
spooler
dbglib
exts
idl
inc
inetpp2
inetsrv
localspl
monitors
oleprn
perflib
prtprocs
scripts
splexts
spllib
splsetup
spoolss
bidispl
client
daytona
hydra
bind.c
change.c
client.h
clusspl.c
cstrings.c
cstrings.h
data.c
defprn.c
defprn.h
devmode.c
dirs
drvsetup.c
drvsetup.h
dsutil.cxx
dsutil.hxx
handle.c
init.c
memory.cxx
memory.hxx
midluser.c
pfdlg.c
pfdlg.h
precomp.h
prnprst.cxx
prnprst.hxx
prnstrm.cxx
prnstrm.hxx
prop.c
property.cxx
property.hxx
pubprn.cxx
pubprn.hxx
resource.h
sources.inc
splinit.c
splperst.cxx
splwow64c.c
stream.cxx
stream.hxx
util.c
varconv.cxx
varconv.hxx
winspla.c
winsplc.c
winspool.c
winspool.def
winspool.prf
winspool.rc
wlkprn.cxx
wlkprn.hxx
dll
idl
perf
server
splwow64
win32
dirs
wpnpinst
dirs
makefil0
dirs
publish
scan
ui
wia
dirs
project.mk
public
published
sdktools
shell
termsrv
tools
windows
dirs
makefil0
WindowsXP/printscan/print/spooler/spoolss/client/splperst.cxx
2025-04-27 07:49:33 -04:00

1011 lines
17 KiB
C++

/*++
Copyright (C) Microsoft Corporation, 1998 - 1998
All rights reserved.
Module Name:
splperst.cxx
Abstract:
Implementation of spooler persisting code
IPrnStream & IStream
Author:
Adina Trufinescu (AdinaTru) 4-Nov-1998
Revision History:
Lazar Ivanov (LazarI) Jul-2000 - moved from printui.
--*/
#include "precomp.h"
#pragma hdrstop
#include "prnprst.hxx"
#include <initguid.h>
#include "winprtp.h"
////////////////////////////////////////
// class TPrnPersist
//
class TPrnPersist: public IPrnStream,
public IStream
{
public:
TPrnPersist(
VOID
);
~TPrnPersist(
VOID
);
/***********
IUnknown
***********/
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
/***********
IPrnStream
***********/
STDMETHODIMP
BindPrinterAndFile(
IN LPCTSTR pszPrinter,
LPCTSTR pszFile
);
STDMETHODIMP
StorePrinterInfo(
IN DWORD Flag
);
STDMETHODIMP
RestorePrinterInfo(
IN DWORD Flag
);
STDMETHODIMP
QueryPrinterInfo(
IN PrinterPersistentQueryFlag Flag,
OUT PersistentInfo *pPrstInfo
);
/***********
IStream
***********/
HRESULT STDMETHODCALLTYPE
Read( // IMPLEMENTED
VOID * pv,
ULONG cb,
ULONG * pcbRead
);
HRESULT STDMETHODCALLTYPE
Write( //IMPLEMENTED
VOID const* pv,
ULONG cb,
ULONG * pcbWritten
);
HRESULT STDMETHODCALLTYPE
Seek( //IMPLEMENTED
LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER * plibNewPosition
);
HRESULT STDMETHODCALLTYPE
SetSize(
ULARGE_INTEGER nSize
);
HRESULT STDMETHODCALLTYPE
CopyTo( //NOT_IMPLEMENTED
LPSTREAM pStrm,
ULARGE_INTEGER cb,
ULARGE_INTEGER * pcbRead,
ULARGE_INTEGER * pcbWritten
);
HRESULT STDMETHODCALLTYPE
Commit( //NOT_IMPLEMENTED
IN DWORD dwFlags
);
HRESULT STDMETHODCALLTYPE
Revert( //NOT_IMPLEMENTED
VOID
);
HRESULT STDMETHODCALLTYPE
LockRegion( //NOT_IMPLEMENTED
ULARGE_INTEGER cbOffset,
ULARGE_INTEGER cbLength,
DWORD dwFlags
);
HRESULT STDMETHODCALLTYPE
UnlockRegion( //NOT_IMPLEMENTED
ULARGE_INTEGER cbOffset,
ULARGE_INTEGER cbLength,
DWORD dwFlags
);
HRESULT STDMETHODCALLTYPE
Stat( //NOT_IMPLEMENTED
STATSTG * pStatStg,
DWORD dwFlags
);
HRESULT STDMETHODCALLTYPE
Clone( //NOT_IMPLEMENTED
OUT LPSTREAM * ppStrm
);
private:
LONG m_cRef;
TPrinterPersist *_pPrnPersist;
};
TPrnPersist::
TPrnPersist(
VOID
): m_cRef(1),
_pPrnPersist(NULL)
{
}
TPrnPersist::
~TPrnPersist(
VOID
)
{
if( _pPrnPersist )
{
delete _pPrnPersist;
}
}
/***********
IUnknown
***********/
STDMETHODIMP TPrnPersist::QueryInterface(REFIID riid, void **ppv)
{
// standard implementation
if( !ppv )
{
return E_INVALIDARG;
}
*ppv = NULL;
if( IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IPrnStream) )
{
*ppv = static_cast<IPrnStream*>(this);
}
else if( IsEqualIID(riid, IID_IStream) )
{
*ppv = static_cast<IStream*>(this);
}
else
{
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) TPrnPersist::AddRef()
{
// standard implementation
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) TPrnPersist::Release()
{
// standard implementation
ULONG cRefs = InterlockedDecrement(&m_cRef);
if( 0 == cRefs )
{
delete this;
}
return cRefs;
}
/*++
Name:
TPrnPersist::BindPrinterAndFile
Description:
Creates a PrnStream object if it don't exists and bind it to a printer and a file
Arguments:
printer name
file name
Return Value:
S_OK if succeeded
--*/
STDMETHODIMP
TPrnPersist::
BindPrinterAndFile(
IN LPCTSTR pszPrinter,
IN LPCTSTR pszFile
)
{
HRESULT hr = E_FAIL;
//
// Create the PrnStream location object if this is the first call.
//
if (!_pPrnPersist)
{
_pPrnPersist = new TPrinterPersist;
}
//
// Invoke the BindPrinterAndFile method if the printer stream
// object was create successfully.
//
if (_pPrnPersist != NULL)
{
DBGMSG(DBG_TRACE , ("TPrnPersist::BindPrinterAndFile \n"));
hr = _pPrnPersist->BindPrinterAndFile(pszPrinter, pszFile);
}
else
{
hr = E_OUTOFMEMORY;
}
DBGMSG(DBG_TRACE , ("TPrnPersist::BindPrinterAndFile %x \n" , hr));
return hr;
}
/*++
Name:
TPrnPersist::StorePrinterInfo
Description:
Creates a PrnStream object if it don't exists and invoke StorePrinterInfo
Arguments:
flags that specifies what settings to store
Return Value:
S_OK if succeeded
--*/
STDMETHODIMP
TPrnPersist::
StorePrinterInfo(
IN DWORD Flag
)
{
TStatusH hr;
hr DBGNOCHK = E_FAIL;
DWORD StoredFlags;
//
// Create the PrnStream location object if this is the first call.
//
if (!_pPrnPersist)
{
_pPrnPersist = new TPrinterPersist;
}
//
// Invoke the stote info method if the printer stream
// object was create successfully.
//
DBGMSG(DBG_TRACE , ("TPrnPersist::StorePrinterInfo Flag %x \n" , Flag));
if(_pPrnPersist != NULL)
{
if (VALID_PTR(_pPrnPersist))
{
//
// Winlogon calls this function for TS. We need to catch any possbile exception,
// otherwise we may cause BSOD.
//
__try
{
hr DBGCHK = _pPrnPersist->StorePrinterInfo(Flag, StoredFlags);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DBGMSG(DBG_WARNING, ("TPrnPersist::StorePrinterInfo exception %x\n", GetExceptionCode()));
hr DBGCHK = E_FAIL;
}
}
else
{
hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
}
}
else
{
hr DBGCHK = E_OUTOFMEMORY;
}
return hr;
}
/*++
Name:
TPrnPersist::RestorePrinterInfo
Description:
Creates a PrnStream object if it don't exists and invoke RestorePrinterInfo
Arguments:
flags that specifies what settings to restore
Return Value:
S_OK if succeeded
--*/
STDMETHODIMP
TPrnPersist::
RestorePrinterInfo(
IN DWORD Flag
)
{
TStatusH hr;
//
// Create the Prnstream location object if this is the first call.
//
if (!_pPrnPersist)
{
_pPrnPersist = new TPrinterPersist;
}
//
// Invoke the restore info method if the printer stream
// object was created successfully.
//
if(_pPrnPersist != NULL)
{
if (VALID_PTR(_pPrnPersist))
{
//
// Winlogon calls this function on the machine where TS runs. If the file from which
// we restore the settings is corrupted, we must protect us against AVs that can occur
// while accessing bad data.
//
__try
{
hr DBGCHK = _pPrnPersist->SafeRestorePrinterInfo(Flag);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DBGMSG(DBG_WARNING, ("TPrnPersist::SafeRestorePrinterInfo exception %x\n", GetExceptionCode()));
hr DBGCHK = E_FAIL;
}
}
else
{
hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
}
}
else
{
hr DBGCHK = E_OUTOFMEMORY;
}
return hr;
}
/*++
Name:
TPrnPersist::QueryPrinterInfo
Description:
Creates a PrnStream object if it don't exists and invoke QueryPrinterInfo
Arguments:
flags that specifies what settings to query
Return Value:
S_OK if succeeded
--*/
STDMETHODIMP
TPrnPersist::
QueryPrinterInfo(
IN PrinterPersistentQueryFlag Flag,
OUT PersistentInfo *pPrstInfo
)
{
TStatusH hr;
hr DBGNOCHK = E_FAIL;
//
// Create the Prnstream location object if this is the first call.
//
if (!_pPrnPersist)
{
_pPrnPersist = new TPrinterPersist;
}
//
// Invoke the query info method if the printer stream
// object was create successfully.
//
if(_pPrnPersist != NULL)
{
if (VALID_PTR(_pPrnPersist))
{
__try
{
hr DBGCHK = _pPrnPersist->QueryPrinterInfo(Flag , pPrstInfo);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DBGMSG(DBG_WARNING, ("TPrnPersist::QueryPrinterInfo exception %x\n", GetExceptionCode()));
hr DBGCHK = E_FAIL;
}
}
else
{
hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
}
}
else
{
hr DBGCHK = E_OUTOFMEMORY;
}
return hr;
}
/*++
Name:
TPrnPersist::Read
Description:
Creates a PrnStream object if it don't exists and invoke 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
--*/
STDMETHODIMP
TPrnPersist::
Read(
VOID * pv,
ULONG cb,
ULONG * pcbRead
)
{
HRESULT hr = E_FAIL;
//
// Create the Prnstream location object if this is the first call.
//
if (!_pPrnPersist)
{
_pPrnPersist = new TPrinterPersist;
}
//
// Invoke the read method if the printer stream
// object was create successfully.
//
if(_pPrnPersist != NULL)
{
if (VALID_PTR(_pPrnPersist))
{
hr = _pPrnPersist->Read(pv, cb, pcbRead);
}
else
{
hr = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
/*++
Name:
TPrnPersist::Write
Description:
Creates a PrnStream object if it don't exists and invoke 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
--*/
STDMETHODIMP
TPrnPersist::
Write(
VOID const* pv,
ULONG cb,
ULONG * pcbWritten
)
{
HRESULT hr = E_FAIL;
//
// Create the Prnstream location object if this is the first call.
//
if (!_pPrnPersist)
{
_pPrnPersist = new TPrinterPersist;
}
//
// Invoke the write method if the printer stream
// object was create successfully.
//
if(_pPrnPersist != NULL)
{
if (VALID_PTR(_pPrnPersist))
{
hr = _pPrnPersist->Write(pv, cb, pcbWritten);
}
else
{
hr = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
/*++
Name:
TPrnPersist::Seek
Description:
Creates a PrnStream object if it don't exists and invoke Seek
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
--*/
STDMETHODIMP
TPrnPersist::
Seek(
LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER * plibNewPosition
)
{
HRESULT hr = E_FAIL;
//
// Create the Prnstream location object if this is the first call.
//
if (!_pPrnPersist)
{
_pPrnPersist = new TPrinterPersist;
}
//
// Invoke the seek method if the printer stream
// object was create successfully.
//
if(_pPrnPersist != NULL)
{
if (VALID_PTR(_pPrnPersist))
{
hr = _pPrnPersist->Seek(dlibMove, dwOrigin, plibNewPosition);
}
else
{
hr = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
/*++
Name:
TPrnPersist::SetSize
Description:
Arguments:
Return Value:
E_NOTIMPL
--*/
STDMETHODIMP
TPrnPersist::
SetSize(
ULARGE_INTEGER nSize
)
{
return E_NOTIMPL;
}
/*++
Name:
TPrnPersist::CopyTo
Description:
Arguments:
Return Value:
E_NOTIMPL
--*/
STDMETHODIMP
TPrnPersist::
CopyTo(
LPSTREAM pStrm,
ULARGE_INTEGER cb,
ULARGE_INTEGER * pcbRead,
ULARGE_INTEGER * pcbWritten
)
{
return E_NOTIMPL;
}
/*++
Name:
TPrnPersist::Commit
Description:
Arguments:
Return Value:
E_NOTIMPL
--*/
STDMETHODIMP
TPrnPersist::
Commit(
IN DWORD dwFlags
)
{
return E_NOTIMPL;
}
/*++
Name:
TPrnPersist::Revert
Description:
Arguments:
Return Value:
E_NOTIMPL
--*/
STDMETHODIMP
TPrnPersist::
Revert(
VOID
)
{
return E_NOTIMPL;
}
/*++
Name:
TPrnPersist::LockRegion
Description:
Arguments:
Return Value:
E_NOTIMPL
--*/
STDMETHODIMP
TPrnPersist::
LockRegion(
ULARGE_INTEGER cbOffset,
ULARGE_INTEGER cbLength,
DWORD dwFlags
)
{
return E_NOTIMPL;
}
/*++
Name:
TPrnPersist::UnlockRegion
Description:
Arguments:
Return Value:
E_NOTIMPL
--*/
STDMETHODIMP
TPrnPersist::
UnlockRegion(
ULARGE_INTEGER cbOffset,
ULARGE_INTEGER cbLength,
DWORD dwFlags
)
{
return E_NOTIMPL;
}
/*++
Name:
TPrnPersist::Stat
Description:
Arguments:
Return Value:
E_NOTIMPL
--*/
STDMETHODIMP
TPrnPersist::
Stat(
STATSTG * pStatStg,
DWORD dwFlags
)
{
return E_NOTIMPL;
}
/*++
Name:
TPrnPersist::Clone
Description:
Arguments:
Return Value:
E_NOTIMPL
--*/
STDMETHODIMP
TPrnPersist::
Clone(
LPSTREAM * ppStrm
)
{
return E_NOTIMPL;
}
#ifdef __cplusplus
extern "C" {
#endif
// forward declarations....
HRESULT TPrnPersist_CreateInstance(REFIID riid, void **ppv);
BOOL WebPnpEntry(LPCTSTR lpszCmdLine);
BOOL WebPnpPostEntry(BOOL fConnection, LPCTSTR lpszBinFile, LPCTSTR lpszPortName, LPCTSTR lpszPrtName);
/*++
Name:
TPrnPersist_CreateInstance
Description:
creates an instance of TPrnPersist
Arguments:
Return Value:
S_OK on sucsess or OLE error on failure.
--*/
HRESULT TPrnPersist_CreateInstance(
IN REFIID riid,
OUT void **ppv
)
{
HRESULT hr = E_INVALIDARG;
if( ppv )
{
*ppv = NULL;
TPrnPersist *pObj = new TPrnPersist;
if( pObj )
{
hr = pObj->QueryInterface( riid, ppv );
pObj->Release( );
}
else
{
hr = E_OUTOFMEMORY;
}
}
return hr;
}
/*++
Name:
PrintUIWebPnpEntry
Description:
wrapper around WebPnpEntry
Arguments:
Return Value:
S_OK on sucsess or OLE error on failure.
--*/
HRESULT PrintUIWebPnpEntry(
LPCTSTR lpszCmdLine
)
{
return WebPnpEntry(lpszCmdLine) ? S_OK : E_FAIL;
}
/*++
Name:
PrintUIWebPnpPostEntry
Description:
wrapper around WebPnpPostEntry
Arguments:
Return Value:
S_OK on sucsess or OLE error on failure.
--*/
HRESULT PrintUIWebPnpPostEntry(BOOL fConnection, LPCTSTR lpszBinFile, LPCTSTR lpszPortName, LPCTSTR lpszPrtName)
{
return WebPnpPostEntry(fConnection, lpszBinFile, lpszPortName, lpszPrtName) ? S_OK : E_FAIL;
}
/*++
Name:
PrintUICreateInstance
Description:
wrapper around TPrnPersist_CreateInstance
Arguments:
Return Value:
S_OK on sucsess or OLE error on failure.
--*/
HRESULT PrintUICreateInstance(REFIID riid, void **ppv)
{
return TPrnPersist_CreateInstance(riid, ppv);
}
#ifdef __cplusplus
}
#endif