Reworked getExePath() to remove some FIXMEs and respect Unicode.

This commit is contained in:
Ryan C. Gordon 2007-03-25 06:26:53 +00:00
parent dc0d27228c
commit da2d3ede59
1 changed files with 56 additions and 55 deletions

View File

@ -172,71 +172,72 @@ static const char *win32strerror(void)
} /* win32strerror */ } /* win32strerror */
static char *getExePath(const char *argv0) static char *getExePath(void)
{ {
DWORD buflen; DWORD buflen = 64;
int success = 0; int success = 0;
char *ptr = NULL; LPWSTR modpath = NULL;
char *retval = (char *) allocator.Malloc(sizeof (TCHAR) * (MAX_PATH + 1)); char *retval = NULL;
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); while (1)
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
{ {
retval[buflen] = '\0'; /* does API always null-terminate this? */ DWORD rc;
void *ptr;
/* make sure the string was not truncated. */ if ( !(ptr = allocator.Realloc(modpath, buflen*sizeof(WCHAR))) )
if (__PHYSFS_stricmpASCII(&retval[buflen - 4], ".exe") != 0) {
__PHYSFS_setError(ERR_GETMODFN_TRUNC); allocator.Free(modpath);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
modpath = (LPWSTR) ptr;
rc = pGetModuleFileNameW(NULL, modpath, buflen);
if (rc == 0)
{
allocator.Free(modpath);
BAIL_MACRO(win32strerror(), NULL);
} /* if */
if (rc < buflen)
{
buflen = rc;
break;
} /* if */
buflen *= 2;
} /* while */
if (buflen > 0) /* just in case... */
{
WCHAR *ptr = (modpath + buflen) - 1;
while (ptr != modpath)
{
if (*ptr == '\\')
break;
ptr--;
} /* while */
if ((ptr == modpath) && (*ptr != '\\'))
__PHYSFS_setError(ERR_GETMODFN_NO_DIR);
else else
{ {
ptr = strrchr(retval, '\\'); *(ptr + 1) = '\0'; /* chop off filename. */
if (ptr == NULL) retval = (char *) allocator.Malloc(buflen * 6);
__PHYSFS_setError(ERR_GETMODFN_NO_DIR); if (retval == NULL)
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
else else
{ PHYSFS_utf8FromUcs2((const PHYSFS_uint16 *) modpath, retval, buflen * 6);
*(ptr + 1) = '\0'; /* chop off filename. */
success = 1;
} /* else */
} /* else */ } /* else */
} /* else */ } /* else */
allocator.Free(modpath);
/* if any part of the previous approach failed, try SearchPath()... */
if (!success)
{
if (argv0 == NULL) /* !!! FIXME: default behaviour does this. */
__PHYSFS_setError(ERR_ARGV0_IS_NULL);
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);
else
success = 1;
} /* else */
} /* if */
if (!success)
{
allocator.Free(retval);
return(NULL); /* physfs error message will be set, above. */
} /* if */
/* free up the bytes we didn't actually use. */ /* free up the bytes we didn't actually use. */
ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1); if (retval != NULL)
if (ptr != NULL) {
retval = ptr; void *ptr = allocator.Realloc(retval, strlen(retval) + 1);
if (ptr != NULL)
retval = (char *) ptr;
} /* if */
return(retval); /* w00t. */ return(retval); /* w00t. */
} /* getExePath */ } /* getExePath */
@ -305,7 +306,7 @@ static int determineUserDir(void)
if (userDir == NULL) /* couldn't get profile for some reason. */ if (userDir == NULL) /* couldn't get profile for some reason. */
{ {
/* Might just be a non-NT system; resort to the basedir. */ /* 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?! */ BAIL_IF_MACRO(userDir == NULL, NULL, 0); /* STILL failed?! */
} /* if */ } /* if */
@ -352,7 +353,7 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
if ((argv0 != NULL) && (strchr(argv0, '\\') != NULL)) if ((argv0 != NULL) && (strchr(argv0, '\\') != NULL))
return(NULL); /* default behaviour can handle this. */ return(NULL); /* default behaviour can handle this. */
return(getExePath(argv0)); return(getExePath());
} /* __PHYSFS_platformCalcBaseDir */ } /* __PHYSFS_platformCalcBaseDir */