src/filesystem/windows/SDL_sysfilesystem.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 21 Apr 2016 03:16:44 -0400
changeset 11729 d1ce8396c356
parent 11222 083133ba8f9b
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Initial shot at a renderer target for Apple's Metal API.

This isn't complete, but is enough to run testsprite2. It's currently
Mac-only; with a little work to figure out how to properly glue in a Metal
layer to a UIView, this will likely work on iOS, too.

This is only wired up to the configure script right now, and disabled by
default. CMake and Xcode still need their bits filled in as appropriate.
icculus@7667
     1
/*
icculus@7667
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
icculus@7667
     4
icculus@7667
     5
  This software is provided 'as-is', without any express or implied
icculus@7667
     6
  warranty.  In no event will the authors be held liable for any damages
icculus@7667
     7
  arising from the use of this software.
icculus@7667
     8
icculus@7667
     9
  Permission is granted to anyone to use this software for any purpose,
icculus@7667
    10
  including commercial applications, and to alter it and redistribute it
icculus@7667
    11
  freely, subject to the following restrictions:
icculus@7667
    12
icculus@7667
    13
  1. The origin of this software must not be misrepresented; you must not
icculus@7667
    14
     claim that you wrote the original software. If you use this software
icculus@7667
    15
     in a product, an acknowledgment in the product documentation would be
icculus@7667
    16
     appreciated but is not required.
icculus@7667
    17
  2. Altered source versions must be plainly marked as such, and must not be
icculus@7667
    18
     misrepresented as being the original software.
icculus@7667
    19
  3. This notice may not be removed or altered from any source distribution.
icculus@7667
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
icculus@7667
    22
icculus@7667
    23
#ifdef SDL_FILESYSTEM_WINDOWS
icculus@7667
    24
icculus@7667
    25
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
icculus@7667
    26
/* System dependent filesystem routines                                */
icculus@7667
    27
icculus@7671
    28
#include "../../core/windows/SDL_windows.h"
icculus@7671
    29
#include <shlobj.h>
icculus@7671
    30
icculus@7671
    31
#include "SDL_assert.h"
icculus@7667
    32
#include "SDL_error.h"
icculus@7667
    33
#include "SDL_stdinc.h"
icculus@7667
    34
#include "SDL_filesystem.h"
icculus@7667
    35
icculus@7667
    36
char *
icculus@7667
    37
SDL_GetBasePath(void)
icculus@7667
    38
{
slouken@9672
    39
    typedef DWORD (WINAPI *GetModuleFileNameExW_t)(HANDLE, HMODULE, LPWSTR, DWORD);
slouken@9672
    40
    GetModuleFileNameExW_t pGetModuleFileNameExW;
icculus@9671
    41
    DWORD buflen = 128;
icculus@9671
    42
    WCHAR *path = NULL;
icculus@9671
    43
    HANDLE psapi = LoadLibrary(L"psapi.dll");
icculus@9671
    44
    char *retval = NULL;
icculus@9671
    45
    DWORD len = 0;
slouken@9672
    46
    int i;
icculus@7667
    47
icculus@9671
    48
    if (!psapi) {
icculus@9671
    49
        WIN_SetError("Couldn't load psapi.dll");
icculus@9671
    50
        return NULL;
icculus@9671
    51
    }
icculus@9671
    52
slouken@9672
    53
    pGetModuleFileNameExW = (GetModuleFileNameExW_t)GetProcAddress(psapi, "GetModuleFileNameExW");
icculus@9671
    54
    if (!pGetModuleFileNameExW) {
icculus@9671
    55
        WIN_SetError("Couldn't find GetModuleFileNameExW");
icculus@9671
    56
        FreeLibrary(psapi);
icculus@9671
    57
        return NULL;
icculus@9671
    58
    }
icculus@9671
    59
icculus@9671
    60
    while (SDL_TRUE) {
icculus@9677
    61
        void *ptr = SDL_realloc(path, buflen * sizeof (WCHAR));
icculus@9676
    62
        if (!ptr) {
icculus@9676
    63
            SDL_free(path);
icculus@9671
    64
            FreeLibrary(psapi);
icculus@9671
    65
            SDL_OutOfMemory();
icculus@9671
    66
            return NULL;
icculus@9671
    67
        }
icculus@9677
    68
icculus@9677
    69
        path = (WCHAR *) ptr;
icculus@9671
    70
slouken@9672
    71
        len = pGetModuleFileNameExW(GetCurrentProcess(), NULL, path, buflen);
icculus@9671
    72
        if (len != buflen) {
icculus@9671
    73
            break;
icculus@9671
    74
        }
icculus@9671
    75
icculus@9671
    76
        /* buffer too small? Try again. */
icculus@9675
    77
        buflen *= 2;
icculus@9671
    78
    }
icculus@9671
    79
icculus@9671
    80
    FreeLibrary(psapi);
icculus@7667
    81
icculus@7667
    82
    if (len == 0) {
icculus@9677
    83
        SDL_free(path);
icculus@7667
    84
        WIN_SetError("Couldn't locate our .exe");
icculus@7667
    85
        return NULL;
icculus@7667
    86
    }
icculus@7667
    87
icculus@7667
    88
    for (i = len-1; i > 0; i--) {
icculus@7667
    89
        if (path[i] == '\\') {
icculus@7667
    90
            break;
icculus@7667
    91
        }
icculus@7667
    92
    }
icculus@7667
    93
icculus@7667
    94
    SDL_assert(i > 0); /* Should have been an absolute path. */
icculus@7667
    95
    path[i+1] = '\0';  /* chop off filename. */
icculus@9671
    96
icculus@9671
    97
    retval = WIN_StringToUTF8(path);
icculus@9671
    98
    SDL_free(path);
icculus@9671
    99
icculus@9671
   100
    return retval;
icculus@7667
   101
}
icculus@7667
   102
icculus@7667
   103
char *
icculus@7667
   104
SDL_GetPrefPath(const char *org, const char *app)
icculus@7667
   105
{
icculus@7667
   106
    /*
icculus@7667
   107
     * Vista and later has a new API for this, but SHGetFolderPath works there,
icculus@7667
   108
     *  and apparently just wraps the new API. This is the new way to do it:
icculus@7667
   109
     *
icculus@7667
   110
     *     SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_CREATE,
icculus@7667
   111
     *                          NULL, &wszPath);
icculus@7667
   112
     */
icculus@7667
   113
icculus@8275
   114
    WCHAR path[MAX_PATH];
icculus@7667
   115
    char *retval = NULL;
icculus@8275
   116
    WCHAR* worg = NULL;
icculus@8275
   117
    WCHAR* wapp = NULL;
icculus@8275
   118
    size_t new_wpath_len = 0;
icculus@8275
   119
    BOOL api_result = FALSE;
icculus@7667
   120
slouken@11222
   121
    if (!app) {
slouken@11222
   122
        SDL_InvalidParamError("app");
slouken@11222
   123
        return NULL;
slouken@11222
   124
    }
slouken@11222
   125
    if (!org) {
slouken@11222
   126
        org = "";
slouken@11222
   127
    }
slouken@11222
   128
icculus@8275
   129
    if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) {
icculus@7667
   130
        WIN_SetError("Couldn't locate our prefpath");
icculus@7667
   131
        return NULL;
icculus@7667
   132
    }
icculus@7667
   133
icculus@8275
   134
    worg = WIN_UTF8ToString(org);
icculus@8275
   135
    if (worg == NULL) {
icculus@8275
   136
        SDL_OutOfMemory();
icculus@8275
   137
        return NULL;
icculus@8275
   138
    }
icculus@8275
   139
icculus@8275
   140
    wapp = WIN_UTF8ToString(app);
icculus@8275
   141
    if (wapp == NULL) {
icculus@8275
   142
        SDL_free(worg);
icculus@8275
   143
        SDL_OutOfMemory();
icculus@8275
   144
        return NULL;
icculus@8275
   145
    }
icculus@8275
   146
icculus@8275
   147
    new_wpath_len = lstrlenW(worg) + lstrlenW(wapp) + lstrlenW(path) + 3;
icculus@8275
   148
icculus@8275
   149
    if ((new_wpath_len + 1) > MAX_PATH) {
icculus@8275
   150
        SDL_free(worg);
icculus@8275
   151
        SDL_free(wapp);
icculus@8275
   152
        WIN_SetError("Path too long.");
icculus@8275
   153
        return NULL;
icculus@8275
   154
    }
icculus@8275
   155
slouken@11222
   156
    if (*worg) {
slouken@11222
   157
        lstrcatW(path, L"\\");
slouken@11222
   158
        lstrcatW(path, worg);
slouken@11222
   159
    }
icculus@8275
   160
    SDL_free(worg);
icculus@8275
   161
icculus@8275
   162
    api_result = CreateDirectoryW(path, NULL);
icculus@8275
   163
    if (api_result == FALSE) {
icculus@8275
   164
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
icculus@8275
   165
            SDL_free(wapp);
icculus@8275
   166
            WIN_SetError("Couldn't create a prefpath.");
icculus@7667
   167
            return NULL;
icculus@7667
   168
        }
icculus@7667
   169
    }
icculus@7667
   170
icculus@8275
   171
    lstrcatW(path, L"\\");
icculus@8275
   172
    lstrcatW(path, wapp);
icculus@8275
   173
    SDL_free(wapp);
icculus@8275
   174
icculus@8275
   175
    api_result = CreateDirectoryW(path, NULL);
icculus@8275
   176
    if (api_result == FALSE) {
icculus@8275
   177
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
icculus@8275
   178
            WIN_SetError("Couldn't create a prefpath.");
icculus@8275
   179
            return NULL;
icculus@8275
   180
        }
icculus@8275
   181
    }
icculus@8275
   182
icculus@8275
   183
    lstrcatW(path, L"\\");
icculus@8275
   184
icculus@8275
   185
    retval = WIN_StringToUTF8(path);
icculus@8275
   186
icculus@7667
   187
    return retval;
icculus@7667
   188
}
icculus@7667
   189
icculus@7667
   190
#endif /* SDL_FILESYSTEM_WINDOWS */
icculus@7667
   191
icculus@7667
   192
/* vi: set ts=4 sw=4 expandtab: */