Windows APIのGetPrivateProfileStringやWritePrivateProfileStringは、プログラムの設定や状態などをお手軽にテキスト形式でiniファイルに読み書きできるため、まだまだ現役で使用されることが多いです。
一つのiniファイルをプログラムの様々な箇所から読み書きするようになると、ある時点でiniファイルの内容を、丸ごと読み取ったり差し替えたりしにくくなってきます。CreateFileでオープンし、ReadFileやWriteFileのAPIで一括で扱えればいいのですが、CreateFileのShareModeパラメータで排他制御をすると、その間、GetPrivateProfileStringやWritePrivateProfileStringは単に失敗してしまいます。
失敗させずに、APIを待機させる方法があります。
もともと、GetPrivateProfileStringやWritePrivateProfileString APIは、API間での読み書きで衝突を起こさないように、内部でLockFileというAPIを使って排他と待機を制御しています。ProcessMonitorで観察すると、読み書き前にLockFileを使っていることがわかります。
LockFile オペレーションを行っています。
GetPrivateProfileStringのコールスタックには NtLockFile APIが呼ばれています。
書き込み時も同じです。LockFile オペレーションが行われています。
WritePrivateProfileStringのコールスタックにもNtLockFile が呼ばれています。
自分のプログラムでもCreateFileで得たハンドルでLockFileを行えば、GetPrivateProfileStringやWritePrivateProfileStringとの排他と待機を実現できます。
具体的には、LockFileExというAPIに、LOCKFILE_FAIL_IMMEDIATELYを指定せず、LOCKFILE_EXCLUSIVE_LOCK だけを指定して使用します。
(使用例)
OVERLAPPED stOvrLap = {0};
LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, (DWORD)-1, (DWORD)-1, &stOvrLap);
ロックを解除するときは、UnlockFileEx APIを使用します。
(使用例)
OVERLAPPED stOvrLap = {0};
UnlockFileEx(hFile, 0, (DWORD)-1, (DWORD)-1, &stOvrLap);
LockFileEx ~ UnlockFileExをしている間は、GetPrivateProfileStringやWritePrivateProfileStringは待機しているので、その間に一括読み書き可能です。