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 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 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 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 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); retval = CreateFile2(fname, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); __PHYSFS_smallFree(cpstr); return(retval); } /* fallbackCreateFileW */
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 = (char*)allocator.Malloc(len); BAIL_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL); PHYSFS_utf8FromUtf16((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 */
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 */