Created
March 4, 2019 13:12
-
-
Save udaken/30fbbe08a4e749814691d21d5207e26c to your computer and use it in GitHub Desktop.
[WindowsAPI]古典的非同期I/Oのサンプルコード
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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