sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_sysfilesystem.cpp (6925B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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 #if defined(NTDDI_WIN10_19H1) && (NTDDI_VERSION >= NTDDI_WIN10_19H1) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) /* Only PC supports mods */
     52                 /* Windows 1903 supports mods, via the EffectiveLocation API */
     53                 if (Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8, 0)) {
     54                     path = Windows::ApplicationModel::Package::Current->EffectiveLocation->Path->Data();
     55                 } else {
     56                     path = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data();
     57                 }
     58 #else
     59                 path = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data();
     60 #endif
     61             }
     62             return path.c_str();
     63         }
     64 
     65         case SDL_WINRT_PATH_LOCAL_FOLDER:
     66         {
     67             static wstring path;
     68             if (path.empty()) {
     69                 path = ApplicationData::Current->LocalFolder->Path->Data();
     70             }
     71             return path.c_str();
     72         }
     73 
     74 #if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
     75         case SDL_WINRT_PATH_ROAMING_FOLDER:
     76         {
     77             static wstring path;
     78             if (path.empty()) {
     79                 path = ApplicationData::Current->RoamingFolder->Path->Data();
     80             }
     81             return path.c_str();
     82         }
     83 
     84         case SDL_WINRT_PATH_TEMP_FOLDER:
     85         {
     86             static wstring path;
     87             if (path.empty()) {
     88                 path = ApplicationData::Current->TemporaryFolder->Path->Data();
     89             }
     90             return path.c_str();
     91         }
     92 #endif
     93 
     94         default:
     95             break;
     96     }
     97 
     98     SDL_Unsupported();
     99     return NULL;
    100 }
    101 
    102 extern "C" const char *
    103 SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType)
    104 {
    105     typedef unordered_map<SDL_WinRT_Path, string> UTF8PathMap;
    106     static UTF8PathMap utf8Paths;
    107 
    108     UTF8PathMap::iterator searchResult = utf8Paths.find(pathType);
    109     if (searchResult != utf8Paths.end()) {
    110         return searchResult->second.c_str();
    111     }
    112 
    113     const wchar_t * ucs2Path = SDL_WinRTGetFSPathUNICODE(pathType);
    114     if (!ucs2Path) {
    115         return NULL;
    116     }
    117 
    118     char * utf8Path = WIN_StringToUTF8(ucs2Path);
    119     utf8Paths[pathType] = utf8Path;
    120     SDL_free(utf8Path);
    121     return utf8Paths[pathType].c_str();
    122 }
    123 
    124 extern "C" char *
    125 SDL_GetBasePath(void)
    126 {
    127     const char * srcPath = SDL_WinRTGetFSPathUTF8(SDL_WINRT_PATH_INSTALLED_LOCATION);
    128     size_t destPathLen;
    129     char * destPath = NULL;
    130 
    131     if (!srcPath) {
    132         SDL_SetError("Couldn't locate our basepath: %s", SDL_GetError());
    133         return NULL;
    134     }
    135 
    136     destPathLen = SDL_strlen(srcPath) + 2;
    137     destPath = (char *) SDL_malloc(destPathLen);
    138     if (!destPath) {
    139         SDL_OutOfMemory();
    140         return NULL;
    141     }
    142 
    143     SDL_snprintf(destPath, destPathLen, "%s\\", srcPath);
    144     return destPath;
    145 }
    146 
    147 extern "C" char *
    148 SDL_GetPrefPath(const char *org, const char *app)
    149 {
    150     /* WinRT note: The 'SHGetFolderPath' API that is used in Windows 7 and
    151      * earlier is not available on WinRT or Windows Phone.  WinRT provides
    152      * a similar API, but SHGetFolderPath can't be called, at least not
    153      * without violating Microsoft's app-store requirements.
    154      */
    155 
    156     const WCHAR * srcPath = NULL;
    157     WCHAR path[MAX_PATH];
    158     char *retval = NULL;
    159     WCHAR* worg = NULL;
    160     WCHAR* wapp = NULL;
    161     size_t new_wpath_len = 0;
    162     BOOL api_result = FALSE;
    163 
    164     if (!app) {
    165         SDL_InvalidParamError("app");
    166         return NULL;
    167     }
    168     if (!org) {
    169         org = "";
    170     }
    171 
    172     srcPath = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_LOCAL_FOLDER);
    173     if ( ! srcPath) {
    174         SDL_SetError("Unable to find a source path");
    175         return NULL;
    176     }
    177 
    178     if (SDL_wcslen(srcPath) >= MAX_PATH) {
    179         SDL_SetError("Path too long.");
    180         return NULL;
    181     }
    182     SDL_wcslcpy(path, srcPath, SDL_arraysize(path));
    183 
    184     worg = WIN_UTF8ToString(org);
    185     if (worg == NULL) {
    186         SDL_OutOfMemory();
    187         return NULL;
    188     }
    189 
    190     wapp = WIN_UTF8ToString(app);
    191     if (wapp == NULL) {
    192         SDL_free(worg);
    193         SDL_OutOfMemory();
    194         return NULL;
    195     }
    196 
    197     new_wpath_len = SDL_wcslen(worg) + SDL_wcslen(wapp) + SDL_wcslen(path) + 3;
    198 
    199     if ((new_wpath_len + 1) > MAX_PATH) {
    200         SDL_free(worg);
    201         SDL_free(wapp);
    202         SDL_SetError("Path too long.");
    203         return NULL;
    204     }
    205 
    206     if (*worg) {
    207         SDL_wcslcat(path, L"\\", new_wpath_len + 1);
    208         SDL_wcslcat(path, worg, new_wpath_len + 1);
    209         SDL_free(worg);
    210     }
    211 
    212     api_result = CreateDirectoryW(path, NULL);
    213     if (api_result == FALSE) {
    214         if (GetLastError() != ERROR_ALREADY_EXISTS) {
    215             SDL_free(wapp);
    216             WIN_SetError("Couldn't create a prefpath.");
    217             return NULL;
    218         }
    219     }
    220 
    221     SDL_wcslcat(path, L"\\", new_wpath_len + 1);
    222     SDL_wcslcat(path, wapp, new_wpath_len + 1);
    223     SDL_free(wapp);
    224 
    225     api_result = CreateDirectoryW(path, NULL);
    226     if (api_result == FALSE) {
    227         if (GetLastError() != ERROR_ALREADY_EXISTS) {
    228             WIN_SetError("Couldn't create a prefpath.");
    229             return NULL;
    230         }
    231     }
    232 
    233     SDL_wcslcat(path, L"\\", new_wpath_len + 1);
    234 
    235     retval = WIN_StringToUTF8(path);
    236 
    237     return retval;
    238 }
    239 
    240 #endif /* __WINRT__ */
    241 
    242 /* vi: set ts=4 sw=4 expandtab: */