2017-05-04 83 views
0

我试图映射文件到存储器,和calc其散列:映射LARGE_INTEGER在两个32位和64位代码的size_t

// 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 s - 有没有更优雅的方式呢?

+0

@harry:当然你是对的。但是,这是一个简化的例子 - 我稍后会调用其他API,它需要整个大小为'SIZE_T'。我编辑了这个问题来反映这一点。 – Jonathan

+0

@Jonathan:哈利是对的,我检查了我的旧代码,我也是这样做的,如果你想要*任何*文件的计算哈希值,就通过0 ... – Malkocoglu

+1

- 你需要准备好文件可以大于4GB。所以你不需要将它映射到内存中(当然,这对于相对较小的文件来说更简单快捷),而对块来说则是部分块。选择块大小 - 然后映射块,计算哈希,取消映射,然后映射下一个块。大块大小必须足够大多数文件使用单个块,但对于非常大的文件,您将有多个映射/取消映射 – RbMm

回答

0

在一般情况下,使用this trick,你可以做这样的事情:

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

编译器应该优化第一线成无操作在64位编译。

(你的具体情况,你可能不需要也无妨;代码将已经失败)

注:在评论已经讨论过,在这种特殊情况下最好将,如果可能的话,使用散列API,允许你散列数据块。