r870 - in trunk: . platform
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Sun Mar 25 01:17:08 EDT 2007
Author: icculus
Date: 2007-03-25 01:17:08 -0400 (Sun, 25 Mar 2007)
New Revision: 870
Modified:
trunk/CHANGELOG.txt
trunk/platform/windows.c
Log:
Improved dynamic loader and initial Unicode work in windows.c ...
Modified: trunk/CHANGELOG.txt
===================================================================
--- trunk/CHANGELOG.txt 2007-03-25 04:59:11 UTC (rev 869)
+++ trunk/CHANGELOG.txt 2007-03-25 05:17:08 UTC (rev 870)
@@ -2,6 +2,7 @@
* CHANGELOG.
*/
+03252007 - Improved dynamic loader and initial Unicode work in windows.c ...
03242007 - Replaced BeOS semaphores with BLockers for the mutex implementation.
It's much simpler, it has "benaphores" built in behind the scenes
for faster performance, and it's recursive...also, we were
Modified: trunk/platform/windows.c
===================================================================
--- trunk/platform/windows.c 2007-03-25 04:59:11 UTC (rev 869)
+++ trunk/platform/windows.c 2007-03-25 05:17:08 UTC (rev 870)
@@ -26,20 +26,25 @@
#define HIGHORDER_UINT64(pos) (PHYSFS_uint32) \
(((pos & 0xFFFFFFFF00000000) >> 32) & 0x00000000FFFFFFFF)
+/*
+ * Users without the platform SDK don't have this defined. The original docs
+ * for SetFilePointer() just said to compare with 0xFFFFFFFF, so this should
+ * work as desired.
+ */
+#define PHYSFS_INVALID_SET_FILE_POINTER 0xFFFFFFFF
-/* !!! FIXME: unicode version. */
-/* GetUserProfileDirectory() is only available on >= NT4 (no 9x/ME systems!) */
-typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETUSERPROFILEDIR) (
- HANDLE hToken,
- LPTSTR lpProfileDir,
- LPDWORD lpcchSize);
+/* just in case... */
+#define PHYSFS_INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
-/* !!! FIXME: unicode version. */
-/* GetFileAttributesEx() is only available on >= Win98 or WinNT4 ... */
-typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETFILEATTRIBUTESEX) (
- LPCTSTR lpFileName,
- GET_FILEEX_INFO_LEVELS fInfoLevelId,
- LPVOID lpFileInformation);
+#define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \
+ if (str == NULL) \
+ w_assignto = NULL; \
+ else { \
+ const PHYSFS_uint64 len = (PHYSFS_uint64) ((strlen(str) * 4) + 1); \
+ w_assignto = (char *) __PHYSFS_smallAlloc(len); \
+ PHYSFS_uc2fromutf8(str, (PHYSFS_uint16 *) w_assignto, len); \
+ } \
+} \
typedef struct
{
@@ -48,22 +53,85 @@
} win32file;
const char *__PHYSFS_platformDirSeparator = "\\";
-static LPFNGETFILEATTRIBUTESEX pGetFileAttributesEx = NULL;
+
+
+/* pointers for APIs that may not exist on some Windows versions... */
static HANDLE libKernel32 = NULL;
+static HANDLE libUserEnv = NULL;
+static HANDLE libAdvApi32 = NULL;
+static DWORD (WINAPI *pGetModuleFileNameA)(HMODULE, LPCH, DWORD);
+static DWORD (WINAPI *pGetModuleFileNameW)(HMODULE, LPWCH, DWORD);
+static BOOL (WINAPI *pGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD);
+static BOOL (WINAPI *pGetUserNameW)(LPWSTR, LPDWORD);
+static DWORD (WINAPI *pGetFileAttributesW)(LPCWSTR);
+static HANDLE (WINAPI *pFindFirstFileW)(LPCWSTR, LPWIN32_FIND_DATAW);
+static BOOL (WINAPI *pFindNextFileW)(HANDLE, LPWIN32_FIND_DATAW);
+static DWORD (WINAPI *pGetCurrentDirectoryW)(DWORD, LPWSTR);
+static BOOL (WINAPI *pDeleteFileW)(LPCWSTR);
+static BOOL (WINAPI *pRemoveDirectoryW)(LPCWSTR);
+static BOOL (WINAPI *pCreateDirectoryW)(LPCWSTR, LPSECURITY_ATTRIBUTES);
+static BOOL (WINAPI *pGetFileAttributesExA)
+ (LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
+static BOOL (WINAPI *pGetFileAttributesExW)
+ (LPCWSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
+static DWORD (WINAPI *pFormatMessageW)
+ (DWORD, LPCVOID, DWORD, DWORD, LPWSTR, DWORD, va_list *);
+static DWORD (WINAPI *pSearchPathW)
+ (LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPWSTR *);
+static HANDLE (WINAPI *pCreateFileW)
+ (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
+
static char *userDir = NULL;
-/*
- * Users without the platform SDK don't have this defined. The original docs
- * for SetFilePointer() just said to compare with 0xFFFFFFFF, so this should
- * work as desired.
- */
-#define PHYSFS_INVALID_SET_FILE_POINTER 0xFFFFFFFF
-/* just in case... */
-#define PHYSFS_INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
+/* A blatant abuse of pointer casting... */
+static void symLookup(HMODULE dll, void **addr, const char *sym)
+{
+ *addr = GetProcAddress(dll, sym);
+} /* symLookup */
+static int findApiSymbols(void)
+{
+ HMODULE dll = NULL;
+ #define LOOKUP(x) { symLookup(dll, (void **) &p##x, #x); }
+
+ dll = libUserEnv = LoadLibrary("userenv.dll");
+ if (dll != NULL)
+ LOOKUP(GetUserProfileDirectoryW);
+
+ /* !!! FIXME: what do they call advapi32.dll on Win64? */
+ dll = libAdvApi32 = LoadLibrary("advapi32.dll");
+ if (dll != NULL)
+ LOOKUP(GetUserNameW);
+
+ /* !!! FIXME: what do they call kernel32.dll on Win64? */
+ dll = libKernel32 = LoadLibrary("kernel32.dll");
+ if (dll != NULL)
+ {
+ LOOKUP(GetModuleFileNameA);
+ LOOKUP(GetModuleFileNameW);
+ LOOKUP(FormatMessageW);
+ LOOKUP(FindFirstFileW);
+ LOOKUP(FindNextFileW);
+ LOOKUP(GetFileAttributesW);
+ LOOKUP(GetFileAttributesExA);
+ LOOKUP(GetFileAttributesExW);
+ LOOKUP(GetCurrentDirectoryW);
+ LOOKUP(CreateDirectoryW);
+ LOOKUP(RemoveDirectoryW);
+ LOOKUP(CreateFileW);
+ LOOKUP(DeleteFileW);
+ LOOKUP(SearchPathW);
+ } /* if */
+
+ #undef LOOKUP
+
+ return(1);
+} /* findApiSymbols */
+
+
/*
* Figure out what the last failing Win32 API call was, and
* generate a human-readable string for the error message.
@@ -175,7 +243,7 @@
/*
- * Try to make use of GetUserProfileDirectory(), which isn't available on
+ * Try to make use of GetUserProfileDirectoryW(), which isn't available on
* some common variants of Win32. If we can't use this, we just punt and
* use the physfs base dir for the user dir, too.
*
@@ -186,64 +254,52 @@
*/
static int determineUserDir(void)
{
- DWORD psize = 0;
- char dummy[1];
- BOOL rc = 0;
- HANDLE processHandle; /* Current process handle */
- HANDLE accessToken = NULL; /* Security handle to process */
- LPFNGETUSERPROFILEDIR GetUserProfileDirectory;
- HMODULE lib;
+ if (userDir != NULL)
+ return(1); /* already good to go. */
- assert(userDir == NULL);
-
/*
- * GetUserProfileDirectory() is only available on NT 4.0 and later.
+ * GetUserProfileDirectoryW() is only available on NT 4.0 and later.
* This means Win95/98/ME (and CE?) users have to do without, so for
* them, we'll default to the base directory when we can't get the
- * function pointer.
+ * function pointer. Since this is originally an NT API, we don't
+ * offer a non-Unicode fallback.
*/
-
- lib = LoadLibrary("userenv.dll");
- if (lib)
+ if (pGetUserProfileDirectoryW != NULL)
{
- /* !!! FIXME: unicode version. */
- GetUserProfileDirectory = (LPFNGETUSERPROFILEDIR)
- GetProcAddress(lib, "GetUserProfileDirectoryA");
- if (GetUserProfileDirectory)
+ HANDLE accessToken = NULL; /* Security handle to process */
+ HANDLE processHandle = GetCurrentProcess();
+ if (OpenProcessToken(processHandle, TOKEN_QUERY, &accessToken))
{
- processHandle = GetCurrentProcess();
- if (OpenProcessToken(processHandle, TOKEN_QUERY, &accessToken))
+ DWORD psize = 0;
+ WCHAR dummy = 0;
+ LPWSTR wstr = NULL;
+ BOOL rc = 0;
+
+ /*
+ * Should fail. Will write the size of the profile path in
+ * psize. Also note that the second parameter can't be
+ * NULL or the function fails.
+ */
+ rc = pGetUserProfileDirectoryW(accessToken, &dummy, &psize);
+ assert(!rc); /* !!! FIXME: handle this gracefully. */
+
+ /* Allocate memory for the profile directory */
+ wstr = (LPWSTR) __PHYSFS_smallAlloc(psize * sizeof (WCHAR));
+ if (wstr != NULL)
{
- /*
- * Should fail. Will write the size of the profile path in
- * psize. Also note that the second parameter can't be
- * NULL or the function fails.
- */
- /* !!! FIXME: unicode version. */
- rc = GetUserProfileDirectory(accessToken, dummy, &psize);
- assert(!rc); /* success?! */
-
- /* Allocate memory for the profile directory */
- userDir = (char *) allocator.Malloc(psize);
- if (userDir != NULL)
+ if (pGetUserProfileDirectoryW(accessToken, wstr, &psize))
{
- /* !!! FIXME: unicode version. */
- if (GetUserProfileDirectory(accessToken, userDir, &psize))
- {
- /* !!! FIXME: convert to UTF-8. */
- } /* if */
- else
- {
- allocator.Free(userDir);
- userDir = NULL;
- } /* else */
- } /* else */
- } /* if */
-
- CloseHandle(accessToken);
+ const PHYSFS_uint64 buflen = psize * 6;
+ userDir = (char *) allocator.Malloc(buflen);
+ if (userDir != NULL)
+ PHYSFS_utf8FromUcs2((const PHYSFS_uint16 *) wstr, userDir, buflen);
+ /* !!! FIXME: shrink allocation... */
+ } /* if */
+ __PHYSFS_smallFree(wstr);
+ } /* else */
} /* if */
- FreeLibrary(lib);
+ CloseHandle(accessToken);
} /* if */
if (userDir == NULL) /* couldn't get profile for some reason. */
@@ -251,7 +307,6 @@
/* Might just be a non-NT system; resort to the basedir. */
userDir = getExePath(NULL);
BAIL_IF_MACRO(userDir == NULL, NULL, 0); /* STILL failed?! */
- /* !!! FIXME: convert to UTF-8. */
} /* if */
return(1); /* We made it: hit the showers. */
@@ -445,6 +500,8 @@
continue;
callback(callbackdata, origdir, ent.cFileName);
+
+ /* !!! FIXME: unicode version. */
} while (FindNextFile(dir, &ent) != 0);
FindClose(dir);
@@ -622,71 +679,30 @@
} /* getOSInfo */
-/*
- * Some things we want/need are in external DLLs that may or may not be
- * available, based on the operating system, etc. This function loads those
- * libraries and hunts down the needed pointers.
- *
- * Libraries that are one-shot deals, or better loaded as needed, are loaded
- * elsewhere (see determineUserDir()).
- *
- * Returns zero if a needed library couldn't load, non-zero if we have enough
- * to go on (which means some useful but non-crucial libraries may _NOT_ be
- * loaded; check the related module-scope variables).
- */
-static int loadLibraries(void)
-{
- /* If this get unwieldy, make it table driven. */
-
- int allNeededLibrariesLoaded = 1; /* flip to zero as needed. */
-
- libKernel32 = LoadLibrary("kernel32.dll");
- if (libKernel32)
- {
- pGetFileAttributesEx = (LPFNGETFILEATTRIBUTESEX)
- GetProcAddress(libKernel32, "GetFileAttributesExA");
- } /* if */
-
- /* add other DLLs here... */
-
-
- /* see if there's any reason to keep kernel32.dll around... */
- if (libKernel32)
- {
- if ((pGetFileAttributesEx == NULL) /* && (somethingElse == NULL) */ )
- {
- FreeLibrary(libKernel32);
- libKernel32 = NULL;
- } /* if */
- } /* if */
-
- return(allNeededLibrariesLoaded);
-} /* loadLibraries */
-
-
int __PHYSFS_platformInit(void)
{
+ BAIL_IF_MACRO(!findApiSymbols(), NULL, 0);
BAIL_IF_MACRO(!getOSInfo(), NULL, 0);
- BAIL_IF_MACRO(!loadLibraries(), NULL, 0);
BAIL_IF_MACRO(!determineUserDir(), NULL, 0);
-
return(1); /* It's all good */
} /* __PHYSFS_platformInit */
int __PHYSFS_platformDeinit(void)
{
- if (userDir != NULL)
- {
- allocator.Free(userDir);
- userDir = NULL;
- } /* if */
+ HANDLE *libs[] = { &libKernel32, &libUserEnv, &libAdvApi32, NULL };
+ int i;
- if (libKernel32)
+ allocator.Free(userDir);
+ userDir = NULL;
+
+ for (i = 0; libs[i] != NULL; i++)
{
- FreeLibrary(libKernel32);
- libKernel32 = NULL;
- } /* if */
+ const HANDLE lib = *(libs[i]);
+ if (lib)
+ FreeLibrary(lib);
+ *(libs[i]) = NULL;
+ } /* for */
return(1); /* It's all good */
} /* __PHYSFS_platformDeinit */
@@ -1054,10 +1070,10 @@
memset(&attrData, '\0', sizeof (attrData));
/* GetFileAttributesEx didn't show up until Win98 and NT4. */
- if (pGetFileAttributesEx != NULL)
+ if (pGetFileAttributesExA != NULL)
{
/* !!! FIXME: unicode version. */
- if (pGetFileAttributesEx(fname, GetFileExInfoStandard, &attrData))
+ if (pGetFileAttributesExA(fname, GetFileExInfoStandard, &attrData))
{
/* 0 return value indicates an error or not supported */
if ( (attrData.ftLastWriteTime.dwHighDateTime != 0) ||
More information about the physfs-commits
mailing list