iooiau

GetPrivateProfileString() の罠

INI ファイルから文字列の設定を読み込むための GetPrivateProfileString() という API 関数がありますが、これを普通に使うと陥る罠があります。
GetPrivateProfileString() は、文字列が " か ' で囲まれている場合、それを除去します。
しかし、この動作がまずい結果を生む場合があります。

例えば、INI ファイルに以下のような項目があるとします。


[Settings]
Command="C:\Program Files\Hoge\Hoge.exe" "%1"

これを GetPrivateProfileString() で読み込んだとします。


TCHAR szCommand[MAX_PATH];
GetPrivateProfileString(TEXT("Settings"), TEXT("Command"), NULL,
    szCommand, sizeof(szCommand) / sizeof(TCHAR), szFileName);

すると、読み込まれた文字列は以下のようになってしまいます。


C:\Program Files\Hoge\Hoge.exe" "%1

これでは、この設定を実際に使う時にまずいことになってしまいます。

対策としては、WritePrivateProfileString() で書き出す際に、全体を余分に " で囲っておけば良いでしょう。
例えば以下のようにします。


BOOL WriteIniString(LPCTSTR pszSection, LPCTSTR pszKeyName, LPCTSTR pszString, LPCTSTR pszFileName)
{
    if (pszString[0] == _T('"') || pszString[0] == _T('\'')) {
        int Length = lstrlen(pszString);
        LPTSTR pszBuffer = new TCHAR[Length + 3];

        pszBuffer[0] = _T('"');
        lstrcpy(pszBuffer + 1, pszString);
        pszBuffer[Length + 1] = _T('"');
        pszBuffer[Length + 2] = _T('\0');
        BOOL Result = WritePrivateProfileString(pszSection, pszKeyName, pszBuffer, pszFileName);
        delete [] pszBuffer;
        return Result;
    }
    return WritePrivateProfileString(pszSection, pszKeyName, pszString, pszFileName);
}

この問題は、そもそも WritePrivateProfileString() と GetPrivateProfileString() とで対応がとれていないことにあるのですが、限りなくバグに近い仕様ですね。