sdl

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

SDL_sysfilesystem.c (4998B)


      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 #ifdef SDL_FILESYSTEM_WINDOWS
     24 
     25 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
     26 /* System dependent filesystem routines                                */
     27 
     28 #include "../../core/windows/SDL_windows.h"
     29 #include <shlobj.h>
     30 
     31 #include "SDL_error.h"
     32 #include "SDL_stdinc.h"
     33 #include "SDL_filesystem.h"
     34 
     35 char *
     36 SDL_GetBasePath(void)
     37 {
     38     typedef DWORD (WINAPI *GetModuleFileNameExW_t)(HANDLE, HMODULE, LPWSTR, DWORD);
     39     GetModuleFileNameExW_t pGetModuleFileNameExW;
     40     DWORD buflen = 128;
     41     WCHAR *path = NULL;
     42     HANDLE psapi = LoadLibrary(L"psapi.dll");
     43     char *retval = NULL;
     44     DWORD len = 0;
     45     int i;
     46 
     47     if (!psapi) {
     48         WIN_SetError("Couldn't load psapi.dll");
     49         return NULL;
     50     }
     51 
     52     pGetModuleFileNameExW = (GetModuleFileNameExW_t)GetProcAddress(psapi, "GetModuleFileNameExW");
     53     if (!pGetModuleFileNameExW) {
     54         WIN_SetError("Couldn't find GetModuleFileNameExW");
     55         FreeLibrary(psapi);
     56         return NULL;
     57     }
     58 
     59     while (SDL_TRUE) {
     60         void *ptr = SDL_realloc(path, buflen * sizeof (WCHAR));
     61         if (!ptr) {
     62             SDL_free(path);
     63             FreeLibrary(psapi);
     64             SDL_OutOfMemory();
     65             return NULL;
     66         }
     67 
     68         path = (WCHAR *) ptr;
     69 
     70         len = pGetModuleFileNameExW(GetCurrentProcess(), NULL, path, buflen);
     71         if (len != buflen) {
     72             break;
     73         }
     74 
     75         /* buffer too small? Try again. */
     76         buflen *= 2;
     77     }
     78 
     79     FreeLibrary(psapi);
     80 
     81     if (len == 0) {
     82         SDL_free(path);
     83         WIN_SetError("Couldn't locate our .exe");
     84         return NULL;
     85     }
     86 
     87     for (i = len-1; i > 0; i--) {
     88         if (path[i] == '\\') {
     89             break;
     90         }
     91     }
     92 
     93     SDL_assert(i > 0); /* Should have been an absolute path. */
     94     path[i+1] = '\0';  /* chop off filename. */
     95 
     96     retval = WIN_StringToUTF8(path);
     97     SDL_free(path);
     98 
     99     return retval;
    100 }
    101 
    102 char *
    103 SDL_GetPrefPath(const char *org, const char *app)
    104 {
    105     /*
    106      * Vista and later has a new API for this, but SHGetFolderPath works there,
    107      *  and apparently just wraps the new API. This is the new way to do it:
    108      *
    109      *     SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_CREATE,
    110      *                          NULL, &wszPath);
    111      */
    112 
    113     WCHAR path[MAX_PATH];
    114     char *retval = NULL;
    115     WCHAR* worg = NULL;
    116     WCHAR* wapp = NULL;
    117     size_t new_wpath_len = 0;
    118     BOOL api_result = FALSE;
    119 
    120     if (!app) {
    121         SDL_InvalidParamError("app");
    122         return NULL;
    123     }
    124     if (!org) {
    125         org = "";
    126     }
    127 
    128     if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) {
    129         WIN_SetError("Couldn't locate our prefpath");
    130         return NULL;
    131     }
    132 
    133     worg = WIN_UTF8ToString(org);
    134     if (worg == NULL) {
    135         SDL_OutOfMemory();
    136         return NULL;
    137     }
    138 
    139     wapp = WIN_UTF8ToString(app);
    140     if (wapp == NULL) {
    141         SDL_free(worg);
    142         SDL_OutOfMemory();
    143         return NULL;
    144     }
    145 
    146     new_wpath_len = lstrlenW(worg) + lstrlenW(wapp) + lstrlenW(path) + 3;
    147 
    148     if ((new_wpath_len + 1) > MAX_PATH) {
    149         SDL_free(worg);
    150         SDL_free(wapp);
    151         WIN_SetError("Path too long.");
    152         return NULL;
    153     }
    154 
    155     if (*worg) {
    156         lstrcatW(path, L"\\");
    157         lstrcatW(path, worg);
    158     }
    159     SDL_free(worg);
    160 
    161     api_result = CreateDirectoryW(path, NULL);
    162     if (api_result == FALSE) {
    163         if (GetLastError() != ERROR_ALREADY_EXISTS) {
    164             SDL_free(wapp);
    165             WIN_SetError("Couldn't create a prefpath.");
    166             return NULL;
    167         }
    168     }
    169 
    170     lstrcatW(path, L"\\");
    171     lstrcatW(path, wapp);
    172     SDL_free(wapp);
    173 
    174     api_result = CreateDirectoryW(path, NULL);
    175     if (api_result == FALSE) {
    176         if (GetLastError() != ERROR_ALREADY_EXISTS) {
    177             WIN_SetError("Couldn't create a prefpath.");
    178             return NULL;
    179         }
    180     }
    181 
    182     lstrcatW(path, L"\\");
    183 
    184     retval = WIN_StringToUTF8(path);
    185 
    186     return retval;
    187 }
    188 
    189 #endif /* SDL_FILESYSTEM_WINDOWS */
    190 
    191 /* vi: set ts=4 sw=4 expandtab: */