فهرست منبع

Lots of cleanups, fixes, and corrections. Should now work on all win32
platforms, and maybe even WinCE.

Ryan C. Gordon 24 سال پیش
والد
کامیت
d75aa8a84f
1فایلهای تغییر یافته به همراه191 افزوده شده و 186 حذف شده
  1. 191 186
      platform/win32.c

+ 191 - 186
platform/win32.c

@@ -15,10 +15,7 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <ctype.h>
 #include <time.h>
 #include <time.h>
-
-#ifndef DISABLE_NT_SUPPORT
-#include <userenv.h>
-#endif
+#include <assert.h>
 
 
 #define __PHYSICSFS_INTERNAL__
 #define __PHYSICSFS_INTERNAL__
 #include "physfs_internal.h"
 #include "physfs_internal.h"
@@ -28,10 +25,7 @@
 
 
 const char *__PHYSFS_platformDirSeparator = "\\";
 const char *__PHYSFS_platformDirSeparator = "\\";
 
 
-static HANDLE ProcessHandle = NULL;     /* Current process handle */
-static HANDLE AccessTokenHandle = NULL; /* Security handle to process */
-static DWORD ProcessID;                 /* ID assigned to current process */
-static int runningNT;                   /* TRUE if NT derived OS */
+static int runningNT = 0;               /* TRUE if NT derived OS */
 static OSVERSIONINFO OSVersionInfo;     /* Information about the OS */
 static OSVERSIONINFO OSVersionInfo;     /* Information about the OS */
 static char *ProfileDirectory = NULL;   /* User profile folder */
 static char *ProfileDirectory = NULL;   /* User profile folder */
 
 
@@ -42,8 +36,32 @@ static char *ProfileDirectory = NULL;   /* User profile folder */
 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
 #define INVALID_SET_FILE_POINTER 0xFFFFFFFF
 #endif
 #endif
 
 
-/* NT specific functions go in here so they don't get compiled when not NT */
-#ifndef DISABLE_NT_SUPPORT
+/*
+ * Figure out what the last failing Win32 API call was, and
+ *  generate a human-readable string for the error message.
+ *
+ * The return value is a static buffer that is overwritten with
+ *  each call to this function.
+ */
+static const char *win32strerror(void)
+{
+    static TCHAR msgbuf[255];
+
+    FormatMessage(
+        FORMAT_MESSAGE_FROM_SYSTEM |
+        FORMAT_MESSAGE_IGNORE_INSERTS,
+        NULL,
+        GetLastError(),
+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+        msgbuf,
+        sizeof (msgbuf) / sizeof (TCHAR),
+        NULL 
+    );
+
+    return((const char *) msgbuf);
+} /* win32strerror */
+
+
 /*
 /*
  * Uninitialize any NT specific stuff done in doNTInit().
  * Uninitialize any NT specific stuff done in doNTInit().
  *
  *
@@ -51,17 +69,16 @@ static char *ProfileDirectory = NULL;   /* User profile folder */
  */
  */
 static int doNTDeinit(void)
 static int doNTDeinit(void)
 {
 {
-    if(CloseHandle(AccessTokenHandle) != S_OK)
-    {
-        return 0;
-    }
+    /* nothing NT-specific to deinit at this point. */
+    return 1;  /* It's all good */
+} /* doNTDeinit */
 
 
-    free(ProfileDirectory);
-
-    /* It's all good */
-    return 1;
-}
 
 
+typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETUSERPROFILEDIR) (
+      HANDLE hToken,
+      LPTSTR lpProfileDir,
+      LPDWORD lpcchSize);
+   
 /*
 /*
  * Initialize any NT specific stuff.  This includes any OS based on NT.
  * Initialize any NT specific stuff.  This includes any OS based on NT.
  *
  *
@@ -70,34 +87,73 @@ static int doNTDeinit(void)
 static int doNTInit(void)
 static int doNTInit(void)
 {
 {
     DWORD pathsize = 0;
     DWORD pathsize = 0;
-    char TempProfileDirectory[1];
+    char dummy[1];
+    BOOL rc = 0;
+    HANDLE ProcessHandle = NULL;     /* Current process handle */
+    HANDLE AccessTokenHandle = NULL; /* Security handle to process */
+    LPFNGETUSERPROFILEDIR GetUserProfileDirectory = NULL;
+    HMODULE lib = NULL;
+    const char *err = NULL;
+
+    /* Hooray for spaghetti code! */
+
+    lib = LoadLibrary("userenv.dll");
+    if (!lib)
+        goto ntinit_failed;
+
+    /* !!! FIXME: Handle Unicode? */
+    GetUserProfileDirectory = (LPFNGETUSERPROFILEDIR)
+                              GetProcAddress(lib, "GetUserProfileDirectoryA");
+    if (!GetUserProfileDirectory)
+        goto ntinit_failed;
+
+    /* Create a process handle associated with the current process ID */
+    ProcessHandle = GetCurrentProcess();
 
 
     /* Create a process access token handle */
     /* Create a process access token handle */
     if(!OpenProcessToken(ProcessHandle, TOKEN_QUERY, &AccessTokenHandle))
     if(!OpenProcessToken(ProcessHandle, TOKEN_QUERY, &AccessTokenHandle))
+        goto ntinit_failed; /* we need that token to get the profile dir. */
+
+    /* Should fail.  Will write the size of the profile path in pathsize */
+    /* Second parameter can't be NULL or the function fails. */
+    rc = GetUserProfileDirectory(AccessTokenHandle, dummy, &pathsize);
+    assert(!rc);  /* success?! */
+
+    /* Allocate memory for the profile directory */
+    ProfileDirectory = (char *) malloc(pathsize);
+    if (ProfileDirectory == NULL)
     {
     {
-        /* Access token is required by other win32 functions */
-        return 0;
-    }
+        err = ERR_OUT_OF_MEMORY;
+        goto ntinit_failed;
+    } /* if */
+
+    /* Try to get the profile directory */
+    if(!GetUserProfileDirectory(AccessTokenHandle, ProfileDirectory, &pathsize))
+        goto ntinit_failed;
+
+    goto ntinit_succeeded;  /* We made it: hit the showers. */
 
 
-    /* Should fail.  Will write the size of the profile path in pathsize*/
-    /*!!! Second parameter can't be NULL or the function fails??? */
-    if(!GetUserProfileDirectory(AccessTokenHandle, TempProfileDirectory, &pathsize))
+ntinit_failed:
+    if (err == NULL) /* set an error string if we haven't yet. */
+        __PHYSFS_setError(win32strerror());
+
+    if (ProfileDirectory != NULL)
     {
     {
-        /* Allocate memory for the profile directory */
-        ProfileDirectory = (char *)malloc(pathsize);
-        BAIL_IF_MACRO(ProfileDirectory == NULL, ERR_OUT_OF_MEMORY, 0);
-        /* Try to get the profile directory */
-        if(!GetUserProfileDirectory(AccessTokenHandle, ProfileDirectory, &pathsize))
-        {
-            free(ProfileDirectory);
-            return 0;
-        }
-    }
+        free(ProfileDirectory);
+        ProfileDirectory = NULL;
+    } /* if */
 
 
-    /* Everything initialized okay */
-    return 1;
-}
-#endif
+    /* drop through and clean up the rest of the stuff... */
+
+ntinit_succeeded:
+    if (lib != NULL)
+        FreeLibrary(lib);
+
+    if (AccessTokenHandle != NULL)
+        CloseHandle(AccessTokenHandle);
+
+    return ((err == NULL) ? 1 : 0);
+} /* doNTInit */
 
 
 static BOOL MediaInDrive(const char *DriveLetter)
 static BOOL MediaInDrive(const char *DriveLetter)
 {
 {
@@ -115,49 +171,7 @@ static BOOL MediaInDrive(const char *DriveLetter)
     SetErrorMode(OldErrorMode);
     SetErrorMode(OldErrorMode);
 
 
     return ReturnValue;
     return ReturnValue;
-}
-
-static time_t FileTimeToTimeT(FILETIME *ft)
-{
-    SYSTEMTIME st_utc;
-    SYSTEMTIME st_localtz;
-    TIME_ZONE_INFORMATION TimeZoneInfo;
-    struct tm tm;
-
-    FileTimeToSystemTime(ft, &st_utc);
-    GetTimeZoneInformation(&TimeZoneInfo);
-    SystemTimeToTzSpecificLocalTime(&TimeZoneInfo, &st_utc, &st_localtz);
-
-    tm.tm_sec = st_localtz.wSecond;
-    tm.tm_min = st_localtz.wMinute;
-    tm.tm_hour = st_localtz.wHour;
-    tm.tm_mday = st_localtz.wDay;
-    tm.tm_mon = st_localtz.wMonth - 1;
-    tm.tm_year = st_localtz.wYear - 1900;
-    tm.tm_wday = st_localtz.wDayOfWeek;
-    tm.tm_yday = -1;
-    tm.tm_isdst = -1;
-    return mktime(&tm);
-}
-
-static const char *win32strerror(void)
-{
-    static TCHAR msgbuf[255];
-
-    FormatMessage(
-        FORMAT_MESSAGE_FROM_SYSTEM |
-        FORMAT_MESSAGE_IGNORE_INSERTS,
-        NULL,
-        GetLastError(),
-        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
-        msgbuf,
-        sizeof (msgbuf) / sizeof (TCHAR),
-        NULL 
-    );
-
-    return((const char *) msgbuf);
-} /* win32strerror */
-
+} /* MediaInDrive */
 
 
 char **__PHYSFS_platformDetectAvailableCDs(void)
 char **__PHYSFS_platformDetectAvailableCDs(void)
 {
 {
@@ -191,8 +205,19 @@ char **__PHYSFS_platformDetectAvailableCDs(void)
 static char *getExePath(const char *argv0)
 static char *getExePath(const char *argv0)
 {
 {
     char *filepart = NULL;
     char *filepart = NULL;
-    char *retval = (char *) malloc(sizeof (TCHAR) * (MAX_PATH + 1));
-    DWORD buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
+    char *retval;
+	DWORD buflen;
+		
+	retval = (char *) malloc(sizeof (TCHAR) * (MAX_PATH + 1));
+	BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+    buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
+	if (buflen == 0)
+    {
+        const char *err = win32strerror();
+        free(retval);
+        BAIL_MACRO(err, NULL);
+    } /* if */
+
     retval[buflen] = '\0';  /* does API always null-terminate the string? */
     retval[buflen] = '\0';  /* does API always null-terminate the string? */
 
 
         /* make sure the string was not truncated. */
         /* make sure the string was not truncated. */
@@ -204,9 +229,11 @@ static char *getExePath(const char *argv0)
             *(ptr + 1) = '\0';  /* chop off filename. */
             *(ptr + 1) = '\0';  /* chop off filename. */
 
 
             /* free up the bytes we didn't actually use. */            
             /* free up the bytes we didn't actually use. */            
-            retval = (char *) realloc(retval, strlen(retval) + 1);
-            if (retval != NULL)
-                return(retval);
+            ptr = (char *) realloc(retval, strlen(retval) + 1);
+            if (ptr != NULL)
+			    retval = ptr;
+
+            return(retval);
         } /* if */
         } /* if */
     } /* if */
     } /* if */
 
 
@@ -240,6 +267,7 @@ char *__PHYSFS_platformGetUserName(void)
         BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
         BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
         if (GetUserName(retval, &bufsize) == 0)  /* ?! */
         if (GetUserName(retval, &bufsize) == 0)  /* ?! */
         {
         {
+            __PHYSFS_setError(win32strerror());
             free(retval);
             free(retval);
             retval = NULL;
             retval = NULL;
         } /* if */
         } /* if */
@@ -251,7 +279,10 @@ char *__PHYSFS_platformGetUserName(void)
 
 
 char *__PHYSFS_platformGetUserDir(void)
 char *__PHYSFS_platformGetUserDir(void)
 {
 {
-	return ProfileDirectory;
+    char *retval = (char *) malloc(strlen(ProfileDirectory) + 1);
+    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+    strcpy(retval, ProfileDirectory); /* calculated at init time. */
+	return retval;
 } /* __PHYSFS_platformGetUserDir */
 } /* __PHYSFS_platformGetUserDir */
 
 
 
 
@@ -352,15 +383,17 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
     size_t len = strlen(dirname);
     size_t len = strlen(dirname);
 
 
     /* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
     /* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
-    SearchPath = alloca(len + 3);
+    SearchPath = (char *) _alloca(len + 3);
+    BAIL_IF_MACRO(SearchPath == NULL, ERR_OUT_OF_MEMORY, NULL);
+
     /* Copy current dirname */
     /* Copy current dirname */
     strcpy(SearchPath, dirname);
     strcpy(SearchPath, dirname);
 
 
     /* if there's no '\\' at the end of the path, stick one in there. */
     /* if there's no '\\' at the end of the path, stick one in there. */
-    if (dirname[len - 1] != '\\')
+    if (SearchPath[len - 1] != '\\')
     {
     {
-        dirname[len++] = '\\';
-        dirname[len] = '\0';
+        SearchPath[len++] = '\\';
+        SearchPath[len] = '\0';
     } /* if */
     } /* if */
 
 
     /* Append the "*" to the end of the string */
     /* Append the "*" to the end of the string */
@@ -549,6 +582,7 @@ int __PHYSFS_platformMkDir(const char *path)
     return(1);
     return(1);
 } /* __PHYSFS_platformMkDir */
 } /* __PHYSFS_platformMkDir */
 
 
+
 /* 
 /* 
  * Get OS info and save it.
  * Get OS info and save it.
  *
  *
@@ -558,10 +592,7 @@ int getOSInfo(void)
 {
 {
     /* Get OS info */
     /* Get OS info */
     OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
     OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
-    if(!GetVersionEx(&OSVersionInfo))
-    {
-        return 0;
-    }
+    BAIL_IF_MACRO(!GetVersionEx(&OSVersionInfo), win32strerror(), 0);
 
 
     /* Set to TRUE if we are runnign a WinNT based OS 4.0 or greater */
     /* Set to TRUE if we are runnign a WinNT based OS 4.0 or greater */
     runningNT = (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
     runningNT = (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
@@ -572,53 +603,37 @@ int getOSInfo(void)
 
 
 int __PHYSFS_platformInit(void)
 int __PHYSFS_platformInit(void)
 {
 {
-    if(!getOSInfo())
-    {
-        return 0;
-    }
+    BAIL_IF_MACRO(!getOSInfo(), NULL, 0);
 
 
-    /* Get Windows ProcessID associated with the current process */
-    ProcessID = GetCurrentProcessId();
-    /* Create a process handle associated with the current process ID */
-    ProcessHandle = GetCurrentProcess();
-
-    if(ProcessHandle == NULL)
-    {
-        /* Process handle is required by other win32 functions */
-        return 0;
-    }
-
-    /* Default profile directory is the exe path */
-	ProfileDirectory = getExePath(NULL);
-
-#ifndef DISABLE_NT_SUPPORT
     /* If running an NT system (NT/Win2k/XP, etc...) */
     /* If running an NT system (NT/Win2k/XP, etc...) */
     if(runningNT)
     if(runningNT)
     {
     {
-        if(!doNTInit())
-        {
-            /* Error initializing NT stuff */
-            return 0;
-        }
-    }
-#endif
+        BAIL_IF_MACRO(!doNTInit(), NULL, 0);
+    } /* if */
+    else
+    {
+        /* Profile directory is the exe path on 95/98/ME systems. */
+    	ProfileDirectory = getExePath(NULL);
+        BAIL_IF_MACRO(ProfileDirectory == NULL, win32strerror(), 0);
+    } /* else */
 
 
-    /* It's all good */
-    return 1;
+    return 1;  /* It's all good */
 }
 }
 
 
 int __PHYSFS_platformDeinit(void)
 int __PHYSFS_platformDeinit(void)
 {
 {
-#ifndef DISABLE_NT_SUPPORT
-    if(!doNTDeinit())
-        return 0;
-#endif
+    if (runningNT)
+    {
+        BAIL_IF_MACRO(!doNTDeinit(), NULL, 0);
+    } /* if */
 
 
-    if(CloseHandle(ProcessHandle) != S_OK)
-        return 0;
+    if (ProfileDirectory != NULL)
+    {
+        free(ProfileDirectory);
+        ProfileDirectory = NULL;
+    } /* if */
 
 
-    /* It's all good */
-    return 1;
+    return 1; /* It's all good */
 }
 }
 
 
 void *__PHYSFS_platformOpenRead(const char *filename)
 void *__PHYSFS_platformOpenRead(const char *filename)
@@ -630,10 +645,7 @@ void *__PHYSFS_platformOpenRead(const char *filename)
     FileHandle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
     FileHandle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 
 
-    /* If CreateFile() failed */
-    if(FileHandle == INVALID_HANDLE_VALUE)
-        return NULL;
-
+    BAIL_IF_MACRO(FileHandle == INVALID_HANDLE_VALUE, win32strerror(), NULL);
     return (void *)FileHandle;
     return (void *)FileHandle;
 }
 }
 
 
@@ -646,10 +658,7 @@ void *__PHYSFS_platformOpenWrite(const char *filename)
     FileHandle = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
     FileHandle = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 
 
-    /* If CreateFile() failed */
-    if(FileHandle == INVALID_HANDLE_VALUE)
-        return NULL;
-
+    BAIL_IF_MACRO(FileHandle == INVALID_HANDLE_VALUE, win32strerror(), NULL);
     return (void *)FileHandle;
     return (void *)FileHandle;
 }
 }
 
 
@@ -660,14 +669,9 @@ void *__PHYSFS_platformOpenAppend(const char *filename)
     /* Open an existing file for appending only.  File can be opened by others
     /* Open an existing file for appending only.  File can be opened by others
        who request read access to the file only. */
        who request read access to the file only. */
     FileHandle = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
     FileHandle = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
-        TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
-    /* If CreateFile() failed */
-    if(FileHandle == INVALID_HANDLE_VALUE)
-        /* CreateFile might have failed because the file doesn't exist, so
-           we'll just create a new file for writing then */
-        return __PHYSFS_platformOpenWrite(filename);
+        OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 
 
+    BAIL_IF_MACRO(FileHandle == INVALID_HANDLE_VALUE, win32strerror(), NULL);
     return (void *)FileHandle;
     return (void *)FileHandle;
 }
 }
 
 
@@ -685,17 +689,14 @@ PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
     /*!!! - uint32 might be a greater # than DWORD */
     /*!!! - uint32 might be a greater # than DWORD */
     if(!ReadFile(FileHandle, buffer, count * size, &CountOfBytesRead, NULL))
     if(!ReadFile(FileHandle, buffer, count * size, &CountOfBytesRead, NULL))
     {
     {
-        /* Set the error to GetLastError */
-        __PHYSFS_setError(win32strerror());
-        /* We errored out */
-        retval = -1;
-    }
+        BAIL_MACRO(win32strerror(), -1);
+    } /* if */
     else
     else
     {
     {
         /* Return the number of "objects" read. */
         /* Return the number of "objects" read. */
         /* !!! - What if not the right amount of bytes was read to make an object? */
         /* !!! - What if not the right amount of bytes was read to make an object? */
         retval = CountOfBytesRead / size;
         retval = CountOfBytesRead / size;
-    }
+    } /* else */
 
 
     return retval;
     return retval;
 }
 }
@@ -714,17 +715,14 @@ PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, void *buffer,
     /*!!! - uint32 might be a greater # than DWORD */
     /*!!! - uint32 might be a greater # than DWORD */
     if(!WriteFile(FileHandle, buffer, count * size, &CountOfBytesWritten, NULL))
     if(!WriteFile(FileHandle, buffer, count * size, &CountOfBytesWritten, NULL))
     {
     {
-        /* Set the error to GetLastError */
-        __PHYSFS_setError(win32strerror());
-        /* We errored out */
-        retval = -1;
-    }
+        BAIL_MACRO(win32strerror(), -1);
+    } /* if */
     else
     else
     {
     {
         /* Return the number of "objects" read. */
         /* Return the number of "objects" read. */
         /*!!! - What if not the right number of bytes was written? */
         /*!!! - What if not the right number of bytes was written? */
         retval = CountOfBytesWritten / size;
         retval = CountOfBytesWritten / size;
-    }
+    } /* else */
 
 
     return retval;
     return retval;
 }
 }
@@ -805,18 +803,15 @@ PHYSFS_sint64 __PHYSFS_platformFileLength(void *handle)
     if(((FileSizeLow = GetFileSize(FileHandle, &FileSizeHigh))
     if(((FileSizeLow = GetFileSize(FileHandle, &FileSizeHigh))
         == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
         == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
     {
     {
-        /* Set the error to GetLastError */
-        __PHYSFS_setError(win32strerror());
-
-        retval = -1;
-    }
+        BAIL_MACRO(win32strerror(), -1);
+    } /* if */
     else
     else
     {
     {
         /* Combine the high/low order to create the 64-bit position value */
         /* Combine the high/low order to create the 64-bit position value */
         retval = FileSizeHigh;
         retval = FileSizeHigh;
         retval = retval << 32;
         retval = retval << 32;
         retval |= FileSizeLow;
         retval |= FileSizeLow;
-    }
+    } /* else */
 
 
     return retval;
     return retval;
 }
 }
@@ -876,17 +871,6 @@ int __PHYSFS_platformClose(void *opaque)
     return retval;
     return retval;
 }
 }
 
 
-/*
- * Remove a file or directory entry in the actual filesystem. (path) is
- *  specified in platform-dependent notation. Note that this deletes files
- *  _and_ directories, so you might need to do some determination.
- *  Non-empty directories should report an error and not delete themselves
- *  or their contents.
- *
- * Deleting a symlink should remove the link, not what it points to.
- *
- * On error, return zero and set the error message. Return non-zero on success.
- */
 int __PHYSFS_platformDelete(const char *path)
 int __PHYSFS_platformDelete(const char *path)
 {
 {
     int retval;
     int retval;
@@ -927,12 +911,12 @@ int __PHYSFS_platformGrabMutex(void *mutex)
     if(WaitForSingleObject((HANDLE)mutex, INFINITE) == WAIT_FAILED)
     if(WaitForSingleObject((HANDLE)mutex, INFINITE) == WAIT_FAILED)
     {
     {
         /* Our wait failed for some unknown reason */
         /* Our wait failed for some unknown reason */
-        retval = 1;
+        retval = 0;
     }
     }
     else
     else
     {
     {
         /* Good to go */
         /* Good to go */
-        retval = 0;
+        retval = 1;
     }
     }
 
 
     return retval;
     return retval;
@@ -943,6 +927,29 @@ void __PHYSFS_platformReleaseMutex(void *mutex)
     ReleaseMutex((HANDLE)mutex);
     ReleaseMutex((HANDLE)mutex);
 }
 }
 
 
+static time_t FileTimeToTimeT(FILETIME *ft)
+{
+    SYSTEMTIME st_utc;
+    SYSTEMTIME st_localtz;
+    TIME_ZONE_INFORMATION TimeZoneInfo;
+    struct tm tm;
+
+    FileTimeToSystemTime(ft, &st_utc);
+    GetTimeZoneInformation(&TimeZoneInfo);
+    SystemTimeToTzSpecificLocalTime(&TimeZoneInfo, &st_utc, &st_localtz);
+
+    tm.tm_sec = st_localtz.wSecond;
+    tm.tm_min = st_localtz.wMinute;
+    tm.tm_hour = st_localtz.wHour;
+    tm.tm_mday = st_localtz.wDay;
+    tm.tm_mon = st_localtz.wMonth - 1;
+    tm.tm_year = st_localtz.wYear - 1900;
+    tm.tm_wday = st_localtz.wDayOfWeek;
+    tm.tm_yday = -1;
+    tm.tm_isdst = -1;
+    return mktime(&tm);
+} /* FileTimeToTimeT */
+
 PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
 PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
 {
 {
     WIN32_FILE_ATTRIBUTE_DATA AttributeData;
     WIN32_FILE_ATTRIBUTE_DATA AttributeData;
@@ -953,14 +960,12 @@ PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
         AttributeData.ftLastWriteTime.dwLowDateTime == 0)
         AttributeData.ftLastWriteTime.dwLowDateTime == 0)
     {
     {
         /* Return error */
         /* Return error */
-        return -1;
-    }
-    else
-    {
-        /* Return UNIX time_t version of last write time */
-        /*return (PHYSFS_sint64)FileTimeToTimeT(&AttributeData.ftLastWriteTime);*/
-        return (PHYSFS_sint64)FileTimeToTimeT(&AttributeData.ftCreationTime);
+        BAIL_MACRO(win32strerror(), -1);
     }
     }
+
+    /* Return UNIX time_t version of last write time */
+    return (PHYSFS_sint64)FileTimeToTimeT(&AttributeData.ftLastWriteTime);
+    /*return (PHYSFS_sint64)FileTimeToTimeT(&AttributeData.ftCreationTime);*/
 } /* __PHYSFS_platformGetLastModTime */
 } /* __PHYSFS_platformGetLastModTime */
 
 
 /* end of win32.c ... */
 /* end of win32.c ... */