windows-nt/Source/XPSP1/NT/enduser/windows.com/wuv3/cdmlib/usecrc.cpp
2020-09-26 16:20:57 +08:00

339 lines
6.3 KiB
C++

//=======================================================================
//
// Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
//
// File: filecrc.h
//
// Purpose: Calculating and using CRC for files
//
//=======================================================================
#include <windows.h>
#include <objbase.h>
#include <filecrc.h>
#include <search.h> // for bsearch
#include <tchar.h>
#include <atlconv.h>
HRESULT GetCRCNameFromList(int iNo, PBYTE pmszCabList, PBYTE pCRCList, LPTSTR pszCRCName, int cbCRCName, LPTSTR pszCabName)
{
USES_CONVERSION;
int i = 0;
WUCRC_HASH* pCRC = (WUCRC_HASH*)pCRCList;
if ( (NULL == pmszCabList) || (NULL == pCRCList) )
return E_INVALIDARG;
for (LPSTR pszFN = (LPSTR)pmszCabList; *pszFN; pszFN += strlen(pszFN) + 1)
{
if (i == iNo)
{
lstrcpy(pszCabName, A2T(pszFN));
return MakeCRCName(A2T(pszFN), pCRC, pszCRCName, cbCRCName);
}
pCRC++;
i++;
}
// if we got here that means we did not find the request element
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
HRESULT StringFromCRC(const WUCRC_HASH* pCRC, LPTSTR pszBuf, int cbBuf)
{
LPTSTR p = pszBuf;
BYTE b;
//check the input argument, to see that it is not NULL
if (NULL == pCRC)
{
return E_INVALIDARG;
}
if (cbBuf < ((WUCRC_HASH_SIZE * 2) + 1))
{
return TYPE_E_BUFFERTOOSMALL;
}
for (int i = 0; i < WUCRC_HASH_SIZE; i++)
{
b = pCRC->HashBytes[i] >> 4;
if (b <= 9)
*p = '0' + (TCHAR)b;
else
*p = 'A' + (TCHAR)(b - 10);
p++;
b = pCRC->HashBytes[i] & 0x0F;
if (b <= 9)
*p = '0' + (TCHAR)b;
else
*p = 'A' + (TCHAR)(b - 10);
p++;
}
*p = _T('\0');
return S_OK;
}
static BYTE hex2dec(char ch)
{
if (ch >= '0' && ch <= '9')
{
return (ch - '0');
}
if (ch >= 'A' && ch <= 'F')
{
return (ch - 'A' + 0xA);
}
if (ch >= 'a' && ch <= 'f')
{
return (ch - 'a' + 0xA);
}
// we do not expect illegal values here
return 0;
}
HRESULT CRCFromString(LPCSTR pszCRC, WUCRC_HASH* pCRC)
{
if (strlen(pszCRC) != (2 * WUCRC_HASH_SIZE))
{
return E_INVALIDARG;
}
LPCSTR p = pszCRC;
for (int i = 0; i < WUCRC_HASH_SIZE; i++)
{
// broken into two lines because the optimizer was doing the wrong thing when on one line
pCRC->HashBytes[i] = (hex2dec(*p++) << 4);
pCRC->HashBytes[i] += hex2dec(*p++);
}
return S_OK;
}
HRESULT MakeCRCName(LPCTSTR pszFromName, const WUCRC_HASH* pCRC, LPTSTR pszToName, int cbToName)
{
int iLen = lstrlen(pszFromName);
LPTSTR pDot;
TCHAR szCRC[WUCRC_HASH_SIZE * 2 + 1];
HRESULT hr = S_OK;
// make sure we have enough space for orignal file name + hash + a '_' + null terminator
if (cbToName < (WUCRC_HASH_SIZE * 2 + iLen + 2))
{
return TYPE_E_BUFFERTOOSMALL;
}
hr = StringFromCRC(pCRC, szCRC, sizeof(szCRC));
if (FAILED(hr))
{
return hr;
}
lstrcpy(pszToName, pszFromName);
// find the extension in the new copy
pDot = _tcschr(pszToName, _T('.'));
if (pDot != NULL)
{
*pDot = _T('\0');
}
lstrcat(pszToName, _T("_"));
lstrcat(pszToName, szCRC);
// copy the extension from the original name
pDot = _tcschr(pszFromName, _T('.'));
if (pDot != NULL)
{
lstrcat(pszToName, pDot);
}
return hr;
}
// splits abc_12345.cab into abc.cab and 12345 returned as CRC
HRESULT SplitCRCName(LPCSTR pszCRCName, WUCRC_HASH* pCRC, LPSTR pszName)
{
// YANL - unreferenced local variable
// char szCRC[WUCRC_HASH_SIZE * 2 + 1];
char szTmp[MAX_PATH];
int l = strlen(pszCRCName);
int i;
LPSTR pszExt = NULL;
LPSTR pszHash = NULL;
pszName[0] = '\0';
if (l < (2 * WUCRC_HASH_SIZE))
{
// cannot be a valid name if it does not have atleast 2*WUCRC_HASH_SIZE characters
return E_INVALIDARG;
}
strcpy(szTmp, pszCRCName);
// start at the end, set pointers to put nulls at last period and last underscore
// record the starting position of the extension and hash code
i = l - 1;
while (i >= 0)
{
if ((szTmp[i] == '.') && (pszExt == NULL))
{
pszExt = &(szTmp[i + 1]);
szTmp[i] = '\0';
}
else if ((szTmp[i] == '_') && (pszHash == NULL))
{
pszHash = &(szTmp[i + 1]);
szTmp[i] = '\0';
}
i--;
}
if (pszHash == NULL)
{
return E_INVALIDARG;
}
// copy original cab name
strcpy(pszName, szTmp);
if (pszExt != NULL)
{
strcat(pszName, ".");
strcat(pszName, pszExt);
}
return CRCFromString(pszHash, pCRC);
}
int __cdecl CompareWUCRCMAP(const void* p1, const void* p2)
{
//check if the input arguments are not NULL
if (NULL == p1 || NULL == p2)
{
return 0;
}
DWORD d1 = ((WUCRCMAP*)p1)->dwKey;
DWORD d2 = ((WUCRCMAP*)p2)->dwKey;
if (d1 > d2)
return +1;
else if (d1 < d2)
return -1;
else
return 0;
}
//
// CCRCMapFile class
//
// Constructs an object to search the CRC index file data passed in
// with pMemData.
//
// NOTE: The memory pointed by pMemData buffer must stay valid
// for the lifetime of this object
//
// structure for map file:
// DWORD count
// WUCRCMAP[0]
// WUCRCMAP[1]
// WUCRCMAP[count - 1]
//
CCRCMapFile::CCRCMapFile(const BYTE* pMemData, DWORD dwMemSize)
{
//check the input argument for NULLs
if (NULL == pMemData)
{
m_pEntries = NULL;
m_cEntries = 0;
return;
}
// get the count
m_cEntries = *((DWORD*)pMemData);
// validate the memory buffer size
if ((sizeof(DWORD) + m_cEntries * sizeof(WUCRCMAP)) != dwMemSize)
{
// invalid size is passed, we cannot process it
m_pEntries = NULL;
m_cEntries = 0;
}
else
{
// set the pointer to begining of the map entries
m_pEntries = (WUCRCMAP*)(pMemData + sizeof(DWORD));
}
}
HRESULT CCRCMapFile::GetValue(DWORD dwKey, WUCRC_HASH* pCRC)
{
WUCRCMAP* pEntry;
WUCRCMAP key;
if (m_cEntries == 0)
{
// memory buffer passed to us was invalid
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
// fill the key field need for compare function in the structure
key.dwKey = dwKey;
// binary search to find the item
pEntry = (WUCRCMAP*)bsearch((void*)&key, (void*)m_pEntries, m_cEntries, sizeof(WUCRCMAP), CompareWUCRCMAP);
if (pEntry == NULL)
{
// not found
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
// found the entry
memcpy(pCRC, &pEntry->CRC, sizeof(WUCRC_HASH));
return S_OK;
}
HRESULT CCRCMapFile::GetCRCName(DWORD dwKey, LPCTSTR pszFromName, LPTSTR pszToName, int cbToName)
{
WUCRC_HASH CRC;
HRESULT hr = GetValue(dwKey, &CRC);
if (SUCCEEDED(hr))
{
hr = MakeCRCName(pszFromName, &CRC, pszToName, cbToName);
}
return hr;
}