You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
791 lines
22 KiB
791 lines
22 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
Stream.cpp
|
|
|
|
Abstract:
|
|
This file contains the implementation of the MPC::*Stream classes.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 07/14/99
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP MPC::BaseStream::Read( /*[out]*/ void* pv ,
|
|
/*[in] */ ULONG cb ,
|
|
/*[out]*/ ULONG *pcbRead )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Read");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::Write( /*[in] */ const void* pv ,
|
|
/*[in] */ ULONG cb ,
|
|
/*[out]*/ ULONG *pcbWritten )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Write");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::Seek( /*[in] */ LARGE_INTEGER libMove ,
|
|
/*[in] */ DWORD dwOrigin ,
|
|
/*[out]*/ ULARGE_INTEGER *plibNewPosition )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Seek");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::SetSize( /*[in]*/ ULARGE_INTEGER libNewSize )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::SetSize");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::CopyTo( /*[in] */ IStream* pstm ,
|
|
/*[in] */ ULARGE_INTEGER cb ,
|
|
/*[out]*/ ULARGE_INTEGER *pcbRead ,
|
|
/*[out]*/ ULARGE_INTEGER *pcbWritten )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::CopyTo");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::Commit( /*[in]*/ DWORD grfCommitFlags )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Commit");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::Revert()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Revert");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::LockRegion( /*[in]*/ ULARGE_INTEGER libOffset ,
|
|
/*[in]*/ ULARGE_INTEGER cb ,
|
|
/*[in]*/ DWORD dwLockType )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::LockRegion");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::UnlockRegion( /*[in]*/ ULARGE_INTEGER libOffset ,
|
|
/*[in]*/ ULARGE_INTEGER cb ,
|
|
/*[in]*/ DWORD dwLockType )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::UnlockRegion");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::Stat( /*[out]*/ STATSTG *pstatstg ,
|
|
/*[in] */ DWORD grfStatFlag )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Stat");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP MPC::BaseStream::Clone( /*[out]*/ IStream* *ppstm )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::Clone");
|
|
|
|
__MPC_FUNC_EXIT(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT MPC::BaseStream::TransferData( /*[in] */ IStream* src ,
|
|
/*[in] */ IStream* dst ,
|
|
/*[in] */ ULONG ulCount ,
|
|
/*[out]*/ ULONG *ulDone )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::BaseStream::TransferData");
|
|
|
|
HRESULT hr;
|
|
BYTE rgBuf[512];
|
|
ULONG ulTot = 0;
|
|
ULONG ulRead;
|
|
ULONG ulWritten;
|
|
ULONG ul;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_NOTNULL(src);
|
|
__MPC_PARAMCHECK_NOTNULL(dst);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
while(1)
|
|
{
|
|
//
|
|
// Compute the amount to read on this pass (-1 == everything).
|
|
//
|
|
if(ulCount == -1)
|
|
{
|
|
ul = sizeof( rgBuf );
|
|
}
|
|
else
|
|
{
|
|
ul = min( sizeof( rgBuf ), ulCount );
|
|
}
|
|
if(ul == 0) break;
|
|
|
|
//
|
|
// Read and write.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, src->Read( rgBuf, ul, &ulRead ));
|
|
if(hr == S_FALSE || ulRead == 0) break;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, dst->Write( rgBuf, ulRead, &ulWritten ));
|
|
|
|
//
|
|
// Update counters.
|
|
//
|
|
if(ulCount != -1)
|
|
{
|
|
ulCount -= ulRead;
|
|
}
|
|
|
|
ulTot += ulWritten;
|
|
if(ulRead != ulWritten)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_MEDIUMFULL);
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
if(ulDone) *ulDone = ulTot;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
MPC::FileStream::FileStream()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::FileStream");
|
|
|
|
// MPC::wstring m_szFile;
|
|
m_dwDesiredAccess = GENERIC_READ; // DWORD m_dwDesiredAccess;
|
|
m_dwDisposition = OPEN_EXISTING; // DWORD m_dwDisposition;
|
|
m_dwSharing = FILE_SHARE_READ | FILE_SHARE_WRITE; // DWORD m_dwSharing;
|
|
m_hfFile = NULL; // HANDLE m_hfFile;
|
|
m_fDeleteOnRelease = false; // bool m_fDeleteOnRelease;
|
|
}
|
|
|
|
MPC::FileStream::~FileStream()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::~FileStream");
|
|
|
|
Close();
|
|
}
|
|
|
|
HRESULT MPC::FileStream::Close()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Close");
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
if(m_hfFile)
|
|
{
|
|
::CloseHandle( m_hfFile ); m_hfFile = NULL;
|
|
|
|
if(m_fDeleteOnRelease)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DeleteFile( m_szFile ));
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT MPC::FileStream::Init( /*[in]*/ LPCWSTR szFile ,
|
|
/*[in]*/ DWORD dwDesiredAccess ,
|
|
/*[in]*/ DWORD dwDisposition ,
|
|
/*[in]*/ DWORD dwSharing ,
|
|
/*[in]*/ HANDLE hfFile )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Init");
|
|
|
|
HRESULT hr;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_NOTNULL(szFile);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
Close();
|
|
|
|
|
|
m_szFile = szFile;
|
|
m_dwDesiredAccess = dwDesiredAccess;
|
|
m_dwDisposition = dwDisposition;
|
|
m_dwSharing = dwSharing;
|
|
|
|
|
|
if(hfFile)
|
|
{
|
|
if(::DuplicateHandle( ::GetCurrentProcess(), hfFile,
|
|
::GetCurrentProcess(), &m_hfFile, m_dwDesiredAccess, FALSE, 0 ) == FALSE)
|
|
{
|
|
m_hfFile = NULL; // For cleanup.
|
|
|
|
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::GetLastError() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__MPC_EXIT_IF_INVALID_HANDLE__CLEAN(hr, m_hfFile, ::CreateFileW( szFile, m_dwDesiredAccess, dwSharing, NULL, dwDisposition, FILE_ATTRIBUTE_NORMAL, NULL ));
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT MPC::FileStream::InitForRead( /*[in]*/ LPCWSTR szFile ,
|
|
/*[in]*/ HANDLE hfFile )
|
|
{
|
|
return Init( szFile, GENERIC_READ, OPEN_EXISTING, FILE_SHARE_READ | FILE_SHARE_WRITE, hfFile );
|
|
}
|
|
|
|
HRESULT MPC::FileStream::InitForReadWrite( /*[in]*/ LPCWSTR szFile ,
|
|
/*[in]*/ HANDLE hfFile )
|
|
{
|
|
return Init( szFile, GENERIC_READ | GENERIC_WRITE, CREATE_ALWAYS, 0, hfFile );
|
|
}
|
|
|
|
HRESULT MPC::FileStream::InitForWrite( /*[in]*/ LPCWSTR szFile ,
|
|
/*[in]*/ HANDLE hfFile )
|
|
{
|
|
return Init( szFile, GENERIC_WRITE, CREATE_ALWAYS, 0, hfFile );
|
|
}
|
|
|
|
HRESULT MPC::FileStream::DeleteOnRelease( /*[in]*/ bool fFlag )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::DeleteOnRelease");
|
|
|
|
m_fDeleteOnRelease = fFlag;
|
|
|
|
__MPC_FUNC_EXIT(S_OK);
|
|
}
|
|
|
|
|
|
STDMETHODIMP MPC::FileStream::Read( /*[out]*/ void* pv ,
|
|
/*[in] */ ULONG cb ,
|
|
/*[out]*/ ULONG *pcbRead )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Read");
|
|
|
|
HRESULT hr;
|
|
DWORD dwRead;
|
|
|
|
if(pcbRead) *pcbRead = 0;
|
|
|
|
if(m_hfFile == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
if(pv == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
|
|
|
|
if(::ReadFile( m_hfFile, pv, cb, &dwRead, NULL ) == FALSE)
|
|
{
|
|
DWORD dwRes = ::GetLastError();
|
|
|
|
if(dwRes == ERROR_ACCESS_DENIED)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_ACCESSDENIED);
|
|
}
|
|
|
|
__MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
|
|
}
|
|
else
|
|
{
|
|
if(dwRead == 0 && cb != 0)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
|
|
}
|
|
}
|
|
|
|
if(pcbRead) *pcbRead = dwRead;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP MPC::FileStream::Write( /*[in] */ const void* pv ,
|
|
/*[in] */ ULONG cb ,
|
|
/*[out]*/ ULONG *pcbWritten )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Write");
|
|
|
|
HRESULT hr;
|
|
DWORD dwWritten;
|
|
|
|
if(pcbWritten) *pcbWritten = 0;
|
|
|
|
if(m_hfFile == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
if(pv == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
|
|
if((m_dwDesiredAccess & GENERIC_WRITE) == 0) // Read-only stream.
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_WRITEFAULT);
|
|
}
|
|
|
|
|
|
if(::WriteFile( m_hfFile, pv, cb, &dwWritten, NULL ) == FALSE)
|
|
{
|
|
DWORD dwRes = ::GetLastError();
|
|
|
|
if(dwRes == ERROR_DISK_FULL)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_MEDIUMFULL);
|
|
}
|
|
|
|
if(dwRes == ERROR_ACCESS_DENIED)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_ACCESSDENIED);
|
|
}
|
|
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_CANTSAVE);
|
|
}
|
|
|
|
if(pcbWritten) *pcbWritten = dwWritten;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP MPC::FileStream::Seek( /*[in] */ LARGE_INTEGER libMove ,
|
|
/*[in] */ DWORD dwOrigin ,
|
|
/*[out]*/ ULARGE_INTEGER *plibNewPosition )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Seek");
|
|
|
|
HRESULT hr;
|
|
|
|
if(plibNewPosition)
|
|
{
|
|
plibNewPosition->HighPart = 0;
|
|
plibNewPosition->LowPart = 0;
|
|
}
|
|
|
|
if(m_hfFile == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
|
|
switch(dwOrigin)
|
|
{
|
|
default :
|
|
case STREAM_SEEK_CUR: dwOrigin = FILE_CURRENT; break;
|
|
case STREAM_SEEK_SET: dwOrigin = FILE_BEGIN ; break;
|
|
case STREAM_SEEK_END: dwOrigin = FILE_END ; break;
|
|
}
|
|
|
|
if(::SetFilePointer( m_hfFile, libMove.LowPart, plibNewPosition ? (LONG*)&plibNewPosition->LowPart : NULL, dwOrigin ) == INVALID_SET_FILE_POINTER)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDFUNCTION );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP MPC::FileStream::Stat( /*[out]*/ STATSTG *pstatstg ,
|
|
/*[in] */ DWORD grfStatFlag )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Stat");
|
|
|
|
HRESULT hr;
|
|
BY_HANDLE_FILE_INFORMATION finfo;
|
|
|
|
if(pstatstg == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
if(m_hfFile == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
|
|
if(::GetFileInformationByHandle( m_hfFile, &finfo ) == FALSE)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_ACCESSDENIED);
|
|
}
|
|
|
|
|
|
pstatstg->pwcsName = NULL;
|
|
pstatstg->type = STGTY_STREAM;
|
|
pstatstg->cbSize.HighPart = finfo.nFileSizeHigh;
|
|
pstatstg->cbSize.LowPart = finfo.nFileSizeLow;
|
|
pstatstg->mtime = finfo.ftCreationTime;
|
|
pstatstg->ctime = finfo.ftLastAccessTime;
|
|
pstatstg->atime = finfo.ftLastWriteTime;
|
|
pstatstg->grfMode = 0;
|
|
pstatstg->grfLocksSupported = 0;
|
|
pstatstg->clsid = CLSID_NULL;
|
|
pstatstg->grfStateBits = 0;
|
|
pstatstg->reserved = 0;
|
|
|
|
if(grfStatFlag != STATFLAG_NONAME)
|
|
{
|
|
pstatstg->pwcsName = (LPWSTR)::CoTaskMemAlloc( (m_szFile.length() + 1) * sizeof(WCHAR) );
|
|
if(pstatstg->pwcsName == NULL)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, STG_E_INSUFFICIENTMEMORY);
|
|
}
|
|
|
|
StringCchCopyW( pstatstg->pwcsName, m_szFile.length() + 1, m_szFile.c_str() );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP MPC::FileStream::Clone( /*[out]*/ IStream* *ppstm )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::FileStream::Clone");
|
|
|
|
HRESULT hr;
|
|
MPC::CComObjectNoLock<MPC::FileStream>* pStm = NULL;
|
|
|
|
if(ppstm == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
|
|
|
|
//
|
|
// Create a new stream object.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pStm->CreateInstance( &pStm ));
|
|
|
|
//
|
|
// Initialize it with the same settings.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pStm->Init( m_szFile.c_str(), m_dwDesiredAccess, m_dwDisposition, m_dwSharing, m_hfFile ));
|
|
|
|
//
|
|
// QI for its IStream interface.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pStm->QueryInterface( IID_IStream, (void**)ppstm )); pStm = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
if(pStm) delete pStm;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
MPC::EncryptedStream::EncryptedStream()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::EncryptedStream");
|
|
|
|
// CComPtr<IStream> m_pStream;
|
|
m_hCryptProv = NULL; // HCRYPTPROV m_hCryptProv;
|
|
m_hKey = NULL; // HCRYPTKEY m_hKey;
|
|
m_hHash = NULL; // HCRYPTHASH m_hHash;
|
|
// BYTE m_rgDecrypted[512];
|
|
m_dwDecryptedPos = 0; // DWORD m_dwDecryptedPos;
|
|
m_dwDecryptedLen = 0; // DWORD m_dwDecryptedLen;
|
|
}
|
|
|
|
MPC::EncryptedStream::~EncryptedStream()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::~EncryptedStream");
|
|
|
|
Close();
|
|
}
|
|
|
|
HRESULT MPC::EncryptedStream::Close()
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Close");
|
|
|
|
m_pStream.Release();
|
|
|
|
if(m_hHash)
|
|
{
|
|
::CryptDestroyHash( m_hHash ); m_hHash = NULL;
|
|
}
|
|
|
|
if(m_hKey)
|
|
{
|
|
::CryptDestroyKey( m_hKey ); m_hKey = NULL;
|
|
}
|
|
|
|
if(m_hCryptProv)
|
|
{
|
|
::CryptReleaseContext( m_hCryptProv, 0 ); m_hCryptProv = NULL;
|
|
}
|
|
|
|
m_dwDecryptedPos = 0;
|
|
m_dwDecryptedLen = 0;
|
|
|
|
__MPC_FUNC_EXIT(S_OK);
|
|
}
|
|
|
|
HRESULT MPC::EncryptedStream::Init( /*[in]*/ IStream* pStream ,
|
|
/*[in]*/ LPCWSTR szPassword )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Init");
|
|
|
|
HRESULT hr;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_NOTNULL(pStream);
|
|
__MPC_PARAMCHECK_STRING_NOT_EMPTY(szPassword);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
Close();
|
|
|
|
m_pStream = pStream;
|
|
|
|
if(!::CryptAcquireContext( &m_hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT ))
|
|
{
|
|
DWORD dwRes = ::GetLastError();
|
|
|
|
if(dwRes != NTE_BAD_KEYSET)
|
|
{
|
|
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
|
|
}
|
|
|
|
//
|
|
// Key set doesn't exist, let's create one.
|
|
//
|
|
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptAcquireContext( &m_hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_SILENT ));
|
|
}
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptCreateHash( m_hCryptProv, CALG_MD5, 0, 0, &m_hHash ));
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptHashData( m_hHash, (BYTE *)szPassword, sizeof(WCHAR) * wcslen( szPassword ), 0 ));
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptDeriveKey( m_hCryptProv, CALG_RC4, m_hHash, CRYPT_EXPORTABLE, &m_hKey ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
if(FAILED(hr)) Close();
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT MPC::EncryptedStream::Init( /*[in]*/ IStream* pStream ,
|
|
/*[in]*/ HCRYPTKEY hKey )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Init");
|
|
|
|
HRESULT hr;
|
|
|
|
__MPC_PARAMCHECK_BEGIN(hr)
|
|
__MPC_PARAMCHECK_NOTNULL(pStream);
|
|
__MPC_PARAMCHECK_NOTNULL(hKey);
|
|
__MPC_PARAMCHECK_END();
|
|
|
|
|
|
Close();
|
|
|
|
m_pStream = pStream;
|
|
m_hKey = hKey;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
if(FAILED(hr)) Close();
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP MPC::EncryptedStream::Read( /*[out]*/ void* pv ,
|
|
/*[in] */ ULONG cb ,
|
|
/*[out]*/ ULONG *pcbRead )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Read");
|
|
|
|
HRESULT hr;
|
|
DWORD dwRead = 0;
|
|
|
|
if(pcbRead) *pcbRead = 0;
|
|
|
|
if(m_pStream == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
if(m_hKey == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
if(pv == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
|
|
|
|
while(cb > 0)
|
|
{
|
|
DWORD dwCount = min( cb, (m_dwDecryptedLen - m_dwDecryptedPos));
|
|
ULONG ulRead;
|
|
|
|
if(dwCount)
|
|
{
|
|
::CopyMemory( pv, &m_rgDecrypted[m_dwDecryptedPos], dwCount );
|
|
|
|
m_dwDecryptedPos += dwCount;
|
|
|
|
dwRead += dwCount;
|
|
cb -= dwCount;
|
|
pv = &((BYTE*)pv)[dwCount];
|
|
}
|
|
else
|
|
{
|
|
dwCount = sizeof(m_rgDecrypted);
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_pStream->Read( m_rgDecrypted, dwCount, &ulRead ));
|
|
if(hr == S_FALSE || ulRead == 0) break;
|
|
|
|
dwCount = ulRead;
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptDecrypt( m_hKey, 0, FALSE, 0, m_rgDecrypted, &dwCount ));
|
|
|
|
m_dwDecryptedPos = 0;
|
|
m_dwDecryptedLen = dwCount;
|
|
}
|
|
}
|
|
|
|
if(pcbRead) *pcbRead = dwRead;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP MPC::EncryptedStream::Write( /*[in] */ const void* pv ,
|
|
/*[in] */ ULONG cb ,
|
|
/*[out]*/ ULONG *pcbWritten )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Write");
|
|
|
|
HRESULT hr;
|
|
DWORD dwWritten = 0;
|
|
|
|
|
|
if(pcbWritten) *pcbWritten = 0;
|
|
|
|
if(m_pStream == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
if(m_hKey == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
if(pv == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
|
|
|
|
while(cb > 0)
|
|
{
|
|
BYTE rgTmp[512];
|
|
DWORD dwCount = min( cb, sizeof(rgTmp) / 2 ); // Let's divide by two, just in case...
|
|
ULONG ulWritten;
|
|
|
|
::CopyMemory( rgTmp, pv, dwCount );
|
|
|
|
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CryptEncrypt( m_hKey, 0, FALSE, 0, rgTmp, &dwCount, sizeof(rgTmp) ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_pStream->Write( rgTmp, dwCount, &ulWritten ));
|
|
|
|
dwWritten += dwCount;
|
|
cb -= dwCount;
|
|
pv = &((BYTE*)pv)[dwCount];
|
|
}
|
|
|
|
if(pcbWritten) *pcbWritten = dwWritten;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP MPC::EncryptedStream::Seek( /*[in] */ LARGE_INTEGER libMove ,
|
|
/*[in] */ DWORD dwOrigin ,
|
|
/*[out]*/ ULARGE_INTEGER *plibNewPosition )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Seek");
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
hr = E_NOTIMPL;
|
|
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP MPC::EncryptedStream::Stat( /*[out]*/ STATSTG *pstatstg ,
|
|
/*[in] */ DWORD grfStatFlag )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Stat");
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
if(m_pStream == NULL) __MPC_SET_ERROR_AND_EXIT(hr, STG_E_INVALIDPOINTER);
|
|
|
|
|
|
hr = m_pStream->Stat( pstatstg, grfStatFlag );
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
STDMETHODIMP MPC::EncryptedStream::Clone( /*[out]*/ IStream* *ppstm )
|
|
{
|
|
__MPC_FUNC_ENTRY( COMMONID, "MPC::EncryptedStream::Clone");
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
hr = E_NOTIMPL;
|
|
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|