在32位和64位代码中将LARGE_INTEGER映射到SIZE_T

时间:2017-05-04 08:03:11

标签: winapi 64-bit

我正在尝试将文件映射到内存,并计算其哈希值:

// Declaration in header file which I don't control
void SymCryptSha256(PCBYTE pbData, SIZE_T cbData, PBYTE pbResult);

// MY code
HANDLE hFile = ::CreateFile(...);
HANDLE hMap = ::CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr));
byte* pMap = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);

BYTE[64] hash;
ULARGE_INTEGER li;
li.LowPart = ::GetFileSize(file , &li.HighPart);
// This compiles in 64-bit, but errors in 32-bit:
// error C4244: 'argument': conversion from 'ULONGLONG' to 'SIZE_T', possible loss of data
::SymCryptSha256(pMap, li.QuadPart, &hash);

这是因为SymCryptSha256的第二个参数是SIZE_T,它在32位编译中是32位。期望的行为是:

  • 64位:使用整个大小,即li.QuadPart
  • 32位:如果大小> 4GB,MapViewOfFile无论如何都会失败。所以,只需使用li.LowPart

在我看来,我需要用#ifdef来做这件事 - 有更优雅的方式吗?

1 个答案:

答案 0 :(得分:0)

在一般情况下,使用this trick,您可以执行以下操作:

if (li.QuadPart > ((ULONGLONG)((size_t)(-1))) too_big();
size_t result = (size_t)(li.QuadPart);

编译器应该在64位编译中将第一行优化为无操作。

(在您的特定情况下,您可能不需要它;代码已经失败。)

注意:正如评论中已经讨论的那样,在这种特殊情况下,如果可能的话,最好使用散列API来允许您以块的形式散列数据。