No longer use SHGetFolderPath on MS Windows.
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@525 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -28,23 +28,14 @@
|
|||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include <direct.h>
|
# include <direct.h>
|
||||||
|
|
||||||
// this would lead to conflicts
|
|
||||||
//# include <shlobj.h>
|
|
||||||
typedef void *HWND;
|
|
||||||
typedef void *HANDLE;
|
|
||||||
typedef char *LPTSTR;
|
|
||||||
typedef long HRESULT;
|
|
||||||
#define SUCCEEDED(Status) ((HRESULT) (Status) >= 0)
|
|
||||||
HRESULT __stdcall SHGetFolderPathA (HWND hwndOwner, int nFolder,
|
|
||||||
HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
|
|
||||||
#define SHGetFolderPath SHGetFolderPathA
|
|
||||||
#define CSIDL_APPDATA 0x001a // <user name>\Application Data
|
|
||||||
#define CSIDL_FLAG_CREATE 0x8000
|
|
||||||
// combine with CSIDL_ value to force folder creation in
|
|
||||||
// SHGetFolderPath()
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Try to find a suitable value for %APPDATA% if it isn't defined on
|
||||||
|
* Windows.
|
||||||
|
*/
|
||||||
|
#define APPDATA_FALLBACK
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
createDirectory(const char *dir, int mode)
|
createDirectory(const char *dir, int mode)
|
||||||
{
|
{
|
||||||
@@ -167,10 +158,11 @@ getHomeDir (void)
|
|||||||
int
|
int
|
||||||
expandPath (char *dest, size_t len, const char *src)
|
expandPath (char *dest, size_t len, const char *src)
|
||||||
{
|
{
|
||||||
const char *destend;
|
char *destend;
|
||||||
|
char *destptr;
|
||||||
|
|
||||||
#define CHECKLEN(n) \
|
#define CHECKLEN(n) \
|
||||||
if (dest + (n) > destend) \
|
if (destptr + (n) >= destend) \
|
||||||
{ \
|
{ \
|
||||||
errno = ENAMETOOLONG; \
|
errno = ENAMETOOLONG; \
|
||||||
return -1; \
|
return -1; \
|
||||||
@@ -178,6 +170,7 @@ expandPath (char *dest, size_t len, const char *src)
|
|||||||
else \
|
else \
|
||||||
(void) 0
|
(void) 0
|
||||||
|
|
||||||
|
destptr = dest;
|
||||||
destend = dest + len;
|
destend = dest + len;
|
||||||
if (src[0] == '~')
|
if (src[0] == '~')
|
||||||
{
|
{
|
||||||
@@ -199,8 +192,8 @@ expandPath (char *dest, size_t len, const char *src)
|
|||||||
homelen = strlen (home);
|
homelen = strlen (home);
|
||||||
|
|
||||||
CHECKLEN (homelen);
|
CHECKLEN (homelen);
|
||||||
memcpy (dest, home, homelen);
|
memcpy (destptr, home, homelen);
|
||||||
dest += homelen;
|
destptr += homelen;
|
||||||
src++; /* skip the ~ */
|
src++; /* skip the ~ */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,14 +201,6 @@ expandPath (char *dest, size_t len, const char *src)
|
|||||||
{
|
{
|
||||||
switch (*src)
|
switch (*src)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
|
||||||
case '\\':
|
|
||||||
/* Replaces backslashes in path by slashes in Windows. */
|
|
||||||
CHECKLEN(1);
|
|
||||||
*(dest++) = '/';
|
|
||||||
src++;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
case '%':
|
case '%':
|
||||||
{
|
{
|
||||||
@@ -242,26 +227,56 @@ expandPath (char *dest, size_t len, const char *src)
|
|||||||
|
|
||||||
if (envVar == NULL)
|
if (envVar == NULL)
|
||||||
{
|
{
|
||||||
#if 1
|
#ifdef APPDATA_FALLBACK
|
||||||
if (strncmp (src, "APPDATA", envNameLen) == 0)
|
if (strncmp (src, "APPDATA", envNameLen) != 0)
|
||||||
{
|
{
|
||||||
// fallback for when the APPDATA env var is not set
|
// Substitute an empty string
|
||||||
if (getUserDataDir (dest, destend - dest) == -1)
|
|
||||||
return -1;
|
|
||||||
dest += strlen (dest);
|
|
||||||
src = end + 1;
|
src = end + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
// fallback for when the APPDATA env var is not set
|
||||||
|
// Using SHGetFolderPath or SHGetSpecialFolderPath
|
||||||
|
// is problematic (not everywhere available).
|
||||||
|
fprintf(stderr, "Warning: %%APPDATA%% is not set. "
|
||||||
|
"Falling back to \"%%USERPROFILE%%\\Application "
|
||||||
|
"Data\"\n");
|
||||||
|
envVar = getenv ("USERPROFILE");
|
||||||
|
if (envVar != NULL)
|
||||||
|
{
|
||||||
|
#define APPDATA_STRING "\\Application Data"
|
||||||
|
envVarLen = strlen (envVar);
|
||||||
|
CHECKLEN (envVarLen + sizeof (APPDATA_STRING) - 1);
|
||||||
|
strcpy (destptr, envVar);
|
||||||
|
destptr += envVarLen;
|
||||||
|
strcpy (destptr, APPDATA_STRING);
|
||||||
|
destptr += sizeof (APPDATA_STRING) - 1;
|
||||||
|
src = end + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback to "../userdata"
|
||||||
|
fprintf(stderr, "Warning: %%USERPROFILE%% is not set. "
|
||||||
|
"Falling back to \"..\\userdata\" for %%APPDATA%%"
|
||||||
|
"\n");
|
||||||
|
#define APPDATA_FALLBACK_STRING "..\\userdata"
|
||||||
|
CHECKLEN (sizeof (APPDATA_FALLBACK_STRING) - 1);
|
||||||
|
strcpy (destptr, APPDATA_FALLBACK_STRING);
|
||||||
|
destptr += sizeof (APPDATA_FALLBACK_STRING) - 1;
|
||||||
|
src = end + 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#else /* !defined (APPDATA_FALLBACK) */
|
||||||
// Substitute an empty string
|
// Substitute an empty string
|
||||||
src = end + 1;
|
src = end + 1;
|
||||||
break;
|
break;
|
||||||
|
#endif /* APPDATA_FALLBACK */
|
||||||
}
|
}
|
||||||
|
|
||||||
envVarLen = strlen (envVar);
|
envVarLen = strlen (envVar);
|
||||||
CHECKLEN (envVarLen);
|
CHECKLEN (envVarLen);
|
||||||
strcpy (dest, envVar);
|
strcpy (destptr, envVar);
|
||||||
dest += envVarLen;
|
destptr += envVarLen;
|
||||||
src = end + 1;
|
src = end + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -270,55 +285,31 @@ expandPath (char *dest, size_t len, const char *src)
|
|||||||
case '$':
|
case '$':
|
||||||
/* Environment variable substitution for Unix */
|
/* Environment variable substitution for Unix */
|
||||||
// not implemented
|
// not implemented
|
||||||
|
// Should accept both $BLA_123 and ${BLA}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
CHECKLEN(1);
|
CHECKLEN(1);
|
||||||
*(dest++) = *(src++);
|
*(destptr++) = *(src++);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*dest = '\0';
|
*destptr = '\0';
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns 0 on success, and fills dir with the path to the dir where there
|
|
||||||
// user data is stored.
|
|
||||||
// return -1 on error, and sets errno.
|
|
||||||
int
|
|
||||||
getUserDataDir (char *dir, size_t len)
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
char buf[PATH_MAX];
|
/* Replacing backslashes in path by slashes in Windows. */
|
||||||
|
destptr = dest;
|
||||||
if (!SUCCEEDED (SHGetFolderPath(NULL,
|
while (*destptr != '\0')
|
||||||
CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, buf)))
|
|
||||||
{
|
{
|
||||||
errno = ENOENT;
|
if (*destptr == '\\')
|
||||||
return -1;
|
{
|
||||||
|
*destptr = '/';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
destptr++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (strlen (buf) >= len)
|
|
||||||
{
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy (dir, buf);
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
|
||||||
const char *homeDir;
|
|
||||||
homeDir = getHomeDir();
|
|
||||||
|
|
||||||
if (strlen (homeDir) >= len)
|
|
||||||
{
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy (dir, homeDir);
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
|||||||
Reference in New Issue
Block a user