|
@@ -144,49 +144,121 @@ SDL_GetPrefPath(const char *org, const char *app)
|
|
|
* without violating Microsoft's app-store requirements.
|
|
|
*/
|
|
|
|
|
|
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
|
|
- /* A 'Roaming' folder is not available in Windows Phone 8.0, however a
|
|
|
- * 'Local' folder is. Use the 'Local' folder in order to preserve
|
|
|
- * compatibility with Windows Phone 8.0, and with app-installs that have
|
|
|
- * been updated from 8.0-based, to 8.1-based apps.
|
|
|
+ /* Default to using a Local/non-Roaming path. WinRT will often attempt
|
|
|
+ * to synchronize files in Roaming paths, and will do so while an app is
|
|
|
+ * running. Using a Local path prevents the possibility that an app's
|
|
|
+ * save-data files will get changed from underneath it, without it
|
|
|
+ * being ready.
|
|
|
+ *
|
|
|
+ * This behavior can be changed via use of the
|
|
|
+ * SDL_HINT_WINRT_PREF_PATH_ROOT hint.
|
|
|
*/
|
|
|
SDL_WinRT_Path pathType = SDL_WINRT_PATH_LOCAL_FOLDER;
|
|
|
-#else
|
|
|
- /* A 'Roaming' folder is available on Windows 8 and 8.1. Use that.
|
|
|
- */
|
|
|
- SDL_WinRT_Path pathType = SDL_WINRT_PATH_ROAMING_FOLDER;
|
|
|
-#endif
|
|
|
|
|
|
const char * hint = SDL_GetHint(SDL_HINT_WINRT_PREF_PATH_ROOT);
|
|
|
if (hint) {
|
|
|
if (SDL_strcasecmp(hint, "local") == 0) {
|
|
|
pathType = SDL_WINRT_PATH_LOCAL_FOLDER;
|
|
|
- }
|
|
|
+ } else if (SDL_strcasecmp(hint, "roaming") == 0) {
|
|
|
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
|
|
|
- else if (SDL_strcasecmp(hint, "roaming") == 0) {
|
|
|
pathType = SDL_WINRT_PATH_ROAMING_FOLDER;
|
|
|
- }
|
|
|
+#else
|
|
|
+ /* Don't apply a 'Roaming' path on Windows Phone 8.0. Roaming
|
|
|
+ * data is not supported by that version of the operating system.
|
|
|
+ */
|
|
|
+ SDL_SetError("A Roaming path was specified via SDL_HINT_WINRT_PREF_PATH_ROOT, but Roaming is not supported on Windows Phone 8.0");
|
|
|
+ return NULL;
|
|
|
#endif
|
|
|
+ } else if (SDL_strcasecmp(hint, "old") == 0) {
|
|
|
+ /* Older versions of SDL/WinRT, including 2.0.3, would return a
|
|
|
+ * pref-path that used a Roaming folder on non-Phone versions of
|
|
|
+ * Windows, such as Windows 8.0 and Windows 8.1. This has since
|
|
|
+ * been reverted to using a Local folder, in order to prevent
|
|
|
+ * problems arising from WinRT automatically synchronizing files
|
|
|
+ * during an app's lifetime. In case this functionality is
|
|
|
+ * desired, setting SDL_HINT_WINRT_PREF_PATH_ROOT to "old" will
|
|
|
+ * trigger the older behavior.
|
|
|
+ */
|
|
|
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
|
|
+ pathType = SDL_WINRT_PATH_LOCAL_FOLDER;
|
|
|
+#else
|
|
|
+ pathType = SDL_WINRT_PATH_ROAMING_FOLDER;
|
|
|
+#endif
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- const char * srcPath = SDL_WinRTGetFSPathUTF8(pathType);
|
|
|
- size_t destPathLen;
|
|
|
- char * destPath = NULL;
|
|
|
+ const WCHAR * srcPath = NULL;
|
|
|
+ WCHAR path[MAX_PATH];
|
|
|
+ char *retval = NULL;
|
|
|
+ WCHAR* worg = NULL;
|
|
|
+ WCHAR* wapp = NULL;
|
|
|
+ size_t new_wpath_len = 0;
|
|
|
+ BOOL api_result = FALSE;
|
|
|
|
|
|
- if (!srcPath) {
|
|
|
- SDL_SetError("Couldn't locate our basepath: %s", SDL_GetError());
|
|
|
+ srcPath = SDL_WinRTGetFSPathUNICODE(pathType);
|
|
|
+ if ( ! srcPath) {
|
|
|
+ SDL_SetError("Unable to find a source path");
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- destPathLen = SDL_strlen(srcPath) + SDL_strlen(org) + SDL_strlen(app) + 4;
|
|
|
- destPath = (char *) SDL_malloc(destPathLen);
|
|
|
- if (!destPath) {
|
|
|
+ if (SDL_wcslen(srcPath) >= MAX_PATH) {
|
|
|
+ SDL_SetError("Path too long.");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ SDL_wcslcpy(path, srcPath, SDL_arraysize(path));
|
|
|
+
|
|
|
+ worg = WIN_UTF8ToString(org);
|
|
|
+ if (worg == NULL) {
|
|
|
SDL_OutOfMemory();
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- SDL_snprintf(destPath, destPathLen, "%s\\%s\\%s\\", srcPath, org, app);
|
|
|
- return destPath;
|
|
|
+ wapp = WIN_UTF8ToString(app);
|
|
|
+ if (wapp == NULL) {
|
|
|
+ SDL_free(worg);
|
|
|
+ SDL_OutOfMemory();
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ new_wpath_len = SDL_wcslen(worg) + SDL_wcslen(wapp) + SDL_wcslen(path) + 3;
|
|
|
+
|
|
|
+ if ((new_wpath_len + 1) > MAX_PATH) {
|
|
|
+ SDL_free(worg);
|
|
|
+ SDL_free(wapp);
|
|
|
+ SDL_SetError("Path too long.");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_wcslcat(path, L"\\", new_wpath_len + 1);
|
|
|
+ SDL_wcslcat(path, worg, new_wpath_len + 1);
|
|
|
+ SDL_free(worg);
|
|
|
+
|
|
|
+ api_result = CreateDirectoryW(path, NULL);
|
|
|
+ if (api_result == FALSE) {
|
|
|
+ if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
|
|
+ SDL_free(wapp);
|
|
|
+ WIN_SetError("Couldn't create a prefpath.");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_wcslcat(path, L"\\", new_wpath_len + 1);
|
|
|
+ SDL_wcslcat(path, wapp, new_wpath_len + 1);
|
|
|
+ SDL_free(wapp);
|
|
|
+
|
|
|
+ api_result = CreateDirectoryW(path, NULL);
|
|
|
+ if (api_result == FALSE) {
|
|
|
+ if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
|
|
+ WIN_SetError("Couldn't create a prefpath.");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_wcslcat(path, L"\\", new_wpath_len + 1);
|
|
|
+
|
|
|
+ retval = WIN_StringToUTF8(path);
|
|
|
+
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
#endif /* __WINRT__ */
|