Skip to content

Latest commit

 

History

History
1369 lines (1120 loc) · 40.9 KB

platform_windows.c

File metadata and controls

1369 lines (1120 loc) · 40.9 KB
 
Aug 23, 2001
Aug 23, 2001
1
/*
Mar 11, 2007
Mar 11, 2007
2
* Windows support routines for PhysicsFS.
Aug 23, 2001
Aug 23, 2001
3
*
Mar 11, 2007
Mar 11, 2007
4
* Please see the file LICENSE.txt in the source's root directory.
Aug 23, 2001
Aug 23, 2001
5
*
Apr 13, 2002
Apr 13, 2002
6
* This file written by Ryan C. Gordon, and made sane by Gregory S. Read.
Aug 23, 2001
Aug 23, 2001
7
8
*/
Mar 11, 2007
Mar 11, 2007
9
10
11
12
#define __PHYSICSFS_INTERNAL__
#include "physfs_platforms.h"
#ifdef PHYSFS_PLATFORM_WINDOWS
Jul 10, 2002
Jul 10, 2002
13
Mar 26, 2007
Mar 26, 2007
14
15
16
17
18
/* Forcibly disable UNICODE, since we manage this ourselves. */
#ifdef UNICODE
#undef UNICODE
#endif
Aug 23, 2001
Aug 23, 2001
19
#include <windows.h>
Jun 29, 2002
Jun 29, 2002
20
#include <errno.h>
Aug 29, 2001
Aug 29, 2001
21
#include <ctype.h>
Jun 7, 2002
Jun 7, 2002
22
#include <time.h>
May 6, 2002
May 6, 2002
23
Aug 23, 2001
Aug 23, 2001
24
25
#include "physfs_internal.h"
Oct 1, 2007
Oct 1, 2007
26
27
#define LOWORDER_UINT64(pos) ((PHYSFS_uint32) (pos & 0xFFFFFFFF))
#define HIGHORDER_UINT64(pos) ((PHYSFS_uint32) ((pos >> 32) & 0xFFFFFFFF))
Apr 3, 2002
Apr 3, 2002
28
Mar 25, 2007
Mar 25, 2007
29
30
31
32
33
34
/*
* Users without the platform SDK don't have this defined. The original docs
* for SetFilePointer() just said to compare with 0xFFFFFFFF, so this should
* work as desired.
*/
#define PHYSFS_INVALID_SET_FILE_POINTER 0xFFFFFFFF
Mar 25, 2007
Mar 25, 2007
35
Mar 25, 2007
Mar 25, 2007
36
37
/* just in case... */
#define PHYSFS_INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
Jun 29, 2002
Jun 29, 2002
38
Apr 1, 2007
Apr 1, 2007
39
40
41
42
/* Not defined before the Vista SDK. */
#define PHYSFS_IO_REPARSE_TAG_SYMLINK 0xA000000C
Mar 25, 2007
Mar 25, 2007
43
44
45
46
#define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \
if (str == NULL) \
w_assignto = NULL; \
else { \
Jan 22, 2008
Jan 22, 2008
47
const PHYSFS_uint64 len = (PHYSFS_uint64) ((strlen(str) + 1) * 2); \
Mar 26, 2007
Mar 26, 2007
48
49
50
w_assignto = (WCHAR *) __PHYSFS_smallAlloc(len); \
if (w_assignto != NULL) \
PHYSFS_utf8ToUcs2(str, (PHYSFS_uint16 *) w_assignto, len); \
Mar 25, 2007
Mar 25, 2007
51
52
} \
} \
Jun 29, 2002
Jun 29, 2002
53
Mar 26, 2007
Mar 26, 2007
54
55
56
57
58
static PHYSFS_uint64 wStrLen(const WCHAR *wstr)
{
PHYSFS_uint64 len = 0;
while (*(wstr++))
len++;
Jan 28, 2010
Jan 28, 2010
59
return len;
Mar 26, 2007
Mar 26, 2007
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
} /* wStrLen */
static char *unicodeToUtf8Heap(const WCHAR *w_str)
{
char *retval = NULL;
if (w_str != NULL)
{
void *ptr = NULL;
const PHYSFS_uint64 len = (wStrLen(w_str) * 4) + 1;
retval = allocator.Malloc(len);
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
PHYSFS_utf8FromUcs2((const PHYSFS_uint16 *) w_str, retval, len);
ptr = allocator.Realloc(retval, strlen(retval) + 1); /* shrink. */
if (ptr != NULL)
retval = (char *) ptr;
} /* if */
Jan 28, 2010
Jan 28, 2010
76
return retval;
Mar 26, 2007
Mar 26, 2007
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
} /* unicodeToUtf8Heap */
static char *codepageToUtf8Heap(const char *cpstr)
{
char *retval = NULL;
if (cpstr != NULL)
{
const int len = (int) (strlen(cpstr) + 1);
WCHAR *wbuf = (WCHAR *) __PHYSFS_smallAlloc(len * sizeof (WCHAR));
BAIL_IF_MACRO(wbuf == NULL, ERR_OUT_OF_MEMORY, NULL);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpstr, len, wbuf, len);
retval = (char *) allocator.Malloc(len * 4);
if (retval == NULL)
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
else
PHYSFS_utf8FromUcs2(wbuf, retval, len * 4);
__PHYSFS_smallFree(wbuf);
} /* if */
Jan 28, 2010
Jan 28, 2010
96
return retval;
Mar 26, 2007
Mar 26, 2007
97
98
99
} /* codepageToUtf8Heap */
Jun 29, 2002
Jun 29, 2002
100
101
102
103
typedef struct
{
HANDLE handle;
int readonly;
Mar 26, 2007
Mar 26, 2007
104
} WinApiFile;
Aug 23, 2001
Aug 23, 2001
105
Mar 26, 2007
Mar 26, 2007
106
Mar 26, 2007
Mar 26, 2007
107
static char *userDir = NULL;
Mar 26, 2007
Mar 26, 2007
108
static int osHasUnicode = 0;
Mar 25, 2007
Mar 25, 2007
109
110
111
/* pointers for APIs that may not exist on some Windows versions... */
Jun 29, 2002
Jun 29, 2002
112
static HANDLE libKernel32 = NULL;
Mar 25, 2007
Mar 25, 2007
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
static HANDLE libUserEnv = NULL;
static HANDLE libAdvApi32 = NULL;
static DWORD (WINAPI *pGetModuleFileNameW)(HMODULE, LPWCH, DWORD);
static BOOL (WINAPI *pGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD);
static BOOL (WINAPI *pGetUserNameW)(LPWSTR, LPDWORD);
static DWORD (WINAPI *pGetFileAttributesW)(LPCWSTR);
static HANDLE (WINAPI *pFindFirstFileW)(LPCWSTR, LPWIN32_FIND_DATAW);
static BOOL (WINAPI *pFindNextFileW)(HANDLE, LPWIN32_FIND_DATAW);
static DWORD (WINAPI *pGetCurrentDirectoryW)(DWORD, LPWSTR);
static BOOL (WINAPI *pDeleteFileW)(LPCWSTR);
static BOOL (WINAPI *pRemoveDirectoryW)(LPCWSTR);
static BOOL (WINAPI *pCreateDirectoryW)(LPCWSTR, LPSECURITY_ATTRIBUTES);
static BOOL (WINAPI *pGetFileAttributesExA)
(LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
static BOOL (WINAPI *pGetFileAttributesExW)
(LPCWSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
static DWORD (WINAPI *pFormatMessageW)
(DWORD, LPCVOID, DWORD, DWORD, LPWSTR, DWORD, va_list *);
static HANDLE (WINAPI *pCreateFileW)
(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
Mar 26, 2007
Mar 26, 2007
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
* Fallbacks for missing Unicode functions on Win95/98/ME. These are filled
* into the function pointers if looking up the real Unicode entry points
* in the system DLLs fails, so they're never used on WinNT/XP/Vista/etc.
* They make an earnest effort to convert to/from UTF-8 and UCS-2 to
* the user's current codepage.
*/
static BOOL WINAPI fallbackGetUserNameW(LPWSTR buf, LPDWORD len)
{
const DWORD cplen = *len;
char *cpstr = __PHYSFS_smallAlloc(cplen);
BOOL retval = GetUserNameA(cpstr, len);
if (buf != NULL)
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpstr, cplen, buf, *len);
__PHYSFS_smallFree(cpstr);
Jan 28, 2010
Jan 28, 2010
151
return retval;
Mar 26, 2007
Mar 26, 2007
152
153
154
155
156
157
158
159
160
161
162
163
164
} /* fallbackGetUserNameW */
static DWORD WINAPI fallbackFormatMessageW(DWORD dwFlags, LPCVOID lpSource,
DWORD dwMessageId, DWORD dwLangId,
LPWSTR lpBuf, DWORD nSize,
va_list *Arguments)
{
char *cpbuf = (char *) __PHYSFS_smallAlloc(nSize);
DWORD retval = FormatMessageA(dwFlags, lpSource, dwMessageId, dwLangId,
cpbuf, nSize, Arguments);
if (retval > 0)
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,lpBuf,nSize);
__PHYSFS_smallFree(cpbuf);
Jan 28, 2010
Jan 28, 2010
165
return retval;
Mar 26, 2007
Mar 26, 2007
166
167
168
169
170
171
172
173
174
175
} /* fallbackFormatMessageW */
static DWORD WINAPI fallbackGetModuleFileNameW(HMODULE hMod, LPWCH lpBuf,
DWORD nSize)
{
char *cpbuf = (char *) __PHYSFS_smallAlloc(nSize);
DWORD retval = GetModuleFileNameA(hMod, cpbuf, nSize);
if (retval > 0)
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,lpBuf,nSize);
__PHYSFS_smallFree(cpbuf);
Jan 28, 2010
Jan 28, 2010
176
return retval;
Mar 26, 2007
Mar 26, 2007
177
178
179
180
181
182
183
184
185
186
} /* fallbackGetModuleFileNameW */
static DWORD WINAPI fallbackGetFileAttributesW(LPCWSTR fname)
{
DWORD retval = 0;
const int buflen = (int) (wStrLen(fname) + 1);
char *cpstr = (char *) __PHYSFS_smallAlloc(buflen);
WideCharToMultiByte(CP_ACP, 0, fname, buflen, cpstr, buflen, NULL, NULL);
retval = GetFileAttributesA(cpstr);
__PHYSFS_smallFree(cpstr);
Jan 28, 2010
Jan 28, 2010
187
return retval;
Mar 26, 2007
Mar 26, 2007
188
189
190
191
192
193
194
195
196
197
198
199
200
201
} /* fallbackGetFileAttributesW */
static DWORD WINAPI fallbackGetCurrentDirectoryW(DWORD buflen, LPWSTR buf)
{
DWORD retval = 0;
char *cpbuf = NULL;
if (buf != NULL)
cpbuf = (char *) __PHYSFS_smallAlloc(buflen);
retval = GetCurrentDirectoryA(buflen, cpbuf);
if (cpbuf != NULL)
{
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,cpbuf,retval,buf,buflen);
__PHYSFS_smallFree(cpbuf);
} /* if */
Jan 28, 2010
Jan 28, 2010
202
return retval;
Mar 26, 2007
Mar 26, 2007
203
204
205
206
207
208
209
210
211
212
} /* fallbackGetCurrentDirectoryW */
static BOOL WINAPI fallbackRemoveDirectoryW(LPCWSTR dname)
{
BOOL retval = 0;
const int buflen = (int) (wStrLen(dname) + 1);
char *cpstr = (char *) __PHYSFS_smallAlloc(buflen);
WideCharToMultiByte(CP_ACP, 0, dname, buflen, cpstr, buflen, NULL, NULL);
retval = RemoveDirectoryA(cpstr);
__PHYSFS_smallFree(cpstr);
Jan 28, 2010
Jan 28, 2010
213
return retval;
Mar 26, 2007
Mar 26, 2007
214
215
216
217
218
219
220
221
222
223
224
} /* fallbackRemoveDirectoryW */
static BOOL WINAPI fallbackCreateDirectoryW(LPCWSTR dname,
LPSECURITY_ATTRIBUTES attr)
{
BOOL retval = 0;
const int buflen = (int) (wStrLen(dname) + 1);
char *cpstr = (char *) __PHYSFS_smallAlloc(buflen);
WideCharToMultiByte(CP_ACP, 0, dname, buflen, cpstr, buflen, NULL, NULL);
retval = CreateDirectoryA(cpstr, attr);
__PHYSFS_smallFree(cpstr);
Jan 28, 2010
Jan 28, 2010
225
return retval;
Mar 26, 2007
Mar 26, 2007
226
227
228
229
230
231
232
233
234
235
} /* fallbackCreateDirectoryW */
static BOOL WINAPI fallbackDeleteFileW(LPCWSTR fname)
{
BOOL retval = 0;
const int buflen = (int) (wStrLen(fname) + 1);
char *cpstr = (char *) __PHYSFS_smallAlloc(buflen);
WideCharToMultiByte(CP_ACP, 0, fname, buflen, cpstr, buflen, NULL, NULL);
retval = DeleteFileA(cpstr);
__PHYSFS_smallFree(cpstr);
Jan 28, 2010
Jan 28, 2010
236
return retval;
Mar 26, 2007
Mar 26, 2007
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
} /* fallbackDeleteFileW */
static HANDLE WINAPI fallbackCreateFileW(LPCWSTR fname,
DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttrs,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttrs, HANDLE hTemplFile)
{
HANDLE retval;
const int buflen = (int) (wStrLen(fname) + 1);
char *cpstr = (char *) __PHYSFS_smallAlloc(buflen);
WideCharToMultiByte(CP_ACP, 0, fname, buflen, cpstr, buflen, NULL, NULL);
retval = CreateFileA(cpstr, dwDesiredAccess, dwShareMode, lpSecurityAttrs,
dwCreationDisposition, dwFlagsAndAttrs, hTemplFile);
__PHYSFS_smallFree(cpstr);
Jan 28, 2010
Jan 28, 2010
252
return retval;
Mar 26, 2007
Mar 26, 2007
253
} /* fallbackCreateFileW */
Aug 23, 2001
Aug 23, 2001
254
May 6, 2002
May 6, 2002
255
Mar 12, 2008
Mar 12, 2008
256
#if (PHYSFS_MINIMUM_GCC_VERSION(3,3))
Mar 12, 2008
Mar 12, 2008
257
258
259
260
261
262
263
264
typedef FARPROC __attribute__((__may_alias__)) PHYSFS_FARPROC;
#else
typedef FARPROC PHYSFS_FARPROC;
#endif
static void symLookup(HMODULE dll, PHYSFS_FARPROC *addr, const char *sym,
int reallyLook, PHYSFS_FARPROC fallback)
Mar 25, 2007
Mar 25, 2007
265
{
Mar 12, 2008
Mar 12, 2008
266
267
268
269
270
PHYSFS_FARPROC proc;
proc = (PHYSFS_FARPROC) ((reallyLook) ? GetProcAddress(dll, sym) : NULL);
if (proc == NULL)
proc = fallback; /* may also be NULL. */
*addr = proc;
Mar 25, 2007
Mar 25, 2007
271
272
273
274
275
276
277
} /* symLookup */
static int findApiSymbols(void)
{
HMODULE dll = NULL;
Mar 12, 2008
Mar 12, 2008
278
279
280
281
282
283
#define LOOKUP_NOFALLBACK(x, reallyLook) \
symLookup(dll, (PHYSFS_FARPROC *) &p##x, #x, reallyLook, NULL)
#define LOOKUP(x, reallyLook) \
symLookup(dll, (PHYSFS_FARPROC *) &p##x, #x, \
reallyLook, (PHYSFS_FARPROC) fallback##x)
Mar 25, 2007
Mar 25, 2007
284
Mar 26, 2007
Mar 26, 2007
285
286
287
/* Apparently Win9x HAS the Unicode entry points, they just don't WORK. */
/* ...so don't look them up unless we're on NT+. (see osHasUnicode.) */
Mar 26, 2007
Mar 26, 2007
288
dll = libUserEnv = LoadLibraryA("userenv.dll");
Mar 25, 2007
Mar 25, 2007
289
if (dll != NULL)
Mar 26, 2007
Mar 26, 2007
290
LOOKUP_NOFALLBACK(GetUserProfileDirectoryW, osHasUnicode);
Mar 25, 2007
Mar 25, 2007
291
Mar 26, 2007
Mar 26, 2007
292
dll = libAdvApi32 = LoadLibraryA("advapi32.dll");
Mar 25, 2007
Mar 25, 2007
293
if (dll != NULL)
Mar 26, 2007
Mar 26, 2007
294
LOOKUP(GetUserNameW, osHasUnicode);
Mar 25, 2007
Mar 25, 2007
295
Mar 26, 2007
Mar 26, 2007
296
dll = libKernel32 = LoadLibraryA("kernel32.dll");
Mar 25, 2007
Mar 25, 2007
297
298
if (dll != NULL)
{
Mar 26, 2007
Mar 26, 2007
299
300
301
302
303
304
305
306
307
308
309
310
LOOKUP_NOFALLBACK(GetFileAttributesExA, 1);
LOOKUP_NOFALLBACK(GetFileAttributesExW, osHasUnicode);
LOOKUP_NOFALLBACK(FindFirstFileW, osHasUnicode);
LOOKUP_NOFALLBACK(FindNextFileW, osHasUnicode);
LOOKUP(GetModuleFileNameW, osHasUnicode);
LOOKUP(FormatMessageW, osHasUnicode);
LOOKUP(GetFileAttributesW, osHasUnicode);
LOOKUP(GetCurrentDirectoryW, osHasUnicode);
LOOKUP(CreateDirectoryW, osHasUnicode);
LOOKUP(RemoveDirectoryW, osHasUnicode);
LOOKUP(CreateFileW, osHasUnicode);
LOOKUP(DeleteFileW, osHasUnicode);
Mar 25, 2007
Mar 25, 2007
311
} /* if */
Dec 8, 2003
Dec 8, 2003
312
Mar 26, 2007
Mar 26, 2007
313
#undef LOOKUP_NOFALLBACK
Mar 25, 2007
Mar 25, 2007
314
315
#undef LOOKUP
Jan 28, 2010
Jan 28, 2010
316
return 1;
Mar 25, 2007
Mar 25, 2007
317
} /* findApiSymbols */
Jun 29, 2002
Jun 29, 2002
318
319
Mar 26, 2007
Mar 26, 2007
320
321
322
const char *__PHYSFS_platformDirSeparator = "\\";
Jun 10, 2002
Jun 10, 2002
323
/*
Mar 26, 2007
Mar 26, 2007
324
* Figure out what the last failing Windows API call was, and
Jun 10, 2002
Jun 10, 2002
325
326
327
328
329
* generate a human-readable string for the error message.
*
* The return value is a static buffer that is overwritten with
* each call to this function.
*/
Mar 26, 2007
Mar 26, 2007
330
static const char *winApiStrError(void)
Jun 10, 2002
Jun 10, 2002
331
{
Mar 26, 2007
Mar 26, 2007
332
333
334
335
336
337
338
339
340
341
static char utf8buf[255];
WCHAR msgbuf[255];
WCHAR *ptr;
DWORD rc = pFormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
msgbuf, __PHYSFS_ARRAYLEN(msgbuf),
NULL);
Jun 10, 2002
Jun 10, 2002
342
Feb 13, 2008
Feb 13, 2008
343
344
345
if (rc == 0)
msgbuf[0] = '\0'; /* oh well. */
Mar 25, 2007
Mar 25, 2007
346
/* chop off newlines. */
Jun 29, 2002
Jun 29, 2002
347
348
349
350
for (ptr = msgbuf; *ptr; ptr++)
{
if ((*ptr == '\n') || (*ptr == '\r'))
{
Mar 26, 2007
Mar 26, 2007
351
*ptr = '\0';
Jun 29, 2002
Jun 29, 2002
352
353
354
355
break;
} /* if */
} /* for */
Mar 26, 2007
Mar 26, 2007
356
357
/* may truncate, but oh well. */
PHYSFS_utf8FromUcs2((PHYSFS_uint16 *) msgbuf, utf8buf, sizeof (utf8buf));
Jan 28, 2010
Jan 28, 2010
358
return ((const char *) utf8buf);
Mar 26, 2007
Mar 26, 2007
359
} /* winApiStrError */
Jun 10, 2002
Jun 10, 2002
360
361
Mar 25, 2007
Mar 25, 2007
362
static char *getExePath(void)
Jun 7, 2002
Jun 7, 2002
363
{
Mar 25, 2007
Mar 25, 2007
364
365
366
DWORD buflen = 64;
LPWSTR modpath = NULL;
char *retval = NULL;
Jun 29, 2002
Jun 29, 2002
367
Mar 25, 2007
Mar 25, 2007
368
while (1)
Jun 29, 2002
Jun 29, 2002
369
{
Mar 25, 2007
Mar 25, 2007
370
371
DWORD rc;
void *ptr;
Jun 29, 2002
Jun 29, 2002
372
Mar 25, 2007
Mar 25, 2007
373
if ( !(ptr = allocator.Realloc(modpath, buflen*sizeof(WCHAR))) )
Jun 29, 2002
Jun 29, 2002
374
{
Mar 25, 2007
Mar 25, 2007
375
376
377
378
allocator.Free(modpath);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
modpath = (LPWSTR) ptr;
Jun 29, 2002
Jun 29, 2002
379
Mar 25, 2007
Mar 25, 2007
380
381
382
383
rc = pGetModuleFileNameW(NULL, modpath, buflen);
if (rc == 0)
{
allocator.Free(modpath);
Mar 26, 2007
Mar 26, 2007
384
BAIL_MACRO(winApiStrError(), NULL);
Mar 25, 2007
Mar 25, 2007
385
} /* if */
Jun 29, 2002
Jun 29, 2002
386
Mar 25, 2007
Mar 25, 2007
387
388
389
390
391
392
393
394
395
396
if (rc < buflen)
{
buflen = rc;
break;
} /* if */
buflen *= 2;
} /* while */
if (buflen > 0) /* just in case... */
Jun 29, 2002
Jun 29, 2002
397
{
Mar 25, 2007
Mar 25, 2007
398
399
400
401
402
403
404
405
406
407
WCHAR *ptr = (modpath + buflen) - 1;
while (ptr != modpath)
{
if (*ptr == '\\')
break;
ptr--;
} /* while */
if ((ptr == modpath) && (*ptr != '\\'))
__PHYSFS_setError(ERR_GETMODFN_NO_DIR);
Jun 29, 2002
Jun 29, 2002
408
409
else
{
Mar 25, 2007
Mar 25, 2007
410
*(ptr + 1) = '\0'; /* chop off filename. */
Mar 26, 2007
Mar 26, 2007
411
retval = unicodeToUtf8Heap(modpath);
Jun 29, 2002
Jun 29, 2002
412
} /* else */
Mar 25, 2007
Mar 25, 2007
413
414
} /* else */
allocator.Free(modpath);
Jun 29, 2002
Jun 29, 2002
415
Jan 28, 2010
Jan 28, 2010
416
return retval; /* w00t. */
Jun 29, 2002
Jun 29, 2002
417
} /* getExePath */
Jun 7, 2002
Jun 7, 2002
418
419
420
/*
Mar 25, 2007
Mar 25, 2007
421
* Try to make use of GetUserProfileDirectoryW(), which isn't available on
Jun 29, 2002
Jun 29, 2002
422
423
* some common variants of Win32. If we can't use this, we just punt and
* use the physfs base dir for the user dir, too.
Jun 7, 2002
Jun 7, 2002
424
*
Jun 29, 2002
Jun 29, 2002
425
426
427
428
* On success, module-scope variable (userDir) will have a pointer to
* a malloc()'d string of the user's profile dir, and a non-zero value is
* returned. If we can't determine the profile dir, (userDir) will
* be NULL, and zero is returned.
Jun 7, 2002
Jun 7, 2002
429
*/
Jun 29, 2002
Jun 29, 2002
430
static int determineUserDir(void)
Jun 7, 2002
Jun 7, 2002
431
{
Mar 25, 2007
Mar 25, 2007
432
if (userDir != NULL)
Jan 28, 2010
Jan 28, 2010
433
return 1; /* already good to go. */
Jun 10, 2002
Jun 10, 2002
434
Jun 29, 2002
Jun 29, 2002
435
/*
Mar 25, 2007
Mar 25, 2007
436
* GetUserProfileDirectoryW() is only available on NT 4.0 and later.
Jun 29, 2002
Jun 29, 2002
437
438
* This means Win95/98/ME (and CE?) users have to do without, so for
* them, we'll default to the base directory when we can't get the
Mar 25, 2007
Mar 25, 2007
439
440
* function pointer. Since this is originally an NT API, we don't
* offer a non-Unicode fallback.
Jun 29, 2002
Jun 29, 2002
441
*/
Mar 25, 2007
Mar 25, 2007
442
if (pGetUserProfileDirectoryW != NULL)
Jun 29, 2002
Jun 29, 2002
443
{
Mar 25, 2007
Mar 25, 2007
444
445
446
HANDLE accessToken = NULL; /* Security handle to process */
HANDLE processHandle = GetCurrentProcess();
if (OpenProcessToken(processHandle, TOKEN_QUERY, &accessToken))
Jun 29, 2002
Jun 29, 2002
447
{
Mar 25, 2007
Mar 25, 2007
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
DWORD psize = 0;
WCHAR dummy = 0;
LPWSTR wstr = NULL;
BOOL rc = 0;
/*
* Should fail. Will write the size of the profile path in
* psize. Also note that the second parameter can't be
* NULL or the function fails.
*/
rc = pGetUserProfileDirectoryW(accessToken, &dummy, &psize);
assert(!rc); /* !!! FIXME: handle this gracefully. */
/* Allocate memory for the profile directory */
wstr = (LPWSTR) __PHYSFS_smallAlloc(psize * sizeof (WCHAR));
if (wstr != NULL)
Jun 29, 2002
Jun 29, 2002
464
{
Mar 25, 2007
Mar 25, 2007
465
if (pGetUserProfileDirectoryW(accessToken, wstr, &psize))
Mar 26, 2007
Mar 26, 2007
466
userDir = unicodeToUtf8Heap(wstr);
Mar 25, 2007
Mar 25, 2007
467
468
__PHYSFS_smallFree(wstr);
} /* else */
Jun 29, 2002
Jun 29, 2002
469
} /* if */
Jun 10, 2002
Jun 10, 2002
470
Mar 25, 2007
Mar 25, 2007
471
CloseHandle(accessToken);
Jun 10, 2002
Jun 10, 2002
472
473
} /* if */
Jun 29, 2002
Jun 29, 2002
474
if (userDir == NULL) /* couldn't get profile for some reason. */
Jun 7, 2002
Jun 7, 2002
475
{
Jun 29, 2002
Jun 29, 2002
476
/* Might just be a non-NT system; resort to the basedir. */
Mar 25, 2007
Mar 25, 2007
477
userDir = getExePath();
Jun 29, 2002
Jun 29, 2002
478
BAIL_IF_MACRO(userDir == NULL, NULL, 0); /* STILL failed?! */
Jun 10, 2002
Jun 10, 2002
479
} /* if */
Jun 7, 2002
Jun 7, 2002
480
Jan 28, 2010
Jan 28, 2010
481
return 1; /* We made it: hit the showers. */
Jun 29, 2002
Jun 29, 2002
482
} /* determineUserDir */
Jun 10, 2002
Jun 10, 2002
483
Jun 7, 2002
Jun 7, 2002
484
Jul 14, 2002
Jul 14, 2002
485
static BOOL mediaInDrive(const char *drive)
Jun 7, 2002
Jun 7, 2002
486
{
Jun 29, 2002
Jun 29, 2002
487
UINT oldErrorMode;
Jul 14, 2002
Jul 14, 2002
488
489
DWORD tmp;
BOOL retval;
Jun 7, 2002
Jun 7, 2002
490
Dec 8, 2003
Dec 8, 2003
491
/* Prevent windows warning message appearing when checking media size */
Jun 29, 2002
Jun 29, 2002
492
oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
Jun 7, 2002
Jun 7, 2002
493
494
/* If this function succeeds, there's media in the drive */
Mar 26, 2007
Mar 26, 2007
495
retval = GetVolumeInformationA(drive, NULL, 0, NULL, NULL, &tmp, NULL, 0);
Jun 7, 2002
Jun 7, 2002
496
497
/* Revert back to old windows error handler */
Jun 29, 2002
Jun 29, 2002
498
499
SetErrorMode(oldErrorMode);
Jan 28, 2010
Jan 28, 2010
500
return retval;
Jun 29, 2002
Jun 29, 2002
501
} /* mediaInDrive */
Jun 7, 2002
Jun 7, 2002
502
Aug 23, 2001
Aug 23, 2001
503
Sep 29, 2004
Sep 29, 2004
504
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
Aug 23, 2001
Aug 23, 2001
505
{
Mar 25, 2007
Mar 25, 2007
506
507
/* !!! FIXME: Can CD drives be non-drive letter paths? */
/* !!! FIXME: (so can they be Unicode paths?) */
Aug 23, 2001
Aug 23, 2001
508
char drive_str[4] = "x:\\";
Sep 29, 2004
Sep 29, 2004
509
510
char ch;
for (ch = 'A'; ch <= 'Z'; ch++)
Aug 23, 2001
Aug 23, 2001
511
{
Sep 29, 2004
Sep 29, 2004
512
drive_str[0] = ch;
Jun 29, 2002
Jun 29, 2002
513
if (GetDriveType(drive_str) == DRIVE_CDROM && mediaInDrive(drive_str))
Sep 29, 2004
Sep 29, 2004
514
cb(data, drive_str);
Aug 23, 2001
Aug 23, 2001
515
} /* for */
Sep 29, 2004
Sep 29, 2004
516
} /* __PHYSFS_platformDetectAvailableCDs */
Aug 23, 2001
Aug 23, 2001
517
518
Oct 9, 2001
Oct 9, 2001
519
520
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
May 22, 2003
May 22, 2003
521
if ((argv0 != NULL) && (strchr(argv0, '\\') != NULL))
Jan 28, 2010
Jan 28, 2010
522
return NULL; /* default behaviour can handle this. */
Oct 9, 2001
Oct 9, 2001
523
Jan 28, 2010
Jan 28, 2010
524
return getExePath();
Aug 23, 2001
Aug 23, 2001
525
526
527
528
529
} /* __PHYSFS_platformCalcBaseDir */
char *__PHYSFS_platformGetUserName(void)
{
Aug 23, 2001
Aug 23, 2001
530
DWORD bufsize = 0;
Mar 26, 2007
Mar 26, 2007
531
532
533
char *retval = NULL;
if (pGetUserNameW(NULL, &bufsize) == 0) /* This SHOULD fail. */
Mar 25, 2007
Mar 25, 2007
534
{
Mar 26, 2007
Mar 26, 2007
535
536
537
538
539
540
541
LPWSTR wbuf = (LPWSTR) __PHYSFS_smallAlloc(bufsize * sizeof (WCHAR));
BAIL_IF_MACRO(wbuf == NULL, ERR_OUT_OF_MEMORY, NULL);
if (pGetUserNameW(wbuf, &bufsize) == 0) /* ?! */
__PHYSFS_setError(winApiStrError());
else
retval = unicodeToUtf8Heap(wbuf);
__PHYSFS_smallFree(wbuf);
Mar 25, 2007
Mar 25, 2007
542
543
} /* if */
Jan 28, 2010
Jan 28, 2010
544
return retval;
Aug 23, 2001
Aug 23, 2001
545
546
547
548
549
} /* __PHYSFS_platformGetUserName */
char *__PHYSFS_platformGetUserDir(void)
{
Mar 14, 2005
Mar 14, 2005
550
char *retval = (char *) allocator.Malloc(strlen(userDir) + 1);
Jun 10, 2002
Jun 10, 2002
551
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
Jun 29, 2002
Jun 29, 2002
552
strcpy(retval, userDir); /* calculated at init time. */
Jan 28, 2010
Jan 28, 2010
553
return retval;
Aug 23, 2001
Aug 23, 2001
554
555
556
} /* __PHYSFS_platformGetUserDir */
Sep 6, 2009
Sep 6, 2009
557
void *__PHYSFS_platformGetThreadID(void)
Aug 23, 2001
Aug 23, 2001
558
{
Jan 28, 2010
Jan 28, 2010
559
return ( (void *) ((size_t) GetCurrentThreadId()) );
Aug 23, 2001
Aug 23, 2001
560
561
562
} /* __PHYSFS_platformGetThreadID */
Apr 1, 2007
Apr 1, 2007
563
static int isSymlinkAttrs(const DWORD attr, const DWORD tag)
Mar 31, 2007
Mar 31, 2007
564
{
Apr 1, 2007
Apr 1, 2007
565
566
return ( (attr & FILE_ATTRIBUTE_REPARSE_POINT) &&
(tag == PHYSFS_IO_REPARSE_TAG_SYMLINK) );
Mar 31, 2007
Mar 31, 2007
567
568
569
} /* isSymlinkAttrs */
Aug 23, 2001
Aug 23, 2001
570
571
572
573
574
575
576
char *__PHYSFS_platformCvtToDependent(const char *prepend,
const char *dirName,
const char *append)
{
int len = ((prepend) ? strlen(prepend) : 0) +
((append) ? strlen(append) : 0) +
strlen(dirName) + 1;
Mar 14, 2005
Mar 14, 2005
577
char *retval = (char *) allocator.Malloc(len);
Aug 23, 2001
Aug 23, 2001
578
char *p;
Aug 23, 2001
Aug 23, 2001
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
if (prepend)
strcpy(retval, prepend);
else
retval[0] = '\0';
strcat(retval, dirName);
if (append)
strcat(retval, append);
for (p = strchr(retval, '/'); p != NULL; p = strchr(p + 1, '/'))
*p = '\\';
Jan 28, 2010
Jan 28, 2010
595
return retval;
Aug 23, 2001
Aug 23, 2001
596
597
598
} /* __PHYSFS_platformCvtToDependent */
Sep 29, 2004
Sep 29, 2004
599
600
void __PHYSFS_platformEnumerateFiles(const char *dirname,
int omitSymLinks,
Sep 18, 2005
Sep 18, 2005
601
602
PHYSFS_EnumFilesCallback callback,
const char *origdir,
Sep 29, 2004
Sep 29, 2004
603
void *callbackdata)
Aug 23, 2001
Aug 23, 2001
604
{
Mar 26, 2007
Mar 26, 2007
605
606
const int unicode = (pFindFirstFileW != NULL) && (pFindNextFileW != NULL);
HANDLE dir = INVALID_HANDLE_VALUE;
Aug 23, 2001
Aug 23, 2001
607
WIN32_FIND_DATA ent;
Mar 26, 2007
Mar 26, 2007
608
WIN32_FIND_DATAW entw;
Jun 8, 2002
Jun 8, 2002
609
size_t len = strlen(dirname);
Mar 26, 2007
Mar 26, 2007
610
611
612
char *searchPath = NULL;
WCHAR *wSearchPath = NULL;
char *utf8 = NULL;
Jun 7, 2002
Jun 7, 2002
613
Jun 8, 2002
Jun 8, 2002
614
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
Mar 26, 2007
Mar 26, 2007
615
616
searchPath = (char *) __PHYSFS_smallAlloc(len + 3);
if (searchPath == NULL)
Sep 29, 2004
Sep 29, 2004
617
return;
Jun 10, 2002
Jun 10, 2002
618
Jun 7, 2002
Jun 7, 2002
619
/* Copy current dirname */
Mar 26, 2007
Mar 26, 2007
620
strcpy(searchPath, dirname);
Jun 8, 2002
Jun 8, 2002
621
622
/* if there's no '\\' at the end of the path, stick one in there. */
Mar 26, 2007
Mar 26, 2007
623
if (searchPath[len - 1] != '\\')
Jun 8, 2002
Jun 8, 2002
624
{
Mar 26, 2007
Mar 26, 2007
625
626
searchPath[len++] = '\\';
searchPath[len] = '\0';
Jun 8, 2002
Jun 8, 2002
627
628
} /* if */
Jun 7, 2002
Jun 7, 2002
629
/* Append the "*" to the end of the string */
Mar 26, 2007
Mar 26, 2007
630
strcat(searchPath, "*");
Aug 23, 2001
Aug 23, 2001
631
Mar 26, 2007
Mar 26, 2007
632
633
634
UTF8_TO_UNICODE_STACK_MACRO(wSearchPath, searchPath);
if (wSearchPath == NULL)
return; /* oh well. */
Aug 23, 2001
Aug 23, 2001
635
Mar 26, 2007
Mar 26, 2007
636
637
638
if (unicode)
dir = pFindFirstFileW(wSearchPath, &entw);
else
Aug 23, 2001
Aug 23, 2001
639
{
Mar 26, 2007
Mar 26, 2007
640
641
642
643
644
645
646
647
648
const int len = (int) (wStrLen(wSearchPath) + 1);
char *cp = (char *) __PHYSFS_smallAlloc(len);
if (cp != NULL)
{
WideCharToMultiByte(CP_ACP, 0, wSearchPath, len, cp, len, 0, 0);
dir = FindFirstFileA(cp, &ent);
__PHYSFS_smallFree(cp);
} /* if */
} /* else */
Aug 23, 2001
Aug 23, 2001
649
Mar 26, 2007
Mar 26, 2007
650
651
652
653
__PHYSFS_smallFree(wSearchPath);
__PHYSFS_smallFree(searchPath);
if (dir == INVALID_HANDLE_VALUE)
return;
Aug 23, 2001
Aug 23, 2001
654
Mar 26, 2007
Mar 26, 2007
655
656
657
658
if (unicode)
{
do
{
Apr 1, 2007
Apr 1, 2007
659
const DWORD attr = entw.dwFileAttributes;
Mar 31, 2007
Mar 31, 2007
660
const DWORD tag = entw.dwReserved0;
Mar 26, 2007
Mar 26, 2007
661
662
663
664
665
const WCHAR *fn = entw.cFileName;
if ((fn[0] == '.') && (fn[1] == '\0'))
continue;
if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0'))
continue;
Mar 31, 2007
Mar 31, 2007
666
667
if ((omitSymLinks) && (isSymlinkAttrs(attr, tag)))
continue;
Mar 26, 2007
Mar 26, 2007
668
Mar 31, 2007
Mar 31, 2007
669
utf8 = unicodeToUtf8Heap(fn);
Mar 26, 2007
Mar 26, 2007
670
671
672
673
674
675
676
if (utf8 != NULL)
{
callback(callbackdata, origdir, utf8);
allocator.Free(utf8);
} /* if */
} while (pFindNextFileW(dir, &entw) != 0);
} /* if */
Mar 25, 2007
Mar 25, 2007
677
Mar 26, 2007
Mar 26, 2007
678
679
680
681
else /* ANSI fallback. */
{
do
{
Apr 1, 2007
Apr 1, 2007
682
const DWORD attr = ent.dwFileAttributes;
Mar 31, 2007
Mar 31, 2007
683
const DWORD tag = ent.dwReserved0;
Mar 26, 2007
Mar 26, 2007
684
685
686
687
688
const char *fn = ent.cFileName;
if ((fn[0] == '.') && (fn[1] == '\0'))
continue;
if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0'))
continue;
Mar 31, 2007
Mar 31, 2007
689
690
if ((omitSymLinks) && (isSymlinkAttrs(attr, tag)))
continue;
Mar 26, 2007
Mar 26, 2007
691
Mar 31, 2007
Mar 31, 2007
692
utf8 = codepageToUtf8Heap(fn);
Mar 26, 2007
Mar 26, 2007
693
694
695
696
697
698
699
if (utf8 != NULL)
{
callback(callbackdata, origdir, utf8);
allocator.Free(utf8);
} /* if */
} while (FindNextFileA(dir, &ent) != 0);
} /* else */
Aug 23, 2001
Aug 23, 2001
700
701
702
703
704
705
706
FindClose(dir);
} /* __PHYSFS_platformEnumerateFiles */
char *__PHYSFS_platformCurrentDir(void)
{
Mar 26, 2007
Mar 26, 2007
707
708
char *retval = NULL;
WCHAR *wbuf = NULL;
Aug 23, 2001
Aug 23, 2001
709
710
DWORD buflen = 0;
Mar 26, 2007
Mar 26, 2007
711
712
713
714
buflen = pGetCurrentDirectoryW(buflen, NULL);
wbuf = (WCHAR *) __PHYSFS_smallAlloc((buflen + 2) * sizeof (WCHAR));
BAIL_IF_MACRO(wbuf == NULL, ERR_OUT_OF_MEMORY, NULL);
pGetCurrentDirectoryW(buflen, wbuf);
Sep 1, 2001
Sep 1, 2001
715
Mar 26, 2007
Mar 26, 2007
716
717
718
719
720
721
722
if (wbuf[buflen - 2] == '\\')
wbuf[buflen-1] = '\0'; /* just in case... */
else
{
wbuf[buflen - 1] = '\\';
wbuf[buflen] = '\0';
} /* else */
Sep 1, 2001
Sep 1, 2001
723
Mar 26, 2007
Mar 26, 2007
724
725
retval = unicodeToUtf8Heap(wbuf);
__PHYSFS_smallFree(wbuf);
Jan 28, 2010
Jan 28, 2010
726
return retval;
Aug 23, 2001
Aug 23, 2001
727
728
729
} /* __PHYSFS_platformCurrentDir */
Sep 1, 2001
Sep 1, 2001
730
/* this could probably use a cleanup. */
Aug 23, 2001
Aug 23, 2001
731
732
char *__PHYSFS_platformRealPath(const char *path)
{
Oct 1, 2007
Oct 1, 2007
733
734
/* !!! FIXME: this should return NULL if (path) doesn't exist? */
/* !!! FIXME: Need to handle symlinks in Vista... */
Mar 26, 2007
Mar 26, 2007
735
/* !!! FIXME: try GetFullPathName() instead? */
Mar 25, 2007
Mar 25, 2007
736
/* this function should be UTF-8 clean. */
Sep 1, 2001
Sep 1, 2001
737
738
739
740
741
742
char *retval = NULL;
char *p = NULL;
BAIL_IF_MACRO(path == NULL, ERR_INVALID_ARGUMENT, NULL);
BAIL_IF_MACRO(*path == '\0', ERR_INVALID_ARGUMENT, NULL);
Mar 14, 2005
Mar 14, 2005
743
retval = (char *) allocator.Malloc(MAX_PATH);
Sep 1, 2001
Sep 1, 2001
744
745
746
747
748
749
750
751
752
753
754
755
756
757
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
/*
* If in \\server\path format, it's already an absolute path.
* We'll need to check for "." and ".." dirs, though, just in case.
*/
if ((path[0] == '\\') && (path[1] == '\\'))
strcpy(retval, path);
else
{
char *currentDir = __PHYSFS_platformCurrentDir();
if (currentDir == NULL)
{
Mar 14, 2005
Mar 14, 2005
758
allocator.Free(retval);
Sep 1, 2001
Sep 1, 2001
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
if (path[1] == ':') /* drive letter specified? */
{
/*
* Apparently, "D:mypath" is the same as "D:\\mypath" if
* D: is not the current drive. However, if D: is the
* current drive, then "D:mypath" is a relative path. Ugh.
*/
if (path[2] == '\\') /* maybe an absolute path? */
strcpy(retval, path);
else /* definitely an absolute path. */
{
if (path[0] == currentDir[0]) /* current drive; relative. */
{
strcpy(retval, currentDir);
strcat(retval, path + 2);
} /* if */
else /* not current drive; absolute. */
{
retval[0] = path[0];
retval[1] = ':';
retval[2] = '\\';
strcpy(retval + 3, path + 2);
} /* else */
} /* else */
} /* if */
else /* no drive letter specified. */
{
if (path[0] == '\\') /* absolute path. */
{
retval[0] = currentDir[0];
retval[1] = ':';
strcpy(retval + 2, path);
} /* if */
else
{
strcpy(retval, currentDir);
strcat(retval, path);
} /* else */
} /* else */
Mar 14, 2005
Mar 14, 2005
804
allocator.Free(currentDir);
Sep 1, 2001
Sep 1, 2001
805
806
807
808
809
810
811
} /* else */
/* (whew.) Ok, now take out "." and ".." path entries... */
p = retval;
while ( (p = strstr(p, "\\.")) != NULL)
{
Mar 25, 2007
Mar 25, 2007
812
/* it's a "." entry that doesn't end the string. */
Sep 1, 2001
Sep 1, 2001
813
814
815
if (p[2] == '\\')
memmove(p + 1, p + 3, strlen(p + 3) + 1);
Mar 25, 2007
Mar 25, 2007
816
/* it's a "." entry that ends the string. */
Sep 1, 2001
Sep 1, 2001
817
818
819
else if (p[2] == '\0')
p[0] = '\0';
Mar 25, 2007
Mar 25, 2007
820
/* it's a ".." entry. */
Sep 1, 2001
Sep 1, 2001
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
else if (p[2] == '.')
{
char *prevEntry = p - 1;
while ((prevEntry != retval) && (*prevEntry != '\\'))
prevEntry--;
if (prevEntry == retval) /* make it look like a "." entry. */
memmove(p + 1, p + 2, strlen(p + 2) + 1);
else
{
if (p[3] != '\0') /* doesn't end string. */
*prevEntry = '\0';
else /* ends string. */
memmove(prevEntry + 1, p + 4, strlen(p + 4) + 1);
p = prevEntry;
} /* else */
} /* else if */
else
{
p++; /* look past current char. */
} /* else */
} /* while */
Mar 25, 2007
Mar 25, 2007
846
/* shrink the retval's memory block if possible... */
Mar 14, 2005
Mar 14, 2005
847
p = (char *) allocator.Realloc(retval, strlen(retval) + 1);
Sep 1, 2001
Sep 1, 2001
848
849
850
if (p != NULL)
retval = p;
Jan 28, 2010
Jan 28, 2010
851
return retval;
Aug 23, 2001
Aug 23, 2001
852
853
854
855
856
} /* __PHYSFS_platformRealPath */
int __PHYSFS_platformMkDir(const char *path)
{
Mar 26, 2007
Mar 26, 2007
857
858
859
860
861
862
WCHAR *wpath;
DWORD rc;
UTF8_TO_UNICODE_STACK_MACRO(wpath, path);
rc = pCreateDirectoryW(wpath, NULL);
__PHYSFS_smallFree(wpath);
BAIL_IF_MACRO(rc == 0, winApiStrError(), 0);
Jan 28, 2010
Jan 28, 2010
863
return 1;
Aug 23, 2001
Aug 23, 2001
864
865
} /* __PHYSFS_platformMkDir */
Jun 10, 2002
Jun 10, 2002
866
Mar 26, 2007
Mar 26, 2007
867
868
869
870
871
/*
* Get OS info and save the important parts.
*
* Returns non-zero if successful, otherwise it returns zero on failure.
*/
Oct 1, 2007
Oct 1, 2007
872
873
874
875
876
877
static int getOSInfo(void)
{
OSVERSIONINFO osVerInfo; /* Information about the OS */
osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo);
BAIL_IF_MACRO(!GetVersionEx(&osVerInfo), winApiStrError(), 0);
osHasUnicode = (osVerInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS);
Jan 28, 2010
Jan 28, 2010
878
return 1;
Oct 1, 2007
Oct 1, 2007
879
} /* getOSInfo */
Mar 26, 2007
Mar 26, 2007
880
881
Jun 29, 2002
Jun 29, 2002
882
883
int __PHYSFS_platformInit(void)
{
Mar 26, 2007
Mar 26, 2007
884
BAIL_IF_MACRO(!getOSInfo(), NULL, 0);
Mar 25, 2007
Mar 25, 2007
885
BAIL_IF_MACRO(!findApiSymbols(), NULL, 0);
Jun 29, 2002
Jun 29, 2002
886
BAIL_IF_MACRO(!determineUserDir(), NULL, 0);
Jan 28, 2010
Jan 28, 2010
887
return 1; /* It's all good */
Jun 29, 2002
Jun 29, 2002
888
} /* __PHYSFS_platformInit */
Mar 24, 2002
Mar 24, 2002
889
890
891
892
int __PHYSFS_platformDeinit(void)
{
Mar 25, 2007
Mar 25, 2007
893
894
895
896
897
HANDLE *libs[] = { &libKernel32, &libUserEnv, &libAdvApi32, NULL };
int i;
allocator.Free(userDir);
userDir = NULL;
Mar 24, 2002
Mar 24, 2002
898
Mar 25, 2007
Mar 25, 2007
899
for (i = 0; libs[i] != NULL; i++)
Jun 29, 2002
Jun 29, 2002
900
{
Mar 25, 2007
Mar 25, 2007
901
902
903
904
905
const HANDLE lib = *(libs[i]);
if (lib)
FreeLibrary(lib);
*(libs[i]) = NULL;
} /* for */
Jun 29, 2002
Jun 29, 2002
906
Jan 28, 2010
Jan 28, 2010
907
return 1; /* It's all good */
Jun 29, 2002
Jun 29, 2002
908
909
910
911
912
913
} /* __PHYSFS_platformDeinit */
static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly)
{
HANDLE fileHandle;
Mar 26, 2007
Mar 26, 2007
914
915
WinApiFile *retval;
WCHAR *wfname;
Jun 29, 2002
Jun 29, 2002
916
Mar 26, 2007
Mar 26, 2007
917
918
UTF8_TO_UNICODE_STACK_MACRO(wfname, fname);
BAIL_IF_MACRO(wfname == NULL, ERR_OUT_OF_MEMORY, NULL);
Mar 17, 2010
Mar 17, 2010
919
920
fileHandle = pCreateFileW(wfname, mode, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
Mar 26, 2007
Mar 26, 2007
921
__PHYSFS_smallFree(wfname);
Jun 29, 2002
Jun 29, 2002
922
Dec 8, 2003
Dec 8, 2003
923
924
BAIL_IF_MACRO
(
Dec 22, 2003
Dec 22, 2003
925
fileHandle == INVALID_HANDLE_VALUE,
Mar 26, 2007
Mar 26, 2007
926
winApiStrError(), NULL
Dec 8, 2003
Dec 8, 2003
927
);
Jun 29, 2002
Jun 29, 2002
928
Mar 26, 2007
Mar 26, 2007
929
retval = (WinApiFile *) allocator.Malloc(sizeof (WinApiFile));
Jun 29, 2002
Jun 29, 2002
930
if (retval == NULL)
Jun 10, 2002
Jun 10, 2002
931
{
Jun 29, 2002
Jun 29, 2002
932
933
CloseHandle(fileHandle);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
Jun 10, 2002
Jun 10, 2002
934
} /* if */
Mar 24, 2002
Mar 24, 2002
935
Jun 29, 2002
Jun 29, 2002
936
937
retval->readonly = rdonly;
retval->handle = fileHandle;
Jan 28, 2010
Jan 28, 2010
938
return retval;
Jun 29, 2002
Jun 29, 2002
939
940
} /* doOpen */
Mar 24, 2002
Mar 24, 2002
941
Apr 3, 2002
Apr 3, 2002
942
943
void *__PHYSFS_platformOpenRead(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
944
return doOpen(filename, GENERIC_READ, OPEN_EXISTING, 1);
Jun 29, 2002
Jun 29, 2002
945
} /* __PHYSFS_platformOpenRead */
Apr 3, 2002
Apr 3, 2002
946
947
948
949
void *__PHYSFS_platformOpenWrite(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
950
return doOpen(filename, GENERIC_WRITE, CREATE_ALWAYS, 0);
Jun 29, 2002
Jun 29, 2002
951
} /* __PHYSFS_platformOpenWrite */
Apr 3, 2002
Apr 3, 2002
952
953
954
955
void *__PHYSFS_platformOpenAppend(const char *filename)
{
Jun 29, 2002
Jun 29, 2002
956
957
958
void *retval = doOpen(filename, GENERIC_WRITE, OPEN_ALWAYS, 0);
if (retval != NULL)
{
Mar 26, 2007
Mar 26, 2007
959
HANDLE h = ((WinApiFile *) retval)->handle;
Dec 8, 2003
Dec 8, 2003
960
961
DWORD rc = SetFilePointer(h, 0, NULL, FILE_END);
if (rc == PHYSFS_INVALID_SET_FILE_POINTER)
Jun 29, 2002
Jun 29, 2002
962
{
Mar 26, 2007
Mar 26, 2007
963
const char *err = winApiStrError();
Jun 29, 2002
Jun 29, 2002
964
CloseHandle(h);
Mar 14, 2005
Mar 14, 2005
965
allocator.Free(retval);
Jun 29, 2002
Jun 29, 2002
966
967
968
969
BAIL_MACRO(err, NULL);
} /* if */
} /* if */
Jan 28, 2010
Jan 28, 2010
970
return retval;
Jun 29, 2002
Jun 29, 2002
971
} /* __PHYSFS_platformOpenAppend */
Apr 3, 2002
Apr 3, 2002
972
973
Jan 21, 2011
Jan 21, 2011
974
/* !!! FIXME: this function fails if len > 0xFFFFFFFF. */
Aug 21, 2010
Aug 21, 2010
975
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len)
Apr 3, 2002
Apr 3, 2002
976
{
Mar 26, 2007
Mar 26, 2007
977
HANDLE Handle = ((WinApiFile *) opaque)->handle;
Aug 21, 2010
Aug 21, 2010
978
DWORD CountOfBytesRead = 0;
Apr 3, 2002
Apr 3, 2002
979
Aug 21, 2010
Aug 21, 2010
980
BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
Apr 3, 2002
Apr 3, 2002
981
Aug 21, 2010
Aug 21, 2010
982
983
984
if(!ReadFile(Handle, buf, (DWORD) len, &CountOfBytesRead, NULL))
BAIL_MACRO(winApiStrError(), -1);
return (PHYSFS_sint64) CountOfBytesRead;
Jun 29, 2002
Jun 29, 2002
985
986
} /* __PHYSFS_platformRead */
Apr 3, 2002
Apr 3, 2002
987
Jan 21, 2011
Jan 21, 2011
988
/* !!! FIXME: this function fails if len > 0xFFFFFFFF. */
Jun 29, 2002
Jun 29, 2002
989
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
Jan 21, 2011
Jan 21, 2011
990
PHYSFS_uint64 len)
Apr 3, 2002
Apr 3, 2002
991
{
Mar 26, 2007
Mar 26, 2007
992
HANDLE Handle = ((WinApiFile *) opaque)->handle;
Aug 21, 2010
Aug 21, 2010
993
DWORD CountOfBytesWritten = 0;
Apr 3, 2002
Apr 3, 2002
994
Aug 21, 2010
Aug 21, 2010
995
BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
Apr 3, 2002
Apr 3, 2002
996
Aug 21, 2010
Aug 21, 2010
997
998
999
if(!WriteFile(Handle, buffer, (DWORD) len, &CountOfBytesWritten, NULL))
BAIL_MACRO(winApiStrError(), -1);
return (PHYSFS_sint64) CountOfBytesWritten;
Jun 29, 2002
Jun 29, 2002
1000
} /* __PHYSFS_platformWrite */