Mercurial > projects > hoofbaby
comparison deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32File.cpp @ 0:3425707ddbf6
Initial import (hopefully this mercurial stuff works...)
author | fraserofthenight |
---|---|
date | Mon, 06 Jul 2009 08:06:28 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3425707ddbf6 |
---|---|
1 /***************************************************************** | |
2 | | |
3 | Neptune - File :: Win32 Implementation | |
4 | | |
5 | (c) 2001-2008 Gilles Boccon-Gibod | |
6 | Author: Gilles Boccon-Gibod (bok@bok.net) | |
7 | | |
8 ****************************************************************/ | |
9 | |
10 /*---------------------------------------------------------------------- | |
11 | includes | |
12 +---------------------------------------------------------------------*/ | |
13 #include "NptLogging.h" | |
14 #include "NptFile.h" | |
15 #include "NptUtils.h" | |
16 | |
17 #if defined(_XBOX) | |
18 #include <xtl.h> | |
19 #else | |
20 #include <windows.h> | |
21 #include <malloc.h> | |
22 #include <limits.h> | |
23 #endif | |
24 #include <assert.h> | |
25 | |
26 | |
27 /*---------------------------------------------------------------------- | |
28 | logging | |
29 +---------------------------------------------------------------------*/ | |
30 //NPT_SET_LOCAL_LOGGER("neptune.win32.file") | |
31 | |
32 /*---------------------------------------------------------------------- | |
33 | fix windows macros | |
34 +---------------------------------------------------------------------*/ | |
35 #if !defined(_WIN32_WCE) | |
36 #if defined(CreateDirectory) | |
37 #undef CreateDirectory | |
38 #endif | |
39 | |
40 #if defined(DeleteFile) | |
41 #undef DeleteFile | |
42 #endif | |
43 #endif | |
44 | |
45 /*---------------------------------------------------------------------- | |
46 | A2WHelper | |
47 +---------------------------------------------------------------------*/ | |
48 static LPWSTR A2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp) | |
49 { | |
50 int ret; | |
51 | |
52 assert(lpa != NULL); | |
53 assert(lpw != NULL); | |
54 if (lpw == NULL || lpa == NULL) return NULL; | |
55 | |
56 lpw[0] = '\0'; | |
57 ret = MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars); | |
58 if (ret == 0) { | |
59 assert(0); | |
60 return NULL; | |
61 } | |
62 return lpw; | |
63 } | |
64 | |
65 /*---------------------------------------------------------------------- | |
66 | W2AHelper | |
67 +---------------------------------------------------------------------*/ | |
68 static LPSTR W2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp) | |
69 { | |
70 int ret; | |
71 | |
72 assert(lpw != NULL); | |
73 assert(lpa != NULL); | |
74 if (lpa == NULL || lpw == NULL) return NULL; | |
75 | |
76 lpa[0] = '\0'; | |
77 ret = WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL); | |
78 if (ret == 0) { | |
79 assert(0); | |
80 return NULL; | |
81 } | |
82 return lpa; | |
83 } | |
84 | |
85 /*---------------------------------------------------------------------- | |
86 | macros | |
87 +---------------------------------------------------------------------*/ | |
88 /* UNICODE support */ | |
89 #if !defined(_XBOX) | |
90 #define NPT_WIN32_USE_CHAR_CONVERSION int _convert = 0; LPCWSTR _lpw = NULL; LPCSTR _lpa = NULL | |
91 | |
92 #define NPT_WIN32_A2W(lpa) (\ | |
93 ((_lpa = lpa) == NULL) ? NULL : (\ | |
94 _convert = (int)(strlen(_lpa)+1),\ | |
95 (INT_MAX/2<_convert)? NULL : \ | |
96 A2WHelper((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, CP_UTF8))) | |
97 | |
98 #define NPT_WIN32_W2A(lpw) (\ | |
99 ((_lpw = lpw) == NULL) ? NULL : (\ | |
100 (_convert = (lstrlenW(_lpw)+1), \ | |
101 (_convert>INT_MAX/2) ? NULL : \ | |
102 W2AHelper((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), CP_UTF8)))) | |
103 | |
104 #else | |
105 #define NPT_WIN32_USE_CHAR_CONVERSION | |
106 #define NPT_WIN32_W2A(_s) (_s) | |
107 #define NPT_WIN32_A2W(_s) (_s) | |
108 #define GetFileAttributesW GetFileAttributes | |
109 #define FindFirstFileW FindFirstFile | |
110 #define FindNextFileW FindNextFile | |
111 #define FindCloseW FindClose | |
112 #define CreateDirectoryW CreateDirectoryA | |
113 #define RemoveDirectoryW RemoveDirectoryA | |
114 #define DeleteFileW DeleteFileA | |
115 #define MoveFileW MoveFileA | |
116 #define WIN32_FIND_DATAW WIN32_FIND_DATA | |
117 #endif | |
118 | |
119 /*---------------------------------------------------------------------- | |
120 | MapError | |
121 +---------------------------------------------------------------------*/ | |
122 static NPT_Result | |
123 MapError(DWORD err) { | |
124 switch (err) { | |
125 case ERROR_ALREADY_EXISTS: return NPT_ERROR_FILE_ALREADY_EXISTS; | |
126 case ERROR_PATH_NOT_FOUND: | |
127 case ERROR_FILE_NOT_FOUND: | |
128 case ERROR_INVALID_DRIVE: | |
129 case ERROR_BAD_PATHNAME: | |
130 case ERROR_BAD_NET_NAME: | |
131 case ERROR_FILENAME_EXCED_RANGE: | |
132 case ERROR_NO_MORE_FILES: | |
133 case ERROR_BAD_NETPATH: return NPT_ERROR_NO_SUCH_FILE; | |
134 case ERROR_LOCK_VIOLATION: | |
135 case ERROR_SEEK_ON_DEVICE: | |
136 case ERROR_CURRENT_DIRECTORY: | |
137 case ERROR_CANNOT_MAKE: | |
138 case ERROR_FAIL_I24: | |
139 case ERROR_NETWORK_ACCESS_DENIED: | |
140 case ERROR_DRIVE_LOCKED: | |
141 case ERROR_ACCESS_DENIED: return NPT_ERROR_PERMISSION_DENIED; | |
142 case ERROR_NOT_LOCKED: | |
143 case ERROR_LOCK_FAILED: | |
144 case ERROR_SHARING_VIOLATION: return NPT_ERROR_FILE_BUSY; | |
145 case ERROR_INVALID_FUNCTION: return NPT_ERROR_INTERNAL; | |
146 case ERROR_NOT_ENOUGH_QUOTA: return NPT_ERROR_OUT_OF_MEMORY; | |
147 case ERROR_ARENA_TRASHED: | |
148 case ERROR_NOT_ENOUGH_MEMORY: | |
149 case ERROR_INVALID_BLOCK: return NPT_ERROR_OUT_OF_MEMORY; | |
150 case ERROR_DISK_FULL: return NPT_ERROR_FILE_NOT_ENOUGH_SPACE; | |
151 case ERROR_TOO_MANY_OPEN_FILES: return NPT_ERROR_OUT_OF_RESOURCES; | |
152 case ERROR_INVALID_HANDLE: | |
153 case ERROR_INVALID_ACCESS: | |
154 case ERROR_INVALID_DATA: return NPT_ERROR_INVALID_PARAMETERS; | |
155 case ERROR_DIR_NOT_EMPTY: return NPT_ERROR_DIRECTORY_NOT_EMPTY; | |
156 case ERROR_NEGATIVE_SEEK: return NPT_ERROR_OUT_OF_RANGE; | |
157 default: return NPT_FAILURE; | |
158 } | |
159 } | |
160 | |
161 #if defined(_WIN32_WCE) | |
162 /*---------------------------------------------------------------------- | |
163 | NPT_stat_utf8 | |
164 +---------------------------------------------------------------------*/ | |
165 int | |
166 NPT_stat_utf8(const char* path, struct __stat64* info) | |
167 { | |
168 return -1; | |
169 } | |
170 | |
171 /*---------------------------------------------------------------------- | |
172 | NPT_getcwd_utf8 | |
173 +---------------------------------------------------------------------*/ | |
174 char* | |
175 NPT_getcwd_utf8(char* dir, int max_size) | |
176 { | |
177 return NULL; | |
178 } | |
179 | |
180 /*---------------------------------------------------------------------- | |
181 | NPT_fopen_utf8 | |
182 +---------------------------------------------------------------------*/ | |
183 FILE* | |
184 NPT_fopen_utf8(const char* path, const char* mode) | |
185 { | |
186 NPT_WIN32_USE_CHAR_CONVERSION; | |
187 return _wfopen(NPT_WIN32_A2W(path), NPT_WIN32_A2W(mode)); | |
188 } | |
189 #elif defined(_XBOX) | |
190 #include <sys/stat.h> | |
191 /*---------------------------------------------------------------------- | |
192 | NPT_stat_utf8 | |
193 +---------------------------------------------------------------------*/ | |
194 int | |
195 NPT_stat_utf8(const char* path, struct __stat64* info) | |
196 { | |
197 return _stat64(path, info); | |
198 } | |
199 | |
200 /*---------------------------------------------------------------------- | |
201 | NPT_getcwd_utf8 | |
202 +---------------------------------------------------------------------*/ | |
203 char* | |
204 NPT_getcwd_utf8(char* dir, unsigned int max_size) | |
205 { | |
206 return NULL; | |
207 } | |
208 | |
209 /*---------------------------------------------------------------------- | |
210 | NPT_fsopen_utf8 | |
211 +---------------------------------------------------------------------*/ | |
212 FILE* | |
213 NPT_fsopen_utf8(const char* path, const char* mode, int sh_flags) | |
214 { | |
215 NPT_WIN32_USE_CHAR_CONVERSION; | |
216 return _fsopen(path, mode, sh_flags); | |
217 } | |
218 #else | |
219 #include <sys/stat.h> | |
220 #include <direct.h> | |
221 | |
222 /*---------------------------------------------------------------------- | |
223 | NPT_stat_utf8 | |
224 +---------------------------------------------------------------------*/ | |
225 int | |
226 NPT_stat_utf8(const char* path, struct __stat64* info) | |
227 { | |
228 NPT_WIN32_USE_CHAR_CONVERSION; | |
229 return _wstat64(NPT_WIN32_A2W(path), info); | |
230 } | |
231 | |
232 /*---------------------------------------------------------------------- | |
233 | NPT_getcwd_utf8 | |
234 +---------------------------------------------------------------------*/ | |
235 char* | |
236 NPT_getcwd_utf8(char* dir, unsigned int max_size) | |
237 { | |
238 NPT_WIN32_USE_CHAR_CONVERSION; | |
239 WCHAR* wdir = (WCHAR*)alloca(2*(max_size+1)); | |
240 WCHAR* result = _wgetcwd(wdir, max_size); | |
241 if (result == NULL) return NULL; | |
242 char* converted = NPT_WIN32_W2A(result); | |
243 NPT_CopyString(dir, converted); | |
244 return dir; | |
245 } | |
246 | |
247 /*---------------------------------------------------------------------- | |
248 | NPT_fsopen_utf8 | |
249 +---------------------------------------------------------------------*/ | |
250 FILE* | |
251 NPT_fsopen_utf8(const char* path, const char* mode, int sh_flags) | |
252 { | |
253 NPT_WIN32_USE_CHAR_CONVERSION; | |
254 return _wfsopen(NPT_WIN32_A2W(path), NPT_WIN32_A2W(mode + NPT_String(", ccs=UNICODE")), sh_flags); | |
255 } | |
256 #endif | |
257 | |
258 /*---------------------------------------------------------------------- | |
259 | NPT_FilePath::Separator | |
260 +---------------------------------------------------------------------*/ | |
261 const NPT_String NPT_FilePath::Separator("\\"); | |
262 | |
263 /*---------------------------------------------------------------------- | |
264 | NPT_File::GetRoots | |
265 +---------------------------------------------------------------------*/ | |
266 NPT_Result | |
267 NPT_File::GetRoots(NPT_List<NPT_String>& roots) | |
268 { | |
269 roots.Clear(); | |
270 #if defined(_WIN32_WCE) || defined(_XBOX) | |
271 return NPT_ERROR_NOT_IMPLEMENTED; | |
272 #else | |
273 DWORD drives = GetLogicalDrives(); | |
274 for (unsigned int i=0; i<26; i++) { | |
275 if (drives & (1<<i)) { | |
276 char drive_name[4] = {'A'+i, ':', '\\', 0}; | |
277 roots.Add(drive_name); | |
278 } | |
279 } | |
280 return NPT_SUCCESS; | |
281 #endif | |
282 } | |
283 | |
284 #if defined(_WIN32_WCE) | |
285 /*---------------------------------------------------------------------- | |
286 | NPT_File::GetWorkingDirectory | |
287 +---------------------------------------------------------------------*/ | |
288 NPT_Result | |
289 NPT_File::GetWorkingDirectory(NPT_String& path) | |
290 { | |
291 path.SetLength(0); | |
292 return NPT_ERROR_NOT_IMPLEMENTED; | |
293 } | |
294 | |
295 /*---------------------------------------------------------------------- | |
296 | NPT_File::GetInfo | |
297 +---------------------------------------------------------------------*/ | |
298 NPT_Result | |
299 NPT_File::GetInfo(const char* path, NPT_FileInfo* info) | |
300 { | |
301 return NPT_ERROR_NOT_IMPLEMENTED; | |
302 } | |
303 #endif | |
304 | |
305 /*---------------------------------------------------------------------- | |
306 | NPT_File::CreateDirectory | |
307 +---------------------------------------------------------------------*/ | |
308 NPT_Result | |
309 NPT_File::CreateDirectory(const char* path) | |
310 { | |
311 NPT_WIN32_USE_CHAR_CONVERSION; | |
312 BOOL result = ::CreateDirectoryW(NPT_WIN32_A2W(path), NULL); | |
313 if (result == 0) { | |
314 return MapError(GetLastError()); | |
315 } | |
316 return NPT_SUCCESS; | |
317 } | |
318 | |
319 /*---------------------------------------------------------------------- | |
320 | NPT_File::DeleteFile | |
321 +---------------------------------------------------------------------*/ | |
322 NPT_Result | |
323 NPT_File::DeleteFile(const char* path) | |
324 { | |
325 NPT_WIN32_USE_CHAR_CONVERSION; | |
326 BOOL result = ::DeleteFileW(NPT_WIN32_A2W(path)); | |
327 if (result == 0) { | |
328 return MapError(GetLastError()); | |
329 } | |
330 return NPT_SUCCESS; | |
331 } | |
332 | |
333 /*---------------------------------------------------------------------- | |
334 | NPT_File::DeleteDirectory | |
335 +---------------------------------------------------------------------*/ | |
336 NPT_Result | |
337 NPT_File::DeleteDirectory(const char* path) | |
338 { | |
339 NPT_WIN32_USE_CHAR_CONVERSION; | |
340 BOOL result = RemoveDirectoryW(NPT_WIN32_A2W(path)); | |
341 if (result == 0) { | |
342 return MapError(GetLastError()); | |
343 } | |
344 return NPT_SUCCESS; | |
345 } | |
346 | |
347 /*---------------------------------------------------------------------- | |
348 | NPT_File::Rename | |
349 +---------------------------------------------------------------------*/ | |
350 NPT_Result | |
351 NPT_File::Rename(const char* from_path, const char* to_path) | |
352 { | |
353 NPT_WIN32_USE_CHAR_CONVERSION; | |
354 BOOL result = MoveFileW(NPT_WIN32_A2W(from_path), NPT_WIN32_A2W(to_path)); | |
355 if (result == 0) { | |
356 return MapError(GetLastError()); | |
357 } | |
358 return NPT_SUCCESS; | |
359 } | |
360 | |
361 /*---------------------------------------------------------------------- | |
362 | NPT_File_ProcessFindData | |
363 +---------------------------------------------------------------------*/ | |
364 static bool | |
365 NPT_File_ProcessFindData(WIN32_FIND_DATAW* find_data) | |
366 { | |
367 NPT_WIN32_USE_CHAR_CONVERSION; | |
368 | |
369 // discard system specific files/shortcuts | |
370 if (NPT_StringsEqual(NPT_WIN32_W2A(find_data->cFileName), ".") || | |
371 NPT_StringsEqual(NPT_WIN32_W2A(find_data->cFileName), "..")) { | |
372 return false; | |
373 } | |
374 | |
375 return true; | |
376 } | |
377 | |
378 /*---------------------------------------------------------------------- | |
379 | NPT_File::ListDirectory | |
380 +---------------------------------------------------------------------*/ | |
381 NPT_Result | |
382 NPT_File::ListDirectory(const char* path, | |
383 NPT_List<NPT_String>& entries, | |
384 NPT_Ordinal start /* = 0 */, | |
385 NPT_Cardinal max /* = 0 */) | |
386 { | |
387 NPT_WIN32_USE_CHAR_CONVERSION; | |
388 | |
389 // default return value | |
390 entries.Clear(); | |
391 | |
392 // check the arguments | |
393 if (path == NULL || path[0] == '\0') return NPT_ERROR_INVALID_PARAMETERS; | |
394 | |
395 // construct a path name with a \* wildcard at the end | |
396 NPT_String path_pattern = path; | |
397 if (path_pattern.EndsWith("\\") || path_pattern.EndsWith("/")) { | |
398 path_pattern += "*"; | |
399 } else { | |
400 path_pattern += "\\*"; | |
401 } | |
402 | |
403 // list the entries | |
404 WIN32_FIND_DATAW find_data; | |
405 HANDLE find_handle = FindFirstFileW(NPT_WIN32_A2W(path_pattern.GetChars()), &find_data); | |
406 if (find_handle == INVALID_HANDLE_VALUE) return MapError(GetLastError()); | |
407 NPT_Cardinal count = 0; | |
408 do { | |
409 if (NPT_File_ProcessFindData(&find_data)) { | |
410 // continue if not yet first item requested | |
411 if (start > 0) { | |
412 --start; | |
413 continue; | |
414 } | |
415 entries.Add(NPT_WIN32_W2A(find_data.cFileName)); | |
416 | |
417 // stop when reaching maximum requested | |
418 if (max && ++count == max) return NPT_SUCCESS; | |
419 } | |
420 } while (FindNextFileW(find_handle, &find_data)); | |
421 DWORD last_error = GetLastError(); | |
422 FindClose(find_handle); | |
423 if (last_error != ERROR_NO_MORE_FILES) return MapError(last_error); | |
424 | |
425 return NPT_SUCCESS; | |
426 } |