Programming Field - プログラミング Tips

ファイル名の比較と長いファイル名2

「ファイル名の比較と長いファイル名」にある MyGetLongPathName 関数は、限られたコンパイラでしか使用できませんでした。

それに対し以下のコードは、int割り込みを使わずに長いファイル名を取得することができる関数です。ここでは、FindFirstFile 関数などのファイル検索関数が、長いファイル名を返すということを利用しています。したがって、Windows 95 でも動作します。

(自分のプログラムで使ったコードをそのまま持ってきたので、汚いです。)

DWORD WINAPI MyGetLongPathName(LPCTSTR lpszPath, LPTSTR lpszBuffer, DWORD dwMaxLen)
{
    LPTSTR lpPath = _tcsdup(lpszPath);
    LPTSTR lp, lp2;
    LPTSTR lpTempBuffer;
    LPTSTR lpCopy;
    WIN32_FIND_DATA wfd;
    HANDLE hFind;
    DWORD dwLen;
    DWORD dwCopied;
    if (lpszBuffer && dwMaxLen)
        lpTempBuffer = (LPTSTR) malloc(sizeof(TCHAR) * (dwMaxLen + 14));
    else
    {
        lpszBuffer = NULL;
        lpTempBuffer = (LPTSTR) malloc(sizeof(TCHAR) * (dwMaxLen = MAX_PATH));
    }
    lpCopy = lpTempBuffer;
    if (*lpPath == _T('\\') && lpPath[1] == _T('\\'))
    {
        goto OnNotCopied;
    }
    else
    {
        lp = _tcschr(lpPath, _T('\\'));
        if (!lp)
            goto OnNotCopied;
        lp2 = _tcschr(lp + 1, _T('\\'));
        if (!lp2)
        {
            lp2 = lp;
            while (*++lp2);
            //goto OnNotCopied;
        }
        dwCopied = 0;
        dwLen = (DWORD)((++lp) - lpPath);
        if (lpszBuffer)
        {
            if (dwLen >= dwMaxLen)
                goto OnCopyLen;
            dwMaxLen -= dwLen;
        }
        _tcsncpy(lpCopy, lpPath, dwLen);
        lpCopy += dwLen;
        *lpCopy = 0;
        dwCopied += dwLen;
        do
        {
            dwLen = (DWORD)(lp2 - lp);
            if (lpszBuffer)
            {
                if (dwLen >= dwMaxLen + 13)
                    goto OnCopyLen;
                //dwMaxLen -= dwLen;
            }
            else if (dwCopied + dwLen >= dwMaxLen)
            {
                LPTSTR lpRe;
                dwMaxLen += dwLen + 1;
                lpRe = (LPTSTR) realloc(lpTempBuffer, sizeof(TCHAR) * dwMaxLen);
                lpCopy = (lpRe + (DWORD)(lpCopy - lpTempBuffer));
                lpTempBuffer = lpRe;
            }
            _tcsncpy(lpCopy, lp, dwLen);
            lpCopy[dwLen] = 0;
            //lpCopy += dwLen;
            hFind = ::FindFirstFile(lpTempBuffer, &wfd);
            if (hFind == INVALID_HANDLE_VALUE)
                goto OnFailed;
            ::FindClose(hFind);
            dwLen = (DWORD) _tcslen(wfd.cFileName);
            if (lpszBuffer)
            {
                if (dwLen >= dwMaxLen)
                {
                    lp = wfd.cFileName;
                    goto OnCopyLen;
                }
                dwMaxLen -= dwLen;
            }
            else if (dwCopied + dwLen >= dwMaxLen)
            {
                LPTSTR lpRe;
                dwMaxLen += dwLen + 2;
                lpRe = (LPTSTR) realloc(lpTempBuffer, sizeof(TCHAR) * dwMaxLen);
                lpCopy = (lpRe + (DWORD)(lpCopy - lpTempBuffer));
                lpTempBuffer = lpRe;
            }
            _tcsncpy(lpCopy, wfd.cFileName, dwLen);
            lpCopy += dwLen;
            *lpCopy = 0;
            dwCopied += dwLen;
            if (!*lp2)
                break;
            if (lpszBuffer)
            {
                if (dwMaxLen == 0)
                {
                    dwLen = dwCopied;
                    goto OnClean;
                }
                dwMaxLen--;
            }
            *lpCopy++ = _T('\\');
            *lpCopy = 0;
            dwCopied++;
            lp = lp2 + 1;
            lp2 = _tcschr(lp, _T('\\'));
            if (!lp2)
            {
                if (!*lp)
                    break;
                lp2 = lp;
                while (*++lp2);
            }
        } while (true);
    }
    dwLen = dwCopied;
    goto OnClean;

OnCopyLen:
    _tcsncpy(lpCopy, lp, dwMaxLen);
    lpCopy[dwMaxLen - 1] = 0;
    dwCopied += dwMaxLen - 1;
    dwLen = dwCopied;
    goto OnClean;

OnFailed:
    if (lpszBuffer && dwMaxLen)
        *lpTempBuffer = 0;
    dwLen = 0;
    goto OnClean;

OnNotCopied:
    dwLen = (DWORD) _tcslen(lpPath);
    if (lpszBuffer && dwMaxLen)
    {
        _tcsncpy(lpTempBuffer, lpPath, dwMaxLen);
        dwLen = min(dwLen, dwMaxLen);
    }
OnClean:
    if (lpszBuffer)
    {
        memcpy(lpszBuffer, lpTempBuffer, sizeof(TCHAR) * (dwLen + 1));
    }
    free(lpTempBuffer);
    free(lpPath);
    return dwLen;
}

最終更新日: 2007/05/23