|
|
//+--------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998 - 1998.
//
// File: expparam.hxx
//
// Contents: Standard Parameter validation for Exposed Interfaces
//
// History: 11-Feb-98 BChapman Created
//
//---------------------------------------------------------------
#ifndef _EXPPARAM_HXX_
#define _EXPPARAM_HXX_
#include <docfilep.hxx>
#include <funcs.hxx>
//
// I can't actually inherit from the real interfaces and declare the
// methods "static inline" like I want, because "virtual" is incompatible with
// both "static" and "inline". So don't inherit in the final version.
//
#if 0
#define PUBLIC_INHERIT :public IStorage, public IStream, \
public ILockBytes, public IEnumSTATSTG #define METHODIMP STDMETHODIMP
#define METHODIMP_(x) STDMETHODIMP_(x)
#else
#define PUBLIC_INHERIT
#define METHODIMP static inline STDMETHODIMP
#define METHODIMP_(x) static inline STDMETHODIMP_(x)
#endif
#define ChkErr(x) { HRESULT sc; if( FAILED( sc = (x) ) ) return sc; }
#if DBG == 1
#define EXP_VALIDATE(comp, x) \
{ \ if (FAILED(sc = CExpParameterValidate::x)) \ { \ comp##DebugOut(( DEB_ERROR, \ "Parameter Error %lX at %s:%d\n", \ sc, __FILE__, __LINE__)); \ return sc; \ } \ } #else
#define EXP_VALIDATE(comp, x) \
{ \ if (FAILED(sc = CExpParameterValidate::x))\ return sc; \ } #endif // DBG
class CExpParameterValidate PUBLIC_INHERIT { public: //
// The IUnknown methods First.
//
METHODIMP QueryInterface( REFIID riid, void** ppvObject ) { ChkErr( ValidateOutPtrBuffer( ppvObject ) ); *ppvObject = NULL; ChkErr( ValidateIid( riid ) ); return S_OK; }
#if 0
//
// Addref and Release are troublesome because they don't
// return HRESULTS. Luckly they have no parameters and are
// therefore unnecessary.
//
METHODIMP_(ULONG) AddRef( void ) { return S_OK; }
METHODIMP_(ULONG) Release( void ) { return S_OK; } #endif
//
// All the other methods in Alphabetical Order.
//
// IEnumSTATSTG
METHODIMP Clone( IEnumSTATSTG** ppenum ) { ChkErr( ValidateOutPtrBuffer( ppenum ) ); *ppenum = NULL; return S_OK; }
// IStream
METHODIMP Clone( IStream** ppstm) { ChkErr( ValidateOutPtrBuffer( ppstm ) ); *ppstm = NULL; return S_OK; }
// IStream
METHODIMP CopyTo( IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten ) { if( NULL != pcbRead ) { ChkErr( ValidateOutBuffer( pcbRead, sizeof( ULARGE_INTEGER ) ) ); pcbRead->QuadPart = 0; } if( NULL != pcbWritten ) { ChkErr( ValidateOutBuffer( pcbWritten, sizeof(ULARGE_INTEGER) ) ); pcbWritten->QuadPart = 0; } ChkErr( ValidateInterface(pstm, IID_IStream) ); return S_OK; }
// IStorage
METHODIMP CopyTo( DWORD ciidExclude, const IID* rgiidExclude, SNB snbExclude, IStorage* pstgDest) { DWORD i;
ChkErr( ValidateInterface( pstgDest, IID_IStorage ) ); if( NULL != rgiidExclude ) { Win4Assert(sizeof(IID)*ciidExclude <= 0xffffUL); ChkErr( ValidateBuffer( rgiidExclude, (size_t)(sizeof(IID)*ciidExclude ) ) ); //
// This check may be useless. I think it is checking if the address
// of given stack variable is a valid address (duh!)
// This check has been in the code a long time make sure in the debugger!
//
for (i = 0; i < ciidExclude; i++) ChkErr(ValidateIid(rgiidExclude[i])); } if( NULL != snbExclude ) ChkErr( ValidateSNB( snbExclude ) ); return S_OK; }
// IStream, IStorage
METHODIMP Commit( DWORD grfCommitFlags ) { ChkErr( VerifyCommitFlags( grfCommitFlags ) ); return S_OK; }
// IStorage
METHODIMP CreateStorage( const OLECHAR* pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStorage** ppstg) { ChkErr( ValidateOutPtrBuffer( ppstg ) ); *ppstg = NULL; ChkErr( CheckName(pwcsName) ); if( reserved1 != 0 || reserved2 != 0 ) return STG_E_INVALIDPARAMETER; ChkErr( VerifyPerms( grfMode, FALSE ) ); if( grfMode & ( STGM_PRIORITY | STGM_DELETEONRELEASE ) ) return STG_E_INVALIDFUNCTION; return S_OK; }
// IStorage
METHODIMP CreateStream( const OLECHAR* pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream** ppstm) { ChkErr( ValidateOutPtrBuffer( ppstm ) ); *ppstm = NULL; ChkErr( CheckName( pwcsName ) ); if( reserved1 != 0 || reserved2 != 0 ) return STG_E_INVALIDPARAMETER; ChkErr( VerifyPerms( grfMode, FALSE ) ); if( grfMode & ( STGM_CONVERT | STGM_TRANSACTED | STGM_PRIORITY | STGM_DELETEONRELEASE ) ) { return STG_E_INVALIDFUNCTION; } return S_OK; }
// IStorage
METHODIMP DestroyElement( const OLECHAR* pwcsName ) { ChkErr( CheckName( pwcsName ) ); return S_OK; }
// IStorage
METHODIMP EnumElements( DWORD reserved1, void* reserved2, DWORD reserved3, IEnumSTATSTG** ppenum) { ChkErr( ValidateOutPtrBuffer( ppenum ) ); *ppenum = NULL; if( reserved1 != 0 || reserved2 != NULL || reserved3 != 0 ) return STG_E_INVALIDPARAMETER; return S_OK; }
// ILockBytes
METHODIMP Flush( void ) { return S_OK; }
// IStream, ILockBytes
METHODIMP LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType ) { ChkErr( VerifyLockType( dwLockType ) ); return S_OK; }
// IStorage
METHODIMP MoveElementTo( const OLECHAR* pwcsName, IStorage* pstgDest, const OLECHAR* pwcsNewName, DWORD grfFlags) { ChkErr( CheckName( pwcsName ) ); ChkErr( CheckName( pwcsNewName ) ); ChkErr( VerifyMoveFlags( grfFlags ) ); ChkErr( ValidateInterface( pstgDest, IID_IStorage ) ); return S_OK; }
// IEnumSTATSTG
METHODIMP Next( ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched) { if (pceltFetched) { ChkErr( ValidateOutBuffer( pceltFetched, sizeof(ULONG) ) ); *pceltFetched = 0; } else if (celt != 1) return STG_E_INVALIDPARAMETER; ChkErr( ValidateOutBuffer( rgelt, sizeof(STATSTGW)*celt) ); memset( rgelt, 0, (size_t)(sizeof(STATSTGW)*celt ) ); return S_OK; }
// IStorage
METHODIMP OpenStorage( const OLECHAR* pwcsName, IStorage* pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage** ppstg) { ChkErr( ValidateOutPtrBuffer( ppstg ) ); *ppstg = NULL; ChkErr( CheckName( pwcsName ) ); if( reserved != 0) return STG_E_INVALIDPARAMETER; ChkErr( VerifyPerms( grfMode, FALSE ) ); if( grfMode & (STGM_CREATE | STGM_CONVERT ) ) return STG_E_INVALIDFLAG; if( NULL != pstgPriority || ( grfMode & ( STGM_PRIORITY | STGM_DELETEONRELEASE ) ) ) { return STG_E_INVALIDFUNCTION; } return S_OK; }
// IStorage
METHODIMP OpenStream( const OLECHAR* pwcsName, void* reserved1, DWORD grfMode, DWORD reserved2, IStream** ppstm) { ChkErr(ValidateOutPtrBuffer(ppstm)); *ppstm = NULL; ChkErr( CheckName( pwcsName ) ); if( reserved1 != NULL || reserved2 != 0 ) return STG_E_INVALIDPARAMETER; ChkErr( VerifyPerms( grfMode, FALSE ) ); if( grfMode & (STGM_CREATE | STGM_CONVERT ) ) return STG_E_INVALIDFLAG; if( grfMode & (STGM_TRANSACTED | STGM_PRIORITY | STGM_DELETEONRELEASE ) ) return STG_E_INVALIDFUNCTION; return S_OK; }
// IStream
METHODIMP Read( void* pv, ULONG cb, ULONG* pcbRead) { if (NULL != pcbRead) { ChkErr( ValidateOutBuffer( pcbRead, sizeof(ULONG) ) ); *pcbRead = 0; } ChkErr( ValidateHugeOutBuffer( pv, cb ) ); return S_OK; }
// ILockBytes
METHODIMP ReadAt( ULARGE_INTEGER ulOffset, void* pv, ULONG cb, ULONG* pcbRead ) { if (NULL != pcbRead) { ChkErr( ValidateOutBuffer( pcbRead, sizeof(ULONG) ) ); *pcbRead = 0; } ChkErr( ValidateHugeOutBuffer( pv, cb ) ); return S_OK; }
// IStorage
METHODIMP RenameElement( const OLECHAR* pwcsOldName, const OLECHAR* pwcsNewName) { ChkErr( CheckName( pwcsOldName ) ); ChkErr( CheckName( pwcsNewName ) ); return S_OK; }
// IEnumSTATSTG
METHODIMP Reset() { return S_OK; }
// IStream, IStorage
METHODIMP Revert( void ) { return S_OK; }
// IStream
METHODIMP Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition ) { if( plibNewPosition ) { ChkErr( ValidateOutBuffer( plibNewPosition, sizeof(ULARGE_INTEGER ) ) ); plibNewPosition->QuadPart = 0; } switch( dwOrigin ) { case STREAM_SEEK_SET: case STREAM_SEEK_CUR: case STREAM_SEEK_END: break; default: return STG_E_INVALIDFUNCTION; } return S_OK; }
// IStorage
METHODIMP SetClass( REFCLSID clsid) { ChkErr( ValidateBuffer( &clsid, sizeof( CLSID ) ) ); return S_OK; }
// IStorage
METHODIMP SetElementTimes( const OLECHAR* pwcsName, const FILETIME* pctime, const FILETIME* patime, const FILETIME* pmtime) { if( NULL != pwcsName ) ChkErr( CheckName( pwcsName ) ); if( NULL != pctime ) ChkErr( ValidateBuffer( pctime, sizeof( FILETIME ) ) ); if( NULL != patime ) ChkErr( ValidateBuffer( patime, sizeof( FILETIME ) ) ); if( NULL != pmtime ) ChkErr( ValidateBuffer( pmtime, sizeof( FILETIME ) ) ); return S_OK; }
// IStream, ILockBytes
METHODIMP SetSize( ULARGE_INTEGER libNewSize ) { return S_OK; }
// IStorage
METHODIMP SetStateBits( DWORD grfStateBits, DWORD grfMask ) { // We could insist that both args be 0.
// But we never have in the past.
return S_OK; }
// IEnumSTATSTG
METHODIMP Skip( ULONG celt ) { // I would like to do some sanity testing but the value
// isn't even signed. All bit values are technically valid.
return S_OK; }
// IStream, IStorage, ILockBytes
METHODIMP Stat( STATSTG* pstatstg, DWORD grfStatFlag ) { ChkErr( ValidateOutBuffer( pstatstg, sizeof( STATSTGW ) ) ); ChkErr( VerifyStatFlag( grfStatFlag ) ); return S_OK; }
// IStream, ILockBytes
METHODIMP UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType ) { ChkErr( VerifyLockType( dwLockType ) ); return S_OK; }
// IStream
METHODIMP Write( const void* pv, ULONG cb, ULONG* pcbWritten ) { if (NULL != pcbWritten) { ChkErr( ValidateOutBuffer( pcbWritten, sizeof(ULONG) ) ); *pcbWritten = 0; } ChkErr( ValidateHugeBuffer( pv, cb ) ); return S_OK; }
// ILockBytes
METHODIMP WriteAt( ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten ) { if (NULL != pcbWritten) { ChkErr( ValidateOutBuffer( pcbWritten, sizeof(ULONG) ) ); *pcbWritten = 0; } ChkErr( ValidateHugeBuffer( pv, cb ) ); return S_OK; } };
#endif // _EXPPARAM_HXX_
|