windows-nt/Source/XPSP1/NT/termsrv/license/lkplite/base24.cpp
2020-09-26 16:20:57 +08:00

423 lines
9.2 KiB
C++

//+--------------------------------------------------------------------------
//
// Copyright (c) 1997-1999 Microsoft Corporation
//
// File:
//
// Contents:
//
// History:
//
//---------------------------------------------------------------------------
#include <windows.h>
#include <assert.h>
#include <math.h>
class CDataCoding {
private:
DWORD m_dwBaseDigits;
DWORD m_dwEncodedLength;
DWORD m_dwInputDataBits;
DWORD m_dwInputDataBytes;
DWORD m_dwDecodedLength;
DWORD m_dwInputEncDataBytes;
DWORD m_dwDecodedBits;
TCHAR * m_tpBaseDigits;
public:
CDataCoding(TCHAR * tpBaseDigits = NULL);
void SetInputDataBitLen(DWORD dwBits);
void SetInputEncDataLen(DWORD dwChars);
DWORD SetBaseDigits(TCHAR * tpBaseDigits);
DWORD EncodeData(LPBYTE pbSource, //[IN] Stream of Bytes to be encoded
TCHAR **pbEncodedData); //[OUT] Pointer to a string containing the encoded data
DWORD DecodeData(TCHAR * pbEncodedData,
LPBYTE * pbDecodedData);
~CDataCoding();
};
class CBase24Coding : public CDataCoding {
public:
CBase24Coding(void) : CDataCoding(L"BCDFGHJKMPQRTVWXY2346789")
{
return;
}
};
static CBase24Coding b24Global;
// **************************************************************
DWORD B24EncodeMSID(LPBYTE pbSource, TCHAR **pbEncodedData)
{
b24Global.SetInputDataBitLen(160);
return b24Global.EncodeData(pbSource, pbEncodedData);
}
// ***************************************************************
DWORD B24DecodeMSID(TCHAR * pbEncodedData, LPBYTE * pbDecodedData)
{
b24Global.SetInputEncDataLen(35);
return b24Global.DecodeData(pbEncodedData, pbDecodedData);
}
// ***********************************************************
DWORD B24EncodeCNumber(LPBYTE pbSource, TCHAR **pbEncodedData)
{
b24Global.SetInputDataBitLen(32);
return b24Global.EncodeData(pbSource, pbEncodedData);
}
// ******************************************************************
DWORD B24DecodeCNumber(TCHAR * pbEncodedData, LPBYTE * pbDecodedData)
{
b24Global.SetInputEncDataLen(7);
return b24Global.DecodeData(pbEncodedData, pbDecodedData);
}
// *******************************************************
DWORD B24EncodeSPK(LPBYTE pbSource, TCHAR **pbEncodedData)
{
b24Global.SetInputDataBitLen(114);
return b24Global.EncodeData(pbSource, pbEncodedData);
}
// ******************************************************************
DWORD B24DecodeSPK(TCHAR * pbEncodedData, LPBYTE * pbDecodedData)
{
b24Global.SetInputEncDataLen(25);
return b24Global.DecodeData(pbEncodedData, pbDecodedData);
}
// *****************************************
CDataCoding::CDataCoding(TCHAR * tpBaseDigits)
{
m_tpBaseDigits = NULL;
m_dwBaseDigits = 0;
m_dwEncodedLength = 0;
m_dwInputDataBits = 0;
m_dwInputDataBytes = 0;
SetBaseDigits(tpBaseDigits);
}
// ********************************************
void CDataCoding::SetInputDataBitLen(DWORD dwBits)
{
assert(dwBits > 0);
assert(log(m_dwBaseDigits) > 0);
// Determine How many Characters would be required to encode the data
// What we have is a dwDataLength of Binary Data stream.
// So, we can represent 2^(dwDataLength*8) amount of information using these bits
// Assuming that our set of digits (which form the base for encoding) is X,
// the above number should then equal X^(NumberofEncoded Digits)
// So,
double dLength = ((double) dwBits*log10(2)) /
((double) log10(m_dwBaseDigits));
// Now round - up
m_dwEncodedLength = (DWORD) dLength;
if ((double) m_dwEncodedLength < dLength)
{
// There was a decimal part
m_dwEncodedLength++;
}
m_dwInputDataBits = dwBits;
m_dwInputDataBytes = (dwBits / 8) + (dwBits % 8 ? 1 : 0);
return;
}
// ***********************************************
void CDataCoding::SetInputEncDataLen(DWORD dwBytes)
{
assert(dwBytes > 0);
assert(log(m_dwBaseDigits) > 0);
m_dwInputEncDataBytes = dwBytes;
// Determine How many bits would be required to decode this data
// So,
double dLength = ((double) dwBytes*log10(m_dwBaseDigits))/
((double) log10(2));
// Now round - up
m_dwDecodedBits = (DWORD) dLength;
if ((double) m_dwDecodedBits < dLength)
{
// There was a decimal part
m_dwDecodedBits++;
}
m_dwDecodedLength = (m_dwDecodedBits / 8) + (m_dwDecodedBits % 8 ? 1 : 0);
return;
}
// **************************************************
DWORD CDataCoding::SetBaseDigits(TCHAR * tpBaseDigits)
{
DWORD dwReturn = ERROR_SUCCESS;
if (tpBaseDigits != NULL)
{
DWORD dwLen = wcslen(tpBaseDigits);
assert(dwLen > 0);
m_tpBaseDigits = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dwLen+1)*sizeof(TCHAR));
if (m_tpBaseDigits == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
memcpy(m_tpBaseDigits, tpBaseDigits, (dwLen+1)*sizeof(TCHAR));
m_dwBaseDigits = dwLen;
}
}
else
{
if (m_tpBaseDigits != NULL)
{
HeapFree(GetProcessHeap(), 0, m_tpBaseDigits);
m_tpBaseDigits = NULL;
m_dwBaseDigits = 0;
}
assert(m_tpBaseDigits == NULL && m_dwBaseDigits == 0);
}
return dwReturn;
}
// ************************************************
DWORD CDataCoding::EncodeData(LPBYTE pbSource, //[IN] Stream of Bytes to be encoded
TCHAR **pbEncodedData) //[OUT] Pointer to a string containing the encoded data
// I allocate the Buffer, you should free it
{
assert(m_dwInputDataBits > 0);
assert(m_dwInputDataBytes > 0);
assert(m_dwEncodedLength > 0);
assert(m_tpBaseDigits != NULL);
DWORD dwReturn = ERROR_SUCCESS;
int nStartIndex = m_dwEncodedLength;
*pbEncodedData = NULL;
BYTE * pbDataToEncode = NULL;
TCHAR * pbEncodeBuffer = NULL;
if (NULL == pbEncodedData)
{
dwReturn = ERROR_INVALID_PARAMETER;
goto done;
}
*pbEncodedData = NULL;
pbEncodeBuffer = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
(m_dwEncodedLength+1)*sizeof(TCHAR));
if (pbEncodeBuffer == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
// Now need to make a copy of the incoming data, so we can run the algorithm below
pbDataToEncode = (BYTE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_dwInputDataBytes);
if (pbDataToEncode == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
memcpy(pbDataToEncode, pbSource, m_dwInputDataBytes);
// Let us get rid of the simple stuff
pbEncodeBuffer[ nStartIndex--] = 0;
for (; nStartIndex >= 0; --nStartIndex)
{
unsigned int i = 0;
for (int nIndex = m_dwInputDataBytes-1; 0 <= nIndex; --nIndex)
{
i = (i * 256) + pbDataToEncode[nIndex];
pbDataToEncode[ nIndex] = (BYTE)(i / m_dwBaseDigits);
i %= m_dwBaseDigits;
}
// i now contains the remainder, which is the current digit
pbEncodeBuffer[ nStartIndex] = m_tpBaseDigits[ i];
}
assert(dwReturn == ERROR_SUCCESS);
*pbEncodedData = pbEncodeBuffer;
done:
if (pbDataToEncode != NULL)
{
HeapFree(GetProcessHeap(), 0, pbDataToEncode);
}
if (dwReturn != ERROR_SUCCESS)
{
// There was an error, so free the memory that you allocated
if (pbEncodeBuffer != NULL)
{
HeapFree(GetProcessHeap(), 0, pbEncodeBuffer);
}
}
return dwReturn;
}
// *************************************************
DWORD CDataCoding::DecodeData(TCHAR * pbEncodedData,
LPBYTE * pbDecodedData)
// Again, I allocate the Buffer, you release it
{
assert(m_dwDecodedBits > 0);
assert(m_dwDecodedLength > 0);
assert(m_tpBaseDigits != NULL);
assert((DWORD) lstrlen(pbEncodedData) == m_dwInputEncDataBytes);
DWORD dwReturn = ERROR_SUCCESS;
TCHAR * tpTemp;
DWORD dwDigit;
unsigned int i;
unsigned int nDecodedBytes, nDecodedBytesMax = 0;
BYTE * pbDecodeBuffer = NULL;
if (NULL == pbDecodedData)
{
dwReturn = ERROR_INVALID_PARAMETER;
goto done;
}
*pbDecodedData = NULL;
pbDecodeBuffer = (BYTE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_dwDecodedLength);
if ( pbDecodeBuffer == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
memset(pbDecodeBuffer, 0, m_dwDecodedLength);
while (*pbEncodedData)
{
// First Find the position of this character in the Base Encoding Character Set
tpTemp = wcschr(m_tpBaseDigits, *pbEncodedData);
if (tpTemp == NULL)
{
// Found a character which is not in base character set
// ERROR ERROR
dwReturn = ERROR_INVALID_DATA;
goto done;
}
dwDigit = (DWORD)(tpTemp - m_tpBaseDigits);
nDecodedBytes = 0;
i = (unsigned int) dwDigit;
while (nDecodedBytes <= nDecodedBytesMax)
{
i += m_dwBaseDigits * pbDecodeBuffer[ nDecodedBytes];
pbDecodeBuffer[ nDecodedBytes] = (unsigned char)i;
i /= 256;
++nDecodedBytes;
}
if (i != 0)
{
assert(nDecodedBytes < m_dwDecodedLength);
pbDecodeBuffer[ nDecodedBytes] = (unsigned char)i;
nDecodedBytesMax = nDecodedBytes;
}
pbEncodedData++;
}
assert(dwReturn == ERROR_SUCCESS);
*pbDecodedData = pbDecodeBuffer;
done:
if (dwReturn != ERROR_SUCCESS)
{
// There was an error, so free the memory that you allocated
if (pbDecodeBuffer != NULL)
{
HeapFree(GetProcessHeap(), 0, pbDecodeBuffer);
}
}
return dwReturn;
}
// **********************
CDataCoding::~CDataCoding()
{
if (m_tpBaseDigits != NULL)
{
HeapFree(GetProcessHeap(), 0, m_tpBaseDigits);
m_tpBaseDigits = NULL;
m_dwBaseDigits = 0;
}
}