src/filesystem/winrt/SDL_sysfilesystem.cpp
author Sam Lantinga <slouken@libsdl.org>
Tue, 26 May 2015 06:27:46 -0700
changeset 9619 b94b6d0bff0f
parent 9255 c2ef0d8d6da0
child 9998 f67cf37e9cd4
permissions -rw-r--r--
Updated the copyright year to 2015
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 /* TODO, WinRT: remove the need to compile this with C++/CX (/ZW) extensions, and if possible, without C++ at all
    24 */
    25 
    26 #ifdef __WINRT__
    27 
    28 extern "C" {
    29 #include "SDL_filesystem.h"
    30 #include "SDL_error.h"
    31 #include "SDL_hints.h"
    32 #include "SDL_stdinc.h"
    33 #include "SDL_system.h"
    34 #include "../../core/windows/SDL_windows.h"
    35 }
    36 
    37 #include <string>
    38 #include <unordered_map>
    39 
    40 using namespace std;
    41 using namespace Windows::Storage;
    42 
    43 extern "C" const wchar_t *
    44 SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType)
    45 {
    46     switch (pathType) {
    47         case SDL_WINRT_PATH_INSTALLED_LOCATION:
    48         {
    49             static wstring path;
    50             if (path.empty()) {
    51                 path = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data();
    52             }
    53             return path.c_str();
    54         }
    55 
    56         case SDL_WINRT_PATH_LOCAL_FOLDER:
    57         {
    58             static wstring path;
    59             if (path.empty()) {
    60                 path = ApplicationData::Current->LocalFolder->Path->Data();
    61             }
    62             return path.c_str();
    63         }
    64 
    65 #if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
    66         case SDL_WINRT_PATH_ROAMING_FOLDER:
    67         {
    68             static wstring path;
    69             if (path.empty()) {
    70                 path = ApplicationData::Current->RoamingFolder->Path->Data();
    71             }
    72             return path.c_str();
    73         }
    74 
    75         case SDL_WINRT_PATH_TEMP_FOLDER:
    76         {
    77             static wstring path;
    78             if (path.empty()) {
    79                 path = ApplicationData::Current->TemporaryFolder->Path->Data();
    80             }
    81             return path.c_str();
    82         }
    83 #endif
    84 
    85         default:
    86             break;
    87     }
    88 
    89     SDL_Unsupported();
    90     return NULL;
    91 }
    92 
    93 extern "C" const char *
    94 SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType)
    95 {
    96     typedef unordered_map<SDL_WinRT_Path, string> UTF8PathMap;
    97     static UTF8PathMap utf8Paths;
    98 
    99     UTF8PathMap::iterator searchResult = utf8Paths.find(pathType);
   100     if (searchResult != utf8Paths.end()) {
   101         return searchResult->second.c_str();
   102     }
   103 
   104     const wchar_t * ucs2Path = SDL_WinRTGetFSPathUNICODE(pathType);
   105     if (!ucs2Path) {
   106         return NULL;
   107     }
   108 
   109     char * utf8Path = WIN_StringToUTF8(ucs2Path);
   110     utf8Paths[pathType] = utf8Path;
   111     SDL_free(utf8Path);
   112     return utf8Paths[pathType].c_str();
   113 }
   114 
   115 extern "C" char *
   116 SDL_GetBasePath(void)
   117 {
   118     const char * srcPath = SDL_WinRTGetFSPathUTF8(SDL_WINRT_PATH_INSTALLED_LOCATION);
   119     size_t destPathLen;
   120     char * destPath = NULL;
   121 
   122     if (!srcPath) {
   123         SDL_SetError("Couldn't locate our basepath: %s", SDL_GetError());
   124         return NULL;
   125     }
   126 
   127     destPathLen = SDL_strlen(srcPath) + 2;
   128     destPath = (char *) SDL_malloc(destPathLen);
   129     if (!destPath) {
   130         SDL_OutOfMemory();
   131         return NULL;
   132     }
   133 
   134     SDL_snprintf(destPath, destPathLen, "%s\\", srcPath);
   135     return destPath;
   136 }
   137 
   138 extern "C" char *
   139 SDL_GetPrefPath(const char *org, const char *app)
   140 {
   141     /* WinRT note: The 'SHGetFolderPath' API that is used in Windows 7 and
   142      * earlier is not available on WinRT or Windows Phone.  WinRT provides
   143      * a similar API, but SHGetFolderPath can't be called, at least not
   144      * without violating Microsoft's app-store requirements.
   145      */
   146 
   147     const WCHAR * srcPath = NULL;
   148     WCHAR path[MAX_PATH];
   149     char *retval = NULL;
   150     WCHAR* worg = NULL;
   151     WCHAR* wapp = NULL;
   152     size_t new_wpath_len = 0;
   153     BOOL api_result = FALSE;
   154 
   155     srcPath = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_LOCAL_FOLDER);
   156     if ( ! srcPath) {
   157         SDL_SetError("Unable to find a source path");
   158         return NULL;
   159     }
   160 
   161     if (SDL_wcslen(srcPath) >= MAX_PATH) {
   162         SDL_SetError("Path too long.");
   163         return NULL;
   164     }
   165     SDL_wcslcpy(path, srcPath, SDL_arraysize(path));
   166 
   167     worg = WIN_UTF8ToString(org);
   168     if (worg == NULL) {
   169         SDL_OutOfMemory();
   170         return NULL;
   171     }
   172 
   173     wapp = WIN_UTF8ToString(app);
   174     if (wapp == NULL) {
   175         SDL_free(worg);
   176         SDL_OutOfMemory();
   177         return NULL;
   178     }
   179 
   180     new_wpath_len = SDL_wcslen(worg) + SDL_wcslen(wapp) + SDL_wcslen(path) + 3;
   181 
   182     if ((new_wpath_len + 1) > MAX_PATH) {
   183         SDL_free(worg);
   184         SDL_free(wapp);
   185         SDL_SetError("Path too long.");
   186         return NULL;
   187     }
   188 
   189     SDL_wcslcat(path, L"\\", new_wpath_len + 1);
   190     SDL_wcslcat(path, worg, new_wpath_len + 1);
   191     SDL_free(worg);
   192 
   193     api_result = CreateDirectoryW(path, NULL);
   194     if (api_result == FALSE) {
   195         if (GetLastError() != ERROR_ALREADY_EXISTS) {
   196             SDL_free(wapp);
   197             WIN_SetError("Couldn't create a prefpath.");
   198             return NULL;
   199         }
   200     }
   201 
   202     SDL_wcslcat(path, L"\\", new_wpath_len + 1);
   203     SDL_wcslcat(path, wapp, new_wpath_len + 1);
   204     SDL_free(wapp);
   205 
   206     api_result = CreateDirectoryW(path, NULL);
   207     if (api_result == FALSE) {
   208         if (GetLastError() != ERROR_ALREADY_EXISTS) {
   209             WIN_SetError("Couldn't create a prefpath.");
   210             return NULL;
   211         }
   212     }
   213 
   214     SDL_wcslcat(path, L"\\", new_wpath_len + 1);
   215 
   216     retval = WIN_StringToUTF8(path);
   217 
   218     return retval;
   219 }
   220 
   221 #endif /* __WINRT__ */