WndProcs.h
#ifndef _WNDPROCS_H_
#define _WNDPROCS_H_
#include <Windows.h>
#include <gdiplus.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <wincrypt.h>
#include <bcrypt.h>
#include <iostream>
#include <vector>
#pragma comment(lib, "Gdiplus.lib")
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "bcrypt.lib")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#define IDC_PROGRESSBAR 100
#define IDC_FILEPATHBT 101
#define IDC_CRC32BT 102
#define IDC_MD5BT 103
#define IDC_SHA1BT 104
#define IDC_SHA256BT 105
#define IDC_SHA512BT 106
#define IDC_CHECKBT 107
#define IDC_HASHCOMPAREBT 108
#define MD5BUFSIZE 1024
#define MD5LEN 16
#define SHA1BUFSIZE 32768
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define SHA256BUFSIZE 65536
#define SHA512BUFSIZE 65536
using namespace Gdiplus;
extern HINSTANCE g_hInstance;
extern ULONG_PTR gdiplusToken;
extern Image* pImage;
extern HWND hFilePathLabelWnd, hFilePathEditWnd, hFilePathButtonWnd;
extern HWND hHashInputLabelWnd, hHashCompareInputWnd, hHashCheckButtonWnd;
extern HWND hCrc32LabelWnd, hCrc32CopyButtonWnd, hCrc32TextEditWnd;
extern HWND hMd5LabelWnd, hMd5CopyButtonWnd, hMd5TextEditWnd;
extern HWND hSha1LabelWnd, hSha1CopyButtonWnd, hSha1TextEditWnd;
extern HWND hSha256LabelWnd, hSha256CopyButtonWnd, hSha256TextEditWnd;
extern HWND hSha512LabelWnd, hSha512CopyButtonWnd, hSha512TextEditWnd;
extern HWND hOkButtonWnd;
extern HWND hProgressbarWnd;
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
#endif
WinMain.cpp
#include "WndProcs.h"
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
LPCTSTR lpszWndClass = TEXT("파일 해시섬 프로그램 Ver 2.0 - 공식배포처 https://korworld.kr");
HINSTANCE g_hInstance;
ULONG_PTR gdiplusToken;
Image* pImage = NULL;
int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpszCmdParam, _In_ int nCmdShow)
{
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HWND hWnd;
MSG Message;
WNDCLASSEX WndClassEx;
g_hInstance = hInstance;
WndClassEx.cbSize = sizeof(WndClassEx); // 구조체 크기를 RegisterClass로 전달하기 위한 멤버이며 보통 값은 자기 자신의 크기를 넘겨주면 됨
WndClassEx.cbClsExtra = 0; // 윈도우 클래스 레벨에서 추가적인 여분 메모리 할당용. 보안상 이슈로 거의 사용되지 않고 0으로 두는 경우가 많음
WndClassEx.cbWndExtra = 0; // 윈도우 인스턴스마다 추가적으로 할당할 여분의 메모리 할당용. 각 윈도우별로 별도 할당되고 윈도우별로 특별한 데이터를 저정하기 위한 예약된 메모리 공간. 이쪽도 그렇게 잘 사용되지는 않음. 프로젝트 규모가 크거나 할때는 어느정도 쓰이나 규모가 작거나 복잡도가 낮은경우에는 거의 쓰일 일이 없음
WndClassEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClassEx.hIcon = LoadIcon(NULL, NULL);
WndClassEx.hIconSm = LoadIcon(NULL, NULL);
WndClassEx.hInstance = hInstance;
WndClassEx.lpfnWndProc = WndProc;
WndClassEx.lpszClassName = lpszWndClass;
WndClassEx.lpszMenuName = NULL;
WndClassEx.style = CS_VREDRAW | CS_HREDRAW;
RegisterClassEx(&WndClassEx);
hWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME, lpszWndClass, lpszWndClass, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT, 1280, 720,
NULL, (HMENU)NULL, g_hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (TRUE)
{
if (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
if (Message.message == WM_QUIT)
{
break;
}
else
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}
else
{
WaitMessage();
}
}
GdiplusShutdown(gdiplusToken);
return (int)Message.wParam;
}
WndProc.cpp
#include "WndProcs.h"
/// CRC32를 포함 각종 파일 해시섬 로직들은 AI(구글 제미나이)에 의해 작성되어진 코드 입니다
/// 일부 AI에 의한 오류나 윈도우 UI환경에 맞추는 부분정도만 직접 진행하였으므로
/// 제가 전부 이해하고 있는 상태가 아닙니다
/// 따라서 파일 해시섬 로직에 대한 궁금증에 대해서는 아쉽지만 AI에 문의해 주시기 바랍니다
/// CRC32 파일 해시섬 함수들 형선언 시작
void makeCRCtable(unsigned long *, unsigned long);
unsigned long calcCRC(const unsigned char *, signed long, unsigned long, unsigned long *);
LPCWSTR getFileCrc(FILE* s);
/// CRC32 파일 해시섬 함수들 형선언 끝
// 윈도우 핸들러
HWND hFilePathLabelWnd, hFilePathEditWnd, hFilePathButtonWnd;
HWND hHashInputLabelWnd, hHashCompareInputWnd, hHashCheckButtonWnd;
HWND hCrc32LabelWnd, hCrc32CopyButtonWnd, hCrc32TextEditWnd;
HWND hMd5LabelWnd, hMd5CopyButtonWnd, hMd5TextEditWnd;
HWND hSha1LabelWnd, hSha1CopyButtonWnd, hSha1TextEditWnd;
HWND hSha256LabelWnd, hSha256CopyButtonWnd, hSha256TextEditWnd;
HWND hSha512LabelWnd, hSha512CopyButtonWnd, hSha512TextEditWnd;
HWND hOkButtonWnd;
HWND hProgressbarWnd;
// 파일 처리
OPENFILENAME OpenFileName;
// 프로그레스바 윈도우 진행도 0 ~ 100
int progressStatus = 0;
// 파일 경로 및 파일 이름+확장자
TCHAR lpstrFile[MAX_PATH] = TEXT("");
TCHAR lpstrFileTitle[MAX_PATH] = TEXT("");
// 파일 해시섬 문자열 전역 변수
wchar_t hashBuffer[256] = L"";
wchar_t crc32ResultBuffer[256] = L"";
wchar_t md5ResultBuffer[256] = L"";
wchar_t sha1ResultBuffer[256] = L"";
wchar_t sha256ResultBuffer[256] = L"";
wchar_t sha512ResultBuffer[256] = L"";
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT PaintStruct;
HDC hdc;
HDROP hDropFile = (HDROP)wParam;
wchar_t dragFileName[MAX_PATH];
wchar_t dragFileExt[MAX_PATH];
// CRC32 해시 관련 변수
FILE *in;
char tempFilePath[256];
errno_t err;
// MD5 해시 관련 변수
HANDLE hFile = INVALID_HANDLE_VALUE;
HCRYPTPROV hCryptProv = 0;
HCRYPTHASH hMd5Hash = 0;
BYTE rgbMd5File[MD5BUFSIZE];
DWORD cbRead = 0;
BYTE rgbMd5Hash[MD5LEN];
DWORD cbHash = 0;
// SHA-1 해시 관련 변수
NTSTATUS functionStatus = NULL;
BCRYPT_ALG_HANDLE hAlg = NULL;
BCRYPT_HASH_HANDLE hSha1Hash = NULL;
DWORD cbData = 0, cbSha1Hash = 0, cbSha1HashObject = 0;
PBYTE pbHashObject = NULL;
PBYTE pbHash = NULL;
// SHA-256 해시 관련 변수
BCRYPT_HASH_HANDLE hSha256Hash = NULL;
DWORD cbSha256Hash = 0, cbSha256HashObject = 0;
BYTE sha256Buffer[SHA256BUFSIZE];
// SHA-512 해시 관련 변수
BCRYPT_HASH_HANDLE hSha512Hash = NULL;
DWORD cbSha512Hash = 0, cbSha512HashObject = 0;
BYTE sha512Buffer[SHA512BUFSIZE];
switch (iMessage)
{
case WM_CREATE: // 프로그램 실행시 윈도우 생성과 동시에 처리되는 로직
{
DragAcceptFiles(hWnd, TRUE); // 드래그앤 드롭 파일 입력 허용
OpenFileName.lStructSize = sizeof(OpenFileName);
OpenFileName.hwndOwner = hWnd;
OpenFileName.lpstrFilter = TEXT("모든 파일\0*.*\0");
OpenFileName.nMaxFile = MAX_PATH;
OpenFileName.nMaxFileTitle = MAX_PATH;
// GDI+로 불러올 이미지 파일 위치
pImage = new Image(L"bg.png");
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_PROGRESS_CLASS;
InitCommonControlsEx(&icex);
// 자식 윈도우 컨트롤들 그리기 및 배치
hFilePathLabelWnd = CreateWindowEx(NULL, TEXT("STATIC"), TEXT("파일 경로"), WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE,
10, 5, 100, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hFilePathEditWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), TEXT("파일을 드래그앤 드롭으로 프로그램에 올려놓아도 자동으로 경로를 입력받습니다"), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY | SS_CENTER,
10, 35, 1130, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hFilePathButtonWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("BUTTON"), TEXT("파일선택"), WS_CHILD | WS_VISIBLE | WS_BORDER,
1150, 35, 100, 25, hWnd, (HMENU)IDC_FILEPATHBT, g_hInstance, NULL);
hHashInputLabelWnd = CreateWindowEx(NULL, TEXT("STATIC"), TEXT("비교할 해시값을 아래에 입력해주세요"), WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE,
10, 100, 300, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hHashCompareInputWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
10, 130, 1130, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hHashCheckButtonWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("BUTTON"), TEXT("해시 값 비교"), WS_CHILD | WS_VISIBLE | WS_BORDER | WS_DISABLED,
1150, 130, 100, 25, hWnd, (HMENU)IDC_HASHCOMPAREBT, g_hInstance, NULL);
hCrc32LabelWnd = CreateWindowEx(NULL, TEXT("STATIC"), TEXT("CRC32"), WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE,
10, 180, 100, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hCrc32CopyButtonWnd = CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("CRC32 해시 값 복사"), WS_CHILD | WS_VISIBLE | SS_CENTER | WS_DISABLED,
130, 180, 175, 25, hWnd, (HMENU)IDC_CRC32BT, g_hInstance, NULL);
hCrc32TextEditWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY,
10, 210, 1240, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hMd5LabelWnd = CreateWindowEx(NULL, TEXT("STATIC"), TEXT("MD5"), WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE,
10, 260, 100, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hMd5CopyButtonWnd = CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("MD5 해시 값 복사"), WS_CHILD | WS_VISIBLE | SS_CENTER | WS_DISABLED,
130, 260, 175, 25, hWnd, (HMENU)IDC_MD5BT, g_hInstance, NULL);
hMd5TextEditWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY,
10, 290, 1240, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hSha1LabelWnd = CreateWindowEx(NULL, TEXT("STATIC"), TEXT("SHA-1"), WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE,
10, 340, 100, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hSha1CopyButtonWnd = CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("SHA-1 해시 값 복사"), WS_CHILD | WS_VISIBLE | SS_CENTER | WS_DISABLED,
130, 340, 175, 25, hWnd, (HMENU)IDC_SHA1BT, g_hInstance, NULL);
hSha1TextEditWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY,
10, 370, 1240, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hSha256LabelWnd = CreateWindowEx(NULL, TEXT("STATIC"), TEXT("SHA-256"), WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE,
10, 420, 100, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hSha256CopyButtonWnd = CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("SHA-256 해시 값 복사"), WS_CHILD | WS_VISIBLE | SS_CENTER | WS_DISABLED,
130, 420, 175, 25, hWnd, (HMENU)IDC_SHA256BT, g_hInstance, NULL);
hSha256TextEditWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY,
10, 450, 1240, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hSha512LabelWnd = CreateWindowEx(NULL, TEXT("STATIC"), TEXT("SHA-512"), WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE,
10, 500, 100, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hSha512CopyButtonWnd = CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("SHA-512 해시 값 복사"), WS_CHILD | WS_VISIBLE | SS_CENTER | WS_DISABLED,
130, 500, 175, 25, hWnd, (HMENU)IDC_SHA512BT, g_hInstance, NULL);
hSha512TextEditWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY,
10, 530, 1240, 25, hWnd, (HMENU)-1, g_hInstance, NULL);
hOkButtonWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("BUTTON"), TEXT("파일 해시섬 확인"), WS_CHILD | WS_VISIBLE | WS_BORDER | WS_DISABLED,
1050, 640, 200, 25, hWnd, (HMENU)IDC_CHECKBT, g_hInstance, NULL);
hProgressbarWnd = CreateWindowEx(NULL, PROGRESS_CLASS, (LPCWSTR)NULL, WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
0, 670, 1280, 15, hWnd, (HMENU)IDC_PROGRESSBAR, g_hInstance, NULL);
SendMessage(hProgressbarWnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
SendMessage(hProgressbarWnd, PBM_SETPOS, 0, 0);
SendMessage(hProgressbarWnd, PBM_SETSTEP, (WPARAM)1, 0);
return 0;
}
case WM_PAINT: // 윈도우 그리기 처리 로직
{
hdc = BeginPaint(hWnd, &PaintStruct);
Graphics graphics(hdc);
graphics.DrawImage(pImage, 0, 0, 1280, 720);
EndPaint(hWnd, &PaintStruct);
return 0;
}
case WM_DROPFILES: // 파일 드래그 온 드롭시 실행될 로직
{
DragQueryFile(hDropFile, 0, lpstrFile, MAX_PATH);
_wsplitpath_s(lpstrFile, NULL, NULL, NULL, NULL, dragFileName, MAX_PATH, dragFileExt, MAX_PATH);
wcscat_s(dragFileName, MAX_PATH, dragFileExt);
ZeroMemory(lpstrFileTitle, sizeof(lpstrFileTitle));
wcscat_s(lpstrFileTitle, MAX_PATH, dragFileName);
SetWindowText(hFilePathEditWnd, lpstrFile);
EnableWindow(hOkButtonWnd, TRUE);
EnableWindow(hCrc32CopyButtonWnd, FALSE);
EnableWindow(hMd5CopyButtonWnd, FALSE);
EnableWindow(hSha1CopyButtonWnd, FALSE);
EnableWindow(hSha256CopyButtonWnd, FALSE);
EnableWindow(hSha512CopyButtonWnd, FALSE);
EnableWindow(hHashCheckButtonWnd, FALSE);
DragFinish(hDropFile);
SetForegroundWindow(hWnd);
return 0;
}
case WM_COMMAND: // 컨트롤 입력 처리 로직
{
switch (LOWORD(wParam))
{
case IDC_FILEPATHBT: // 파일 열기 버튼 로직
if (HIWORD(wParam) == BN_CLICKED)
{
memset(&OpenFileName, 0, sizeof(OPENFILENAME));
OpenFileName.lStructSize = sizeof(OPENFILENAME);
OpenFileName.hwndOwner = hWnd;
OpenFileName.lpstrFilter = TEXT("모든 파일\0*.*\0");
OpenFileName.nMaxFile = MAX_PATH;
OpenFileName.lpstrFile = lpstrFile;
OpenFileName.nMaxFileTitle = MAX_PATH;
OpenFileName.lpstrFileTitle = lpstrFileTitle;
if (GetOpenFileName(&OpenFileName) != 0)
{
SetWindowText(hFilePathEditWnd, lpstrFile);
EnableWindow(hOkButtonWnd, TRUE);
EnableWindow(hCrc32CopyButtonWnd, FALSE);
EnableWindow(hMd5CopyButtonWnd, FALSE);
EnableWindow(hSha1CopyButtonWnd, FALSE);
EnableWindow(hSha256CopyButtonWnd, FALSE);
EnableWindow(hSha512CopyButtonWnd, FALSE);
EnableWindow(hHashCheckButtonWnd, FALSE);
}
}
break;
case IDC_CRC32BT: // CRC32 해시 값 복사 버튼 로직
if (HIWORD(wParam) == BN_CLICKED)
{
SendMessage(hCrc32TextEditWnd, EM_SETSEL, 0, -1);
SendMessage(hCrc32TextEditWnd, WM_COPY, 0, 0);
MessageBox(hWnd, TEXT("CRC32 해시 값이 클립보드에 복사되었습니다\n복사된 값을 붙여 넣으려면 Ctrl + V키를 누르거나 마우스 오른쪽으로 메뉴를 호출 한뒤에 \'붙여넣기\'로 값을 붙여넣기 할수 있습니다"), TEXT("알림"), MB_OK);
}
break;
case IDC_MD5BT: // MD5 해시 값 복사 버튼 로직
if (HIWORD(wParam) == BN_CLICKED)
{
SendMessage(hMd5TextEditWnd, EM_SETSEL, 0, -1);
SendMessage(hMd5TextEditWnd, WM_COPY, 0, 0);
MessageBox(hWnd, TEXT("MD5 해시 값이 클립보드에 복사되었습니다\n복사된 값을 붙여 넣으려면 Ctrl + V키를 누르거나 마우스 오른쪽으로 메뉴를 호출 한뒤에 \'붙여넣기\'로 값을 붙여넣기 할수 있습니다"), TEXT("알림"), MB_OK);
}
break;
case IDC_SHA1BT: // SHA-1 해시 값 복사 버튼 로직
if (HIWORD(wParam) == BN_CLICKED)
{
SendMessage(hSha1TextEditWnd, EM_SETSEL, 0, -1);
SendMessage(hSha1TextEditWnd, WM_COPY, 0, 0);
MessageBox(hWnd, TEXT("SHA-1 해시 값이 클립보드에 복사되었습니다\n복사된 값을 붙여 넣으려면 Ctrl + V키를 누르거나 마우스 오른쪽으로 메뉴를 호출 한뒤에 \'붙여넣기\'로 값을 붙여넣기 할수 있습니다"), TEXT("알림"), MB_OK);
}
break;
case IDC_SHA256BT: // SHA-256 해시 값 복사 버튼 로직
if (HIWORD(wParam) == BN_CLICKED)
{
SendMessage(hSha256TextEditWnd, EM_SETSEL, 0, -1);
SendMessage(hSha256TextEditWnd, WM_COPY, 0, 0);
MessageBox(hWnd, TEXT("SHA-256 해시 값이 클립보드에 복사되었습니다\n복사된 값을 붙여 넣으려면 Ctrl + V키를 누르거나 마우스 오른쪽으로 메뉴를 호출 한뒤에 \'붙여넣기\'로 값을 붙여넣기 할수 있습니다"), TEXT("알림"), MB_OK);
}
break;
case IDC_SHA512BT: // SHA-256 해시 값 복사 버튼 로직
if (HIWORD(wParam) == BN_CLICKED)
{
SendMessage(hSha512TextEditWnd, EM_SETSEL, 0, -1);
SendMessage(hSha512TextEditWnd, WM_COPY, 0, 0);
MessageBox(hWnd, TEXT("SHA-512 해시 값이 클립보드에 복사되었습니다\n복사된 값을 붙여 넣으려면 Ctrl + V키를 누르거나 마우스 오른쪽으로 메뉴를 호출 한뒤에 \'붙여넣기\'로 값을 붙여넣기 할수 있습니다"), TEXT("알림"), MB_OK);
}
break;
case IDC_CHECKBT: // SHA-512 해시 값 복사 버튼 로직
if (HIWORD(wParam) == BN_CLICKED)
{
SendMessage(hProgressbarWnd, PBM_SETPOS, 0, 0);
progressStatus = 0;
// CRC32 처리 로직 시작
WideCharToMultiByte(CP_ACP, 0, lpstrFile, -1, tempFilePath, sizeof(tempFilePath), NULL, NULL);
err = fopen_s(&in, tempFilePath, "rb");
if (err != 0)
{
MessageBox(hWnd, TEXT("지정된 파일이 없습니다. 파일을 선택 한후에 해시섬 확인을 진행해 주세요"), TEXT("경고"), MB_OK | MB_ICONWARNING);
break;
}
if (progressStatus < 20)
{
for (int i = 0; i < 20; i++)
{
SendMessage(hProgressbarWnd, PBM_STEPIT, 0, 0);
progressStatus++;
}
}
wcscpy_s(crc32ResultBuffer, getFileCrc(in));
SetWindowText(hCrc32TextEditWnd, crc32ResultBuffer);
// MD5 처리 로직 시작
hFile = CreateFile(lpstrFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
functionStatus = CryptAcquireContext(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
functionStatus = CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hMd5Hash);
while (ReadFile(hFile, rgbMd5File, MD5BUFSIZE, &cbRead, NULL) && cbRead > 0)
{
if (!CryptHashData(hMd5Hash, rgbMd5File, cbRead, 0))
{
CryptDestroyHash(hMd5Hash);
CryptReleaseContext(hCryptProv, 0);
CloseHandle(hFile);
}
}
cbHash = MD5LEN;
if (CryptGetHashParam(hMd5Hash, HP_HASHVAL, rgbMd5Hash, &cbHash, 0))
{
for (DWORD i = 0; i < cbHash; i++)
{
swprintf_s(md5ResultBuffer, 256, L"%s%02x", md5ResultBuffer, rgbMd5Hash[i]);
if (progressStatus < 40)
{
SendMessage(hProgressbarWnd, PBM_STEPIT, 0, 0);
progressStatus++;
}
}
}
CryptDestroyHash(hMd5Hash);
CryptReleaseContext(hCryptProv, 0);
CloseHandle(hFile);
SetWindowText(hMd5TextEditWnd, md5ResultBuffer);
// SHA-1 처리 로직 시작
functionStatus = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, NULL, 0);
functionStatus = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbSha1HashObject, sizeof(DWORD), &cbData, 0);
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSha1HashObject);
functionStatus = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&cbSha1Hash, sizeof(DWORD), &cbData, 0);
pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSha1Hash);
functionStatus = BCryptCreateHash(hAlg, &hSha1Hash, pbHashObject, cbSha1HashObject, NULL, 0, 0);
hFile = CreateFile(lpstrFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
BYTE sha1Buffer[1024 * 4];
DWORD byteRead = 0;
while (ReadFile(hFile, sha1Buffer, sizeof(sha1Buffer), &byteRead, NULL) && byteRead > 0)
{
functionStatus = BCryptHashData(hSha1Hash, sha1Buffer, byteRead, 0);
}
functionStatus = BCryptFinishHash(hSha1Hash, pbHash, cbSha1Hash, 0);
for (DWORD i = 0; i < cbSha1Hash; i++)
{
swprintf_s(sha1ResultBuffer, 256, L"%s%02x", sha1ResultBuffer, pbHash[i]);
if (progressStatus < 60)
{
SendMessage(hProgressbarWnd, PBM_STEPIT, 0, 0);
progressStatus++;
}
}
CloseHandle(hFile);
SetWindowText(hSha1TextEditWnd, sha1ResultBuffer);
// SHA-256 처리 로직 시작
hAlg = NULL;
cbData = 0;
pbHashObject = NULL;
pbHash = NULL;
functionStatus = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0);
functionStatus = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbSha256HashObject, sizeof(DWORD), &cbData, 0);
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSha256HashObject);
functionStatus = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&cbSha256Hash, sizeof(DWORD), &cbData, 0);
pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSha256Hash);
functionStatus = BCryptCreateHash(hAlg, &hSha256Hash, pbHashObject, cbSha256HashObject, NULL, 0, 0);
hFile = CreateFile(lpstrFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
byteRead = 0;
while (ReadFile(hFile, sha256Buffer, SHA256BUFSIZE, &byteRead, NULL) && byteRead > 0)
{
functionStatus = BCryptHashData(hSha256Hash, sha256Buffer, byteRead, 0);
}
functionStatus = BCryptFinishHash(hSha256Hash, pbHash, cbSha256Hash, 0);
for (DWORD i = 0; i < cbSha256Hash; i++)
{
swprintf_s(sha256ResultBuffer, 256, L"%s%02x", sha256ResultBuffer, pbHash[i]);
if (progressStatus < 80)
{
SendMessage(hProgressbarWnd, PBM_STEPIT, 0, 0);
progressStatus++;
}
}
CloseHandle(hFile);
SetWindowText(hSha256TextEditWnd, sha256ResultBuffer);
// SHA-512 처리 로직 시작
hAlg = NULL;
cbData = 0;
pbHashObject = NULL;
pbHash = NULL;
functionStatus = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA512_ALGORITHM, NULL, 0);
functionStatus = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbSha512HashObject, sizeof(DWORD), &cbData, 0);
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSha512HashObject);
functionStatus = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&cbSha512Hash, sizeof(DWORD), &cbData, 0);
pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSha512Hash);
functionStatus = BCryptCreateHash(hAlg, &hSha512Hash, pbHashObject, cbSha512HashObject, NULL, 0, 0);
hFile = CreateFile(lpstrFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
byteRead = 0;
while (ReadFile(hFile, sha512Buffer, SHA512BUFSIZE, &byteRead, NULL) && byteRead > 0)
{
functionStatus = BCryptHashData(hSha512Hash, sha512Buffer, byteRead, 0);
}
functionStatus = BCryptFinishHash(hSha512Hash, pbHash, cbSha512Hash, 0);
for (DWORD i = 0; i < cbSha512Hash; i++)
{
swprintf_s(sha512ResultBuffer, 256, L"%s%02x", sha512ResultBuffer, pbHash[i]);
if (progressStatus < 100)
{
SendMessage(hProgressbarWnd, PBM_STEPIT, 0, 0);
progressStatus++;
}
}
CloseHandle(hFile);
SetWindowText(hSha512TextEditWnd, sha512ResultBuffer);
// 해시 값 출력 처리 완료 후 처리
if (progressStatus < 100)
{
for (int i = 0; i < (100 - progressStatus); i++)
{
SendMessage(hProgressbarWnd, PBM_STEPIT, 0, 0);
}
}
SendMessage(hProgressbarWnd, PBM_SETPOS, 100, 0);
wmemset(crc32ResultBuffer, 0, 256);
wmemset(md5ResultBuffer, 0, 256);
wmemset(sha1ResultBuffer, 0, 256);
wmemset(sha256ResultBuffer, 0, 256);
wmemset(sha512ResultBuffer, 0, 256);
EnableWindow(hCrc32CopyButtonWnd, TRUE);
EnableWindow(hMd5CopyButtonWnd, TRUE);
EnableWindow(hSha1CopyButtonWnd, TRUE);
EnableWindow(hSha256CopyButtonWnd, TRUE);
EnableWindow(hSha512CopyButtonWnd, TRUE);
EnableWindow(hHashCheckButtonWnd, TRUE);
}
break;
case IDC_HASHCOMPAREBT: // 해시 값 비교 버튼 로직
if (HIWORD(wParam) == BN_CLICKED)
{
TCHAR messageText[MAX_PATH];
int hashTextLength = GetWindowTextLength(hHashCompareInputWnd) + 1;
int crc32TextLength = GetWindowTextLength(hCrc32TextEditWnd) + 1;
int md5TextLength = GetWindowTextLength(hMd5TextEditWnd) + 1;
int sha1TextLength = GetWindowTextLength(hSha1TextEditWnd) + 1;
int sha256TextLength = GetWindowTextLength(hSha256TextEditWnd) + 1;
int sha512TextLength = GetWindowTextLength(hSha512TextEditWnd) + 1;
GetWindowText(hHashCompareInputWnd, hashBuffer, hashTextLength);
GetWindowText(hCrc32TextEditWnd, crc32ResultBuffer, crc32TextLength);
GetWindowText(hMd5TextEditWnd, md5ResultBuffer, md5TextLength);
GetWindowText(hSha1TextEditWnd, sha1ResultBuffer, sha1TextLength);
GetWindowText(hSha256TextEditWnd, sha256ResultBuffer, sha256TextLength);
GetWindowText(hSha512TextEditWnd, sha512ResultBuffer, sha512TextLength);
if (wcscmp(hashBuffer, crc32ResultBuffer) == 0)
{
wsprintf(messageText, TEXT("%s 파일에 CRC32해시 값 %ls 와 일치합니다"), lpstrFileTitle, crc32ResultBuffer);
MessageBox(hWnd, messageText, TEXT("일치하는 해시 값이 있습니다"), MB_OK);
}
else if (wcscmp(hashBuffer, md5ResultBuffer) == 0)
{
wsprintf(messageText, TEXT("%s 파일에 MD5해시 값 %s 와 일치합니다"), lpstrFileTitle, md5ResultBuffer);
MessageBox(hWnd, messageText, TEXT("일치하는 해시 값이 있습니다"), MB_OK);
}
else if (wcscmp(hashBuffer, sha1ResultBuffer) == 0)
{
wsprintf(messageText, TEXT("%s 파일에 SHA-1해시 값 %s 와 일치합니다"), lpstrFileTitle, sha1ResultBuffer);
MessageBox(hWnd, messageText, TEXT("일치하는 해시 값이 있습니다"), MB_OK);
}
else if (wcscmp(hashBuffer, sha256ResultBuffer) == 0)
{
wsprintf(messageText, TEXT("%s 파일에 SHA-256해시 값 %s 와 일치합니다"), lpstrFileTitle, sha256ResultBuffer);
MessageBox(hWnd, messageText, TEXT("일치하는 해시 값이 있습니다"), MB_OK);
}
else if (wcscmp(hashBuffer, sha512ResultBuffer) == 0)
{
wsprintf(messageText, TEXT("%s 파일에 SHA-512해시 값 %s 와 일치합니다"), lpstrFileTitle, sha512ResultBuffer);
MessageBox(hWnd, messageText, TEXT("일치하는 해시 값이 있습니다"), MB_OK);
}
else
{
MessageBox(hWnd, TEXT("일치하는 해시값이 없습니다"), TEXT("일치하는 해시값이 없습니다"), MB_OK);
}
wmemset(hashBuffer, 0, 256);
wmemset(crc32ResultBuffer, 0, 256);
wmemset(md5ResultBuffer, 0, 256);
wmemset(sha1ResultBuffer, 0, 256);
wmemset(sha256ResultBuffer, 0, 256);
wmemset(sha512ResultBuffer, 0, 256);
}
break;
}
return 0;
}
case WM_DESTROY: // 윈도우 종료시 실행될 로직
{// !!!메모리 누수 방지를 위해 메모리 릴리즈 처리를 반드시 해줄것
delete pImage;
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, iMessage, wParam, lParam);
}
/// CRC32 파일 해시섬 함수들 시작
void Crc32Table(unsigned long* table, unsigned long id)
{
unsigned long i, j, k;
for (i = 0; i < 256; ++i)
{
k = i;
for (j = 0; j < 8; ++j)
{
if (k & 1) k = (k >> 1) ^ id;
else k >>= 1;
}
table[i] = k;
}
}
unsigned long calcCrc(const unsigned char* mem, signed long size, unsigned long CRC, unsigned long* table)
{
CRC = ~CRC;
while (size--)
{
CRC = table[(CRC ^ *(mem++)) & 0xff] ^ (CRC >> 8);
}
return ~CRC;
}
LPCWSTR getFileCrc(FILE* s)
{
unsigned char buf[32768];
unsigned long CRC = 0;
unsigned long table[256];
size_t len;
wchar_t buffer[256];
Crc32Table(table, 0xEDB88320);
while ((len = fread(buf, 1, sizeof(buf), s)) != NULL)
{
CRC = calcCrc(buf, (unsigned long)len, CRC, table);
}
_ultow_s(CRC, buffer, sizeof(buffer) / sizeof(wchar_t), 16);
return buffer;
}
/// CRC32 파일 해시섬 함수들 끝

