SDL  2.0
SDL_sysfilesystem.cpp
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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 
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  if (!app) {
156  SDL_InvalidParamError("app");
157  return NULL;
158  }
159  if (!org) {
160  org = "";
161  }
162 
163  srcPath = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_LOCAL_FOLDER);
164  if ( ! srcPath) {
165  SDL_SetError("Unable to find a source path");
166  return NULL;
167  }
168 
169  if (SDL_wcslen(srcPath) >= MAX_PATH) {
170  SDL_SetError("Path too long.");
171  return NULL;
172  }
173  SDL_wcslcpy(path, srcPath, SDL_arraysize(path));
174 
175  worg = WIN_UTF8ToString(org);
176  if (worg == NULL) {
177  SDL_OutOfMemory();
178  return NULL;
179  }
180 
181  wapp = WIN_UTF8ToString(app);
182  if (wapp == NULL) {
183  SDL_free(worg);
184  SDL_OutOfMemory();
185  return NULL;
186  }
187 
188  new_wpath_len = SDL_wcslen(worg) + SDL_wcslen(wapp) + SDL_wcslen(path) + 3;
189 
190  if ((new_wpath_len + 1) > MAX_PATH) {
191  SDL_free(worg);
192  SDL_free(wapp);
193  SDL_SetError("Path too long.");
194  return NULL;
195  }
196 
197  if (*worg) {
198  SDL_wcslcat(path, L"\\", new_wpath_len + 1);
199  SDL_wcslcat(path, worg, new_wpath_len + 1);
200  SDL_free(worg);
201  }
202 
203  api_result = CreateDirectoryW(path, NULL);
204  if (api_result == FALSE) {
205  if (GetLastError() != ERROR_ALREADY_EXISTS) {
206  SDL_free(wapp);
207  WIN_SetError("Couldn't create a prefpath.");
208  return NULL;
209  }
210  }
211 
212  SDL_wcslcat(path, L"\\", new_wpath_len + 1);
213  SDL_wcslcat(path, wapp, new_wpath_len + 1);
214  SDL_free(wapp);
215 
216  api_result = CreateDirectoryW(path, NULL);
217  if (api_result == FALSE) {
218  if (GetLastError() != ERROR_ALREADY_EXISTS) {
219  WIN_SetError("Couldn't create a prefpath.");
220  return NULL;
221  }
222  }
223 
224  SDL_wcslcat(path, L"\\", new_wpath_len + 1);
225 
226  retval = WIN_StringToUTF8(path);
227 
228  return retval;
229 }
230 
231 #endif /* __WINRT__ */
232 
233 /* vi: set ts=4 sw=4 expandtab: */
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
GLuint srcPath
#define SDL_GetError
STL namespace.
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
SDL_bool retval
#define SDL_wcslen
#define SDL_free
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:46
#define SDL_wcslcat
#define SDL_wcslcpy
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
int WIN_SetError(const char *prefix)
#define SDL_SetError
#define SDL_strlen
#define SDL_GetPrefPath
Include file for filesystem SDL API functions.
#define SDL_WinRTGetFSPathUTF8
#define SDL_snprintf
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
#define SDL_malloc
GLsizei const GLchar *const * path
#define SDL_WinRTGetFSPathUNICODE
#define FALSE
Definition: edid-parse.c:34
char * SDL_GetBasePath(void)
Get the path where the application resides.
#define SDL_Unsupported()
Definition: SDL_error.h:53