diff --git a/SystemTools.cxx b/SystemTools.cxx
index 65b7b26b5b5c7947b8a1a2237390a039d34151e3..3b651856eaa082bf06c65a6365dba3651417f183 100644
--- a/SystemTools.cxx
+++ b/SystemTools.cxx
@@ -54,7 +54,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <time.h>
 
 #if defined(_WIN32) && !defined(_MSC_VER) && defined(__GNUC__)
@@ -1257,6 +1256,33 @@ bool SystemTools::TestFileAccess(const std::string& filename,
 #endif
 }
 
+//----------------------------------------------------------------------------
+int SystemTools::Stat(const char* path, SystemTools::Stat_t* buf)
+{
+  if (!path) {
+    errno = EFAULT;
+    return -1;
+  }
+  return SystemTools::Stat(std::string(path), buf);
+}
+
+//----------------------------------------------------------------------------
+int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf)
+{
+  if (path.empty()) {
+    errno = ENOENT;
+    return -1;
+  }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // Ideally we should use ConvertToWindowsExtendedPath to support
+  // long paths, but _wstat64 rejects paths with '?' in them, thinking
+  // they are wildcards.
+  return _wstat64(Encoding::ToWide(path).c_str(), buf);
+#else
+  return stat(path.c_str(), buf);
+#endif
+}
+
 //----------------------------------------------------------------------------
 #ifdef __CYGWIN__
 bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path)
diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in
index 7a5256b236fc94c035bff7285d6e73b266909703..bfd979d2a5c43adafaa882c7050d76e368dc41d0 100644
--- a/SystemTools.hxx.in
+++ b/SystemTools.hxx.in
@@ -13,6 +13,9 @@
 #include <@KWSYS_NAMESPACE@/String.hxx>
 
 #include <sys/types.h>
+// include sys/stat.h after sys/types.h
+#include <sys/stat.h>
+
 #if !defined(_WIN32) || defined(__CYGWIN__)
 #include <unistd.h> // For access permissions for use with access()
 #endif
@@ -324,6 +327,23 @@ public:
                              TestFilePermissions permissions);
   static bool TestFileAccess(const std::string& filename,
                              TestFilePermissions permissions);
+/**
+ * Cross platform wrapper for stat struct
+ */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  typedef struct _stat64 Stat_t;
+#else
+  typedef struct stat Stat_t;
+#endif
+
+  /**
+   * Cross platform wrapper for stat system call
+   *
+   * On Windows this may not work for paths longer than 250 characters
+   * due to limitations of the underlying '_wstat64' call.
+   */
+  static int Stat(const char* path, Stat_t* buf);
+  static int Stat(const std::string& path, Stat_t* buf);
 
 /**
  * Converts Cygwin path to Win32 path. Uses dictionary container for
diff --git a/testSystemTools.cxx b/testSystemTools.cxx
index 8e1ea258a806d315ff97e232bc2f9f9a2899eca8..9b08a04a034511883e59104ec8751865ea67c126 100644
--- a/testSystemTools.cxx
+++ b/testSystemTools.cxx
@@ -135,6 +135,19 @@ static bool CheckFileOperations()
     res = false;
   }
 
+  kwsys::SystemTools::Stat_t buf;
+  if (kwsys::SystemTools::Stat(testTxtFile.c_str(), &buf) != 0) {
+    std::cerr << "Problem with Stat - unable to stat text file: "
+              << testTxtFile << std::endl;
+    res = false;
+  }
+
+  if (kwsys::SystemTools::Stat(testBinFile, &buf) != 0) {
+    std::cerr << "Problem with Stat - unable to stat bin file: " << testBinFile
+              << std::endl;
+    res = false;
+  }
+
   if (!kwsys::SystemTools::MakeDirectory(testNewDir)) {
     std::cerr << "Problem with MakeDirectory for: " << testNewDir << std::endl;
     res = false;