aboutsummaryrefslogtreecommitdiff
path: root/common/fmplayer_file_win.c
blob: 71fb2632a983ddc9fd8c32f24a06459ebb2b4bb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include "common/fmplayer_file.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlwapi.h>
#include <stdlib.h>
#include <wchar.h>

#if !defined(FMPLAYER_FILE_WIN_UTF16) && !defined(FMPLAYER_FILE_WIN_UTF8)
#error "specify path string format"
#endif

static void *fileread(const wchar_t *path,
                      size_t maxsize, size_t *filesize,
                      enum fmplayer_file_error *error) {
  HANDLE file = INVALID_HANDLE_VALUE;
  void *buf = 0;
  file = CreateFileW(path, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if (file == INVALID_HANDLE_VALUE) {
    if (error) *error = FMPLAYER_FILE_ERR_NOTFOUND;
    goto err;
  }
  LARGE_INTEGER li;
  if (!GetFileSizeEx(file, &li)) {
    if (error) *error = FMPLAYER_FILE_ERR_FILEIO;
    goto err;
  }
  if (li.HighPart || (maxsize && (li.LowPart > maxsize))) {
    if (error) *error = FMPLAYER_FILE_ERR_BADFILE_SIZE;
    goto err;
  }
  buf = malloc(li.LowPart);
  if (!buf) {
    if (error) *error = FMPLAYER_FILE_ERR_NOMEM;
    goto err;
  }
  DWORD readlen;
  if (!ReadFile(file, buf, li.LowPart, &readlen, 0) || (readlen != li.LowPart)) {
    if (error) *error = FMPLAYER_FILE_ERR_FILEIO;
    goto err;
  }
  *filesize = li.QuadPart;
  CloseHandle(file);
  return buf;
err:
  free(buf);
  if (file != INVALID_HANDLE_VALUE) CloseHandle(file);
  return 0;
}

static inline wchar_t *u8tou16(const char *s) {
  wchar_t *ws = 0;
  int slen = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0);
  if (!slen) goto err;
  ws = malloc(slen * sizeof(wchar_t));
  if (!ws) goto err;
  if (!MultiByteToWideChar(CP_UTF8, 0, s, -1, ws, slen)) goto err;
  return ws;
err:
  free(ws);
  return 0;
}

void *fmplayer_fileread(const void *pathptr, const char *pcmname, const char *extension,
                        size_t maxsize, size_t *filesize, enum fmplayer_file_error *error) {
  const wchar_t *path = 0;
#if defined(FMPLAYER_FILE_WIN_UTF16)
  path = wcsdup(pathptr);
#elif defined(FMPLAYER_FILE_WIN_UTF8)
  path = u8tou16(pathptr);
#endif
  wchar_t *wpcmpath = 0, *wpcmname = 0, *wpcmextname = 0;
  if (!pcmname) return fileread(path, maxsize, filesize, error);
  int wpcmnamelen = MultiByteToWideChar(932, 0, pcmname, -1, 0, 0);
  if (!wpcmnamelen) goto err;
  if (extension) {
    int wextensionlen = MultiByteToWideChar(932, 0, extension, -1, 0, 0);
    if (!wextensionlen) goto err;
    wpcmnamelen += wextensionlen;
    wpcmnamelen -= 1;
    wpcmextname = malloc(wextensionlen * sizeof(wchar_t));
    if (!wpcmextname) goto err;
    if (!MultiByteToWideChar(932, 0, extension, -1, wpcmextname, wextensionlen)) goto err;
  }
  wpcmname = malloc(wpcmnamelen * sizeof(wchar_t));
  if (!wpcmname) goto err;
  if (!MultiByteToWideChar(932, 0, pcmname, -1, wpcmname, wpcmnamelen)) goto err;
  if (wpcmextname) wcscat(wpcmname, wpcmextname);
  wpcmpath = malloc((wcslen(path) + 1 + wcslen(wpcmname) + 1) * sizeof(wchar_t));
  if (!wpcmpath) goto err;
  wcscpy(wpcmpath, path);
  PathRemoveFileSpecW(wpcmpath);
  wcscat(wpcmpath, L"\\");
  wcscat(wpcmpath, wpcmname);
  void *buf = fileread(wpcmpath, maxsize, filesize, error);
  free(wpcmextname);
  free(wpcmname);
  free(wpcmpath);
  free((void *)path);
  return buf;
err:
  free(wpcmextname);
  free(wpcmname);
  free(wpcmpath);
  free((void *)path);
  return 0;
}

void *fmplayer_path_dup(const void *pathptr) {
#if defined(FMPLAYER_FILE_WIN_UTF16)
  const wchar_t *path = pathptr;
  return wcsdup(path);
#elif defined(FMPLAYER_FILE_WIN_UTF8)
  const char *path = pathptr;
  return strdup(path);
#endif
}

char *fmplayer_path_filename_sjis(const void *pathptr) {
  wchar_t *u16_path = 0;
  char *filename_sjis = 0;
#if defined(FMPLAYER_FILE_WIN_UTF16)
  const wchar_t *path = pathptr;
  u16_path = wcsdup(path);
#elif defined(FMPLAYER_FILE_WIN_UTF8)
  const char *path = pathptr;
  u16_path = u8tou16(path);
#endif
  if (!u16_path) goto err;
  PathStripPath(u16_path);
  int bufsize = WideCharToMultiByte(932, 0, u16_path, -1, 0, 0, 0, 0);
  if (bufsize <= 0) goto err;
  filename_sjis = malloc(bufsize);
  if (!filename_sjis) goto err;
  bufsize = WideCharToMultiByte(
      932, 0, u16_path, -1, filename_sjis, bufsize, 0, 0);
  if (!bufsize) goto err;
  free(u16_path);
  return filename_sjis;

err:
  free(filename_sjis);
  free(u16_path);
  return 0;
}