From da2d3ede59e32f7b0b6d6a084b5a1bf0440592ff Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 25 Mar 2007 06:26:53 +0000 Subject: [PATCH] Reworked getExePath() to remove some FIXMEs and respect Unicode. --- platform/windows.c | 103 +++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/platform/windows.c b/platform/windows.c index 95560533..51aaded1 100644 --- a/platform/windows.c +++ b/platform/windows.c @@ -172,72 +172,73 @@ static const char *win32strerror(void) } /* win32strerror */ -static char *getExePath(const char *argv0) +static char *getExePath(void) { - DWORD buflen; + DWORD buflen = 64; int success = 0; - char *ptr = NULL; - char *retval = (char *) allocator.Malloc(sizeof (TCHAR) * (MAX_PATH + 1)); - - BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); + LPWSTR modpath = NULL; + char *retval = NULL; - retval[0] = '\0'; - /* !!! FIXME: don't preallocate here? */ - /* !!! FIXME: use smallAlloc? */ - /* !!! FIXME: unicode version. */ - buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1); - if (buflen <= 0) - __PHYSFS_setError(win32strerror()); - else + while (1) { - retval[buflen] = '\0'; /* does API always null-terminate this? */ + DWORD rc; + void *ptr; - /* make sure the string was not truncated. */ - if (__PHYSFS_stricmpASCII(&retval[buflen - 4], ".exe") != 0) - __PHYSFS_setError(ERR_GETMODFN_TRUNC); - else + if ( !(ptr = allocator.Realloc(modpath, buflen*sizeof(WCHAR))) ) { - ptr = strrchr(retval, '\\'); - if (ptr == NULL) - __PHYSFS_setError(ERR_GETMODFN_NO_DIR); - else - { - *(ptr + 1) = '\0'; /* chop off filename. */ - success = 1; - } /* else */ - } /* else */ - } /* else */ + allocator.Free(modpath); + BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); + } /* if */ + modpath = (LPWSTR) ptr; - /* if any part of the previous approach failed, try SearchPath()... */ + rc = pGetModuleFileNameW(NULL, modpath, buflen); + if (rc == 0) + { + allocator.Free(modpath); + BAIL_MACRO(win32strerror(), NULL); + } /* if */ - if (!success) + if (rc < buflen) + { + buflen = rc; + break; + } /* if */ + + buflen *= 2; + } /* while */ + + if (buflen > 0) /* just in case... */ { - if (argv0 == NULL) /* !!! FIXME: default behaviour does this. */ - __PHYSFS_setError(ERR_ARGV0_IS_NULL); + WCHAR *ptr = (modpath + buflen) - 1; + while (ptr != modpath) + { + if (*ptr == '\\') + break; + ptr--; + } /* while */ + + if ((ptr == modpath) && (*ptr != '\\')) + __PHYSFS_setError(ERR_GETMODFN_NO_DIR); else { - /* !!! FIXME: unicode version. */ - buflen = SearchPath(NULL, argv0, NULL, MAX_PATH+1, retval, &ptr); - if (buflen == 0) - __PHYSFS_setError(win32strerror()); - else if (buflen > MAX_PATH) - __PHYSFS_setError(ERR_SEARCHPATH_TRUNC); + *(ptr + 1) = '\0'; /* chop off filename. */ + retval = (char *) allocator.Malloc(buflen * 6); + if (retval == NULL) + __PHYSFS_setError(ERR_OUT_OF_MEMORY); else - success = 1; + PHYSFS_utf8FromUcs2((const PHYSFS_uint16 *) modpath, retval, buflen * 6); } /* else */ - } /* if */ + } /* else */ + allocator.Free(modpath); - if (!success) + /* free up the bytes we didn't actually use. */ + if (retval != NULL) { - allocator.Free(retval); - return(NULL); /* physfs error message will be set, above. */ + void *ptr = allocator.Realloc(retval, strlen(retval) + 1); + if (ptr != NULL) + retval = (char *) ptr; } /* if */ - /* free up the bytes we didn't actually use. */ - ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1); - if (ptr != NULL) - retval = ptr; - return(retval); /* w00t. */ } /* getExePath */ @@ -305,7 +306,7 @@ static int determineUserDir(void) if (userDir == NULL) /* couldn't get profile for some reason. */ { /* Might just be a non-NT system; resort to the basedir. */ - userDir = getExePath(NULL); + userDir = getExePath(); BAIL_IF_MACRO(userDir == NULL, NULL, 0); /* STILL failed?! */ } /* if */ @@ -352,7 +353,7 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0) if ((argv0 != NULL) && (strchr(argv0, '\\') != NULL)) return(NULL); /* default behaviour can handle this. */ - return(getExePath(argv0)); + return(getExePath()); } /* __PHYSFS_platformCalcBaseDir */