#ifndef __AdminSessionSecure_h__
#define __AdminSessionSecure_h__
/////////////////////////////////////////////////////////////////////////////
#ifndef RETURN_FAILED
///////////////////////////////////////////////////////////////////////////
// Evaluates an HRESULT expression and returns it if it indicates failure.
// This should only be used from a function that has an HRESULT (or
// compatible) return type.
//
// Parameters:
// exp - The HRESULT expression to be evaluated.
//
// See Also: RETURN_FAILED_VOID, ThrowError, ThrowErrorFAILED
//
#define RETURN_FAILED(exp) \
do \
{ \
HRESULT _hr = exp; \
if (FAILED(_hr)) \
return _hr; \
} while (false)
#endif // !RETURN_FAILED
/////////////////////////////////////////////////////////////////////////////
//
template <const GUID* pguid>
struct CAdminSessionSecure
{
static HRESULT CreateEncryptedStream(IStream* pstmIn, IStream** ppstmOut)
{
// Rewind the input stream
LARGE_INTEGER li = {0};
RETURN_FAILED(pstmIn->Seek(li, STREAM_SEEK_SET, NULL));
// Create a new memory stream
IStreamPtr spStmOut;
RETURN_FAILED(CreateStreamOnHGlobal(NULL, true, &spStmOut));
// XOR the stream with specified GUID
const BYTE* pbGUID = reinterpret_cast<const BYTE*>(pguid);
const BYTE* pbEnd = pbGUID + sizeof(GUID);
while (true)
{
// Read in a GUID-sized chunk from the stream
BYTE pBuffer[sizeof(GUID)];
ULONG cbRead;
RETURN_FAILED(pstmIn->Read(pBuffer, sizeof(GUID), &cbRead));
if (!cbRead)
break;
// Loop through each DWORD and XOR it with the GUID
BYTE* pbData = pBuffer;
for (const BYTE* pb = pbGUID; pb < pbEnd; pb += sizeof(DWORD),
pbData += sizeof(DWORD))
{
const DWORD* pdwGUID = reinterpret_cast<const DWORD*>(pb);
DWORD* pdwData = reinterpret_cast< DWORD*>(pbData);
*pdwData ^= *pdwGUID;
}
// Write the encoded chunk to the output stream
RETURN_FAILED(spStmOut->Write(pBuffer, cbRead, NULL));
}
// Detach the new stream to the [out] parameter
*ppstmOut = spStmOut.Detach();
// Indicate success
return S_OK;
}
static HRESULT CreateDecryptedStream(IStream* pstmIn, IStream** ppstmOut)
{
// Current algorithm is the same for encrypt and decrypt
return CreateEncryptedStream(pstmIn, ppstmOut);
}
};
/////////////////////////////////////////////////////////////////////////////
#endif // !__AdminSessionSecure_h__