fixed GetLongPath(): it never used ::GetLongPath() before and didn't work at all when called for the first time

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33950 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2005-05-04 19:36:25 +00:00
parent 6c0b29749c
commit 2f3d9587ab
2 changed files with 97 additions and 99 deletions

View File

@ -26,7 +26,8 @@ wxMSW:
- Worked around an apparent bug in deferred window positioning (moving a - Worked around an apparent bug in deferred window positioning (moving a
window from (x, y) to (a, b) and back to (x, y) misses the last step) by window from (x, y) to (a, b) and back to (x, y) misses the last step) by
checking window positions against corresponding sizer state, if any. checking window positions against corresponding sizer state, if any.
- A control's text colour now reflects the system colour setting. - A control's text colour now reflects the system colour setting again.
- Fixed wxFileName::GetLongPath() to behave correctly during the first call too
wxMac: wxMac:

View File

@ -1502,27 +1502,26 @@ wxString wxFileName::GetFullPath( wxPathFormat format ) const
// Return the short form of the path (returns identity on non-Windows platforms) // Return the short form of the path (returns identity on non-Windows platforms)
wxString wxFileName::GetShortPath() const wxString wxFileName::GetShortPath() const
{ {
#if defined(__WXMSW__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
wxString path(GetFullPath()); wxString path(GetFullPath());
wxString pathOut;
#if defined(__WXMSW__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
DWORD sz = ::GetShortPathName(path, NULL, 0); DWORD sz = ::GetShortPathName(path, NULL, 0);
bool ok = sz != 0; if ( sz != 0 )
if ( ok )
{ {
ok = ::GetShortPathName wxString pathOut;
if ( ::GetShortPathName
( (
path, path,
wxStringBuffer(pathOut, sz), wxStringBuffer(pathOut, sz),
sz sz
) != 0; ) != 0 )
{
return pathOut;
}
} }
if (ok) #endif // Windows
return pathOut;
return path; return path;
#else
return GetFullPath();
#endif
} }
// Return the long form of the path (returns identity on non-Windows platforms) // Return the long form of the path (returns identity on non-Windows platforms)
@ -1532,116 +1531,114 @@ wxString wxFileName::GetLongPath() const
path = GetFullPath(); path = GetFullPath();
#if defined(__WIN32__) && !defined(__WXMICROWIN__) #if defined(__WIN32__) && !defined(__WXMICROWIN__)
bool success = false;
#if wxUSE_DYNAMIC_LOADER #if wxUSE_DYNAMIC_LOADER
typedef DWORD (WINAPI *GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD); typedef DWORD (WINAPI *GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD);
static bool s_triedToLoad = false; // this is MT-safe as in the worst case we're going to resolve the function
// twice -- but as the result is the same in both threads, it's ok
if ( !s_triedToLoad ) static GET_LONG_PATH_NAME s_pfnGetLongPathName = NULL;
if ( !s_pfnGetLongPathName )
{ {
// suppress the errors about missing GetLongPathName[AW] static bool s_triedToLoad = false;
wxLogNull noLog;
s_triedToLoad = true; if ( !s_triedToLoad )
wxDynamicLibrary dllKernel(_T("kernel32"));
if ( dllKernel.IsLoaded() )
{ {
// may succeed or fail depending on the Windows version s_triedToLoad = true;
static GET_LONG_PATH_NAME s_pfnGetLongPathName = NULL;
wxDynamicLibrary dllKernel(_T("kernel32"));
#ifdef _UNICODE #ifdef _UNICODE
s_pfnGetLongPathName = (GET_LONG_PATH_NAME) dllKernel.GetSymbol(_T("GetLongPathNameW")); #define ADD_STR_SFX(name) L#name L"W"
#else #else
s_pfnGetLongPathName = (GET_LONG_PATH_NAME) dllKernel.GetSymbol(_T("GetLongPathNameA")); #define ADD_STR_SFX(name) #name "A"
#endif #endif
if ( s_pfnGetLongPathName ) if ( dllKernel.HasSymbol(ADD_STR_SFX(GetLongPathName)) )
{ {
DWORD dwSize = (*s_pfnGetLongPathName)(path, NULL, 0); s_pfnGetLongPathName = (GET_LONG_PATH_NAME)
bool ok = dwSize > 0; dllKernel.GetSymbol(ADD_STR_SFX(GetLongPathName));
if ( ok )
{
DWORD sz = (*s_pfnGetLongPathName)(path, NULL, 0);
ok = sz != 0;
if ( ok )
{
ok = (*s_pfnGetLongPathName)
(
path,
wxStringBuffer(pathOut, sz),
sz
) != 0;
success = true;
}
}
} }
// note that kernel32.dll can be unloaded, it stays in memory
// anyhow as all Win32 programs link to it and so it's safe to call
// GetLongPathName() even after unloading it
} }
} }
if (success) if ( s_pfnGetLongPathName )
return pathOut; {
DWORD dwSize = (*s_pfnGetLongPathName)(path, NULL, 0);
if ( dwSize > 0 )
{
if ( (*s_pfnGetLongPathName)
(
path,
wxStringBuffer(pathOut, dwSize),
dwSize
) != 0 )
{
return pathOut;
}
}
}
#endif // wxUSE_DYNAMIC_LOADER #endif // wxUSE_DYNAMIC_LOADER
if (!success) // The OS didn't support GetLongPathName, or some other error.
// We need to call FindFirstFile on each component in turn.
WIN32_FIND_DATA findFileData;
HANDLE hFind;
if ( HasVolume() )
pathOut = GetVolume() +
GetVolumeSeparator(wxPATH_DOS) +
GetPathSeparator(wxPATH_DOS);
else
pathOut = wxEmptyString;
wxArrayString dirs = GetDirs();
dirs.Add(GetFullName());
wxString tmpPath;
size_t count = dirs.GetCount();
for ( size_t i = 0; i < count; i++ )
{ {
// The OS didn't support GetLongPathName, or some other error. // We're using pathOut to collect the long-name path, but using a
// We need to call FindFirstFile on each component in turn. // temporary for appending the last path component which may be
// short-name
tmpPath = pathOut + dirs[i];
WIN32_FIND_DATA findFileData; if ( tmpPath.empty() )
HANDLE hFind; continue;
if ( HasVolume() ) // can't see this being necessary? MF
pathOut = GetVolume() + if ( tmpPath.Last() == GetVolumeSeparator(wxPATH_DOS) )
GetVolumeSeparator(wxPATH_DOS) +
GetPathSeparator(wxPATH_DOS);
else
pathOut = wxEmptyString;
wxArrayString dirs = GetDirs();
dirs.Add(GetFullName());
wxString tmpPath;
size_t count = dirs.GetCount();
for ( size_t i = 0; i < count; i++ )
{ {
// We're using pathOut to collect the long-name path, but using a // Can't pass a drive and root dir to FindFirstFile,
// temporary for appending the last path component which may be // so continue to next dir
// short-name tmpPath += wxFILE_SEP_PATH;
tmpPath = pathOut + dirs[i]; pathOut = tmpPath;
continue;
if ( tmpPath.empty() )
continue;
// can't see this being necessary? MF
if ( tmpPath.Last() == GetVolumeSeparator(wxPATH_DOS) )
{
// Can't pass a drive and root dir to FindFirstFile,
// so continue to next dir
tmpPath += wxFILE_SEP_PATH;
pathOut = tmpPath;
continue;
}
hFind = ::FindFirstFile(tmpPath, &findFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
// Error: most likely reason is that path doesn't exist, so
// append any unprocessed parts and return
for ( i += 1; i < count; i++ )
tmpPath += wxFILE_SEP_PATH + dirs[i];
return tmpPath;
}
pathOut += findFileData.cFileName;
if ( (i < (count-1)) )
pathOut += wxFILE_SEP_PATH;
::FindClose(hFind);
} }
hFind = ::FindFirstFile(tmpPath, &findFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
// Error: most likely reason is that path doesn't exist, so
// append any unprocessed parts and return
for ( i += 1; i < count; i++ )
tmpPath += wxFILE_SEP_PATH + dirs[i];
return tmpPath;
}
pathOut += findFileData.cFileName;
if ( (i < (count-1)) )
pathOut += wxFILE_SEP_PATH;
::FindClose(hFind);
} }
#else // !Win32 #else // !Win32
pathOut = path; pathOut = path;