From Jean-Sebastien Guay,"As discussed yesterday on the osg-users list, I have altered
src/osgDB/FileUtils.cpp to implement the official Windows DLL search order as described on the page http://msdn2.microsoft.com/en-us/library/ms682586.aspx . As mentioned, the search order is now: 1. The directory from which the application loaded. 2. The system directory. (C:\Windows\System32 by default, gotten using the GetSystemDirectory function) 3. The 16-bit system directory. (C:\Windows\System by default, gotten by adding "\System" to the path gotten in the next step...) 4. The Windows directory. (C:\Windows by default, gotten using the GetWindowsDirectory function) 5. The current directory. (".") 6. The directories that are listed in the PATH environment variable. (as before) The first four directories are obtained using Win32 API calls, so they should work correctly even on non-standard Windows installs. The changes are well commented and should be clear, even to someone not familiar with the Win32 API. I have tested in a few scenarios and it works as expected. Serge Lages has also tested the changes and confirmed they worked as described. I have not had any other reports though (positive or negative). I also fixed the issue with a trailing semicolon on the PATH adding an empty string to the end of the search paths, as this was an inconsistent side effect rather than a desirable effect. This change will take effect on other platforms as well, but since it tests for an empty string in the last item added to the search paths, it should have no adverse effect. "
This commit is contained in:
@@ -165,7 +165,9 @@ void osgDB::convertStringPathIntoFilePathList(const std::string& paths,FilePathL
|
||||
start = end+1;
|
||||
}
|
||||
|
||||
filepath.push_back(std::string(paths,start,std::string::npos));
|
||||
std::string lastPath(paths,start,std::string::npos);
|
||||
if (!lastPath.empty())
|
||||
filepath.push_back(lastPath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -469,13 +471,89 @@ std::string osgDB::findFileInDirectory(const std::string& fileName,const std::st
|
||||
|
||||
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
|
||||
{
|
||||
// See http://msdn2.microsoft.com/en-us/library/ms682586.aspx
|
||||
|
||||
// Safe DLL search mode changes the DLL search order to search for
|
||||
// DLLs in the current directory right after the application's
|
||||
// directory, instead of after the system directories. According to
|
||||
// the article linked above, on Windows XP and Windows 2000, Safe DLL
|
||||
// search mode is disabled by default. However, it is a good idea to
|
||||
// enable it. We will search as if it was enabled.
|
||||
|
||||
// So if SafeDllSearchMode is enabled, the search order is as follows:
|
||||
|
||||
// 1. The directory from which the application loaded.
|
||||
DWORD retval = 0;
|
||||
const DWORD size = MAX_PATH;
|
||||
char path[size];
|
||||
retval = GetModuleFileName(NULL, path, size);
|
||||
if (retval != 0 && retval < size)
|
||||
{
|
||||
std::string pathstr(path);
|
||||
std::string executableDir(pathstr, 0,
|
||||
pathstr.find_last_of("\\/"));
|
||||
convertStringPathIntoFilePathList(executableDir, filepath);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Could not get application directory "
|
||||
"using Win32 API. It will not be searched." << std::endl;
|
||||
}
|
||||
|
||||
// 2. The system directory. Use the GetSystemDirectory function to
|
||||
// get the path of this directory.
|
||||
char systemDir[(UINT)size];
|
||||
retval = GetSystemDirectory(systemDir, (UINT)size);
|
||||
if (retval != 0 && retval < size)
|
||||
{
|
||||
convertStringPathIntoFilePathList(std::string(systemDir),
|
||||
filepath);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Could not get system directory using "
|
||||
"Win32 API, using default directory." << std::endl;
|
||||
convertStringPathIntoFilePathList("C:\\Windows\\System32",
|
||||
filepath);
|
||||
}
|
||||
|
||||
// 3. The 16-bit system directory. There is no function that obtains
|
||||
// the path of this directory, but it is searched.
|
||||
// 4. The Windows directory. Use the GetWindowsDirectory function to
|
||||
// get the path of this directory.
|
||||
char windowsDir[(UINT)size];
|
||||
retval = GetWindowsDirectory(windowsDir, (UINT)size);
|
||||
if (retval != 0 && retval < size)
|
||||
{
|
||||
convertStringPathIntoFilePathList(std::string(windowsDir) +
|
||||
"\\System", filepath);
|
||||
convertStringPathIntoFilePathList(std::string(windowsDir),
|
||||
filepath);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Could not get Windows directory using "
|
||||
"Win32 API, using default directory." << std::endl;
|
||||
convertStringPathIntoFilePathList("C:\\Windows", filepath);
|
||||
convertStringPathIntoFilePathList("C:\\Windows\\System", filepath);
|
||||
}
|
||||
|
||||
|
||||
// 5. The current directory.
|
||||
convertStringPathIntoFilePathList(".", filepath);
|
||||
|
||||
// 6. The directories that are listed in the PATH environment
|
||||
// variable. Note that this does not include the per-application
|
||||
// path specified by the App Paths registry key.
|
||||
char* ptr;
|
||||
if ((ptr = getenv( "PATH" )))
|
||||
{
|
||||
convertStringPathIntoFilePathList(ptr,filepath);
|
||||
// Note that on any sane Windows system, some of the paths above
|
||||
// will also be on the PATH (the values gotten in systemDir and
|
||||
// windowsDir), but the DLL search goes sequentially and stops
|
||||
// when a DLL is found, so I see no point in removing duplicates.
|
||||
convertStringPathIntoFilePathList(ptr, filepath);
|
||||
}
|
||||
|
||||
convertStringPathIntoFilePathList("C:/Windows/System/",filepath);
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
Reference in New Issue
Block a user