⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctrialmgr.cpp

📁 研读AxCrypt对加解密的处理方法
💻 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 + -