Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

338 lines
6.3 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: filecrc.h
  6. //
  7. // Purpose: Calculating and using CRC for files
  8. //
  9. //=======================================================================
  10. #include <windows.h>
  11. #include <objbase.h>
  12. #include <filecrc.h>
  13. #include <search.h> // for bsearch
  14. #include <tchar.h>
  15. #include <atlconv.h>
  16. HRESULT GetCRCNameFromList(int iNo, PBYTE pmszCabList, PBYTE pCRCList, LPTSTR pszCRCName, int cbCRCName, LPTSTR pszCabName)
  17. {
  18. USES_CONVERSION;
  19. int i = 0;
  20. WUCRC_HASH* pCRC = (WUCRC_HASH*)pCRCList;
  21. if ( (NULL == pmszCabList) || (NULL == pCRCList) )
  22. return E_INVALIDARG;
  23. for (LPSTR pszFN = (LPSTR)pmszCabList; *pszFN; pszFN += strlen(pszFN) + 1)
  24. {
  25. if (i == iNo)
  26. {
  27. lstrcpy(pszCabName, A2T(pszFN));
  28. return MakeCRCName(A2T(pszFN), pCRC, pszCRCName, cbCRCName);
  29. }
  30. pCRC++;
  31. i++;
  32. }
  33. // if we got here that means we did not find the request element
  34. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  35. }
  36. HRESULT StringFromCRC(const WUCRC_HASH* pCRC, LPTSTR pszBuf, int cbBuf)
  37. {
  38. LPTSTR p = pszBuf;
  39. BYTE b;
  40. //check the input argument, to see that it is not NULL
  41. if (NULL == pCRC)
  42. {
  43. return E_INVALIDARG;
  44. }
  45. if (cbBuf < ((WUCRC_HASH_SIZE * 2) + 1))
  46. {
  47. return TYPE_E_BUFFERTOOSMALL;
  48. }
  49. for (int i = 0; i < WUCRC_HASH_SIZE; i++)
  50. {
  51. b = pCRC->HashBytes[i] >> 4;
  52. if (b <= 9)
  53. *p = '0' + (TCHAR)b;
  54. else
  55. *p = 'A' + (TCHAR)(b - 10);
  56. p++;
  57. b = pCRC->HashBytes[i] & 0x0F;
  58. if (b <= 9)
  59. *p = '0' + (TCHAR)b;
  60. else
  61. *p = 'A' + (TCHAR)(b - 10);
  62. p++;
  63. }
  64. *p = _T('\0');
  65. return S_OK;
  66. }
  67. static BYTE hex2dec(char ch)
  68. {
  69. if (ch >= '0' && ch <= '9')
  70. {
  71. return (ch - '0');
  72. }
  73. if (ch >= 'A' && ch <= 'F')
  74. {
  75. return (ch - 'A' + 0xA);
  76. }
  77. if (ch >= 'a' && ch <= 'f')
  78. {
  79. return (ch - 'a' + 0xA);
  80. }
  81. // we do not expect illegal values here
  82. return 0;
  83. }
  84. HRESULT CRCFromString(LPCSTR pszCRC, WUCRC_HASH* pCRC)
  85. {
  86. if (strlen(pszCRC) != (2 * WUCRC_HASH_SIZE))
  87. {
  88. return E_INVALIDARG;
  89. }
  90. LPCSTR p = pszCRC;
  91. for (int i = 0; i < WUCRC_HASH_SIZE; i++)
  92. {
  93. // broken into two lines because the optimizer was doing the wrong thing when on one line
  94. pCRC->HashBytes[i] = (hex2dec(*p++) << 4);
  95. pCRC->HashBytes[i] += hex2dec(*p++);
  96. }
  97. return S_OK;
  98. }
  99. HRESULT MakeCRCName(LPCTSTR pszFromName, const WUCRC_HASH* pCRC, LPTSTR pszToName, int cbToName)
  100. {
  101. int iLen = lstrlen(pszFromName);
  102. LPTSTR pDot;
  103. TCHAR szCRC[WUCRC_HASH_SIZE * 2 + 1];
  104. HRESULT hr = S_OK;
  105. // make sure we have enough space for orignal file name + hash + a '_' + null terminator
  106. if (cbToName < (WUCRC_HASH_SIZE * 2 + iLen + 2))
  107. {
  108. return TYPE_E_BUFFERTOOSMALL;
  109. }
  110. hr = StringFromCRC(pCRC, szCRC, sizeof(szCRC));
  111. if (FAILED(hr))
  112. {
  113. return hr;
  114. }
  115. lstrcpy(pszToName, pszFromName);
  116. // find the extension in the new copy
  117. pDot = _tcschr(pszToName, _T('.'));
  118. if (pDot != NULL)
  119. {
  120. *pDot = _T('\0');
  121. }
  122. lstrcat(pszToName, _T("_"));
  123. lstrcat(pszToName, szCRC);
  124. // copy the extension from the original name
  125. pDot = _tcschr(pszFromName, _T('.'));
  126. if (pDot != NULL)
  127. {
  128. lstrcat(pszToName, pDot);
  129. }
  130. return hr;
  131. }
  132. // splits abc_12345.cab into abc.cab and 12345 returned as CRC
  133. HRESULT SplitCRCName(LPCSTR pszCRCName, WUCRC_HASH* pCRC, LPSTR pszName)
  134. {
  135. // YANL - unreferenced local variable
  136. // char szCRC[WUCRC_HASH_SIZE * 2 + 1];
  137. char szTmp[MAX_PATH];
  138. int l = strlen(pszCRCName);
  139. int i;
  140. LPSTR pszExt = NULL;
  141. LPSTR pszHash = NULL;
  142. pszName[0] = '\0';
  143. if (l < (2 * WUCRC_HASH_SIZE))
  144. {
  145. // cannot be a valid name if it does not have atleast 2*WUCRC_HASH_SIZE characters
  146. return E_INVALIDARG;
  147. }
  148. strcpy(szTmp, pszCRCName);
  149. // start at the end, set pointers to put nulls at last period and last underscore
  150. // record the starting position of the extension and hash code
  151. i = l - 1;
  152. while (i >= 0)
  153. {
  154. if ((szTmp[i] == '.') && (pszExt == NULL))
  155. {
  156. pszExt = &(szTmp[i + 1]);
  157. szTmp[i] = '\0';
  158. }
  159. else if ((szTmp[i] == '_') && (pszHash == NULL))
  160. {
  161. pszHash = &(szTmp[i + 1]);
  162. szTmp[i] = '\0';
  163. }
  164. i--;
  165. }
  166. if (pszHash == NULL)
  167. {
  168. return E_INVALIDARG;
  169. }
  170. // copy original cab name
  171. strcpy(pszName, szTmp);
  172. if (pszExt != NULL)
  173. {
  174. strcat(pszName, ".");
  175. strcat(pszName, pszExt);
  176. }
  177. return CRCFromString(pszHash, pCRC);
  178. }
  179. int __cdecl CompareWUCRCMAP(const void* p1, const void* p2)
  180. {
  181. //check if the input arguments are not NULL
  182. if (NULL == p1 || NULL == p2)
  183. {
  184. return 0;
  185. }
  186. DWORD d1 = ((WUCRCMAP*)p1)->dwKey;
  187. DWORD d2 = ((WUCRCMAP*)p2)->dwKey;
  188. if (d1 > d2)
  189. return +1;
  190. else if (d1 < d2)
  191. return -1;
  192. else
  193. return 0;
  194. }
  195. //
  196. // CCRCMapFile class
  197. //
  198. // Constructs an object to search the CRC index file data passed in
  199. // with pMemData.
  200. //
  201. // NOTE: The memory pointed by pMemData buffer must stay valid
  202. // for the lifetime of this object
  203. //
  204. // structure for map file:
  205. // DWORD count
  206. // WUCRCMAP[0]
  207. // WUCRCMAP[1]
  208. // WUCRCMAP[count - 1]
  209. //
  210. CCRCMapFile::CCRCMapFile(const BYTE* pMemData, DWORD dwMemSize)
  211. {
  212. //check the input argument for NULLs
  213. if (NULL == pMemData)
  214. {
  215. m_pEntries = NULL;
  216. m_cEntries = 0;
  217. return;
  218. }
  219. // get the count
  220. m_cEntries = *((DWORD*)pMemData);
  221. // validate the memory buffer size
  222. if ((sizeof(DWORD) + m_cEntries * sizeof(WUCRCMAP)) != dwMemSize)
  223. {
  224. // invalid size is passed, we cannot process it
  225. m_pEntries = NULL;
  226. m_cEntries = 0;
  227. }
  228. else
  229. {
  230. // set the pointer to begining of the map entries
  231. m_pEntries = (WUCRCMAP*)(pMemData + sizeof(DWORD));
  232. }
  233. }
  234. HRESULT CCRCMapFile::GetValue(DWORD dwKey, WUCRC_HASH* pCRC)
  235. {
  236. WUCRCMAP* pEntry;
  237. WUCRCMAP key;
  238. if (m_cEntries == 0)
  239. {
  240. // memory buffer passed to us was invalid
  241. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  242. }
  243. // fill the key field need for compare function in the structure
  244. key.dwKey = dwKey;
  245. // binary search to find the item
  246. pEntry = (WUCRCMAP*)bsearch((void*)&key, (void*)m_pEntries, m_cEntries, sizeof(WUCRCMAP), CompareWUCRCMAP);
  247. if (pEntry == NULL)
  248. {
  249. // not found
  250. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  251. }
  252. // found the entry
  253. memcpy(pCRC, &pEntry->CRC, sizeof(WUCRC_HASH));
  254. return S_OK;
  255. }
  256. HRESULT CCRCMapFile::GetCRCName(DWORD dwKey, LPCTSTR pszFromName, LPTSTR pszToName, int cbToName)
  257. {
  258. WUCRC_HASH CRC;
  259. HRESULT hr = GetValue(dwKey, &CRC);
  260. if (SUCCEEDED(hr))
  261. {
  262. hr = MakeCRCName(pszFromName, &CRC, pszToName, cbToName);
  263. }
  264. return hr;
  265. }