DPAPIのプログラム解説最終回は、動作の中核となるDPAPIProc.hです。
//////////////////////////////////////////
// DPAPIProc.h
// Copyright (c) 10/05/2021 by BCCSkelton
//////////////////////////////////////////
/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//ウィンドウメッセージ関数
/////////////////////////////////
bool CMyWnd::OnInit(WPARAM wParam, LPARAM lParam) {
(解説:ダイアログの初期設定です。ラジオボックスとファイルを開くボタンを設定します。)
//暗号化ラジオボタンにチェックを入れる
SendItemMsg(IDC_RBCRYPT, BM_SETCHECK, BST_CHECKED, 0);
(解説:BM_SETCHECKメッセージでチェックを入れます。(外す場合はBST_UNCHECKED))
//IDI_ICONアイコンをIDC_SELECTボタンに張り付ける
HICON hIcon = (HICON)LoadImage(m_hInstance, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
(解説:まずリソースのアイコンをロードし、ハンドルを取得します。)
SendItemMsg(IDC_SELECT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
(解説:そのハンドルを使ってBM_SETIMAGEで貼り付けます。)
return TRUE;
}
bool CMyWnd::OnClose(WPARAM wParam, LPARAM lParam) {
if(MessageBox(m_hWnd, "終了しますか", "終了確認",
MB_YESNO | MB_ICONINFORMATION) == IDYES) {
//処理をするとDestroyWindow、PostQuitMessageが呼ばれる
return TRUE;
}
else
//そうでなければウィンドウではDefWindowProc関数をreturn、ダイアログではreturn FALSEとなる。
return FALSE;
}
//ダイアログベースの場合はこれが必要
bool CMyWnd::OnDestroy(WPARAM wPram, LPARAM lParam) {
PostQuitMessage(0);
return TRUE;
}
/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//メニュー項目、コントロール関数
/////////////////////////////////
bool CMyWnd::OnSelect() {
char* cp = cmndlg.GetFileName(m_hWnd, "全てのファイル(*.*)\0*.*\0\0", TRUE);
if(cp) {
SendItemMsg(IDC_FILE, WM_SETTEXT, 0, (LPARAM)cp);
return TRUE;
}
else
return FALSE;
}
(解説:文字列ポインターcpを使ってCMNDLGクラス変数でファイルパス、名を取得してエディットコントロールに表示します。)
bool CMyWnd::OnCrypt() {
//変数定義
char fn[MAX_PATH]; //ファイル名用バッファ
char* dat; //ファイルデータ読み込み用
bool bSuccess = FALSE; //処理結果フラグ
(解説:成功した場合のみTRUEとし、それ以外は規定値FALSEを使います。)
DWORD dwRead; //読み込んだファイルサイズ
//選択ファイル名の取得
SendItemMsg(IDC_FILE, WM_GETTEXT, MAX_PATH, (LPARAM)fn);
(解説:まずはfn配列変数にファイルパス、名を取り込みます。)
//選択ファイルの読み込み
HANDLE hFile = CreateFile(fn, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, NULL, NULL); //ファイルを読込みでオープン
if(hFile == INVALID_HANDLE_VALUE) //オープンできなかった場合
MessageBox(m_hWnd, "ファイルを開けませんでした", "エラー",
MB_OK | MB_ICONERROR);
(解説:ここですぐにreturnしないで、次のelse処理を合わせてFALSEならreturnさせます。)
else{
DWORD dwFileSize = GetFileSize(hFile, NULL);
if(dwFileSize == 0xFFFFFFFF) { //-1は(0xFFFFFFFF)エラー
MessageBox(m_hWnd, "ファイルサイズを取得できませんでした", "エラー",
MB_OK | MB_ICONERROR);
CloseHandle(hFile); //ファイルのクローズ
(解説:ここでも一括FALSE処理に任せますが、ファイルを開いているので閉じましょう。)
}
else {
dat = new char[dwFileSize]; //データバッファを確保する
if(ReadFile(hFile, (LPVOID)dat, dwFileSize, &dwRead, NULL))
bSuccess = TRUE;
(解説:唯一読み込みに成功したときだけTRUEにします。)
else {
MessageBox(m_hWnd, "ファイルを読めませんでした", "エラー",
MB_OK | MB_ICONERROR);
delete [] dat; //バッファの開放
(解説:ここも一括FALSE処理ですが、newでメモリーを確保したので、忘れずに解放します。)
}
}
CloseHandle(hFile); //ファイルのクローズ
}
//ファイル読み込みの結論とbSuccesの再初期化
if(!bSuccess)
return FALSE;
(解説:これが一括FALSE処理です。)
else
bSuccess = FALSE;
(解説:読み込めた時にはまたFALSEの規定値に戻します。)
//暗号化、復号化の開始
DATA_BLOB blobIn;
blobIn.cbData = dwRead; //暗号化するデータのサイズ
blobIn.pbData = (BYTE*)dat; //暗号化するデータのバイトポインター
(解説:読み込んだ暗号化/復号化ファイルデータをセットします。)
DATA_BLOB blobOut;
CRYPTPROTECT_PROMPTSTRUCT promptStruct;
promptStruct.cbSize = sizeof(CRYPTPROTECT_PROMPTSTRUCT);
promptStruct.dwPromptFlags = CRYPTPROTECT_PROMPT_ON_PROTECT;
promptStruct.hwndApp = m_hWnd;
(解説:これがDPAPI専用ダイアログ用の構造体です。構造体サイズ、プロンプトは定番の暗号化時、親はメインダイアログとします。)
//暗号化、復号化の確認
if(SendItemMsg(IDC_RBCRYPT, BM_GETCHECK, 0, 0) == BST_CHECKED) {
(解説:「暗号化」ラジオボックスのチェックを確認し、TRUEなら暗号化、FALSEなら復号化処理を行います。)
promptStruct.szPrompt = L"データの暗号化";
(解説:文字列の前のLは、wchar_tのマクロでワイド文字であることを示します。)
if(CryptProtectData(&blobIn, NULL, NULL, NULL, &promptStruct, 0, &blobOut)) {
MessageBox(m_hWnd, "ファイルを暗号化しました", "暗号化", MB_OK | MB_ICONEXCLAMATION);
bSuccess = TRUE;
(解説:暗号化に成功したときだけTRUEにします。)
}
else
MessageBox(NULL, TEXT("データの暗号化に失敗しました。"), "エラー", MB_OK | MB_ICONWARNING);
}
else {
promptStruct.szPrompt = L"データの復号化";
if(CryptUnprotectData(&blobIn, NULL, NULL, NULL, &promptStruct, 0, &blobOut)) {
MessageBox(m_hWnd, "ファイルを復号化しました", "復号化", MB_OK | MB_ICONEXCLAMATION);
bSuccess = TRUE;
(解説:復号化に成功したときだけTRUEにします。)
}
else
MessageBox(NULL, TEXT("データの復号化に失敗しました。"), "エラー", MB_OK | MB_ICONWARNING);
}
delete [] dat; //もう必要が無いのでバッファを解放
//暗号化復号化の結論とbSuccesの再初期化
if(!bSuccess)
return FALSE;
(解説:一括FALSE処理です。)
else
bSuccess = FALSE;
(解説:TRUEを、再度規定値FALSEにします。)
//ファイルを書込みでオープン
DWORD dwWritten; //読み込んだファイルサイズ
hFile = CreateFile(fn, GENERIC_WRITE, NULL, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE) { //ファイルオープン成功
DWORD dwWritten; //読み込んだファイルサイズ
//{blobOut.pbDataが暗号化されたデータ、blobOut.cbDataはそのサイズ
bSuccess = WriteFile(hFile, blobOut.pbData, blobOut.cbData, &dwWritten, NULL);
(解説:bSuccessに書き込み結果の成功TRUE、失敗FALSE情報が入ります。)
CloseHandle(hFile); //ファイルのクローズ
(解説:開いたファイルは閉じます。)
}
LocalFree(blobOut.pbData); //blobOutのメモリーを解放
(解説:暗号化、復号化処理で確保したメモリーを解放します。)
return bSuccess; //書き込みに成功している場合はTRUE、それ以外はFALSE
}
bool CMyWnd::OnIdok() {
SendMsg(WM_CLOSE, 0, 0);
return TRUE;
}
///////////////////////////////
//ユーザーダイアログの関数定義
//コントロール関数
///////////////////////////////
以上でプログラミングを終了し、ビルドすると
というプログラムになります。
使い方は簡単です。まず「DPAPIフォールダー」ボタンを押してファイルを選択します。次に暗号化ラジオボタンにチェックが入っていることを確認して「実行」ボタンを押します。
するとDPAPI専用のダイアログが現れます。
このまま「OK」しても暗号化されますが、「セキュリティレベルの設定」を押して現れるダイアログで「高」を選ぶとパスワードを設定できます。
最初の「~のパスワード」の入力は「そのパスワードのID」です。(英語では"Password of (エディットボックス)"だったのでしょう。)復号化の時にこのIDが表示されてパスワードを求められます。パスワード自体はその下の「パスワード」と「確認入力」にタイプインします。
暗号化に成功すると"ファイルを暗号化しました"というダイアログが現れますので、ファイルをチェックして暗号化されていることを確認してください。
暗号化されたファイルは同じ様に復号化ラジオボタンにチェックが入っていることを確認して「実行」ボタンを押すことで復号化します。"ファイルを復号化しました"というダイアログが現れたら、もう一度ファイルが元に戻っているか確認してください。
では、今度はまたIDListに戻って最後の仕上げをしましょう。




