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; BOOL rc; BAIL_IF_MACRO(!FileTimeToSystemTime(ft, &st_utc), errcodeFromWinApi(), -1); tzid = GetTimeZoneInformation(&tzi); BAIL_IF_MACRO(tzid == TIME_ZONE_ID_INVALID, errcodeFromWinApi(), -1); rc = SystemTimeToTzSpecificLocalTime(&tzi, &st_utc, &st_localtz); BAIL_IF_MACRO(!rc, errcodeFromWinApi(), -1); /* 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, PHYSFS_ERR_OS_ERROR, -1); return retval; } /* FileTimeToPhysfsTime */
char *__PHYSFS_platformCalcUserDir(void) { typedef BOOL (WINAPI *fnGetUserProfDirW)(HANDLE, LPWSTR, LPDWORD); fnGetUserProfDirW pGetDir = NULL; HANDLE lib = NULL; HANDLE accessToken = NULL; /* Security handle to process */ char *retval = NULL; lib = LoadLibraryA("userenv.dll"); BAIL_IF_MACRO(!lib, errcodeFromWinApi(), NULL); pGetDir=(fnGetUserProfDirW) GetProcAddress(lib,"GetUserProfileDirectoryW"); GOTO_IF_MACRO(!pGetDir, errcodeFromWinApi(), done); if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &accessToken)) GOTO_MACRO(errcodeFromWinApi(), done); else { DWORD psize = 0; WCHAR dummy = 0; LPWSTR wstr = NULL; BOOL rc = 0; /* * Should fail. Will write the size of the profile path in * psize. Also note that the second parameter can't be * NULL or the function fails. */ rc = pGetDir(accessToken, &dummy, &psize); assert(!rc); /* !!! FIXME: handle this gracefully. */ (void) rc; /* Allocate memory for the profile directory */ wstr = (LPWSTR) __PHYSFS_smallAlloc((psize + 1) * sizeof (WCHAR)); if (wstr != NULL) { if (pGetDir(accessToken, wstr, &psize)) { /* Make sure it ends in a dirsep. We allocated +1 for this. */ if (wstr[psize - 2] != '\\') { wstr[psize - 1] = '\\'; wstr[psize - 0] = '\0'; } /* if */ retval = unicodeToUtf8Heap(wstr); } /* if */ __PHYSFS_smallFree(wstr); } /* if */ CloseHandle(accessToken); } /* if */ done: FreeLibrary(lib); return retval; /* We made it: hit the showers. */ } /* __PHYSFS_platformCalcUserDir */
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 */
static int doPlatformDelete(LPWSTR wpath) { const int isdir = (GetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY); const BOOL rc = (isdir) ? RemoveDirectoryW(wpath) : DeleteFileW(wpath); BAIL_IF_MACRO(!rc, errcodeFromWinApi(), 0); return 1; /* if you made it here, it worked. */ } /* doPlatformDelete */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos) { HANDLE Handle = ((WinApiFile *) opaque)->handle; LONG HighOrderPos; PLONG 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; /* Move pointer "pos" count from start of file */ rc = SetFilePointer(Handle, LOWORDER_UINT64(pos), pHighOrderPos, FILE_BEGIN); if ( (rc == PHYSFS_INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) { BAIL_MACRO(errcodeFromWinApi(), 0); } /* if */ return 1; /* No error occured */ } /* __PHYSFS_platformSeek */
int __PHYSFS_platformFlush(void *opaque) { WinApiFile *fh = ((WinApiFile *)opaque); if (!fh->readonly) BAIL_IF_MACRO(!FlushFileBuffers(fh->handle), errcodeFromWinApi(), 0); return 1; } /* __PHYSFS_platformFlush */
char *__PHYSFS_platformCalcBaseDir(const char *argv0) { DWORD buflen = 64; LPWSTR modpath = NULL; char *retval = NULL; while (1) { DWORD rc; void *ptr; if ( (ptr = allocator.Realloc(modpath, buflen*sizeof(WCHAR))) == NULL ) { allocator.Free(modpath); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* if */ modpath = (LPWSTR) ptr; rc = GetModuleFileNameW(NULL, modpath, buflen); if (rc == 0) { allocator.Free(modpath); BAIL_MACRO(errcodeFromWinApi(), NULL); } /* if */ if (rc < buflen) { buflen = rc; break; } /* if */ buflen *= 2; } /* while */ if (buflen > 0) /* just in case... */ { WCHAR *ptr = (modpath + buflen) - 1; while (ptr != modpath) { if (*ptr == '\\') break; ptr--; } /* while */ if ((ptr == modpath) && (*ptr != '\\')) __PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR); /* oh well. */ else { *(ptr+1) = '\0'; /* chop off filename. */ retval = unicodeToUtf8Heap(modpath); } /* else */ } /* else */ allocator.Free(modpath); return retval; /* w00t. */ } /* __PHYSFS_platformCalcBaseDir */
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 */
static int doPlatformDelete(LPWSTR wpath) { //const int isdir = (GetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY); int isdir = 0; WIN32_FILE_ATTRIBUTE_DATA file_info; const BOOL res = GetFileAttributesEx(wpath, GetFileExInfoStandard, &file_info); if (res) { isdir = (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); } const BOOL rc = (isdir) ? RemoveDirectoryW(wpath) : DeleteFileW(wpath); BAIL_IF_MACRO(!rc, errcodeFromWinApi(), 0); return 1; /* if you made it here, it worked. */ } /* doPlatformDelete */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos) { HANDLE Handle = ((WinApiFile *)opaque)->handle; BOOL rc; LARGE_INTEGER li; li.LowPart = LOWORDER_UINT64(pos); li.HighPart = HIGHORDER_UINT64(pos); rc = SetFilePointerEx(Handle, li, NULL, FILE_BEGIN); if (!rc && (GetLastError() != NO_ERROR)) { BAIL_MACRO(errcodeFromWinApi(), 0); } /* if */ return 1; /* No error occured */ } /* __PHYSFS_platformSeek */
void *__PHYSFS_platformOpenAppend(const char *filename) { void *retval = doOpen(filename, GENERIC_WRITE, OPEN_ALWAYS, 0); if (retval != NULL) { HANDLE h = ((WinApiFile *) retval)->handle; DWORD rc = SetFilePointer(h, 0, NULL, FILE_END); if (rc == PHYSFS_INVALID_SET_FILE_POINTER) { const PHYSFS_ErrorCode err = errcodeFromWinApi(); CloseHandle(h); allocator.Free(retval); BAIL_MACRO(err, NULL); } /* if */ } /* if */ return retval; } /* __PHYSFS_platformOpenAppend */
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len) { HANDLE Handle = ((WinApiFile *)opaque)->handle; PHYSFS_sint64 totalRead = 0; if (!__PHYSFS_ui64FitsAddressSpace(len)) BAIL_MACRO(PHYSFS_ERR_INVALID_ARGUMENT, -1); while (len > 0) { const DWORD thislen = (len > 0xFFFFFFFF) ? 0xFFFFFFFF : (DWORD)len; DWORD numRead = 0; if (!ReadFile(Handle, buf, thislen, &numRead, NULL)) BAIL_MACRO(errcodeFromWinApi(), -1); len -= (PHYSFS_uint64)numRead; totalRead += (PHYSFS_sint64)numRead; if (numRead != thislen) break; } /* while */ return totalRead; } /* __PHYSFS_platformRead */
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque) { HANDLE Handle = ((WinApiFile *) opaque)->handle; DWORD SizeHigh; DWORD SizeLow; PHYSFS_sint64 retval; SizeLow = GetFileSize(Handle, &SizeHigh); if ( (SizeLow == PHYSFS_INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) { BAIL_MACRO(errcodeFromWinApi(), -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_platformTell(void *opaque) { HANDLE Handle = ((WinApiFile *)opaque)->handle; PHYSFS_sint64 retval; BOOL rc; LARGE_INTEGER zero; zero.QuadPart = 0; LARGE_INTEGER out; rc = SetFilePointerEx(Handle, zero, &out, FILE_CURRENT); if (!rc) { BAIL_MACRO(errcodeFromWinApi(), -1); } /* if */ else { retval = out.QuadPart; assert(retval >= 0); } /* else */ return retval; } /* __PHYSFS_platformTell */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer, PHYSFS_uint64 len) { HANDLE Handle = ((WinApiFile *)opaque)->handle; PHYSFS_sint64 totalWritten = 0; if (!__PHYSFS_ui64FitsAddressSpace(len)) BAIL_MACRO(PHYSFS_ERR_INVALID_ARGUMENT, -1); while (len > 0) { const DWORD thislen = (len > 0xFFFFFFFF) ? 0xFFFFFFFF : (DWORD)len; DWORD numWritten = 0; if (!WriteFile(Handle, buffer, thislen, &numWritten, NULL)) BAIL_MACRO(errcodeFromWinApi(), -1); len -= (PHYSFS_uint64)numWritten; totalWritten += (PHYSFS_sint64)numWritten; if (numWritten != thislen) break; } /* while */ return totalWritten; } /* __PHYSFS_platformWrite */
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque) { HANDLE Handle = ((WinApiFile *) opaque)->handle; LONG HighPos = 0; DWORD LowPos; PHYSFS_sint64 retval; /* Get current position */ LowPos = SetFilePointer(Handle, 0, &HighPos, FILE_CURRENT); if ( (LowPos == PHYSFS_INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) { BAIL_MACRO(errcodeFromWinApi(), -1); } /* 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 */