|
|
//=======================================================================
//
// 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; }
|