📄 win32.c
字号:
strcpy(retval + 3, path + 2); } /* else */ } /* else */ } /* if */ else /* no drive letter specified. */ { if (path[0] == '\\') /* absolute path. */ { retval[0] = currentDir[0]; retval[1] = ':'; strcpy(retval + 2, path); } /* if */ else { strcpy(retval, currentDir); strcat(retval, path); } /* else */ } /* else */ free(currentDir); } /* else */ /* (whew.) Ok, now take out "." and ".." path entries... */ p = retval; while ( (p = strstr(p, "\\.")) != NULL) { /* it's a "." entry that doesn't end the string. */ if (p[2] == '\\') memmove(p + 1, p + 3, strlen(p + 3) + 1); /* it's a "." entry that ends the string. */ else if (p[2] == '\0') p[0] = '\0'; /* it's a ".." entry. */ else if (p[2] == '.') { char *prevEntry = p - 1; while ((prevEntry != retval) && (*prevEntry != '\\')) prevEntry--; if (prevEntry == retval) /* make it look like a "." entry. */ memmove(p + 1, p + 2, strlen(p + 2) + 1); else { if (p[3] != '\0') /* doesn't end string. */ *prevEntry = '\0'; else /* ends string. */ memmove(prevEntry + 1, p + 4, strlen(p + 4) + 1); p = prevEntry; } /* else */ } /* else if */ else { p++; /* look past current char. */ } /* else */ } /* while */ /* shrink the retval's memory block if possible... */ p = (char *) realloc(retval, strlen(retval) + 1); if (p != NULL) retval = p; return(retval);} /* __PHYSFS_platformRealPath */int __PHYSFS_platformMkDir(const char *path){ DWORD rc = CreateDirectory(path, NULL); BAIL_IF_MACRO(rc == 0, win32strerror(), 0); return(1);} /* __PHYSFS_platformMkDir *//* * 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 *//* * Some things we want/need are in external DLLs that may or may not be * available, based on the operating system, etc. This function loads those * libraries and hunts down the needed pointers. * * Libraries that are one-shot deals, or better loaded as needed, are loaded * elsewhere (see determineUserDir()). * * Returns zero if a needed library couldn't load, non-zero if we have enough * to go on (which means some useful but non-crucial libraries may _NOT_ be * loaded; check the related module-scope variables). */static int loadLibraries(void){ /* If this get unwieldy, make it table driven. */ int allNeededLibrariesLoaded = 1; /* flip to zero as needed. */ libKernel32 = LoadLibrary("kernel32.dll"); if (libKernel32) { pGetFileAttributesEx = (LPFNGETFILEATTRIBUTESEX) GetProcAddress(libKernel32, "GetFileAttributesExA"); } /* if */ /* add other DLLs here... */ /* see if there's any reason to keep kernel32.dll around... */ if (libKernel32) { if ((pGetFileAttributesEx == NULL) /* && (somethingElse == NULL) */ ) { FreeLibrary(libKernel32); libKernel32 = NULL; } /* if */ } /* if */ return(allNeededLibrariesLoaded);} /* loadLibraries */int __PHYSFS_platformInit(void){ BAIL_IF_MACRO(!getOSInfo(), NULL, 0); BAIL_IF_MACRO(!loadLibraries(), NULL, 0); BAIL_IF_MACRO(!determineUserDir(), NULL, 0); return(1); /* It's all good */} /* __PHYSFS_platformInit */int __PHYSFS_platformDeinit(void){ if (userDir != NULL) { free(userDir); userDir = NULL; } /* if */ if (libKernel32) { FreeLibrary(libKernel32); libKernel32 = NULL; } /* if */ return(1); /* It's all good */} /* __PHYSFS_platformDeinit */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 */void *__PHYSFS_platformOpenRead(const char *filename){ return(doOpen(filename, GENERIC_READ, OPEN_EXISTING, 1));} /* __PHYSFS_platformOpenRead */void *__PHYSFS_platformOpenWrite(const char *filename){ return(doOpen(filename, GENERIC_WRITE, CREATE_ALWAYS, 0));} /* __PHYSFS_platformOpenWrite */void *__PHYSFS_platformOpenAppend(const char *filename){ void *retval = doOpen(filename, GENERIC_WRITE, OPEN_ALWAYS, 0); if (retval != NULL) { HANDLE h = ((win32file *) retval)->handle; if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) { const char *err = win32strerror(); CloseHandle(h); free(retval); BAIL_MACRO(err, NULL); } /* if */ } /* if */ return(retval);} /* __PHYSFS_platformOpenAppend */PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer, PHYSFS_uint32 size, PHYSFS_uint32 count){ HANDLE FileHandle = ((win32file *) opaque)->handle; DWORD CountOfBytesRead; PHYSFS_sint64 retval; /* Read data from the file */ /* !!! FIXME: uint32 might be a greater # than DWORD */ if(!ReadFile(FileHandle, 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_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 */int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos){ HANDLE FileHandle = ((win32file *) opaque)->handle; DWORD HighOrderPos; DWORD rc; /* Get the high order 32-bits of the position */ HighOrderPos = HIGHORDER_UINT64(pos); /* !!! FIXME: SetFilePointer needs a signed 64-bit value. */ /* Move pointer "pos" count from start of file */ rc = SetFilePointer(FileHandle, LOWORDER_UINT64(pos), &HighOrderPos, FILE_BEGIN); if ((rc == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR)) BAIL_MACRO(win32strerror(), 0); return(1); /* No error occured */} /* __PHYSFS_platformSeek */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 == 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 */PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque){ HANDLE FileHandle = ((win32file *) opaque)->handle; DWORD SizeHigh; DWORD SizeLow; PHYSFS_sint64 retval; SizeLow = GetFileSize(FileHandle, &SizeHigh); if ((SizeLow == 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 */int __PHYSFS_platformEOF(void *opaque){ PHYSFS_sint64 FilePosition; int retval = 0; /* Get the current position in the file */ if ((FilePosition = __PHYSFS_platformTell(opaque)) != 0) { /* Non-zero if EOF is equal to the file length */ retval = FilePosition == __PHYSFS_platformFileLength(opaque); } /* if */ return(retval);} /* __PHYSFS_platformEOF */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_platformClose(void *opaque){ HANDLE FileHandle = ((win32file *) opaque)->handle; BAIL_IF_MACRO(!CloseHandle(FileHandle), win32strerror(), 0); free(opaque); return(1);} /* __PHYSFS_platformClose */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 */void *__PHYSFS_platformCreateMutex(void){ return((void *) CreateMutex(NULL, FALSE, NULL));} /* __PHYSFS_platformCreateMutex */void __PHYSFS_platformDestroyMutex(void *mutex){ CloseHandle((HANDLE) mutex);} /* __PHYSFS_platformDestroyMutex */int __PHYSFS_platformGrabMutex(void *mutex){ return(WaitForSingleObject((HANDLE) mutex, INFINITE) != WAIT_FAILED);} /* __PHYSFS_platformGrabMutex */void __PHYSFS_platformReleaseMutex(void *mutex){ ReleaseMutex((HANDLE) mutex);} /* __PHYSFS_platformReleaseMutex */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 */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 */#endif/* end of win32.c ... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -