Jean-Marc, all,
following our earlier discussion, I attach a little test code to show what
I think we need to produce robust code on Windows. The attached code should
compile on all flavours of Windows >= Win95 and should behave gracefully on
older versions for which GetLongPathName is just a stub.
I propose to post this sample off to Luis Rivera and get him to try it out
on Win95/Win98 but I'd of course welcome any sanity checks and comments
from you first.
Angus (the one of questionable moral character :-P)
$ g++ -I$HOME/lyx/13x/boost -o trial trial.cpp
$ ./trial
Temp dir is C:/Documents and Settings/Angus/Local Settings/Temp/
#include <boost/assert.hpp>
#include <iostream>
#include <string>
#include <vector>
/*
* MinGW's version of winver.h contains this comment:
*
* If you need Win32 API features newer the Win95 and WinNT then you must
* define WINVER before including windows.h or any other method of including
* the windef.h header.
*
* GetLongPathNameA requires WINVER == 0x0500.
*
* It doesn't matter if the Windows version is older than this because the
* function will compile but will fail at run time. See
*
http://msdn.microsoft.com/library/en-us/mslu/winprog/microsoft_layer_for_unicode_apis_with_limited_support.asp
*/
# if defined(__MINGW32__)
# define WINVER 0x0500
# endif
#include <windows.h>
using std::string;
using std::vector;
namespace {
string const subst(string const & a,
string const & oldstr, string const & newstr)
{
BOOST_ASSERT(!oldstr.empty());
string lstr(a);
string::size_type i = 0;
string::size_type const olen = oldstr.length();
while ((i = lstr.find(oldstr, i)) != string::npos) {
lstr.replace(i, olen, newstr);
i += newstr.length(); // We need to be sure that we dont
// use the same i over and over again.
}
return lstr;
}
namespace os {
string const internal_path(string const &p)
{
string const short_path = subst(p, "\\", "/");
vector<char> long_path(PATH_MAX);
DWORD result = GetLongPathName(short_path.c_str(),
&long_path[0], long_path.size());
if (result > long_path.size()) {
long_path.resize(result);
result = GetLongPathName(short_path.c_str(),
&long_path[0], long_path.size());
BOOST_ASSERT(result <= long_path.size());
}
return (result == 0) ? short_path : &long_path[0];
}
} // namespace os
string const get_temp_dir()
{
// Typical example: C:/TEMP/.
char path[PATH_MAX];
DWORD const result = GetTempPath(PATH_MAX, path);
BOOST_ASSERT(result > 0 && result <= PATH_MAX);
return os::internal_path(path);
}
} // namespace anon
int main()
{
string const temp_dir = get_temp_dir();
std::cout << "Temp dir is " << temp_dir << std::endl;
return 0;
}