dreamsity
驱动小牛
驱动小牛
  • 注册日期2006-09-01
  • 最后登录2013-07-04
  • 粉丝0
  • 关注0
  • 积分40分
  • 威望821点
  • 贡献值1点
  • 好评度68点
  • 原创分1分
  • 专家分0分
阅读:1435回复:0

GetLongPathNameW

楼主#
更多 发布于:2007-12-15 09:21
在win2k内找到的获得长文件名的源代码
DWORD
APIENTRY
GetLongPathNameW(
    IN  LPCWSTR lpszShortPath,
    IN  LPWSTR  lpszLongPath,
    IN  DWORD   cchBuffer
)
{

    LPCWSTR pcs;
    DWORD ReturnLen, Length;
    LPWSTR pSrc, pSrcCopy, pFirst, pLast, Buffer, pDst;
    WCHAR   wch;
    HANDLE          FindHandle;
    WIN32_FIND_DATAW        FindData;
    UINT PrevErrorMode;

    if (!ARGUMENT_PRESENT(lpszShortPath)) {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
        }
    //
    // override the error mode since we will be touching the media.
    // This is to prevent file system's pop-up when the given path does not
    // exist or the media is not available.
    // we are doing this because we can not depend on the caller's current
    // error mode. NOTE: the old error mode must be restored.
    PrevErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);

    try {

        Buffer = NULL;
        pSrcCopy = NULL;
        // first make sure the given path exist.
        //
        if (0xFFFFFFFF == GetFileAttributesW(lpszShortPath))
        {
            // last error has been set by GetFileAttributes
            ReturnLen = 0;
            goto glnTryExit;
        }
        pcs = SkipPathTypeIndicator_U(lpszShortPath);
        if (!pcs || *pcs == UNICODE_NULL || !FindLFNorSFN_U((LPWSTR)pcs, &pFirst, &pLast, FALSE))
            {
            // The path is ok and does not need conversion at all.
            // Check if we need to do copy
            ReturnLen = wcslen(lpszShortPath);
            if (cchBuffer > ReturnLen && ARGUMENT_PRESENT(lpszLongPath))
                {
                if (lpszLongPath != lpszShortPath)
                    RtlMoveMemory(lpszLongPath, lpszShortPath,
                                      (ReturnLen + 1)* sizeof(WCHAR)
                                      );
                }
            else {
                // No buffer or buffer too small, the return size
                // has to count the terminated NULL char
                ReturnLen++;
                }
            goto glnTryExit;
            }


        // conversions  are necessary, make a local copy of the string
        // because we have to party on it.

        ASSERT(!pSrcCopy);

        Length = wcslen(lpszShortPath) + 1;
        pSrcCopy = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( VDM_TAG ),
                                   Length * sizeof(WCHAR)
                                   );
        if (!pSrcCopy) {
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
            goto glnTryExit;
            }
        RtlMoveMemory(pSrcCopy, lpszShortPath, Length * sizeof(WCHAR));
        // pFirst points to the first char of the very first SFN in the path
        // pLast points to the char right after the last char of the very
        // first SFN in the path. *pLast could be UNICODE_NULL
        pFirst = pSrcCopy + (pFirst - lpszShortPath);
        pLast = pSrcCopy + (pLast - lpszShortPath);
        //
        // We allow lpszShortPath be overlapped with lpszLongPath so
        // allocate a local buffer if necessary:
        // (1) the caller does provide a legitimate buffer and
        // (2) the buffer overlaps with lpszShortName

        pDst = lpszLongPath;
        if (cchBuffer && ARGUMENT_PRESENT(lpszLongPath) &&
            (lpszLongPath >= lpszShortPath && lpszLongPath < lpszShortPath + Length ||
             lpszLongPath < lpszShortPath && lpszLongPath + cchBuffer >= lpszShortPath))
            {
            ASSERT(!Buffer);

            Buffer = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( VDM_TAG ),
                                           cchBuffer * sizeof(WCHAR));
            if (!Buffer){
                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
                goto glnTryExit;
                }
            pDst = Buffer;
            }

        pSrc = pSrcCopy;
        ReturnLen = 0;
        do {
            // there are three pointers involve in the conversion loop:
            // pSrc, pFirst and pLast. Their relationship
            // is:
            //
            // "c:\long~1.1\\foo.bar\\long~2.2\\bar"
            //  ^          ^          ^       ^
            //  |          |          |       |
            //  |          pSrc       pFirst  pLast
            //  pSrcCopy
            //
            // pSrcCopy always points to the very first char of the entire
            // path.
            //
            // chars between pSrc(included) and pFirst(not included)
            // do not need conversion so we simply copy them.
            // chars between pFirst(included) and pLast(not included)
            // need conversion.
            //
            Length = (ULONG)(pFirst - pSrc);
            ReturnLen += Length;
            if (Length && cchBuffer > ReturnLen && ARGUMENT_PRESENT(lpszShortPath))
                {
                RtlMoveMemory(pDst, pSrc, Length * sizeof(WCHAR));
                pDst += Length;
                }
            // now try to convert the name, chars between pFirst and (pLast - 1)
            wch = *pLast;
            *pLast = UNICODE_NULL;
            FindHandle = FindFirstFileW(pSrcCopy, &FindData);
            *pLast = wch;
            if (FindHandle != INVALID_HANDLE_VALUE){
                FindClose(FindHandle);
                // if no long name, copy the original name
                // starts with pFirst(included) and ends with pLast(excluded)
                if (!(Length = wcslen(FindData.cFileName)))
                    Length = (ULONG)(pLast - pFirst);
                else
                    pFirst = FindData.cFileName;
                ReturnLen += Length;
                if (cchBuffer > ReturnLen && ARGUMENT_PRESENT(lpszLongPath))
                    {
                    RtlMoveMemory(pDst, pFirst, Length * sizeof(WCHAR));
                    pDst += Length;
                    }
                }
            else {
                // invalid path, reset the length, mark the error and
                // bail out of the loop. We will be copying the source
                // to destination later.
                //
                ReturnLen = 0;
                break;
                }
            pSrc = pLast;
            if (*pSrc == UNICODE_NULL)
                break;
            } while (FindLFNorSFN_U(pSrc, &pFirst, &pLast, FALSE));

        if (ReturnLen) {
            //copy the rest of the path from pSrc. This may only contain
            //a single NULL char
            Length = wcslen(pSrc);
            ReturnLen += Length;
            if (cchBuffer > ReturnLen && ARGUMENT_PRESENT(lpszLongPath))
                {
                RtlMoveMemory(pDst, pSrc, (Length + 1) * sizeof(WCHAR));
                if (Buffer)
                    RtlMoveMemory(lpszLongPath, Buffer, (ReturnLen + 1) * sizeof(WCHAR));
                }
            else
                ReturnLen++;
            }

glnTryExit:
        ;
        }
        finally {
            if (pSrcCopy)
                RtlFreeHeap(RtlProcessHeap(), 0, pSrcCopy);
            if (Buffer)
                RtlFreeHeap(RtlProcessHeap(), 0, Buffer);
            }

    // restore error mode.
    SetErrorMode(PrevErrorMode);
    return ReturnLen;
}
一切都是时间问题!
游客

返回顶部