+namespace
+{
+
+#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
+
+void RemoveTrailingSeparatorsFromPath(wxString& strPath)
+{
+ // Windows fails to find directory named "c:\dir\" even if "c:\dir" exists,
+ // so remove all trailing backslashes from the path - but don't do this for
+ // the paths "d:\" (which are different from "d:"), for just "\" or for
+ // windows unique volume names ("\\?\Volume{GUID}\")
+ while ( wxEndsWithPathSeparator( strPath ) )
+ {
+ size_t len = strPath.length();
+ if ( len == 1 || (len == 3 && strPath[len - 2] == wxT(':')) ||
+ (len == wxMSWUniqueVolumePrefixLength &&
+ wxFileName::IsMSWUniqueVolumeNamePath(strPath)))
+ {
+ break;
+ }
+
+ strPath.Truncate(len - 1);
+ }
+}
+
+#endif // __WINDOWS__ || __OS2__
+
+bool
+wxFileSystemObjectExists(const wxString& path, int flags)
+{
+
+ // Should the existence of file/directory with this name be accepted, i.e.
+ // result in the true return value from this function?
+ const bool acceptFile = (flags & wxFILE_EXISTS_REGULAR) != 0;
+ const bool acceptDir = (flags & wxFILE_EXISTS_DIR) != 0;
+
+ wxString strPath(path);
+
+#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
+ if ( acceptDir )
+ {
+ // Ensure that the path doesn't have any trailing separators when
+ // checking for directories.
+ RemoveTrailingSeparatorsFromPath(strPath);
+ }
+
+ // we must use GetFileAttributes() instead of the ANSI C functions because
+ // it can cope with network (UNC) paths unlike them
+ DWORD ret = ::GetFileAttributes(strPath.t_str());
+
+ if ( ret == INVALID_FILE_ATTRIBUTES )
+ return false;
+
+ if ( ret & FILE_ATTRIBUTE_DIRECTORY )
+ return acceptDir;
+
+ // Anything else must be a file (perhaps we should check for
+ // FILE_ATTRIBUTE_REPARSE_POINT?)
+ return acceptFile;
+#elif defined(__OS2__)
+ if ( acceptDir )
+ {
+ // OS/2 can't handle "d:", it wants either "d:\" or "d:."
+ if (strPath.length() == 2 && strPath[1u] == wxT(':'))
+ strPath << wxT('.');
+ }
+
+ FILESTATUS3 Info = {{0}};
+ APIRET rc = ::DosQueryPathInfo((PSZ)(WXSTRINGCAST strPath), FIL_STANDARD,
+ (void*) &Info, sizeof(FILESTATUS3));
+
+ if ( rc == NO_ERROR )
+ {
+ if ( Info.attrFile & FILE_DIRECTORY )
+ return acceptDir;
+ else
+ return acceptFile;
+ }
+
+ // We consider that the path must exist if we get a sharing violation for
+ // it but we don't know what is it in this case.
+ if ( rc == ERROR_SHARING_VIOLATION )
+ return flags & wxFILE_EXISTS_ANY;
+
+ // Any other error (usually ERROR_PATH_NOT_FOUND), means there is nothing
+ // there.
+ return false;
+#else // Non-MSW, non-OS/2
+ wxStructStat st;
+ if ( !StatAny(st, strPath, flags) )
+ return false;
+
+ if ( S_ISREG(st.st_mode) )
+ return acceptFile;
+ if ( S_ISDIR(st.st_mode) )
+ return acceptDir;
+ if ( S_ISLNK(st.st_mode) )
+ {
+ // Take care to not test for "!= 0" here as this would erroneously
+ // return true if only wxFILE_EXISTS_NO_FOLLOW, which is part of
+ // wxFILE_EXISTS_SYMLINK, is set too.
+ return (flags & wxFILE_EXISTS_SYMLINK) == wxFILE_EXISTS_SYMLINK;
+ }
+ if ( S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) )
+ return (flags & wxFILE_EXISTS_DEVICE) != 0;
+ if ( S_ISFIFO(st.st_mode) )
+ return (flags & wxFILE_EXISTS_FIFO) != 0;
+ if ( S_ISSOCK(st.st_mode) )
+ return (flags & wxFILE_EXISTS_SOCKET) != 0;
+
+ return flags & wxFILE_EXISTS_ANY;
+#endif // Platforms
+}
+
+} // anonymous namespace
+