/****************************************************************************** FileInfo MD5 コマンドソースファイル Coded by Wraith in Dec 23, 2007. ******************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // // ■ md5.cpp // http://tricklib.com/cxx/ex/fileinfo/md5.cpp // // □ 関連ファイル // ありません。このファイルは単体で利用できます。 // // □ リファレンス・サポートページ // http://tricklib.com/cxx/ex/fileinfo/ // // □ ライセンス情報 // http://tricklib.com/license.htm // // □ コンパイル方法(MD5) // case Borland C++ // bcc32 md5.cpp // case Visual C++ // cl /EHsc md5.cpp // case CodeWarrior // mwcc md5.cpp // // □ コンパイル方法(SHA1) // case Borland C++ // bcc32 -DHASH_ALGORITHM=CALG_SHA1 md5.cpp -o sha1.exe // case Visual C++ // cl /EHsc -DHASH_ALGORITHM=CALG_SHA1 md5.cpp -o sha1.exe // case CodeWarrior // mwcc -DHASH_ALGORITHM=CALG_SHA1 md5.cpp -o sha1.exe // #if !defined(MD5_CPP) #define MD5_CPP #include #include #include #include #pragma comment(lib, "ADVAPI32.lib") ////////////////////////////////////////////////////////////////////////////// // // Declare auto closers // template class demi { public: T value; demi() {} demi(const T &X) :value(X) {} operator T& () { return value; } operator const T& () const { return value; } T * operator & () { return &value; } const T * operator & () const { return &value; } T & operator () () { return value; } const T & operator () () const { return value; } }; #define DECLARE_AUTO_CLOSE(name, type, param, init, close_command) \ class name :public demi \ { \ public: \ name(param) :demi(init) { } \ ~name() \ { \ close(); \ } \ void close() \ { \ if (value) \ { \ close_command; \ value = NULL; \ } \ } \ }; DECLARE_AUTO_CLOSE(AUTO_HANDLE, HANDLE, HANDLE X = NULL, X, INVALID_HANDLE_VALUE != value && (CloseHandle(value), false)) DECLARE_AUTO_CLOSE(AUTO_CRYPTPROV, HCRYPTPROV, HCRYPTPROV X = NULL, X, CryptReleaseContext(value, 0)) DECLARE_AUTO_CLOSE(AUTO_CRYPTHASH, HCRYPTHASH, HCRYPTHASH X = NULL, X, CryptDestroyHash(value)) DECLARE_AUTO_CLOSE(AUTO_MAPVIEW, LPVOID, LPVOID X = NULL, X, UnmapViewOfFile(value)) ////////////////////////////////////////////////////////////////////////////// // // Win32 Error // class win32_error :public std::runtime_error { DWORD code; public: win32_error(DWORD X_code = GetLastError()) :std::runtime_error(win32_error::make_error_message(X_code)), code(X_code) { } static const std::string make_error_message(DWORD X_code = GetLastError()); DWORD get_error_code() const { return code; } const char * get_error_message() const { return what(); } }; const std::string win32_error::make_error_message(DWORD X_code) { LPVOID lpMsgBuf; FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, X_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&lpMsgBuf, 0, NULL); const std::string result = (const char *)lpMsgBuf; LocalFree(lpMsgBuf); return result; } ////////////////////////////////////////////////////////////////////////////// // // ファイルオープン(読み込み専用、自動クローズ) // class OpenReadFile :public AUTO_HANDLE { public: OpenReadFile(const char *filename) :AUTO_HANDLE( CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ |FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)) { } OpenReadFile(const wchar_t *filename) :AUTO_HANDLE( CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ |FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)) { } }; ////////////////////////////////////////////////////////////////////////////// // // ハッシュ値の取得 // DWORD CalcHash(ALG_ID algid, HANDLE stream, BYTE *buffer, DWORD buffer_size) { // // 準備 // AUTO_CRYPTPROV prov_handle = NULL; AUTO_CRYPTHASH hash_handle = NULL; AUTO_HANDLE file_mapping = NULL; LARGE_INTEGER file_size; file_size.QuadPart = 0L; if ( NULL == stream || INVALID_HANDLE_VALUE == stream || ( !CryptAcquireContext(&prov_handle, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT) && ( (DWORD)NTE_BAD_KEYSET != GetLastError() || !CryptAcquireContext(&prov_handle, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_NEWKEYSET) ) ) || !CryptCreateHash(prov_handle, algid, 0, 0, &hash_handle) || !GetFileSizeEx(stream, &file_size) || ( 0L < file_size.QuadPart && NULL == (file_mapping.value = CreateFileMapping(stream, NULL, PAGE_READONLY, file_size.HighPart, file_size.LowPart, NULL)) ) ) { throw win32_error(); } // // pump // LARGE_INTEGER file_pos; file_pos.QuadPart = 0L; __int64 rest_size = file_size.QuadPart; SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); const DWORD pump_buffer_size = sys_info.dwAllocationGranularity; while(0 < rest_size) { SIZE_T data_size = ((__int64)pump_buffer_size <= rest_size) ? pump_buffer_size: rest_size; AUTO_MAPVIEW data; if ( NULL == (LPVOID)(data.value = MapViewOfFile(file_mapping, FILE_MAP_READ, file_pos.HighPart, file_pos.LowPart, data_size)) || FALSE == CryptHashData(hash_handle, (LPBYTE)(LPVOID)data, data_size, 0) ) { throw win32_error(); } file_pos.QuadPart += data_size; rest_size -= data_size; } // // ハッシュ値の取得 // DWORD hash_size = buffer_size; if (FALSE == CryptGetHashParam(hash_handle, HP_HASHVAL, buffer, &hash_size, NULL)) { throw win32_error(); } return hash_size; } ////////////////////////////////////////////////////////////////////////////// // // commandline user interface // #if !defined(HASH_ALGORITHM) #define HASH_ALGORITHM CALG_MD5 #endif int main(int argc, char *args[]) { for(int i = 1; i < argc; ++i) { try { BYTE hash[256]; int hash_size = CalcHash(HASH_ALGORITHM, OpenReadFile(args[i]), hash, sizeof(hash)); if (hash_size) { printf("%s:", args[i]); for (int i = 0; i < hash_size; ++i) { printf("%02.2X", hash[i]); } printf("\n"); } } catch(const win32_error &err) { printf("%s\n", err.get_error_message()); } } return EXIT_SUCCESS; } #endif