339 lines
6.3 KiB
C++
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;
|
|
}
|