#include #pragma hdrstop #include #include CMutexSem g_mxsCDLGetLongPathNameGlobals; // stolen from shellp.h #define ILCreateFromPathORD 157 #define ILFreeORD 155 // stolen from shsemip.h typedef LPITEMIDLIST (WINAPI *ILCreateFromPathPtr)(LPCWSTR pszPath); typedef void (WINAPI *ILFreePtr)(LPITEMIDLIST pidl); // We'll use this if we're running on Memphis or NT5 #ifdef UNICODE #define STR_GETLONGPATHNAMEW "GetLongPathNameW" typedef DWORD (WINAPI *GetLongPathNameWPtr)( LPCWSTR lpszShortPath, LPWSTR lpszLongPath, DWORD cchBuffer ); #else #define STR_GETLONGPATHNAMEA "GetLongPathNameA" typedef DWORD (WINAPI *GetLongPathNameAPtr)( LPCSTR lpszShortPath, LPSTR lpszLongPath, DWORD cchBuffer ); #endif STATIC ILCreateFromPathPtr s_pfnILCreate; STATIC ILFreePtr s_pfnILFree; STATIC GetLongPathNameAPtr s_pfnGetLongPathNameA; #define cKnownDirs 5 STATIC struct KnownDirsMap { BOOL m_bInited; LPTSTR m_aszCaches[cKnownDirs]; struct _tagKDMap { TCHAR szShort[MAX_PATH]; int cchShort; TCHAR szCanonical[MAX_PATH]; int cchCanonical; } m_aKDMap[cKnownDirs]; int IndexKnownDirs( LPTSTR szName ) { int i; for ( i = 0; i < cKnownDirs; i++ ) { // we only want to compare out through the cache folder itself BOOL fMatch = (m_aKDMap[i].cchShort != 0 && CompareString( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, m_aKDMap[i].szShort, m_aKDMap[i].cchShort, szName, m_aKDMap[i].cchShort ) == 2) || (m_aKDMap[i].cchCanonical != 0 && CompareString( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, m_aKDMap[i].szCanonical, m_aKDMap[i].cchCanonical, szName, m_aKDMap[i].cchCanonical ) == 2); if ( fMatch ) break; } if ( i >= cKnownDirs ) i = -1; // signal a miss return i; }; } s_kdMap = { FALSE, { "\\Occache\\", "\\OC Cache\\", "\\Downloaded ActiveX Controls\\", "\\Downloaded Components\\", "\\Downloaded Program Files\\" }, { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } }; DWORD GetFullPathNameA_Wrap( LPCSTR lpFileName, // file name DWORD nBufferLength, // size of path buffer LPSTR lpBuffer, // path buffer LPSTR *lpFilePart // address of file name in path ) { DWORD dwRet = GetFullPathName(lpFileName, nBufferLength, lpBuffer, lpFilePart); if (dwRet && (dwRet= 0 ) { WIN32_FIND_DATA wfd; int cchBase = lstrlen(szT) - lstrlen(szFileName); // okay, it's in one of our caches if ( !IsCanonicalName( szFileName ) ) { HANDLE hfind = FindFirstFile( szShort, &wfd ); if ( hfind != INVALID_HANDLE_VALUE ) { szFileName = wfd.cFileName; FindClose(hfind); } else szFileName = NULL; } if ( szFileName != NULL ) { StrNCpy( szLong, s_kdMap.m_aKDMap[iKnownDir].szCanonical, cchBuffer); // chop off szT right before the file name. // if this is longer than the known dir name, we have a // conflict.* subdirectory and must add this before the file if ( cchBase != s_kdMap.m_aKDMap[iKnownDir].cchShort && cchBase != s_kdMap.m_aKDMap[iKnownDir].cchCanonical ) { LPTSTR szConflict; CHAR chT = szT[cchBase]; szT[cchBase] = '\0'; // search back from before the file name. for ( szConflict = &szT[cchBase - 2]; *szConflict != '\\'; szConflict-- ); szConflict++; // we already have a '\' StrCatBuff( szLong, szConflict, cchBuffer); szT[cchBase] = chT; } StrCatBuff( szLong, szFileName, cchBuffer); hr = S_OK; } } else { #ifndef UNICODE WCHAR *szwT = new WCHAR[MAX_PATH]; if ( szwT && MultiByteToWideChar( CP_ACP, 0, szShort, -1, szwT, MAX_PATH ) ) pidl = s_pfnILCreate( szwT ); delete szwT; #else pidl = s_pfnILCreate( szShort ); #endif if ( pidl != NULL ) { // Now we get the shell to turn the item id list back into // a path rich in long file names, which is our canonical form if ( SHGetPathFromIDList( pidl, szT ) ) { if ( szLong != NULL ) { #ifdef UNICODE LPWSTR szLongW; hr = Ansi2Unicode( szT, &szLongW ); if ( SUCCEEDED(hr) ) { StrCpyNW( szLong, szLongW, cchBuffer ); delete szLongW; } #else //BUFFER OVERRUN lstrcpyA( szLong, szT ); StrCpyN( szLong, szT, cchBuffer ); hr = S_OK; #endif } } s_pfnILFree( pidl ); } // if we got the pidl } // else we're getting shell32 to do the dirty-work } // if we got the full path/file name } // else we can't use GetLongPathName delete szT; } // if we can get out temp string } FreeLibrary( hmodS32 ); FreeLibrary( hmodK32 ); } return ((hr==S_OK)? lstrlen(szLong) : 0); } STDAPI_(DWORD) CDLGetLongPathNameA( LPSTR szLong, LPCSTR szShort, DWORD cchBuffer) { DEBUG_ENTER((DBG_DOWNLOAD, Dword, "CDLGetLongPathNameA", "%.80q, %.80q, %#x", szLong, szShort, cchBuffer )); HRESULT hr; if (!szShort || !szLong) { hr = E_FAIL; DEBUG_LEAVE(hr); return hr; } #ifndef UNICODE hr = s_CDLGetLongPathName( szLong, szShort, cchBuffer ); DEBUG_LEAVE(hr); return hr; #else LPWSTR szShortW; TCHAR szLongT[MAX_PATH]; hr = Ansi2Unicode( szShort, &szShortW ); if ( SUCCEEDED(hr) ) { hr = s_CDLGetLongPathName( szLongT, szShortW, MAX_PATH ); if ( SUCCEEDED(hr) ) { LPSTR szLongA; hr = Unicode2Ansi( szLongT, &szLongA ); if ( SUCCEEDED(hr) ) { lstrcpynA( szLong, szLongA, cchBuffer ); delete szLongA; } } delete szShortW; } DEBUG_LEAVE(hr); return hr; #endif } STDAPI_(DWORD) CDLGetLongPathNameW( LPWSTR szLong, LPCWSTR szShort, DWORD cchBuffer) { DEBUG_ENTER((DBG_DOWNLOAD, Dword, "CDLGetLongPathNameW", "%.80q, %.80q, %#x", szLong, szShort, cchBuffer )); HRESULT hr; if (!szShort || !szLong) { hr = E_FAIL; DEBUG_LEAVE(hr); return hr; } #ifdef UNICODE hr = s_CDLGetLongPathName( szLong, szShort, cchBuffer ); DEBUG_LEAVE(hr); return hr; #else LPSTR szShortA; TCHAR szLongT[MAX_PATH]; hr = Unicode2Ansi( szShort, &szShortA ); if ( SUCCEEDED(hr) ) { hr = s_CDLGetLongPathName( szLongT, szShortA, cchBuffer ); if ( SUCCEEDED(hr) ) { LPWSTR szLongW; hr = Ansi2Unicode( szLongT, &szLongW ); if ( SUCCEEDED(hr) ) { StrCpyNW( szLong, szLongW, cchBuffer ); delete szLongW; } } delete szShortA; } DEBUG_LEAVE(hr); return hr; #endif }