Skip to content

Latest commit

 

History

History
1397 lines (1155 loc) · 41.3 KB

windows.c

File metadata and controls

1397 lines (1155 loc) · 41.3 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
20
#include <windows.h>
#include <stdio.h>
Aug 29, 2001
Aug 29, 2001
21
#include <stdlib.h>
Jun 29, 2002
Jun 29, 2002
22
23
#include <string.h>
#include <errno.h>
Aug 29, 2001
Aug 29, 2001
24
#include <ctype.h>
Jun 7, 2002
Jun 7, 2002
25
#include <time.h>
May 6, 2002
May 6, 2002
26
Aug 23, 2001
Aug 23, 2001
27
28
#include "physfs_internal.h"
Oct 1, 2007
Oct 1, 2007
29
30
#define LOWORDER_UINT64(pos) ((PHYSFS_uint32) (pos & 0xFFFFFFFF))
#define HIGHORDER_UINT64(pos) ((PHYSFS_uint32) ((pos >> 32) & 0xFFFFFFFF))
Apr 3, 2002
Apr 3, 2002
31
Mar 25, 2007
Mar 25, 2007
32
33
34
35
36
37
/*
* 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
38
Mar 25, 2007
Mar 25, 2007
39
40
/* just in case... */
#define PHYSFS_INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
Jun 29, 2002
Jun 29, 2002
41
Apr 1, 2007
Apr 1, 2007
42
43
44
45
/* Not defined before the Vista SDK. */
#define PHYSFS_IO_REPARSE_TAG_SYMLINK 0xA000000C
Mar 25, 2007
Mar 25, 2007
46
47
48
49
#define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \
if (str == NULL) \
w_assignto = NULL; \
else { \
Jan 22, 2008
Jan 22, 2008
50
const PHYSFS_uint64 len = (PHYSFS_uint64) ((strlen(str) + 1) * 2); \
Mar 26, 2007
Mar 26, 2007
51
52
53
w_assignto = (WCHAR *) __PHYSFS_smallAlloc(len); \
if (w_assignto != NULL) \
PHYSFS_utf8ToUcs2(str, (PHYSFS_uint16 *) w_assignto, len); \
Mar 25, 2007
Mar 25, 2007
54
55
} \
} \
Jun 29, 2002
Jun 29, 2002
56
Mar 26, 2007
Mar 26, 2007
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
static PHYSFS_uint64 wStrLen(const WCHAR *wstr)
{
PHYSFS_uint64 len = 0;
while (*(wstr++))
len++;
return(len);
} /* 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 */
return(retval);
} /* 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 */
return(retval);
} /* codepageToUtf8Heap */
Jun 29, 2002
Jun 29, 2002
103
104
105
106
typedef struct
{
HANDLE handle;
int readonly;
Mar 26, 2007
Mar 26, 2007
107
} WinApiFile;
Aug 23, 2001
Aug 23, 2001
108
Mar 26, 2007
Mar 26, 2007
109
Mar 26, 2007
Mar 26, 2007
110
static char *userDir = NULL;
Mar 26, 2007
Mar 26, 2007
111
static int osHasUnicode = 0;
Mar 25, 2007
Mar 25, 2007
112
113
114
/* pointers for APIs that may not exist on some Windows versions... */
Jun 29, 2002
Jun 29, 2002
115
static HANDLE libKernel32 = NULL;
Mar 25, 2007
Mar 25, 2007
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*
* 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);
return(retval);
} /* 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);
return(retval);
} /* 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);
return(retval);
} /* 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);
return(retval);
} /* 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 */
return(retval);
} /* 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);
return(retval);
} /* 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);
return(retval);
} /* 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);
return(retval);
} /* 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);
return(retval);
} /* fallbackCreateFileW */
Aug 23, 2001
Aug 23, 2001
257
May 6, 2002
May 6, 2002
258
Mar 25, 2007
Mar 25, 2007
259
/* A blatant abuse of pointer casting... */
Mar 26, 2007
Mar 26, 2007
260
static int symLookup(HMODULE dll, void **addr, const char *sym)
Mar 25, 2007
Mar 25, 2007
261
{
Mar 26, 2007
Mar 26, 2007
262
return( (*addr = GetProcAddress(dll, sym)) != NULL );
Mar 25, 2007
Mar 25, 2007
263
264
265
266
267
268
269
} /* symLookup */
static int findApiSymbols(void)
{
HMODULE dll = NULL;
Mar 26, 2007
Mar 26, 2007
270
271
272
273
274
275
276
277
278
#define LOOKUP_NOFALLBACK(x, reallyLook) { \
if (reallyLook) \
symLookup(dll, (void **) &p##x, #x); \
else \
p##x = NULL; \
}
#define LOOKUP(x, reallyLook) { \
if ((!reallyLook) || (!symLookup(dll, (void **) &p##x, #x))) \
Mar 26, 2007
Mar 26, 2007
279
280
p##x = fallback##x; \
}
Mar 25, 2007
Mar 25, 2007
281
Mar 26, 2007
Mar 26, 2007
282
283
284
/* 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
285
dll = libUserEnv = LoadLibraryA("userenv.dll");
Mar 25, 2007
Mar 25, 2007
286
if (dll != NULL)
Mar 26, 2007
Mar 26, 2007
287
LOOKUP_NOFALLBACK(GetUserProfileDirectoryW, osHasUnicode);
Mar 25, 2007
Mar 25, 2007
288
289
/* !!! FIXME: what do they call advapi32.dll on Win64? */
Mar 26, 2007
Mar 26, 2007
290
dll = libAdvApi32 = LoadLibraryA("advapi32.dll");
Mar 25, 2007
Mar 25, 2007
291
if (dll != NULL)
Mar 26, 2007
Mar 26, 2007
292
LOOKUP(GetUserNameW, osHasUnicode);
Mar 25, 2007
Mar 25, 2007
293
294
/* !!! FIXME: what do they call kernel32.dll on Win64? */
Mar 26, 2007
Mar 26, 2007
295
dll = libKernel32 = LoadLibraryA("kernel32.dll");
Mar 25, 2007
Mar 25, 2007
296
297
if (dll != NULL)
{
Mar 26, 2007
Mar 26, 2007
298
299
300
301
302
303
304
305
306
307
308
309
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
310
} /* if */
Dec 8, 2003
Dec 8, 2003
311
Mar 26, 2007
Mar 26, 2007
312
#undef LOOKUP_NOFALLBACK
Mar 25, 2007
Mar 25, 2007
313
314
315
316
#undef LOOKUP
return(1);
} /* findApiSymbols */
Jun 29, 2002
Jun 29, 2002
317
318
Mar 26, 2007
Mar 26, 2007
319
320
321
const char *__PHYSFS_platformDirSeparator = "\\";
Jun 10, 2002
Jun 10, 2002
322
/*
Mar 26, 2007
Mar 26, 2007
323
* Figure out what the last failing Windows API call was, and
Jun 10, 2002
Jun 10, 2002
324
325
326
327
328
* 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
329
static const char *winApiStrError(void)
Jun 10, 2002
Jun 10, 2002
330
{
Mar 26, 2007
Mar 26, 2007
331
332
333
334
335
336
337
338
339
340
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
341
Feb 13, 2008
Feb 13, 2008
342
343
344
if (rc == 0)
msgbuf[0] = '\0'; /* oh well. */
Mar 25, 2007
Mar 25, 2007
345
/* chop off newlines. */
Jun 29, 2002
Jun 29, 2002
346
347
348
349
for (ptr = msgbuf; *ptr; ptr++)
{
if ((*ptr == '\n') || (*ptr == '\r'))
{
Mar 26, 2007
Mar 26, 2007
350
*ptr = '\0';
Jun 29, 2002
Jun 29, 2002
351
352
353
354
break;
} /* if */
} /* for */
Mar 26, 2007
Mar 26, 2007
355
356
357
358
/* may truncate, but oh well. */
PHYSFS_utf8FromUcs2((PHYSFS_uint16 *) msgbuf, utf8buf, sizeof (utf8buf));
return((const char *) utf8buf);
} /* winApiStrError */
Jun 10, 2002
Jun 10, 2002
359
360
Mar 25, 2007
Mar 25, 2007
361
static char *getExePath(void)
Jun 7, 2002
Jun 7, 2002
362
{
Mar 25, 2007
Mar 25, 2007
363
364
365
DWORD buflen = 64;
LPWSTR modpath = NULL;
char *retval = NULL;
Jun 29, 2002
Jun 29, 2002
366
Mar 25, 2007
Mar 25, 2007
367
while (1)
Jun 29, 2002
Jun 29, 2002
368
{
Mar 25, 2007
Mar 25, 2007
369
370
DWORD rc;
void *ptr;
Jun 29, 2002
Jun 29, 2002
371
Mar 25, 2007
Mar 25, 2007
372
if ( !(ptr = allocator.Realloc(modpath, buflen*sizeof(WCHAR))) )
Jun 29, 2002
Jun 29, 2002
373
{
Mar 25, 2007
Mar 25, 2007
374
375
376
377
allocator.Free(modpath);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
modpath = (LPWSTR) ptr;
Jun 29, 2002
Jun 29, 2002
378
Mar 25, 2007
Mar 25, 2007
379
380
381
382
rc = pGetModuleFileNameW(NULL, modpath, buflen);
if (rc == 0)
{
allocator.Free(modpath);
Mar 26, 2007
Mar 26, 2007
383
BAIL_MACRO(winApiStrError(), NULL);
Mar 25, 2007
Mar 25, 2007
384
} /* if */
Jun 29, 2002
Jun 29, 2002
385
Mar 25, 2007
Mar 25, 2007
386
387
388
389
390
391
392
393
394
395
if (rc < buflen)
{
buflen = rc;
break;
} /* if */
buflen *= 2;
} /* while */
if (buflen > 0) /* just in case... */
Jun 29, 2002
Jun 29, 2002
396
{
Mar 25, 2007
Mar 25, 2007
397
398
399
400
401
402
403
404
405
406
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
407
408
else
{
Mar 25, 2007
Mar 25, 2007
409
*(ptr + 1) = '\0'; /* chop off filename. */
Mar 26, 2007
Mar 26, 2007
410
retval = unicodeToUtf8Heap(modpath);
Jun 29, 2002
Jun 29, 2002
411
} /* else */
Mar 25, 2007
Mar 25, 2007
412
413
} /* else */
allocator.Free(modpath);
Jun 29, 2002
Jun 29, 2002
414
415
416
return(retval); /* w00t. */
} /* getExePath */
Jun 7, 2002
Jun 7, 2002
417
418
419
/*
Mar 25, 2007
Mar 25, 2007
420
* Try to make use of GetUserProfileDirectoryW(), which isn't available on
Jun 29, 2002
Jun 29, 2002
421
422
* 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
423
*
Jun 29, 2002
Jun 29, 2002
424
425
426
427
* 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
428
*/
Jun 29, 2002
Jun 29, 2002
429
static int determineUserDir(void)
Jun 7, 2002
Jun 7, 2002
430
{
Mar 25, 2007
Mar 25, 2007
431
432
if (userDir != NULL)
return(1); /* already good to go. */
Jun 10, 2002
Jun 10, 2002
433
Jun 29, 2002
Jun 29, 2002
434
/*
Mar 25, 2007
Mar 25, 2007
435
* GetUserProfileDirectoryW() is only available on NT 4.0 and later.
Jun 29, 2002
Jun 29, 2002
436
437
* 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
438
439
* function pointer. Since this is originally an NT API, we don't
* offer a non-Unicode fallback.
Jun 29, 2002
Jun 29, 2002
440
*/
Mar 25, 2007
Mar 25, 2007
441
if (pGetUserProfileDirectoryW != NULL)
Jun 29, 2002
Jun 29, 2002
442
{
Mar 25, 2007
Mar 25, 2007
443
444
445
HANDLE accessToken = NULL; /* Security handle to process */
HANDLE processHandle = GetCurrentProcess();
if (OpenProcessToken(processHandle, TOKEN_QUERY, &accessToken))
Jun 29, 2002
Jun 29, 2002
446
{
Mar 25, 2007
Mar 25, 2007
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
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
463
{
Mar 25, 2007
Mar 25, 2007
464
if (pGetUserProfileDirectoryW(accessToken, wstr, &psize))
Mar 26, 2007
Mar 26, 2007
465
userDir = unicodeToUtf8Heap(wstr);
Mar 25, 2007
Mar 25, 2007
466
467
__PHYSFS_smallFree(wstr);
} /* else */
Jun 29, 2002
Jun 29, 2002
468
} /* if */
Jun 10, 2002
Jun 10, 2002
469
Mar 25, 2007
Mar 25, 2007
470
CloseHandle(accessToken);
Jun 10, 2002
Jun 10, 2002
471
472
} /* if */
Jun 29, 2002
Jun 29, 2002
473
if (userDir == NULL) /* couldn't get profile for some reason. */
Jun 7, 2002
Jun 7, 2002
474
{
Jun 29, 2002
Jun 29, 2002
475
/* Might just be a non-NT system; resort to the basedir. */
Mar 25, 2007
Mar 25, 2007
476
userDir = getExePath();
Jun 29, 2002
Jun 29, 2002
477
BAIL_IF_MACRO(userDir == NULL, NULL, 0); /* STILL failed?! */
Jun 10, 2002
Jun 10, 2002
478
} /* if */
Jun 7, 2002
Jun 7, 2002
479
Jun 29, 2002
Jun 29, 2002
480
481
return(1); /* We made it: hit the showers. */
} /* determineUserDir */
Jun 10, 2002
Jun 10, 2002
482
Jun 7, 2002
Jun 7, 2002
483
Jul 14, 2002
Jul 14, 2002
484
static BOOL mediaInDrive(const char *drive)
Jun 7, 2002
Jun 7, 2002
485
{
Jun 29, 2002
Jun 29, 2002
486
UINT oldErrorMode;
Jul 14, 2002
Jul 14, 2002
487
488
DWORD tmp;
BOOL retval;
Jun 7, 2002
Jun 7, 2002
489
Dec 8, 2003
Dec 8, 2003
490
/* Prevent windows warning message appearing when checking media size */
Jun 29, 2002
Jun 29, 2002
491
oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
Jun 7, 2002
Jun 7, 2002
492
493
/* If this function succeeds, there's media in the drive */
Mar 26, 2007
Mar 26, 2007
494
retval = GetVolumeInformationA(drive, NULL, 0, NULL, NULL, &tmp, NULL, 0);
Jun 7, 2002
Jun 7, 2002
495
496
/* Revert back to old windows error handler */
Jun 29, 2002
Jun 29, 2002
497
498
SetErrorMode(oldErrorMode);
Jul 14, 2002
Jul 14, 2002
499
return(retval);
Jun 29, 2002
Jun 29, 2002
500
} /* mediaInDrive */
Jun 7, 2002
Jun 7, 2002
501
Aug 23, 2001
Aug 23, 2001
502
Sep 29, 2004
Sep 29, 2004
503
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
Aug 23, 2001
Aug 23, 2001
504
{
Mar 25, 2007
Mar 25, 2007
505
506
/* !!! FIXME: Can CD drives be non-drive letter paths? */
/* !!! FIXME: (so can they be Unicode paths?) */
Aug 23, 2001
Aug 23, 2001
507
char drive_str[4] = "x:\\";
Sep 29, 2004
Sep 29, 2004
508
509
char ch;
for (ch = 'A'; ch <= 'Z'; ch++)
Aug 23, 2001
Aug 23, 2001
510
{
Sep 29, 2004
Sep 29, 2004
511
drive_str[0] = ch;
Jun 29, 2002
Jun 29, 2002
512
if (GetDriveType(drive_str) == DRIVE_CDROM && mediaInDrive(drive_str))
Sep 29, 2004
Sep 29, 2004
513
cb(data, drive_str);
Aug 23, 2001
Aug 23, 2001
514
} /* for */
Sep 29, 2004
Sep 29, 2004
515
} /* __PHYSFS_platformDetectAvailableCDs */
Aug 23, 2001
Aug 23, 2001
516
517
Oct 9, 2001
Oct 9, 2001
518
519
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
May 22, 2003
May 22, 2003
520
521
if ((argv0 != NULL) && (strchr(argv0, '\\') != NULL))
return(NULL); /* default behaviour can handle this. */
Oct 9, 2001
Oct 9, 2001
522
Mar 25, 2007
Mar 25, 2007
523
return(getExePath());
Aug 23, 2001
Aug 23, 2001
524
525
526
527
528
} /* __PHYSFS_platformCalcBaseDir */
char *__PHYSFS_platformGetUserName(void)
{
Aug 23, 2001
Aug 23, 2001
529
DWORD bufsize = 0;
Mar 26, 2007
Mar 26, 2007
530
531
532
char *retval = NULL;
if (pGetUserNameW(NULL, &bufsize) == 0) /* This SHOULD fail. */
Mar 25, 2007
Mar 25, 2007
533
{
Mar 26, 2007
Mar 26, 2007
534
535
536
537
538
539
540
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
541
542
} /* if */
Mar 26, 2007
Mar 26, 2007
543
return(retval);
Aug 23, 2001
Aug 23, 2001
544
545
546
547
548
} /* __PHYSFS_platformGetUserName */
char *__PHYSFS_platformGetUserDir(void)
{
Mar 14, 2005
Mar 14, 2005
549
char *retval = (char *) allocator.Malloc(strlen(userDir) + 1);
Jun 10, 2002
Jun 10, 2002
550
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
Jun 29, 2002
Jun 29, 2002
551
552
strcpy(retval, userDir); /* calculated at init time. */
return(retval);
Aug 23, 2001
Aug 23, 2001
553
554
555
} /* __PHYSFS_platformGetUserDir */
Apr 3, 2002
Apr 3, 2002
556
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
Aug 23, 2001
Aug 23, 2001
557
{
Jun 29, 2002
Jun 29, 2002
558
return((PHYSFS_uint64) GetCurrentThreadId());
Aug 23, 2001
Aug 23, 2001
559
560
561
} /* __PHYSFS_platformGetThreadID */
Mar 26, 2007
Mar 26, 2007
562
static int doPlatformExists(LPWSTR wpath)
Aug 23, 2001
Aug 23, 2001
563
{
Dec 8, 2003
Dec 8, 2003
564
565
BAIL_IF_MACRO
(
Mar 26, 2007
Mar 26, 2007
566
567
pGetFileAttributesW(wpath) == PHYSFS_INVALID_FILE_ATTRIBUTES,
winApiStrError(), 0
Dec 8, 2003
Dec 8, 2003
568
);
Aug 21, 2002
Aug 21, 2002
569
return(1);
Mar 26, 2007
Mar 26, 2007
570
571
572
573
574
575
576
577
578
579
580
581
} /* doPlatformExists */
int __PHYSFS_platformExists(const char *fname)
{
int retval = 0;
LPWSTR wpath;
UTF8_TO_UNICODE_STACK_MACRO(wpath, fname);
BAIL_IF_MACRO(wpath == NULL, ERR_OUT_OF_MEMORY, 0);
retval = doPlatformExists(wpath);
__PHYSFS_smallFree(wpath);
return(retval);
Aug 23, 2001
Aug 23, 2001
582
583
584
} /* __PHYSFS_platformExists */
Apr 1, 2007
Apr 1, 2007
585
static int isSymlinkAttrs(const DWORD attr, const DWORD tag)
Mar 31, 2007
Mar 31, 2007
586
{
Apr 1, 2007
Apr 1, 2007
587
588
return ( (attr & FILE_ATTRIBUTE_REPARSE_POINT) &&
(tag == PHYSFS_IO_REPARSE_TAG_SYMLINK) );
Mar 31, 2007
Mar 31, 2007
589
590
591
} /* isSymlinkAttrs */
Aug 23, 2001
Aug 23, 2001
592
593
int __PHYSFS_platformIsSymLink(const char *fname)
{
Mar 31, 2007
Mar 31, 2007
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
/* !!! FIXME:
* Windows Vista can have NTFS symlinks. Can older Windows releases have
* them when talking to a network file server? What happens when you
* mount a NTFS partition on XP that was plugged into a Vista install
* that made a symlink?
*/
int retval = 0;
LPWSTR wpath;
HANDLE dir;
WIN32_FIND_DATAW entw;
/* no unicode entry points? Probably no symlinks. */
BAIL_IF_MACRO(pFindFirstFileW == NULL, NULL, 0);
UTF8_TO_UNICODE_STACK_MACRO(wpath, fname);
BAIL_IF_MACRO(wpath == NULL, ERR_OUT_OF_MEMORY, 0);
/* !!! FIXME: filter wildcard chars? */
dir = pFindFirstFileW(wpath, &entw);
if (dir != INVALID_HANDLE_VALUE)
{
retval = isSymlinkAttrs(entw.dwFileAttributes, entw.dwReserved0);
FindClose(dir);
} /* if */
__PHYSFS_smallFree(wpath);
return(retval);
Aug 23, 2001
Aug 23, 2001
622
623
624
625
626
} /* __PHYSFS_platformIsSymlink */
int __PHYSFS_platformIsDirectory(const char *fname)
{
Mar 26, 2007
Mar 26, 2007
627
628
629
630
631
632
633
int retval = 0;
LPWSTR wpath;
UTF8_TO_UNICODE_STACK_MACRO(wpath, fname);
BAIL_IF_MACRO(wpath == NULL, ERR_OUT_OF_MEMORY, 0);
retval = ((pGetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY) != 0);
__PHYSFS_smallFree(wpath);
return(retval);
Aug 23, 2001
Aug 23, 2001
634
635
636
637
638
639
640
641
642
643
} /* __PHYSFS_platformIsDirectory */
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
644
char *retval = (char *) allocator.Malloc(len);
Aug 23, 2001
Aug 23, 2001
645
char *p;
Aug 23, 2001
Aug 23, 2001
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
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 = '\\';
return(retval);
} /* __PHYSFS_platformCvtToDependent */
Sep 29, 2004
Sep 29, 2004
666
667
void __PHYSFS_platformEnumerateFiles(const char *dirname,
int omitSymLinks,
Sep 18, 2005
Sep 18, 2005
668
669
PHYSFS_EnumFilesCallback callback,
const char *origdir,
Sep 29, 2004
Sep 29, 2004
670
void *callbackdata)
Aug 23, 2001
Aug 23, 2001
671
{
Mar 26, 2007
Mar 26, 2007
672
673
const int unicode = (pFindFirstFileW != NULL) && (pFindNextFileW != NULL);
HANDLE dir = INVALID_HANDLE_VALUE;
Aug 23, 2001
Aug 23, 2001
674
WIN32_FIND_DATA ent;
Mar 26, 2007
Mar 26, 2007
675
WIN32_FIND_DATAW entw;
Jun 8, 2002
Jun 8, 2002
676
size_t len = strlen(dirname);
Mar 26, 2007
Mar 26, 2007
677
678
679
char *searchPath = NULL;
WCHAR *wSearchPath = NULL;
char *utf8 = NULL;
Jun 7, 2002
Jun 7, 2002
680
Jun 8, 2002
Jun 8, 2002
681
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
Mar 26, 2007
Mar 26, 2007
682
683
searchPath = (char *) __PHYSFS_smallAlloc(len + 3);
if (searchPath == NULL)
Sep 29, 2004
Sep 29, 2004
684
return;
Jun 10, 2002
Jun 10, 2002
685
Jun 7, 2002
Jun 7, 2002
686
/* Copy current dirname */
Mar 26, 2007
Mar 26, 2007
687
strcpy(searchPath, dirname);
Jun 8, 2002
Jun 8, 2002
688
689
/* if there's no '\\' at the end of the path, stick one in there. */
Mar 26, 2007
Mar 26, 2007
690
if (searchPath[len - 1] != '\\')
Jun 8, 2002
Jun 8, 2002
691
{
Mar 26, 2007
Mar 26, 2007
692
693
searchPath[len++] = '\\';
searchPath[len] = '\0';
Jun 8, 2002
Jun 8, 2002
694
695
} /* if */
Jun 7, 2002
Jun 7, 2002
696
/* Append the "*" to the end of the string */
Mar 26, 2007
Mar 26, 2007
697
strcat(searchPath, "*");
Aug 23, 2001
Aug 23, 2001
698
Mar 26, 2007
Mar 26, 2007
699
700
701
UTF8_TO_UNICODE_STACK_MACRO(wSearchPath, searchPath);
if (wSearchPath == NULL)
return; /* oh well. */
Aug 23, 2001
Aug 23, 2001
702
Mar 26, 2007
Mar 26, 2007
703
704
705
if (unicode)
dir = pFindFirstFileW(wSearchPath, &entw);
else
Aug 23, 2001
Aug 23, 2001
706
{
Mar 26, 2007
Mar 26, 2007
707
708
709
710
711
712
713
714
715
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
716
Mar 26, 2007
Mar 26, 2007
717
718
719
720
__PHYSFS_smallFree(wSearchPath);
__PHYSFS_smallFree(searchPath);
if (dir == INVALID_HANDLE_VALUE)
return;
Aug 23, 2001
Aug 23, 2001
721
Mar 26, 2007
Mar 26, 2007
722
723
724
725
if (unicode)
{
do
{
Apr 1, 2007
Apr 1, 2007
726
const DWORD attr = entw.dwFileAttributes;
Mar 31, 2007
Mar 31, 2007
727
const DWORD tag = entw.dwReserved0;
Mar 26, 2007
Mar 26, 2007
728
729
730
731
732
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
733
734
if ((omitSymLinks) && (isSymlinkAttrs(attr, tag)))
continue;
Mar 26, 2007
Mar 26, 2007
735
Mar 31, 2007
Mar 31, 2007
736
utf8 = unicodeToUtf8Heap(fn);
Mar 26, 2007
Mar 26, 2007
737
738
739
740
741
742
743
if (utf8 != NULL)
{
callback(callbackdata, origdir, utf8);
allocator.Free(utf8);
} /* if */
} while (pFindNextFileW(dir, &entw) != 0);
} /* if */
Mar 25, 2007
Mar 25, 2007
744
Mar 26, 2007
Mar 26, 2007
745
746
747
748
else /* ANSI fallback. */
{
do
{
Apr 1, 2007
Apr 1, 2007
749
const DWORD attr = ent.dwFileAttributes;
Mar 31, 2007
Mar 31, 2007
750
const DWORD tag = ent.dwReserved0;
Mar 26, 2007
Mar 26, 2007
751
752
753
754
755
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
756
757
if ((omitSymLinks) && (isSymlinkAttrs(attr, tag)))
continue;
Mar 26, 2007
Mar 26, 2007
758
Mar 31, 2007
Mar 31, 2007
759
utf8 = codepageToUtf8Heap(fn);
Mar 26, 2007
Mar 26, 2007
760
761
762
763
764
765
766
if (utf8 != NULL)
{
callback(callbackdata, origdir, utf8);
allocator.Free(utf8);
} /* if */
} while (FindNextFileA(dir, &ent) != 0);
} /* else */
Aug 23, 2001
Aug 23, 2001
767
768
769
770
771
772
773
FindClose(dir);
} /* __PHYSFS_platformEnumerateFiles */
char *__PHYSFS_platformCurrentDir(void)
{
Mar 26, 2007
Mar 26, 2007
774
775
char *retval = NULL;
WCHAR *wbuf = NULL;
Aug 23, 2001
Aug 23, 2001
776
777
DWORD buflen = 0;
Mar 26, 2007
Mar 26, 2007
778
779
780
781
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
782
Mar 26, 2007
Mar 26, 2007
783
784
785
786
787
788
789
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
790
Mar 26, 2007
Mar 26, 2007
791
792
793
retval = unicodeToUtf8Heap(wbuf);
__PHYSFS_smallFree(wbuf);
return(retval);
Aug 23, 2001
Aug 23, 2001
794
795
796
} /* __PHYSFS_platformCurrentDir */
Sep 1, 2001
Sep 1, 2001
797
/* this could probably use a cleanup. */
Aug 23, 2001
Aug 23, 2001
798
799
char *__PHYSFS_platformRealPath(const char *path)
{
Oct 1, 2007
Oct 1, 2007
800
801
/* !!! FIXME: this should return NULL if (path) doesn't exist? */
/* !!! FIXME: Need to handle symlinks in Vista... */
Mar 26, 2007
Mar 26, 2007
802
/* !!! FIXME: try GetFullPathName() instead? */
Mar 25, 2007
Mar 25, 2007
803
/* this function should be UTF-8 clean. */
Sep 1, 2001
Sep 1, 2001
804
805
806
807
808
809
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
810
retval = (char *) allocator.Malloc(MAX_PATH);
Sep 1, 2001
Sep 1, 2001
811
812
813
814
815
816
817
818
819
820
821
822
823
824
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
825
allocator.Free(retval);
Sep 1, 2001
Sep 1, 2001
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
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
871
allocator.Free(currentDir);
Sep 1, 2001
Sep 1, 2001
872
873
874
875
876
877
878
} /* else */
/* (whew.) Ok, now take out "." and ".." path entries... */
p = retval;
while ( (p = strstr(p, "\\.")) != NULL)
{
Mar 25, 2007
Mar 25, 2007
879
/* it's a "." entry that doesn't end the string. */
Sep 1, 2001
Sep 1, 2001
880
881
882
if (p[2] == '\\')
memmove(p + 1, p + 3, strlen(p + 3) + 1);
Mar 25, 2007
Mar 25, 2007
883
/* it's a "." entry that ends the string. */
Sep 1, 2001
Sep 1, 2001
884
885
886
else if (p[2] == '\0')
p[0] = '\0';
Mar 25, 2007
Mar 25, 2007
887
/* it's a ".." entry. */
Sep 1, 2001
Sep 1, 2001
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
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
913
/* shrink the retval's memory block if possible... */
Mar 14, 2005
Mar 14, 2005
914
p = (char *) allocator.Realloc(retval, strlen(retval) + 1);
Sep 1, 2001
Sep 1, 2001
915
916
917
918
if (p != NULL)
retval = p;
return(retval);
Aug 23, 2001
Aug 23, 2001
919
920
921
922
923
} /* __PHYSFS_platformRealPath */
int __PHYSFS_platformMkDir(const char *path)
{
Mar 26, 2007
Mar 26, 2007
924
925
926
927
928
929
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);
Aug 23, 2001
Aug 23, 2001
930
931
932
return(1);
} /* __PHYSFS_platformMkDir */
Jun 10, 2002
Jun 10, 2002
933
Mar 26, 2007
Mar 26, 2007
934
935
936
937
938
/*
* 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
939
940
941
942
943
944
945
946
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);
return(1);
} /* getOSInfo */
Mar 26, 2007
Mar 26, 2007
947
948
Jun 29, 2002
Jun 29, 2002
949
950
int __PHYSFS_platformInit(void)
{
Mar 26, 2007
Mar 26, 2007
951
BAIL_IF_MACRO(!getOSInfo(), NULL, 0);
Mar 25, 2007
Mar 25, 2007
952
BAIL_IF_MACRO(!findApiSymbols(), NULL, 0);
Jun 29, 2002
Jun 29, 2002
953
954
955
BAIL_IF_MACRO(!determineUserDir(), NULL, 0);
return(1); /* It's all good */
} /* __PHYSFS_platformInit */
Mar 24, 2002
Mar 24, 2002
956
957
958
959
int __PHYSFS_platformDeinit(void)
{
Mar 25, 2007
Mar 25, 2007
960
961
962
963
964
HANDLE *libs[] = { &libKernel32, &libUserEnv, &libAdvApi32, NULL };
int i;
allocator.Free(userDir);
userDir = NULL;
Mar 24, 2002
Mar 24, 2002
965
Mar 25, 2007
Mar 25, 2007
966
for (i = 0; libs[i] != NULL; i++)
Jun 29, 2002
Jun 29, 2002
967
{
Mar 25, 2007
Mar 25, 2007
968
969
970
971
972
const HANDLE lib = *(libs[i]);
if (lib)
FreeLibrary(lib);
*(libs[i]) = NULL;
} /* for */
Jun 29, 2002
Jun 29, 2002
973
Jun 29, 2002
Jun 29, 2002
974
975
976
977
978
979
980
return(1); /* It's all good */
} /* __PHYSFS_platformDeinit */
static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly)
{
HANDLE fileHandle;
Mar 26, 2007
Mar 26, 2007
981
982
WinApiFile *retval;
WCHAR *wfname;
Jun 29, 2002
Jun 29, 2002
983
Mar 26, 2007
Mar 26, 2007
984
985
986
987
988
UTF8_TO_UNICODE_STACK_MACRO(wfname, fname);
BAIL_IF_MACRO(wfname == NULL, ERR_OUT_OF_MEMORY, NULL);
fileHandle = pCreateFileW(wfname, mode, FILE_SHARE_READ, NULL,
creation, FILE_ATTRIBUTE_NORMAL, NULL);
__PHYSFS_smallFree(wfname);
Jun 29, 2002
Jun 29, 2002
989
Dec 8, 2003
Dec 8, 2003
990
991
BAIL_IF_MACRO
(
Dec 22, 2003
Dec 22, 2003
992
fileHandle == INVALID_HANDLE_VALUE,
Mar 26, 2007
Mar 26, 2007
993
winApiStrError(), NULL
Dec 8, 2003
Dec 8, 2003
994
);
Jun 29, 2002
Jun 29, 2002
995
Mar 26, 2007
Mar 26, 2007
996
retval = (WinApiFile *) allocator.Malloc(sizeof (WinApiFile));
Jun 29, 2002
Jun 29, 2002
997
if (retval == NULL)
Jun 10, 2002
Jun 10, 2002
998
{
Jun 29, 2002
Jun 29, 2002
999
1000
CloseHandle(fileHandle);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);