Skip to content

Instantly share code, notes, and snippets.

@udaken
Created March 4, 2019 13:12
Show Gist options
  • Save udaken/30fbbe08a4e749814691d21d5207e26c to your computer and use it in GitHub Desktop.
Save udaken/30fbbe08a4e749814691d21d5207e26c to your computer and use it in GitHub Desktop.
[WindowsAPI]古典的非同期I/Oのサンプルコード
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0502
#endif
#include <windows.h>
#include <tchar.h>
#include <wincrypt.h>
#include <bcrypt.h>
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "crypt32.lib")
#define BUFSIZE (4 * 1024 * 1024)
#define SHA512LEN (512/8)
struct BUF
{
LPBYTE lpBuffer;
OVERLAPPED ol;
DWORD dwBufferSize;
DWORD dwReaded;
BOOL fPending;
};
static void initBuf(struct BUF * pBuf)
{
memset(pBuf, 0x00, sizeof(struct BUF));
pBuf->lpBuffer = malloc(BUFSIZE);
pBuf->dwBufferSize = BUFSIZE;
//pBuf->ol.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}
DWORD CalcHashAsync(LPCTSTR lpFileName, HCRYPTHASH hHash)
{
struct BUF buffers[2] = {0};
HANDLE hFile;
BOOL fContinue = TRUE;
BOOL index = 0;
ULARGE_INTEGER offset = {0};
DWORD dwError = ERROR_SUCCESS;
hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
dwError = GetLastError();
DebugBreak();
return dwError;
}
initBuf(&buffers[0]);
initBuf(&buffers[1]);
while(fContinue)
{
// -------------------------------
if(buffers[index].fPending)
{
DWORD dwPendingTick = timeGetTime();
//_tprintf(TEXT("[%d]Wait Pending I/O...\n"), index);
if(!GetOverlappedResult(hFile, &buffers[index].ol, &buffers[index].dwReaded, TRUE))
{
DWORD overlappedResult = GetLastError();
fContinue = FALSE;
if(overlappedResult != ERROR_HANDLE_EOF)
{
dwError = overlappedResult;
DebugBreak();
break;
}
}
_tprintf(TEXT("[%d] %u\n"), index, timeGetTime() - dwPendingTick);
}
// -------------------------------
if(fContinue)
{
BOOL nextIndex = !index;
buffers[nextIndex].dwReaded = 0;
buffers[nextIndex].ol.Offset = offset.LowPart;
buffers[nextIndex].ol.OffsetHigh = offset.HighPart;
memset(buffers[nextIndex].lpBuffer, 0xCC, buffers[nextIndex].dwBufferSize);
buffers[nextIndex].fPending = FALSE;
_tprintf(TEXT("[%d]Start ReadFile(offset:0x%X%08X)...\n"), nextIndex, offset.HighPart, offset.LowPart );
if(!ReadFile(hFile, buffers[nextIndex].lpBuffer, buffers[nextIndex].dwBufferSize, &buffers[nextIndex].dwReaded, &buffers[nextIndex].ol))
{
DWORD dwReadFileResult = GetLastError();
switch(dwReadFileResult)
{
case ERROR_IO_PENDING:
buffers[nextIndex].fPending = TRUE;
break;
case ERROR_HANDLE_EOF:
fContinue = FALSE;
break;
default:
fContinue = FALSE;
dwError = dwReadFileResult;
break;
}
}
else
{
_tprintf(TEXT("[%d]ReadFile completed synchronously.\n"), nextIndex);
}
offset.QuadPart += buffers[nextIndex].dwBufferSize;
}
// -------------------------------
if(buffers[index].dwReaded)
{
_tprintf(TEXT("[%d]CryptHashData(0x%08X)...\n"), index, buffers[index].dwReaded);
if(!CryptHashData(hHash, buffers[index].lpBuffer, buffers[index].dwReaded, 0))
{
dwError = GetLastError();
DebugBreak();
break;
}
}
index = !index; // 0, 1, 0, 1 ...
}
CloseHandle(hFile);
free(buffers[0].lpBuffer);
free(buffers[1].lpBuffer);
return dwError;
}
// see: https://docs.microsoft.com/ja-jp/windows/desktop/SecCrypto/example-c-program--creating-an-md-5-hash-from-file-content
DWORD CalcHash(LPCTSTR lpFileName, HCRYPTHASH hHash)
{
LPBYTE lpBuffer;
HANDLE hFile;
DWORD dwError = ERROR_SUCCESS;
hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN , NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
dwError = GetLastError();
DebugBreak();
return dwError;
}
lpBuffer = malloc(BUFSIZE);
while(TRUE)
{
static const LARGE_INTEGER liZero = {0};
LARGE_INTEGER offset;
DWORD dwReaded = 0;
memset(lpBuffer, 0xCC, BUFSIZE);
SetFilePointerEx(hFile, liZero, &offset, FILE_CURRENT);
_tprintf(TEXT("Start ReadFile(offset:0x%X%08X)...\n"), offset.HighPart, offset.LowPart );
if(!ReadFile(hFile, lpBuffer, BUFSIZE, &dwReaded, NULL))
{
dwError = GetLastError();
DebugBreak();
break;
}
if(dwReaded == 0)
{
break;
}
if(!CryptHashData(hHash, lpBuffer, dwReaded, 0))
{
dwError = GetLastError();
DebugBreak();
break;
}
}
CloseHandle(hFile);
free(lpBuffer);
return dwError;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwStartTick = 0;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
BYTE hashVal[SHA512LEN] = {0};
DWORD dwHashSize = sizeof(hashVal);
TCHAR hashStr[SHA512LEN * 4 + 1] = TEXT("");
DWORD cchStr = _countof(hashStr);
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
{
DebugBreak();
return 1;
}
if(!CryptCreateHash(hProv, CALG_SHA_512, 0, 0, &hHash))
{
DebugBreak();
CryptReleaseContext(hProv, 0);
return 1;
}
timeBeginPeriod(1);
dwStartTick = timeGetTime();
#if 0
CalcHashAsync(argv[1], hHash);
#else
CalcHash(argv[1], hHash);
#endif
_tprintf(TEXT("Done (%u)\n"), timeGetTime() - dwStartTick);
timeEndPeriod(1);
if(CryptGetHashParam(hHash, HP_HASHVAL, hashVal, &dwHashSize, 0))
{
CryptBinaryToString(hashVal, sizeof(hashVal),CRYPT_STRING_HEX | CRYPT_STRING_NOCR,hashStr, &cchStr);
_tprintf(TEXT("%s\n"), hashStr);
}
else
{
_ftprintf(stderr, TEXT("CryptGetHashParam failed.(0x%08X)\n"), GetLastError());
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment