📄 ctrialmgr.cpp
字号:
/*
@(#) $Id$
AxCrypt - Compressing and Encrypting Wrapper and Application Launcher for Secure Local,
Server or Web Storage of Document Files.
Copyright (C) 2004 Svante Seleborg/Axantum Software AB, All rights reserved.
This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program;
if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
The author may be reached at mailto:axcrypt@axondata.se and http://axcrypt.sourceforge.net
----
CTrialMgr.cpp Handle trial counters etc.
*/
#include "stdafx.h"
#include "CTrialMgr.h"
#include "AxAssert.h"
#define AXLIB_ASSERT_FILE "CTrialMgr.cpp"
/// \brief Initialize access to the trial counter storage.
CTrialMgr::CTrialMgr(const string &sProgram) {
// InitializeCriticalSection(&m_CritObj);
// m_pCritSect = auto_ptr<CCriticalSection>(new CCriticalSection(&m_CritObj));
m_fTryCryptSilentFirst = true;
m_sProgram = sProgram;
}
CTrialMgr::~CTrialMgr() {
}
/// \brief Convert an integer to a string
/// \param i An integer to convert to a decimal string
/// \return A decimal representation of the integer
string
CTrialMgr::IntStr(int i) {
_TCHAR szCount[34]; // Base 2^32 is 32 bits/chars + sign + NUL for itoa et.al.
_itot(i, szCount, 10);
return szCount;
}
/// \brief Acquire context with Windows 98 compatibility
bool
CTrialMgr::AcquireContext(HCRYPTPROV *hProv, const string &sContainer, unsigned long ulFlags) {
if (m_fTryCryptSilentFirst) {
if (!CryptAcquireContext(hProv, sContainer.c_str(), MS_DEF_PROV, PROV_RSA_FULL, ulFlags|CRYPT_SILENT)) {
if (GetLastError() == NTE_BAD_FLAGS) {
m_fTryCryptSilentFirst = false;
} else {
return false;
}
} else {
return true;
}
}
return !!CryptAcquireContext(hProv, sContainer.c_str(), MS_DEF_PROV, PROV_RSA_FULL, ulFlags);
}
/// \brief enumerate available containers.
/// When the MS documentation says that this does not work in a multi-thread context - they are not
/// kidding. It does not. Period. I cannot get PP_ENUMCONTAINERS to work consistently in any reasonable
/// way (although I have not tried linking with the single-threaded library). If anybody spots the obvious?
/// problem with the commented code, please let me know. This is annoying, but I just don't have the time
/// to dig deeper at this time.
/// So for the time being, we simply loop incrementingly...
/// \reutrn The current value for the given type.
int
CTrialMgr::GetCounterRep(const string &sType, const int iMax) {
const string sPrefix = m_sProgram + sType;
HCRYPTPROV hProv = NULL;
// We have an absolut maximum here of 100 - we can't sit here for ever even if no maximum is specified
// in the call.
for (int iCount = 0; (iMax < 0 && iCount <= 100) || iCount <= iMax; iCount++) {
// Convert the new use-counter to a string and use it to reference a container
if (!AcquireContext(&hProv, sPrefix + IntStr(iCount))) {
// The normal error is NTE_BAD_KEYS - which means not found
ASSAPI(GetLastError() == NTE_BAD_KEYSET || GetLastError() == ERROR_FILE_NOT_FOUND);
// ERROR_FILE_NOT_FOUND may be returned if we do not have a profile loaded, specifically
// if we're running impersonated. This appears to work differently (as always) in different
// windowses, but at least in Windows 2000 this is a problem, so we treat this as a case
// of no counter present.
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
return 0;
}
} else {
CryptReleaseContext(hProv, 0);
return iCount;
}
}
return 0;
/*
DWORD dwLen = 0, dwFlags = CRYPT_FIRST;
auto_ptr<_TCHAR> szContainerName;
HCRYPTPROV hProv = NULL;
if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_SILENT)) {
ASSAPI(GetLastError() == NTE_BAD_KEYSET);
ASSAPI(CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_SILENT|CRYPT_NEWKEYSET));
}
//m_pCritSect->Enter();
if (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, NULL, &dwLen, dwFlags) != TRUE) {
// Probaby we don't need this and the code below both. This appears to be severly confused
// by multi-threading.
ASSAPI(GetLastError() == ERROR_NO_MORE_ITEMS);
return _T("");
}
szContainerName = auto_ptr<_TCHAR>(new _TCHAR[dwLen / sizeof _TCHAR]);
while (true) {
if (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, (BYTE *)szContainerName.get(), &dwLen, dwFlags) != TRUE) {
ASSAPI(GetLastError() == ERROR_NO_MORE_ITEMS);
szContainerName = auto_ptr<_TCHAR>(NULL);
break;
}
MessageBox(NULL, szContainerName.get(), _T("Test"), MB_OK);
if (_tcslen(szContainerName.get()) > sPrefix.length() && _tcsncicmp(szContainerName.get(), sPrefix.c_str(), m_sProgram.length()) == 0) {
break;
}
dwFlags = 0; // Continue enumerating...
}
//m_pCritSect->Leave();
ASSAPI(CryptReleaseContext(hProv, 0));
hProv = NULL;
if (szContainerName.get()) {
return szContainerName.get();
} else {
return _T("");
}
*/
}
/// \brief Add a new container
void
CTrialMgr::AddCounterRep(const string &sType, const int iCtr) {
string sContainer = m_sProgram + sType + IntStr(iCtr);
// We should check if it's there first...
HCRYPTPROV hProv = NULL;
if (!AcquireContext(&hProv, sContainer)) {
// It' ok - it's just not there...
ASSAPI(GetLastError() == NTE_BAD_KEYSET);
} else {
// We could acquire a context! Release and return. We're done - it was already there.
ASSAPI(CryptReleaseContext(hProv, 0));
hProv = NULL;
return;
}
ASSAPI(AcquireContext(&hProv, sContainer, CRYPT_NEWKEYSET));
// Let's generate a key to make the container contain something. It may also be useful in encoding
// higher bandwidth trial-info than just a small counter.
// HCRYPTKEY hKey;
// ASSAPI(CryptGenKey(hProv, AT_SIGNATURE, 0, &hKey));
// ASSAPI(CryptDestroyKey(hKey));
// hKey = NULL;
ASSAPI(CryptReleaseContext(hProv, 0));
hProv = NULL;
}
/// \brief Delete an existing counter
void CTrialMgr::DeleteCounterRep(const string &sType, const int iCtr) {
// We should check if it's there first...
HCRYPTPROV hProv = NULL;
if (!AcquireContext(&hProv, m_sProgram + sType + IntStr(iCtr))) {
ASSAPI(GetLastError() == NTE_BAD_KEYSET);
return;
}
ASSAPI(CryptReleaseContext(hProv, 0));
hProv = NULL;
ASSAPI(AcquireContext(&hProv, m_sProgram + sType + IntStr(iCtr), CRYPT_DELETEKEYSET));
}
/// \brief Get the trial counter as it is now
int CTrialMgr::Get(const string &sCounterName, int iMax) {
// Check if we already have this counter
if (m_simTypeCtr.find(sCounterName) == m_simTypeCtr.end()) {
// Nope - get it from our counter store
m_simTypeCtr[sCounterName] = GetCounterRep(sCounterName, iMax);
}
// Now we do - get it from our memory map
return m_simTypeCtr[sCounterName];
}
/// \brief Increment a trial counter by one, and return the result.
/// The result returned is maximized by the iMax parameter + 1. If
/// iMax is < 0, there is no limit.
/// \param iMax The maximum value of the counter.
/// \return The new value, or what it would have been if allowed.
int
CTrialMgr::Increment(int iMax, const string &sCounterName) {
int iCount = Get(sCounterName, iMax);
// If we are at or above the legal limit, if any, just return that plus one.
if (iMax >= 0 && iCount >= iMax) {
return iMax + 1;
}
// Start by writing a new container.
AddCounterRep(sCounterName, iCount + 1);
Clear(iCount);
// Update the current counter value, and return
return m_simTypeCtr[sCounterName] = iCount + 1;
}
/// \brief Clear a counter, if it exists.
/// \param iCount the counter to clear. Nothing happens if it is zero.
void
CTrialMgr::Clear(const int iCount, const string &sCounterName) {
if (iCount) {
// We never write a zero-counter - so it only makes sense to delete if non-zero
DeleteCounterRep(sCounterName, iCount);
// We keep this around to avoid re-searching if asked again via Get()
m_simTypeCtr[sCounterName] = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -