static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly) { HANDLE fileh; WinApiFile *retval; WCHAR *wfname; UTF8_TO_UNICODE_STACK_MACRO(wfname, fname); BAIL_IF_MACRO(!wfname, PHYSFS_ERR_OUT_OF_MEMORY, NULL); //fileh = CreateFileW(wfname, mode, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); fileh = CreateFile2(wfname, mode, FILE_SHARE_READ | FILE_SHARE_WRITE, creation, NULL); __PHYSFS_smallFree(wfname); BAIL_IF_MACRO(fileh == INVALID_HANDLE_VALUE, errcodeFromWinApi(), NULL); retval = (WinApiFile *)allocator.Malloc(sizeof(WinApiFile)); if (!retval) { CloseHandle(fileh); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* if */ retval->readonly = rdonly; retval->handle = fileh; return retval; } /* doOpen */
int __PHYSFS_platformIsSymLink(const char *fname) { /* !!! 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); } /* __PHYSFS_platformIsSymlink */
PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname) { PHYSFS_sint64 retval = -1; WIN32_FILE_ATTRIBUTE_DATA attr; int rc = 0; memset(&attr, '\0', sizeof(attr)); /* GetFileAttributesEx didn't show up until Win98 and NT4. */ if ((pGetFileAttributesExW != NULL) || (pGetFileAttributesExA != NULL)) { WCHAR *wstr; UTF8_TO_UNICODE_STACK_MACRO(wstr, fname); if (wstr != NULL) /* if NULL, maybe the fallback will work. */ { if (pGetFileAttributesExW != NULL) /* NT/XP/Vista/etc system. */ rc = pGetFileAttributesExW(wstr, GetFileExInfoStandard, &attr); else /* Win98/ME system */ { const int len = (int)(wStrLen(wstr) + 1); char *cp = (char *)__PHYSFS_smallAlloc(len); if (cp != NULL) { WideCharToMultiByte(CP_ACP, 0, wstr, len, cp, len, 0, 0); rc = pGetFileAttributesExA(cp, GetFileExInfoStandard, &attr); __PHYSFS_smallFree(cp); } /* if */ } /* else */ __PHYSFS_smallFree(wstr); } /* if */ } /* if */ if (rc) /* had API entry point and it worked. */ { /* 0 return value indicates an error or not supported */ if ((attr.ftLastWriteTime.dwHighDateTime != 0) || (attr.ftLastWriteTime.dwLowDateTime != 0)) { retval = FileTimeToPhysfsTime(&attr.ftLastWriteTime); } /* if */ } /* if */ /* GetFileTime() has been in the Win32 API since the start. */ if (retval == -1) /* try a fallback... */ { FILETIME ft; BOOL rc; const char *err; WinApiFile *f = (WinApiFile *)__PHYSFS_platformOpenRead(fname); BAIL_IF_MACRO(f == NULL, NULL, -1) rc = GetFileTime(f->handle, NULL, NULL, &ft); err = winApiStrError(); CloseHandle(f->handle); allocator.Free(f); BAIL_IF_MACRO(!rc, err, -1); retval = FileTimeToPhysfsTime(&ft); } /* if */ return(retval); } /* __PHYSFS_platformGetLastModTime */
static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly) { HANDLE fileHandle; WinApiFile *retval; WCHAR *wfname; 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); BAIL_IF_MACRO ( fileHandle == INVALID_HANDLE_VALUE, winApiStrError(), NULL ); retval = (WinApiFile *) allocator.Malloc(sizeof (WinApiFile)); if (retval == NULL) { CloseHandle(fileHandle); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ retval->readonly = rdonly; retval->handle = fileHandle; return(retval); } /* doOpen */
int __PHYSFS_platformDelete(const char *path) { int retval = 0; LPWSTR wpath = NULL; UTF8_TO_UNICODE_STACK_MACRO(wpath, path); BAIL_IF_MACRO(!wpath, PHYSFS_ERR_OUT_OF_MEMORY, 0); retval = doPlatformDelete(wpath); __PHYSFS_smallFree(wpath); return retval; } /* __PHYSFS_platformDelete */
int __PHYSFS_platformMkDir(const char *path) { WCHAR *wpath; DWORD rc; UTF8_TO_UNICODE_STACK_MACRO(wpath, path); rc = CreateDirectoryW(wpath, NULL); __PHYSFS_smallFree(wpath); BAIL_IF_MACRO(rc == 0, errcodeFromWinApi(), 0); return 1; } /* __PHYSFS_platformMkDir */
int __PHYSFS_platformMkDir(const char *path) { 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); return(1); } /* __PHYSFS_platformMkDir */
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); } /* __PHYSFS_platformExists */
int __PHYSFS_platformIsDirectory(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 = ((pGetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY) != 0); __PHYSFS_smallFree(wpath); return(retval); } /* __PHYSFS_platformIsDirectory */
int __PHYSFS_platformIsDirectory(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 = ((pGetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY) != 0); WIN32_FILE_ATTRIBUTE_DATA file_info; const BOOL res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &file_info); if (res) { retval = ((file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); } __PHYSFS_smallFree(wpath); return(retval); } /* __PHYSFS_platformIsDirectory */
int __PHYSFS_platformStat(const char *filename, int *exists, PHYSFS_Stat *stat) { WIN32_FILE_ATTRIBUTE_DATA winstat; WCHAR *wstr = NULL; DWORD err = 0; BOOL rc = 0; UTF8_TO_UNICODE_STACK_MACRO(wstr, filename); BAIL_IF_MACRO(!wstr, PHYSFS_ERR_OUT_OF_MEMORY, 0); rc = GetFileAttributesExW(wstr, GetFileExInfoStandard, &winstat); err = (!rc) ? GetLastError() : 0; *exists = ((err != ERROR_FILE_NOT_FOUND) && (err != ERROR_PATH_NOT_FOUND)); __PHYSFS_smallFree(wstr); BAIL_IF_MACRO(!rc, errcodeFromWinApiError(err), 0); stat->modtime = FileTimeToPhysfsTime(&winstat.ftLastWriteTime); stat->accesstime = FileTimeToPhysfsTime(&winstat.ftLastAccessTime); stat->createtime = FileTimeToPhysfsTime(&winstat.ftCreationTime); if(winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { stat->filetype = PHYSFS_FILETYPE_DIRECTORY; stat->filesize = 0; } /* if */ else if(winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE)) { /* !!! FIXME: what are reparse points? */ stat->filetype = PHYSFS_FILETYPE_OTHER; /* !!! FIXME: don't rely on this */ stat->filesize = 0; } /* else if */ /* !!! FIXME: check for symlinks on Vista. */ else { stat->filetype = PHYSFS_FILETYPE_REGULAR; stat->filesize = (((PHYSFS_uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow; } /* else */ stat->readonly = ((winstat.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0); return 1; } /* __PHYSFS_platformStat */
void __PHYSFS_platformEnumerateFiles(const char *dirname, PHYSFS_EnumFilesCallback callback, const char *origdir, void *callbackdata) { HANDLE dir = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW entw; size_t len = strlen(dirname); char *searchPath = NULL; WCHAR *wSearchPath = NULL; /* Allocate a new string for path, maybe '\\', "*", and NULL terminator */ searchPath = (char *)__PHYSFS_smallAlloc(len + 3); if (searchPath == NULL) return; /* Copy current dirname */ strcpy(searchPath, dirname); /* if there's no '\\' at the end of the path, stick one in there. */ if (searchPath[len - 1] != '\\') { searchPath[len++] = '\\'; searchPath[len] = '\0'; } /* if */ /* Append the "*" to the end of the string */ strcat(searchPath, "*"); UTF8_TO_UNICODE_STACK_MACRO(wSearchPath, searchPath); if (!wSearchPath) return; /* oh well. */ //dir = FindFirstFileW(wSearchPath, &entw); dir = FindFirstFileExW(wSearchPath, FindExInfoStandard, &entw, FindExSearchNameMatch, NULL, 0); __PHYSFS_smallFree(wSearchPath); __PHYSFS_smallFree(searchPath); if (dir == INVALID_HANDLE_VALUE) return; do { const DWORD attr = entw.dwFileAttributes; const DWORD tag = entw.dwReserved0; const WCHAR *fn = entw.cFileName; char *utf8; if ((fn[0] == '.') && (fn[1] == '\0')) continue; if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0')) continue; utf8 = unicodeToUtf8Heap(fn); if (utf8 != NULL) { callback(callbackdata, origdir, utf8); allocator.Free(utf8); } /* if */ } while (FindNextFileW(dir, &entw) != 0); FindClose(dir); } /* __PHYSFS_platformEnumerateFiles */
void __PHYSFS_platformEnumerateFiles(const char *dirname, int omitSymLinks, PHYSFS_EnumFilesCallback callback, const char *origdir, void *callbackdata) { const int unicode = (pFindFirstFileW != NULL) && (pFindNextFileW != NULL); HANDLE dir = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ent; WIN32_FIND_DATAW entw; size_t len = strlen(dirname); char *searchPath = NULL; WCHAR *wSearchPath = NULL; char *utf8 = NULL; /* Allocate a new string for path, maybe '\\', "*", and NULL terminator */ searchPath = (char *)__PHYSFS_smallAlloc(len + 3); if (searchPath == NULL) return; /* Copy current dirname */ strcpy(searchPath, dirname); /* if there's no '\\' at the end of the path, stick one in there. */ if (searchPath[len - 1] != '\\') { searchPath[len++] = '\\'; searchPath[len] = '\0'; } /* if */ /* Append the "*" to the end of the string */ strcat(searchPath, "*"); UTF8_TO_UNICODE_STACK_MACRO(wSearchPath, searchPath); if (wSearchPath == NULL) return; /* oh well. */ if (unicode) dir = pFindFirstFileW(wSearchPath, &entw); else { 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); dir = FindFirstFileExA(cp, FindExInfoStandard, &ent, FindExSearchNameMatch, NULL, 0); __PHYSFS_smallFree(cp); } /* if */ } /* else */ __PHYSFS_smallFree(wSearchPath); __PHYSFS_smallFree(searchPath); if (dir == INVALID_HANDLE_VALUE) return; if (unicode) { do { const DWORD attr = entw.dwFileAttributes; const DWORD tag = entw.dwReserved0; const WCHAR *fn = entw.cFileName; if ((fn[0] == '.') && (fn[1] == '\0')) continue; if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0')) continue; if ((omitSymLinks) && (isSymlinkAttrs(attr, tag))) continue; utf8 = unicodeToUtf8Heap(fn); if (utf8 != NULL) { callback(callbackdata, origdir, utf8); allocator.Free(utf8); } /* if */ } while (pFindNextFileW(dir, &entw) != 0); } /* if */ else /* ANSI fallback. */ { do { const DWORD attr = ent.dwFileAttributes; const DWORD tag = ent.dwReserved0; const char *fn = ent.cFileName; if ((fn[0] == '.') && (fn[1] == '\0')) continue; if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0')) continue; if ((omitSymLinks) && (isSymlinkAttrs(attr, tag))) continue; utf8 = codepageToUtf8Heap(fn); if (utf8 != NULL) { callback(callbackdata, origdir, utf8); allocator.Free(utf8); } /* if */ } while (FindNextFileA(dir, &ent) != 0); } /* else */ FindClose(dir); } /* __PHYSFS_platformEnumerateFiles */