int __PHYSFS_platformDelete(const char *path) { /* If filename is a folder */ if (GetFileAttributes(path) == FILE_ATTRIBUTE_DIRECTORY) { BAIL_IF_MACRO(!RemoveDirectory(path), win32strerror(), 0); } /* if */ else { BAIL_IF_MACRO(!DeleteFile(path), win32strerror(), 0); } /* else */ return(1); /* if you got here, it worked. */ } /* __PHYSFS_platformDelete */
static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly) { HANDLE fileHandle; win32file *retval; fileHandle = CreateFile(fname, mode, FILE_SHARE_READ, NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); BAIL_IF_MACRO ( fileHandle == INVALID_HANDLE_VALUE, win32strerror(), NULL ); retval = malloc(sizeof (win32file)); if (retval == NULL) { CloseHandle(fileHandle); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ retval->readonly = rdonly; retval->handle = fileHandle; return(retval); } /* doOpen */
int __PHYSFS_platformClose(void *opaque) { HANDLE FileHandle = ((win32file *) opaque)->handle; BAIL_IF_MACRO(!CloseHandle(FileHandle), win32strerror(), 0); free(opaque); return(1); } /* __PHYSFS_platformClose */
int __PHYSFS_platformFlush(void *opaque) { win32file *fh = ((win32file *) opaque); if (!fh->readonly) BAIL_IF_MACRO(!FlushFileBuffers(fh->handle), win32strerror(), 0); return(1); } /* __PHYSFS_platformFlush */
int __PHYSFS_platformExists(const char *fname) { BAIL_IF_MACRO ( GetFileAttributes(fname) == PHYSFS_INVALID_FILE_ATTRIBUTES, win32strerror(), 0 ); return(1); } /* __PHYSFS_platformExists */
/* * Get OS info and save the important parts. * * Returns non-zero if successful, otherwise it returns zero on failure. */ static int getOSInfo(void) { #if 0 /* we don't actually use this at the moment, but may in the future. */ OSVERSIONINFO OSVersionInfo; /* Information about the OS */ OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo); BAIL_IF_MACRO(!GetVersionEx(&OSVersionInfo), win32strerror(), 0); /* Set to TRUE if we are runnign a WinNT based OS 4.0 or greater */ runningNT = ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (OSVersionInfo.dwMajorVersion >= 4)); #endif return(1); } /* getOSInfo */
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname, int omitSymLinks) { LinkedStringList *retval = NULL, *p = NULL; HANDLE dir; WIN32_FIND_DATA ent; char *SearchPath; size_t len = strlen(dirname); /* Allocate a new string for path, maybe '\\', "*", and NULL terminator */ SearchPath = (char *) alloca(len + 3); BAIL_IF_MACRO(SearchPath == NULL, ERR_OUT_OF_MEMORY, NULL); /* 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, "*"); dir = FindFirstFile(SearchPath, &ent); BAIL_IF_MACRO ( dir == INVALID_HANDLE_VALUE, win32strerror(), NULL ); do { if (strcmp(ent.cFileName, ".") == 0) continue; if (strcmp(ent.cFileName, "..") == 0) continue; retval = __PHYSFS_addToLinkedStringList(retval, &p, ent.cFileName, -1); } while (FindNextFile(dir, &ent) != 0); FindClose(dir); return(retval); } /* __PHYSFS_platformEnumerateFiles */
void *__PHYSFS_platformOpenAppend(const char *filename) { void *retval = doOpen(filename, GENERIC_WRITE, OPEN_ALWAYS, 0); if (retval != NULL) { HANDLE h = ((win32file *) retval)->handle; DWORD rc = SetFilePointer(h, 0, NULL, FILE_END); if (rc == PHYSFS_INVALID_SET_FILE_POINTER) { const char *err = win32strerror(); CloseHandle(h); free(retval); BAIL_MACRO(err, NULL); } /* if */ } /* if */ return(retval); } /* __PHYSFS_platformOpenAppend */
char *__PHYSFS_platformGetUserName(void) { DWORD bufsize = 0; LPTSTR retval = NULL; if (GetUserName(NULL, &bufsize) == 0) /* This SHOULD fail. */ { retval = (LPTSTR) malloc(bufsize); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); if (GetUserName(retval, &bufsize) == 0) /* ?! */ { __PHYSFS_setError(win32strerror()); free(retval); retval = NULL; } /* if */ } /* if */ return((char *) retval); } /* __PHYSFS_platformGetUserName */
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer, PHYSFS_uint32 size, PHYSFS_uint32 count) { HANDLE Handle = ((win32file *) opaque)->handle; DWORD CountOfBytesRead; PHYSFS_sint64 retval; /* Read data from the file */ /* !!! FIXME: uint32 might be a greater # than DWORD */ if(!ReadFile(Handle, buffer, count * size, &CountOfBytesRead, NULL)) { BAIL_MACRO(win32strerror(), -1); } /* if */ else { /* Return the number of "objects" read. */ /* !!! FIXME: What if not the right amount of bytes was read to make an object? */ retval = CountOfBytesRead / size; } /* else */ return(retval); } /* __PHYSFS_platformRead */
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque) { HANDLE FileHandle = ((win32file *) opaque)->handle; DWORD SizeHigh; DWORD SizeLow; PHYSFS_sint64 retval; SizeLow = GetFileSize(FileHandle, &SizeHigh); if ( (SizeLow == PHYSFS_INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) { BAIL_MACRO(win32strerror(), -1); } /* if */ else { /* Combine the high/low order to create the 64-bit position value */ retval = (((PHYSFS_uint64) SizeHigh) << 32) | SizeLow; assert(retval >= 0); } /* else */ return(retval); } /* __PHYSFS_platformFileLength */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer, PHYSFS_uint32 size, PHYSFS_uint32 count) { HANDLE FileHandle = ((win32file *) opaque)->handle; DWORD CountOfBytesWritten; PHYSFS_sint64 retval; /* Read data from the file */ /* !!! FIXME: uint32 might be a greater # than DWORD */ if(!WriteFile(FileHandle, buffer, count * size, &CountOfBytesWritten, NULL)) { BAIL_MACRO(win32strerror(), -1); } /* if */ else { /* Return the number of "objects" read. */ /* !!! FIXME: What if not the right number of bytes was written? */ retval = CountOfBytesWritten / size; } /* else */ return(retval); } /* __PHYSFS_platformWrite */
PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname) { PHYSFS_sint64 retval = -1; WIN32_FILE_ATTRIBUTE_DATA attrData; memset(&attrData, '\0', sizeof (attrData)); /* GetFileAttributesEx didn't show up until Win98 and NT4. */ if (pGetFileAttributesEx != NULL) { if (pGetFileAttributesEx(fname, GetFileExInfoStandard, &attrData)) { /* 0 return value indicates an error or not supported */ if ( (attrData.ftLastWriteTime.dwHighDateTime != 0) || (attrData.ftLastWriteTime.dwLowDateTime != 0) ) { retval = FileTimeToPhysfsTime(&attrData.ftLastWriteTime); } /* if */ } /* 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; win32file *f = (win32file *) __PHYSFS_platformOpenRead(fname); BAIL_IF_MACRO(f == NULL, NULL, -1) rc = GetFileTime(f->handle, NULL, NULL, &ft); err = win32strerror(); CloseHandle(f->handle); free(f); BAIL_IF_MACRO(!rc, err, -1); retval = FileTimeToPhysfsTime(&ft); } /* if */ return(retval); } /* __PHYSFS_platformGetLastModTime */
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque) { HANDLE FileHandle = ((win32file *) opaque)->handle; DWORD HighPos = 0; DWORD LowPos; PHYSFS_sint64 retval; /* Get current position */ LowPos = SetFilePointer(FileHandle, 0, &HighPos, FILE_CURRENT); if ( (LowPos == PHYSFS_INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) { BAIL_MACRO(win32strerror(), 0); } /* if */ else { /* Combine the high/low order to create the 64-bit position value */ retval = (((PHYSFS_uint64) HighPos) << 32) | LowPos; assert(retval >= 0); } /* else */ return(retval); } /* __PHYSFS_platformTell */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos) { HANDLE FileHandle = ((win32file *) opaque)->handle; DWORD HighOrderPos; DWORD *pHighOrderPos; DWORD rc; /* Get the high order 32-bits of the position */ HighOrderPos = HIGHORDER_UINT64(pos); /* * MSDN: "If you do not need the high-order 32 bits, this * pointer must be set to NULL." */ pHighOrderPos = (HighOrderPos) ? &HighOrderPos : NULL; /* * !!! FIXME: MSDN: "Windows Me/98/95: If the pointer * !!! FIXME: lpDistanceToMoveHigh is not NULL, then it must * !!! FIXME: point to either 0, INVALID_SET_FILE_POINTER, or * !!! FIXME: the sign extension of the value of lDistanceToMove. * !!! FIXME: Any other value will be rejected." */ /* Move pointer "pos" count from start of file */ rc = SetFilePointer(FileHandle, LOWORDER_UINT64(pos), pHighOrderPos, FILE_BEGIN); if ( (rc == PHYSFS_INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) { BAIL_MACRO(win32strerror(), 0); } /* if */ return(1); /* No error occured */ } /* __PHYSFS_platformSeek */
static PHYSFS_sint64 FileTimeToPhysfsTime(const FILETIME *ft) { SYSTEMTIME st_utc; SYSTEMTIME st_localtz; TIME_ZONE_INFORMATION tzi; DWORD tzid; PHYSFS_sint64 retval; struct tm tm; BAIL_IF_MACRO(!FileTimeToSystemTime(ft, &st_utc), win32strerror(), -1); tzid = GetTimeZoneInformation(&tzi); BAIL_IF_MACRO(tzid == TIME_ZONE_ID_INVALID, win32strerror(), -1); /* (This API is unsupported and fails on non-NT systems. */ if (!SystemTimeToTzSpecificLocalTime(&tzi, &st_utc, &st_localtz)) { /* do it by hand. Grumble... */ ULARGE_INTEGER ui64; FILETIME new_ft; ui64.LowPart = ft->dwLowDateTime; ui64.HighPart = ft->dwHighDateTime; if (tzid == TIME_ZONE_ID_STANDARD) tzi.Bias += tzi.StandardBias; else if (tzid == TIME_ZONE_ID_DAYLIGHT) tzi.Bias += tzi.DaylightBias; /* convert from minutes to 100-nanosecond increments... */ #if 0 /* For compilers that puke on 64-bit math. */ /* goddamn this is inefficient... */ while (tzi.Bias > 0) { DWORD tmp = ui64.LowPart - 60000000; if ((ui64.LowPart < tmp) && (tmp > 60000000)) ui64.HighPart--; ui64.LowPart = tmp; tzi.Bias--; } /* while */ while (tzi.Bias < 0) { DWORD tmp = ui64.LowPart + 60000000; if ((ui64.LowPart > tmp) && (tmp < 60000000)) ui64.HighPart++; ui64.LowPart = tmp; tzi.Bias++; } /* while */ #else ui64.QuadPart -= (((LONGLONG) tzi.Bias) * (600000000)); #endif /* Move it back into a FILETIME structure... */ new_ft.dwLowDateTime = ui64.LowPart; new_ft.dwHighDateTime = ui64.HighPart; /* Convert to something human-readable... */ if (!FileTimeToSystemTime(&new_ft, &st_localtz)) BAIL_MACRO(win32strerror(), -1); } /* if */ /* Convert to a format that mktime() can grok... */ tm.tm_sec = st_localtz.wSecond; tm.tm_min = st_localtz.wMinute; tm.tm_hour = st_localtz.wHour; tm.tm_mday = st_localtz.wDay; tm.tm_mon = st_localtz.wMonth - 1; tm.tm_year = st_localtz.wYear - 1900; tm.tm_wday = -1 /*st_localtz.wDayOfWeek*/; tm.tm_yday = -1; tm.tm_isdst = -1; /* Convert to a format PhysicsFS can grok... */ retval = (PHYSFS_sint64) mktime(&tm); BAIL_IF_MACRO(retval == -1, strerror(errno), -1); return(retval); } /* FileTimeToPhysfsTime */
int __PHYSFS_platformMkDir(const char *path) { DWORD rc = CreateDirectory(path, NULL); BAIL_IF_MACRO(rc == 0, win32strerror(), 0); return(1); } /* __PHYSFS_platformMkDir */
static char *getExePath(const char *argv0) { DWORD buflen; int success = 0; char *ptr = NULL; char *retval = (char *) malloc(sizeof (TCHAR) * (MAX_PATH + 1)); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); retval[0] = '\0'; buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1); if (buflen <= 0) __PHYSFS_setError(win32strerror()); else { retval[buflen] = '\0'; /* does API always null-terminate this? */ /* make sure the string was not truncated. */ if (__PHYSFS_platformStricmp(&retval[buflen - 4], ".exe") != 0) __PHYSFS_setError(ERR_GETMODFN_TRUNC); else { ptr = strrchr(retval, '\\'); if (ptr == NULL) __PHYSFS_setError(ERR_GETMODFN_NO_DIR); else { *(ptr + 1) = '\0'; /* chop off filename. */ success = 1; } /* else */ } /* else */ } /* else */ /* if any part of the previous approach failed, try SearchPath()... */ if (!success) { if (argv0 == NULL) __PHYSFS_setError(ERR_ARGV0_IS_NULL); else { buflen = SearchPath(NULL, argv0, NULL, MAX_PATH+1, retval, &ptr); if (buflen == 0) __PHYSFS_setError(win32strerror()); else if (buflen > MAX_PATH) __PHYSFS_setError(ERR_SEARCHPATH_TRUNC); else success = 1; } /* else */ } /* if */ if (!success) { free(retval); return(NULL); /* physfs error message will be set, above. */ } /* if */ /* free up the bytes we didn't actually use. */ ptr = (char *) realloc(retval, strlen(retval) + 1); if (ptr != NULL) retval = ptr; return(retval); /* w00t. */ } /* getExePath */