//
// (w)ritten by andreas saurwein 2002, mailto:saurwein@uniwares.com
//
#include "StdAfx.h"
#include "protecteddata.h"
CProtectedData::CProtectedData(BOOL bSilent, BOOL bLocal, BOOL bAudit) :
m_bSilent(bSilent),
m_bLocal(bLocal),
m_bAudit(bAudit)
{
m_ProtectedData.cbData = 0;
m_ProtectedData.pbData = NULL;
m_Prompt.cbSize = sizeof(m_Prompt);
m_Prompt.hwndApp = NULL;
m_Prompt.szPrompt = NULL;
}
CProtectedData::~CProtectedData()
{
#ifndef _UNICODE
if(m_Prompt.szPrompt) // only non-unicode builds allocate memory for the conversion
delete[] m_Prompt.szPrompt;
#endif
// call FreeProtectedData() before dtor
ASSERT(m_ProtectedData.cbData==0 && m_ProtectedData.pbData == NULL);
}
void CProtectedData::SetAudit(BOOL bAudit)
{
m_bAudit = bAudit;
}
void CProtectedData::SetLocal(BOOL bLocal)
{
m_bLocal = bLocal;
}
void CProtectedData::SetUI(HWND hWnd, LPCTSTR pPrompt)
{
// setting the UI params clears the silence flag
m_bSilent = FALSE;
m_Prompt.hwndApp = hWnd;
#ifdef _UNICODE
m_Prompt.szPrompt = pPrompt;
#else
// Convert to Unicode, free if existing
if(m_Prompt.szPrompt)
delete[] m_Prompt.szPrompt;
size_t nLen = strlen(pPrompt);
m_Prompt.szPrompt = new WCHAR[nLen+1];
::MultiByteToWideChar(CP_ACP, 0, pPrompt, -1, (LPWSTR)m_Prompt.szPrompt, (int)nLen+1);
#endif
}
void CProtectedData::SetData(LPBYTE pData, DWORD dwSize)
{
m_pData = pData;
m_dwSize = dwSize;
}
const DATA_BLOB* CProtectedData::ProtectData()
{
return ProtectData(NULL, NULL, 0);
}
const DATA_BLOB* CProtectedData::ProtectData(LPCTSTR pDesc)
{
return ProtectData(pDesc, NULL, 0);
}
const DATA_BLOB* CProtectedData::ProtectData(LPCTSTR pDesc, const CString& rString)
{
return ProtectData(pDesc, (LPBYTE)(LPCTSTR)rString, rString.GetLength());
}
const DATA_BLOB* CProtectedData::ProtectData(LPCTSTR pDesc, LPCTSTR pString)
{
return ProtectData(pDesc, (LPBYTE)pString, (DWORD)_tcslen(pString));
}
const DATA_BLOB* CProtectedData::ProtectData(LPCTSTR pDesc, LPBYTE pEntropy, DWORD dwEntropySize)
{
PCRYPTPROTECT_PROMPTSTRUCT pps = NULL;
DATA_BLOB dbIn;
DATA_BLOB dbEntropy;
PDATA_BLOB pdbEntropy=NULL;
// cryptoapi takes UNICODE strings, so we need to convert.
LPWSTR pwDesc = NULL;
ASSERT(m_dwSize > 0);
ASSERT(m_pData != NULL);
// set up the data
dbIn.cbData = m_dwSize;
dbIn.pbData = m_pData;
// set up the entropy
if(dwEntropySize)
{
dbEntropy.cbData = dwEntropySize;
dbEntropy.pbData = pEntropy;
pdbEntropy = &dbEntropy;
}
// set up the prompt if needed
if(!m_bSilent)
{
m_Prompt.dwPromptFlags = CRYPTPROTECT_PROMPT_ON_PROTECT;
pps = &m_Prompt;
}
// if we have a description for the data_blob, prepare it for use
if(pDesc && _tcslen(pDesc))
{
#ifndef _UNICODE
size_t nLen = strlen(pDesc);
pwDesc = new WCHAR[nLen+1];
::MultiByteToWideChar(CP_ACP, 0, pDesc, -1, pwDesc, (int)nLen+1);
#else
pwDesc = (LPWSTR)pDesc;
#endif
}
m_ProtectedData.cbData = 0;
m_ProtectedData.pbData = NULL;
//
// prepare the flags
//
DWORD dwFlags = NULL;
if(m_bSilent)
dwFlags |= CRYPTPROTECT_UI_FORBIDDEN;
if(m_bLocal)
dwFlags |= CRYPTPROTECT_LOCAL_MACHINE;
if(m_bAudit)
dwFlags |= CRYPTPROTECT_AUDIT;
// do the encryption
::CryptProtectData(&dbIn, pwDesc, pdbEntropy, NULL, pps, dwFlags, &m_ProtectedData);
#ifndef _UNICODE
if(pwDesc) delete[] pwDesc;
#endif
return &m_ProtectedData;
}
void CProtectedData::FreeProtectedData()
{
if(m_ProtectedData.pbData)
{
::LocalFree(m_ProtectedData.pbData);
m_ProtectedData.pbData = NULL;
m_ProtectedData.cbData = 0;
}
}
DATA_BLOB* CProtectedData::UnprotectData()
{
return UnprotectData(NULL, NULL, 0);
}
DATA_BLOB* CProtectedData::UnprotectData(LPTSTR* pDesc)
{
return UnprotectData(pDesc, NULL, 0);
}
DATA_BLOB* CProtectedData::UnprotectData(LPTSTR* pDesc, const CString& rString)
{
return UnprotectData(pDesc, (LPBYTE)(LPCTSTR)rString, rString.GetLength());
}
DATA_BLOB* CProtectedData::UnprotectData(LPTSTR* pDesc, LPCTSTR pString)
{
return UnprotectData(pDesc, (LPBYTE)pString, (DWORD)_tcslen(pString));
}
DATA_BLOB* CProtectedData::UnprotectData(LPTSTR* pDesc, LPBYTE pEntropy, DWORD dwEntropySize)
{
PCRYPTPROTECT_PROMPTSTRUCT pps = NULL;
DATA_BLOB dbIn;
DATA_BLOB dbEntropy;
PDATA_BLOB pdbEntropy=NULL;
LPWSTR pwDesc = NULL;
ASSERT(m_dwSize > 0);
ASSERT(m_pData != NULL);
// set up the data
dbIn.cbData = m_dwSize;
dbIn.pbData = m_pData;
// set up the entropy
if(dwEntropySize)
{
dbEntropy.cbData = dwEntropySize;
dbEntropy.pbData = pEntropy;
pdbEntropy = &dbEntropy;
}
// set up the prompt if needed
if(!m_bSilent)
{
m_Prompt.dwPromptFlags = CRYPTPROTECT_PROMPT_ON_UNPROTECT;
pps = &m_Prompt;
}
m_ProtectedData.cbData = 0;
m_ProtectedData.pbData = NULL;
//
// prepare the flags
//
DWORD dwFlags = NULL;
if(m_bSilent)
dwFlags |= CRYPTPROTECT_UI_FORBIDDEN;
if(m_bLocal)
dwFlags |= CRYPTPROTECT_LOCAL_MACHINE;
if(m_bAudit)
dwFlags |= CRYPTPROTECT_AUDIT;
// do the encryption
if(::CryptUnprotectData(&dbIn, pDesc ? &pwDesc : NULL, pdbEntropy, NULL, pps, dwFlags, &m_ProtectedData) && pDesc)
{
// if pDesc actuall points to somewhere, put the description there if available in pwDesc
if(pwDesc && wcslen(pwDesc))
{
#ifndef _UNICODE
BOOL bDefault;
size_t nLen = wcslen(pwDesc);
LPSTR p = (LPSTR) ::LocalAlloc(LPTR, nLen+1);
::WideCharToMultiByte(CP_ACP, 0, pwDesc, -1, p, (int)nLen+1, _T(""), &bDefault);
*pDesc = p;
#else
*pDesc = pwDesc;
#endif
}
}
return &m_ProtectedData;
}
void CProtectedData::FreeUnprotectedData()
{
if(m_ProtectedData.pbData)
{
::LocalFree(m_ProtectedData.pbData);
m_ProtectedData.pbData = NULL;
m_ProtectedData.cbData = 0;
}
}