diff options
Diffstat (limited to 'lib/libUPnP/Neptune/Source/System/Win32/NptWin32File.cpp')
-rw-r--r-- | lib/libUPnP/Neptune/Source/System/Win32/NptWin32File.cpp | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/lib/libUPnP/Neptune/Source/System/Win32/NptWin32File.cpp b/lib/libUPnP/Neptune/Source/System/Win32/NptWin32File.cpp new file mode 100644 index 0000000..587b16e --- /dev/null +++ b/lib/libUPnP/Neptune/Source/System/Win32/NptWin32File.cpp @@ -0,0 +1,414 @@ +/***************************************************************** +| +| Neptune - File :: Win32 Implementation +| +| (c) 2001-2008 Gilles Boccon-Gibod +| Author: Gilles Boccon-Gibod (bok@bok.net) +| + ****************************************************************/ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#include "NptLogging.h" +#include "NptFile.h" +#include "NptUtils.h" + +#if defined(_XBOX) +#include <xtl.h> +#else +#include <windows.h> +#include <malloc.h> +#include <limits.h> +#endif +#include <assert.h> + +/*---------------------------------------------------------------------- +| logging ++---------------------------------------------------------------------*/ +//NPT_SET_LOCAL_LOGGER("neptune.win32.file") + +/*---------------------------------------------------------------------- +| A2WHelper ++---------------------------------------------------------------------*/ +static LPWSTR A2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp) +{ + int ret; + + assert(lpa != NULL); + assert(lpw != NULL); + if (lpw == NULL || lpa == NULL) return NULL; + + lpw[0] = '\0'; + ret = MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars); + if (ret == 0) { + assert(0); + return NULL; + } + return lpw; +} + +/*---------------------------------------------------------------------- +| W2AHelper ++---------------------------------------------------------------------*/ +static LPSTR W2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp) +{ + int ret; + + assert(lpw != NULL); + assert(lpa != NULL); + if (lpa == NULL || lpw == NULL) return NULL; + + lpa[0] = '\0'; + ret = WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL); + if (ret == 0) { + int error = GetLastError(); + assert(error); + return NULL; + } + return lpa; +} + +/*---------------------------------------------------------------------- +| macros ++---------------------------------------------------------------------*/ +/* UNICODE support */ +#if !defined(_XBOX) +#define NPT_WIN32_USE_CHAR_CONVERSION int _convert = 0; LPCWSTR _lpw = NULL; LPCSTR _lpa = NULL + +#define NPT_WIN32_A2W(lpa) (\ + ((_lpa = lpa) == NULL) ? NULL : (\ + _convert = (int)(strlen(_lpa)+1),\ + (INT_MAX/2<_convert)? NULL : \ + A2WHelper((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, CP_UTF8))) + +/* +2 instead of +1 temporary fix for Chinese characters */ +#define NPT_WIN32_W2A(lpw) (\ + ((_lpw = lpw) == NULL) ? NULL : (\ + (_convert = (lstrlenW(_lpw)+2), \ + (_convert>INT_MAX/2) ? NULL : \ + W2AHelper((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), CP_UTF8)))) + +#else +#define NPT_WIN32_USE_CHAR_CONVERSION +#define NPT_WIN32_W2A(_s) (_s) +#define NPT_WIN32_A2W(_s) (_s) +#define GetFileAttributesW GetFileAttributes +#define FindFirstFileW FindFirstFile +#define FindNextFileW FindNextFile +#define FindCloseW FindClose +#define CreateDirectoryW CreateDirectoryA +#define RemoveDirectoryW RemoveDirectoryA +#define DeleteFileW DeleteFileA +#define MoveFileW MoveFileA +#define WIN32_FIND_DATAW WIN32_FIND_DATA +#endif + +/*---------------------------------------------------------------------- +| MapError ++---------------------------------------------------------------------*/ +static NPT_Result +MapError(DWORD err) { + switch (err) { + case ERROR_ALREADY_EXISTS: return NPT_ERROR_FILE_ALREADY_EXISTS; + case ERROR_PATH_NOT_FOUND: + case ERROR_FILE_NOT_FOUND: + case ERROR_INVALID_DRIVE: + case ERROR_BAD_PATHNAME: + case ERROR_BAD_NET_NAME: + case ERROR_FILENAME_EXCED_RANGE: + case ERROR_NO_MORE_FILES: + case ERROR_BAD_NETPATH: return NPT_ERROR_NO_SUCH_FILE; + case ERROR_LOCK_VIOLATION: + case ERROR_SEEK_ON_DEVICE: + case ERROR_CURRENT_DIRECTORY: + case ERROR_CANNOT_MAKE: + case ERROR_FAIL_I24: + case ERROR_NETWORK_ACCESS_DENIED: + case ERROR_DRIVE_LOCKED: + case ERROR_ACCESS_DENIED: return NPT_ERROR_PERMISSION_DENIED; + case ERROR_NOT_LOCKED: + case ERROR_LOCK_FAILED: + case ERROR_SHARING_VIOLATION: return NPT_ERROR_FILE_BUSY; + case ERROR_INVALID_FUNCTION: return NPT_ERROR_INTERNAL; + case ERROR_NOT_ENOUGH_QUOTA: return NPT_ERROR_OUT_OF_MEMORY; + case ERROR_ARENA_TRASHED: + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_INVALID_BLOCK: return NPT_ERROR_OUT_OF_MEMORY; + case ERROR_DISK_FULL: return NPT_ERROR_FILE_NOT_ENOUGH_SPACE; + case ERROR_TOO_MANY_OPEN_FILES: return NPT_ERROR_OUT_OF_RESOURCES; + case ERROR_INVALID_HANDLE: + case ERROR_INVALID_ACCESS: + case ERROR_INVALID_DATA: return NPT_ERROR_INVALID_PARAMETERS; + case ERROR_DIR_NOT_EMPTY: return NPT_ERROR_DIRECTORY_NOT_EMPTY; + case ERROR_NEGATIVE_SEEK: return NPT_ERROR_OUT_OF_RANGE; + default: return NPT_FAILURE; + } +} + +#if defined(_WIN32_WCE) +/*---------------------------------------------------------------------- +| NPT_stat_utf8 ++---------------------------------------------------------------------*/ +int +NPT_stat_utf8(const char* path, struct __stat64* info) +{ + return -1; +} + +/*---------------------------------------------------------------------- +| NPT_getcwd_utf8 ++---------------------------------------------------------------------*/ +char* +NPT_getcwd_utf8(char* dir, int max_size) +{ + return NULL; +} + +/*---------------------------------------------------------------------- +| NPT_fopen_utf8 ++---------------------------------------------------------------------*/ +FILE* +NPT_fopen_utf8(const char* path, const char* mode) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + return _wfopen(NPT_WIN32_A2W(path), NPT_WIN32_A2W(mode)); +} +#elif defined(_XBOX) +#include <sys/stat.h> +/*---------------------------------------------------------------------- +| NPT_stat_utf8 ++---------------------------------------------------------------------*/ +int +NPT_stat_utf8(const char* path, struct __stat64* info) +{ + return _stat64(path, info); +} + +/*---------------------------------------------------------------------- +| NPT_getcwd_utf8 ++---------------------------------------------------------------------*/ +char* +NPT_getcwd_utf8(char* dir, unsigned int max_size) +{ + return NULL; +} + +/*---------------------------------------------------------------------- +| NPT_fsopen_utf8 ++---------------------------------------------------------------------*/ +FILE* +NPT_fsopen_utf8(const char* path, const char* mode, int sh_flags) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + return _fsopen(path, mode, sh_flags); +} +#else +#include <sys/stat.h> +#include <direct.h> + +/*---------------------------------------------------------------------- +| NPT_stat_utf8 ++---------------------------------------------------------------------*/ +int +NPT_stat_utf8(const char* path, struct __stat64* info) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + return _wstat64(NPT_WIN32_A2W(path), info); +} + +/*---------------------------------------------------------------------- +| NPT_getcwd_utf8 ++---------------------------------------------------------------------*/ +char* +NPT_getcwd_utf8(char* dir, unsigned int max_size) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + WCHAR* wdir = (WCHAR*)alloca(2*(max_size+1)); + WCHAR* result = _wgetcwd(wdir, max_size); + if (result == NULL) return NULL; + char* converted = NPT_WIN32_W2A(result); + NPT_CopyString(dir, converted); + return dir; +} + +/*---------------------------------------------------------------------- +| NPT_fsopen_utf8 ++---------------------------------------------------------------------*/ +FILE* +NPT_fsopen_utf8(const char* path, const char* mode, int sh_flags) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + return _wfsopen(NPT_WIN32_A2W(path), NPT_WIN32_A2W(mode), sh_flags); +} +#endif + +/*---------------------------------------------------------------------- +| NPT_FilePath::Separator ++---------------------------------------------------------------------*/ +const char* const NPT_FilePath::Separator = "\\"; + +/*---------------------------------------------------------------------- +| NPT_File::GetRoots ++---------------------------------------------------------------------*/ +NPT_Result +NPT_File::GetRoots(NPT_List<NPT_String>& roots) +{ + roots.Clear(); +#if defined(_WIN32_WCE) || defined(_XBOX) + return NPT_ERROR_NOT_IMPLEMENTED; +#else + DWORD drives = GetLogicalDrives(); + for (unsigned int i=0; i<26; i++) { + if (drives & (1<<i)) { + char drive_name[4] = {(char)('A'+i), ':', '\\', 0}; + roots.Add(drive_name); + } + } + return NPT_SUCCESS; +#endif +} + +#if defined(_WIN32_WCE) +/*---------------------------------------------------------------------- +| NPT_File::GetWorkingDir ++---------------------------------------------------------------------*/ +NPT_Result +NPT_File::GetWorkingDir(NPT_String& path) +{ + path.SetLength(0); + return NPT_ERROR_NOT_IMPLEMENTED; +} + +/*---------------------------------------------------------------------- +| NPT_File::GetInfo ++---------------------------------------------------------------------*/ +NPT_Result +NPT_File::GetInfo(const char* path, NPT_FileInfo* info) +{ + return NPT_ERROR_NOT_IMPLEMENTED; +} +#endif + +/*---------------------------------------------------------------------- +| NPT_File::CreateDir ++---------------------------------------------------------------------*/ +NPT_Result +NPT_File::CreateDir(const char* path) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + BOOL result = ::CreateDirectoryW(NPT_WIN32_A2W(path), NULL); + if (result == 0) { + return MapError(GetLastError()); + } + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_File::RemoveFile ++---------------------------------------------------------------------*/ +NPT_Result +NPT_File::RemoveFile(const char* path) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + BOOL result = ::DeleteFileW(NPT_WIN32_A2W(path)); + if (result == 0) { + return MapError(GetLastError()); + } + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_File::RemoveDir ++---------------------------------------------------------------------*/ +NPT_Result +NPT_File::RemoveDir(const char* path) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + BOOL result = RemoveDirectoryW(NPT_WIN32_A2W(path)); + if (result == 0) { + return MapError(GetLastError()); + } + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_File::Rename ++---------------------------------------------------------------------*/ +NPT_Result +NPT_File::Rename(const char* from_path, const char* to_path) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + BOOL result = MoveFileW(NPT_WIN32_A2W(from_path), NPT_WIN32_A2W(to_path)); + if (result == 0) { + return MapError(GetLastError()); + } + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_File_ProcessFindData ++---------------------------------------------------------------------*/ +static bool +NPT_File_ProcessFindData(WIN32_FIND_DATAW* find_data) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + + // discard system specific files/shortcuts + if (NPT_StringsEqual(NPT_WIN32_W2A(find_data->cFileName), ".") || + NPT_StringsEqual(NPT_WIN32_W2A(find_data->cFileName), "..")) { + return false; + } + + return true; +} + +/*---------------------------------------------------------------------- +| NPT_File::ListDir ++---------------------------------------------------------------------*/ +NPT_Result +NPT_File::ListDir(const char* path, + NPT_List<NPT_String>& entries, + NPT_Ordinal start /* = 0 */, + NPT_Cardinal max /* = 0 */) +{ + NPT_WIN32_USE_CHAR_CONVERSION; + + // default return value + entries.Clear(); + + // check the arguments + if (path == NULL || path[0] == '\0') return NPT_ERROR_INVALID_PARAMETERS; + + // construct a path name with a \* wildcard at the end + NPT_String path_pattern = path; + if (path_pattern.EndsWith("\\") || path_pattern.EndsWith("/")) { + path_pattern += "*"; + } else { + path_pattern += "\\*"; + } + + // list the entries + WIN32_FIND_DATAW find_data; + HANDLE find_handle = FindFirstFileW(NPT_WIN32_A2W(path_pattern.GetChars()), &find_data); + if (find_handle == INVALID_HANDLE_VALUE) return MapError(GetLastError()); + NPT_Cardinal count = 0; + do { + if (NPT_File_ProcessFindData(&find_data)) { + // continue if we still have entries to skip + if (start > 0) { + --start; + continue; + } + entries.Add(NPT_WIN32_W2A(find_data.cFileName)); + + // stop when we have reached the maximum requested + if (max && ++count == max) return NPT_SUCCESS; + } + } while (FindNextFileW(find_handle, &find_data)); + DWORD last_error = GetLastError(); + FindClose(find_handle); + if (last_error != ERROR_NO_MORE_FILES) return MapError(last_error); + + return NPT_SUCCESS; +} |