阅读:1528回复:0
GetLongPathNameW
在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; } |
|
|