diff --git a/source/lib/debug.cpp b/source/lib/debug.cpp index cbe6266bbc..58cc1aad53 100644 --- a/source/lib/debug.cpp +++ b/source/lib/debug.cpp @@ -22,7 +22,6 @@ #include "lib/posix/posix_pthread.h" #include "lib/sysdep/cpu.h" // CAS #include "lib/sysdep/sysdep.h" -#include "lib/res/file/file.h" // FILE_ACCESS // some functions here are called from within mmgr; disable its hooks // so that our allocations don't cause infinite recursion. #ifdef REDEFINED_NEW @@ -237,7 +236,7 @@ LibError debug_write_crashlog(const wchar_t* text) if(!f) { in_progress = 0; - WARN_RETURN(ERR::FILE_ACCESS); + WARN_RETURN(ERR::FAIL); } fputwc(0xfeff, f); // BOM diff --git a/source/lib/sysdep/acpi.cpp b/source/lib/sysdep/acpi.cpp index 85ca3dec99..0c29544088 100644 --- a/source/lib/sysdep/acpi.cpp +++ b/source/lib/sysdep/acpi.cpp @@ -28,32 +28,27 @@ static u8 ComputeChecksum(const void* buf, size_t numBytes) // free() the returned pointer. static const AcpiTable* AllocateCopyOfTable(u64 physicalAddress) { - // ACPI table sizes are not known until they've been mapped and copied. - // since that is slow, we don't want to do it twice; solution is to copy - // into a buffer big enough to hold a typical table. if it should be too - // small, we map and copy again. using a temporary buffer, rather than - // allocating that much up-front, avoids wasting memory for each table. - static const size_t tempTableSize = 4*KiB; - static u8 tempTableBuf[tempTableSize]; - const AcpiTable* tempTable = (const AcpiTable*)tempTableBuf; - if(!mahaf_CopyPhysicalMemory(physicalAddress, tempTableSize, (void*)tempTable)) + // ACPI table sizes are not known until they've been mapped. since that + // is slow, we don't want to do it twice; solution is map enough to + // hold a typical table. if it should be too small, we do so again. + static const size_t initialSize = 4*KiB; + const volatile AcpiTable* mappedTable = (const volatile AcpiTable*)mahaf_MapPhysicalMemory(physicalAddress, initialSize); + if(!mappedTable) return 0; - - // allocate the final table - const size_t size = tempTable->size; - const AcpiTable* table = (const AcpiTable*)malloc(size); - if(!table) - return 0; - - // and fill it. - if(size <= tempTableSize) - cpu_memcpy((void*)table, tempTable, size); - else + const size_t size = mappedTable->size; + if(initialSize < size) { - if(!mahaf_CopyPhysicalMemory(physicalAddress, size, (void*)table)) + mappedTable = (const volatile AcpiTable*)mahaf_MapPhysicalMemory(physicalAddress, size); + if(!mappedTable) return 0; } + const AcpiTable* table = (const AcpiTable*)malloc(size); + if(table) + cpu_memcpy((void*)table, (const void*)mappedTable, size); + + mahaf_UnmapPhysicalMemory((volatile void*)mappedTable); + return table; } @@ -128,31 +123,37 @@ static const RSDP* LocateRsdp(const u8* buf, size_t numBytes) static bool LocateAndRetrieveRsdp(uintptr_t physicalAddress, size_t numBytes, RSDP& rsdp) { - void* virtualAddress = mahaf_MapPhysicalMemory(physicalAddress, numBytes); + const volatile u8* buffer = (const volatile u8*)mahaf_MapPhysicalMemory(physicalAddress, numBytes); + if(!buffer) + return false; - const RSDP* prsdp = LocateRsdp((const u8*)virtualAddress, numBytes); + const RSDP* prsdp = LocateRsdp((const u8*)buffer, numBytes); if(prsdp) rsdp = *prsdp; // stash in output parameter before unmapping - mahaf_UnmapPhysicalMemory(virtualAddress); + mahaf_UnmapPhysicalMemory((volatile void*)buffer); return (prsdp != 0); } - static uintptr_t LocateEbdaPhysicalAddress() { +#pragma pack(push, 1) struct BiosDataArea { u16 serialBase[4]; u16 parallelBase[3]; u16 ebdaSegment; - // ... }; - const BiosDataArea* bda = (const BiosDataArea*)mahaf_MapPhysicalMemory(0x400, 0x100); +#pragma pack(pop) + const volatile BiosDataArea* bda = (const volatile BiosDataArea*)mahaf_MapPhysicalMemory(0x400, 0x100); if(!bda) + { + debug_assert(0); return 0; - const uintptr_t ebdaPhysicalAddress = ((uintptr_t)bda->ebdaSegment) * 16; + } + const uintptr_t ebdaPhysicalAddress = ((uintptr_t)bda->ebdaSegment) * 16; + mahaf_UnmapPhysicalMemory((void*)bda); return ebdaPhysicalAddress; } @@ -161,7 +162,9 @@ static bool RetrieveRsdp(RSDP& rsdp) { // See ACPIspec30b, section 5.2.5.1: // RSDP is either in the first KIB of the extended BIOS data area, - if(LocateAndRetrieveRsdp(LocateEbdaPhysicalAddress(), 1*KiB, rsdp)) + const uintptr_t ebdaPhysicalAddress = LocateEbdaPhysicalAddress(); + debug_assert(ebdaPhysicalAddress != 0); + if(LocateAndRetrieveRsdp(ebdaPhysicalAddress, 1*KiB, rsdp)) return true; // or in read-only BIOS memory. diff --git a/source/lib/sysdep/win/aken/aken.cpp b/source/lib/sysdep/win/aken/aken.cpp index 892b7efb22..9b455fe500 100644 --- a/source/lib/sysdep/win/aken/aken.cpp +++ b/source/lib/sysdep/win/aken/aken.cpp @@ -13,8 +13,48 @@ extern "C" { // must come before ntddk.h // memory mapping //----------------------------------------------------------------------------- -// references: DDK mapmem.c sample, -// http://support.microsoft.com/kb/189327/en-us +/* + +there are three approaches to mapping physical memory: +(http://www.microsoft.com/whdc/driver/kernel/mem-mgmt.mspx) + +- MmMapIoSpace (http://support.microsoft.com/kb/189327/en-us). despite the + name, it maps physical pages of any kind by allocating PTEs. very easy to + implement, but occupies precious kernel address space. possible bugs: + http://www.osronline.com/showThread.cfm?link=96737 + http://support.microsoft.com/kb/925793/en-us + +- ZwMapViewOfSection of PhysicalMemory (http://tinyurl.com/yozmgy). + a bit bulky, but the WinXP implementation prevents mapping pages with + conflicting attributes (see below). + +- MmMapLockedPagesSpecifyCache or MmGetSystemAddressForMdlSafe + (http://www.osronline.com/article.cfm?id=423). note: the latter is a macro + that calls the former. this is the 'normal' and fully documented way, + but it doesn't appear able to map a fixed physical address. + (MmAllocatePagesForMdl understandably doesn't work since some pages we + want to map are marked as unavailable for allocation, and I don't see + another documented way to fill an MDL with PFNs.) + +our choice here is forced by a very insidious issue. if someone else has +already mapped a page with different attributes (e.g. cacheable), TLBs +may end up corrupted, leading to disaster. the search for a documented +means of accessing the page frame database (to check if mapped anywhere +and determine the previously set attributes) has not borne fruit, so we +must use ZwMapViewOfSection. + +*/ + + +static bool IsMemoryUncacheable(DWORD64 physicalAddress64) +{ + // original PC memory - contains BIOS + if(physicalAddress64 < 0x100000) + return true; + + return false; +} + static NTSTATUS AkenMapPhysicalMemory(const DWORD64 physicalAddress64, const DWORD64 numBytes64, DWORD64& virtualAddress64) { NTSTATUS ntStatus; @@ -51,8 +91,11 @@ static NTSTATUS AkenMapPhysicalMemory(const DWORD64 physicalAddress64, const DWO } } - // map desired memory into user PTEs (note: don't use MmMapIoSpace - // because that occupies precious non-paged pool) + // note: mapmem.c does HalTranslateBusAddress, but we only care about + // system memory. translating doesn't appear to be necessary, even if + // much existing code uses it (probably due to cargo cult). + + // map desired memory into user PTEs { const HANDLE hProcess = (HANDLE)-1; PVOID virtualBaseAddress = 0; // let ZwMapViewOfSection pick @@ -61,7 +104,9 @@ static NTSTATUS AkenMapPhysicalMemory(const DWORD64 physicalAddress64, const DWO LARGE_INTEGER physicalBaseAddress = physicalAddress; // will be rounded down to 64KB boundary const SECTION_INHERIT inheritDisposition = ViewShare; const ULONG allocationType = 0; - const ULONG protect = PAGE_READWRITE|PAGE_NOCACHE; + ULONG protect = PAGE_READWRITE; + if(IsMemoryUncacheable(physicalAddress64)) + protect |= PAGE_NOCACHE; ntStatus = ZwMapViewOfSection(hMemory, hProcess, &virtualBaseAddress, zeroBits, mappedSize, &physicalBaseAddress, &mappedSize, inheritDisposition, allocationType, protect); if(!NT_SUCCESS(ntStatus)) { @@ -173,6 +218,7 @@ static NTSTATUS AkenIoctlMap(PVOID buf, const ULONG inSize, ULONG& outSize) const AkenMapIn* in = (const AkenMapIn*)buf; const DWORD64 physicalAddress = in->physicalAddress; const DWORD64 numBytes = in->numBytes; + DWORD64 virtualAddress; NTSTATUS ntStatus = AkenMapPhysicalMemory(physicalAddress, numBytes, virtualAddress); @@ -193,29 +239,6 @@ static NTSTATUS AkenIoctlUnmap(PVOID buf, const ULONG inSize, ULONG& outSize) return ntStatus; } -static NTSTATUS AkenIoctlCopyPhysical(PVOID buf, const ULONG inSize, ULONG& outSize) -{ - if(inSize != sizeof(AkenCopyPhysicalIn) || outSize != 0) - return STATUS_BUFFER_TOO_SMALL; - - const AkenCopyPhysicalIn* in = (const AkenCopyPhysicalIn*)buf; - PHYSICAL_ADDRESS physicalAddress; - physicalAddress.QuadPart = in->physicalAddress; - const ULONG numBytes = (ULONG)in->numBytes; - void* userBuffer = (void*)(UINT_PTR)in->userAddress; - - PVOID kernelBuffer = MmMapIoSpace(physicalAddress, numBytes, MmNonCached); - if(!kernelBuffer) - return STATUS_NO_MEMORY; - - // (this works because we're called in the user's context) - RtlCopyMemory(userBuffer, kernelBuffer, numBytes); - - MmUnmapIoSpace(kernelBuffer, numBytes); - - return STATUS_SUCCESS; -} - static NTSTATUS AkenIoctlUnknown(PVOID buf, const ULONG inSize, ULONG& outSize) { KdPrint(("AkenIoctlUnknown\n")); @@ -242,9 +265,6 @@ static inline AkenIoctl AkenIoctlFromCode(ULONG ioctlCode) case IOCTL_AKEN_UNMAP: return AkenIoctlUnmap; - case IOCTL_AKEN_COPY_PHYSICAL: - return AkenIoctlCopyPhysical; - default: return AkenIoctlUnknown; } diff --git a/source/lib/sysdep/win/aken/aken.h b/source/lib/sysdep/win/aken/aken.h index c8da5fe811..a02dbcb440 100644 --- a/source/lib/sysdep/win/aken/aken.h +++ b/source/lib/sysdep/win/aken/aken.h @@ -25,7 +25,6 @@ #define IOCTL_AKEN_WRITE_PORT CTL_CODE(FILE_DEVICE_AKEN, AKEN_IOCTL+1, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AKEN_MAP CTL_CODE(FILE_DEVICE_AKEN, AKEN_IOCTL+2, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AKEN_UNMAP CTL_CODE(FILE_DEVICE_AKEN, AKEN_IOCTL+3, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_AKEN_COPY_PHYSICAL CTL_CODE(FILE_DEVICE_AKEN, AKEN_IOCTL+4, METHOD_BUFFERED, FILE_ANY_ACCESS) // input and output data structures for the IOCTLs @@ -68,13 +67,6 @@ struct AkenUnmapIn DWORD64 virtualAddress; }; -struct AkenCopyPhysicalIn -{ - DWORD64 physicalAddress; - DWORD64 numBytes; - DWORD64 userAddress; -}; - #pragma pack(pop) #endif // #ifndef INCLUDED_AKEN diff --git a/source/lib/sysdep/win/mahaf.cpp b/source/lib/sysdep/win/mahaf.cpp index 8d26651288..49bfba4243 100644 --- a/source/lib/sysdep/win/mahaf.cpp +++ b/source/lib/sysdep/win/mahaf.cpp @@ -94,8 +94,14 @@ void mahaf_WritePort32(u16 port, u32 value) } -void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes) +volatile void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes) { + // WinXP introduced checks that ensure we don't re-map pages with + // incompatible attributes. without this, mapping physical pages risks + // disaster due to TLB corruption, so disable it for safety. + if(wutil_WindowsVersion() < WUTIL_VERSION_XP) + return 0; + AkenMapIn in; in.physicalAddress = (DWORD64)physicalAddress; in.numBytes = (DWORD64)numBytes; @@ -111,12 +117,12 @@ void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes) } debug_assert(bytesReturned == sizeof(out)); - void* virtualAddress = (void*)out.virtualAddress; + volatile void* virtualAddress = (volatile void*)out.virtualAddress; return virtualAddress; } -void mahaf_UnmapPhysicalMemory(void* virtualAddress) +void mahaf_UnmapPhysicalMemory(volatile void* virtualAddress) { AkenUnmapIn in; in.virtualAddress = (DWORD64)virtualAddress; @@ -128,26 +134,6 @@ void mahaf_UnmapPhysicalMemory(void* virtualAddress) } -bool mahaf_CopyPhysicalMemory(uintptr_t physicalAddress, size_t numBytes, void* buffer) -{ - AkenCopyPhysicalIn in; - in.physicalAddress = (DWORD64)physicalAddress; - in.numBytes = (DWORD64)numBytes; - in.userAddress = (DWORD64)buffer; - - DWORD bytesReturned; - LPOVERLAPPED ovl = 0; // synchronous - BOOL ok = DeviceIoControl(hAken, (DWORD)IOCTL_AKEN_COPY_PHYSICAL, &in, sizeof(in), 0, 0, &bytesReturned, ovl); - if(!ok) - { - WARN_WIN32_ERR; - return false; - } - - return true; -} - - //----------------------------------------------------------------------------- // driver installation //----------------------------------------------------------------------------- diff --git a/source/lib/sysdep/win/mahaf.h b/source/lib/sysdep/win/mahaf.h index 57e6f4185b..3acdae0c7c 100644 --- a/source/lib/sysdep/win/mahaf.h +++ b/source/lib/sysdep/win/mahaf.h @@ -24,12 +24,7 @@ extern void mahaf_WritePort8 (u16 port, u8 value); extern void mahaf_WritePort16(u16 port, u16 value); extern void mahaf_WritePort32(u16 port, u32 value); -extern void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes); -extern void mahaf_UnmapPhysicalMemory(void* virtualAddress); - -/** - * @return false on failure (insufficient paged pool?) - **/ -extern bool mahaf_CopyPhysicalMemory(uintptr_t physicalAddress, size_t numBytes, void* buffer); +extern volatile void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes); +extern void mahaf_UnmapPhysicalMemory(volatile void* virtualAddress); #endif // INCLUDED_MAHAF diff --git a/source/lib/sysdep/win/whrt/counter.h b/source/lib/sysdep/win/whrt/counter.h index 7adb418ec1..3c8058251f 100644 --- a/source/lib/sysdep/win/whrt/counter.h +++ b/source/lib/sysdep/win/whrt/counter.h @@ -46,7 +46,7 @@ public: /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ virtual double NominalFrequency() const = 0; diff --git a/source/lib/sysdep/win/whrt/hpet.cpp b/source/lib/sysdep/win/whrt/hpet.cpp index c851945478..6825b99550 100644 --- a/source/lib/sysdep/win/whrt/hpet.cpp +++ b/source/lib/sysdep/win/whrt/hpet.cpp @@ -111,7 +111,7 @@ uint CounterHPET::CounterBits() const /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ double CounterHPET::NominalFrequency() const { diff --git a/source/lib/sysdep/win/whrt/hpet.h b/source/lib/sysdep/win/whrt/hpet.h index cfea652ff3..11ea719754 100644 --- a/source/lib/sysdep/win/whrt/hpet.h +++ b/source/lib/sysdep/win/whrt/hpet.h @@ -42,7 +42,7 @@ public: /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ virtual double NominalFrequency() const; diff --git a/source/lib/sysdep/win/whrt/pmt.cpp b/source/lib/sysdep/win/whrt/pmt.cpp index 5164521b85..3d279b0741 100644 --- a/source/lib/sysdep/win/whrt/pmt.cpp +++ b/source/lib/sysdep/win/whrt/pmt.cpp @@ -83,7 +83,7 @@ uint CounterPMT::CounterBits() const /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ double CounterPMT::NominalFrequency() const { diff --git a/source/lib/sysdep/win/whrt/pmt.h b/source/lib/sysdep/win/whrt/pmt.h index 4dc7b7b48d..2309e80631 100644 --- a/source/lib/sysdep/win/whrt/pmt.h +++ b/source/lib/sysdep/win/whrt/pmt.h @@ -43,7 +43,7 @@ public: /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ virtual double NominalFrequency() const; diff --git a/source/lib/sysdep/win/whrt/qpc.cpp b/source/lib/sysdep/win/whrt/qpc.cpp index d5330d32f0..0affa3b4eb 100644 --- a/source/lib/sysdep/win/whrt/qpc.cpp +++ b/source/lib/sysdep/win/whrt/qpc.cpp @@ -110,7 +110,7 @@ uint CounterQPC::CounterBits() const /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ double CounterQPC::NominalFrequency() const { diff --git a/source/lib/sysdep/win/whrt/qpc.h b/source/lib/sysdep/win/whrt/qpc.h index 3221b86a6d..1e359c7f5f 100644 --- a/source/lib/sysdep/win/whrt/qpc.h +++ b/source/lib/sysdep/win/whrt/qpc.h @@ -41,7 +41,7 @@ public: /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ virtual double NominalFrequency() const; diff --git a/source/lib/sysdep/win/whrt/tgt.cpp b/source/lib/sysdep/win/whrt/tgt.cpp index b3b2aaee72..7fb33901b4 100644 --- a/source/lib/sysdep/win/whrt/tgt.cpp +++ b/source/lib/sysdep/win/whrt/tgt.cpp @@ -69,7 +69,7 @@ uint CounterTGT::CounterBits() const /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ double CounterTGT::NominalFrequency() const { diff --git a/source/lib/sysdep/win/whrt/tgt.h b/source/lib/sysdep/win/whrt/tgt.h index 14845ef4c6..3b972ab42b 100644 --- a/source/lib/sysdep/win/whrt/tgt.h +++ b/source/lib/sysdep/win/whrt/tgt.h @@ -36,7 +36,7 @@ public: /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ virtual double NominalFrequency() const; diff --git a/source/lib/sysdep/win/whrt/tsc.cpp b/source/lib/sysdep/win/whrt/tsc.cpp index 7a0a7adca1..c62bfcaea8 100644 --- a/source/lib/sysdep/win/whrt/tsc.cpp +++ b/source/lib/sysdep/win/whrt/tsc.cpp @@ -147,9 +147,9 @@ uint CounterTSC::CounterBits() const /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ double CounterTSC::NominalFrequency() const { - return cpu_ClockFrequency(); + return wcpu_ClockFrequency(); } diff --git a/source/lib/sysdep/win/whrt/tsc.h b/source/lib/sysdep/win/whrt/tsc.h index bbbdf4673c..a7e54ef119 100644 --- a/source/lib/sysdep/win/whrt/tsc.h +++ b/source/lib/sysdep/win/whrt/tsc.h @@ -36,7 +36,7 @@ public: /** * initial measurement of the tick rate. not necessarily correct - * (e.g. when using TSC: cpu_ClockFrequency isn't exact). + * (e.g. when using TSC: wcpu_ClockFrequency isn't exact). **/ virtual double NominalFrequency() const; }; diff --git a/source/lib/sysdep/win/whrt/whrt.cpp b/source/lib/sysdep/win/whrt/whrt.cpp index 6987b8969c..5b1239d12e 100644 --- a/source/lib/sysdep/win/whrt/whrt.cpp +++ b/source/lib/sysdep/win/whrt/whrt.cpp @@ -283,6 +283,9 @@ static LibError whrt_Init() InitCounter(); + // latch initial counter value so that timer starts at 0 + ts->counter = Counter(); // must come before UpdateTimerState + UpdateTimerState(); // must come before InitUpdateThread to avoid race RETURN_ERR(InitUpdateThread()); diff --git a/source/lib/sysdep/win/wsnd.cpp b/source/lib/sysdep/win/wsnd.cpp index bbc674d873..6a58c7f166 100644 --- a/source/lib/sysdep/win/wsnd.cpp +++ b/source/lib/sysdep/win/wsnd.cpp @@ -141,7 +141,7 @@ LibError win_get_snd_info() // find all DLLs related to OpenAL, retrieve their versions, // and store in snd_drv_ver string. wdll_ver_list_init(snd_drv_ver, SND_DRV_VER_LEN); - if(!wutil_IsVista()) + if(wutil_WindowsVersion() < WUTIL_VERSION_VISTA) (void)wdll_ver_list_add(GetDirectSoundDriverPath()); StringSet dlls; // ensures uniqueness (void)add_oal_dlls_in_dir(win_exe_dir, &dlls); diff --git a/source/lib/sysdep/win/wutil.cpp b/source/lib/sysdep/win/wutil.cpp index b3caac9066..88923b67fe 100644 --- a/source/lib/sysdep/win/wutil.cpp +++ b/source/lib/sysdep/win/wutil.cpp @@ -228,7 +228,8 @@ static void EnableLowFragmentationHeap() //----------------------------------------------------------------------------- // version -static char versionString[20]; +static char windowsVersionString[20]; +static uint windowsVersion; // see WUTIL_VERSION_* static void DetectWindowsVersion() { @@ -237,8 +238,14 @@ static void DetectWindowsVersion() HKEY hKey; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { - DWORD size = ARRAY_SIZE(versionString); - (void)RegQueryValueEx(hKey, "CurrentVersion", 0, 0, (LPBYTE)versionString, &size); + DWORD size = ARRAY_SIZE(windowsVersionString); + (void)RegQueryValueEx(hKey, "CurrentVersion", 0, 0, (LPBYTE)windowsVersionString, &size); + + uint major = 0, minor = 0; + int ret = sscanf(windowsVersionString, "%d.%d", &major, &minor); + debug_assert(ret == 2); + debug_assert(major <= 0xFF && minor <= 0xFF); + windowsVersion = (major << 8) | minor; RegCloseKey(hKey); } @@ -248,16 +255,17 @@ static void DetectWindowsVersion() const char* wutil_WindowsVersionString() { - debug_assert(versionString[0] != '\0'); - return versionString; + debug_assert(windowsVersionString[0] != '\0'); + return windowsVersionString; } -bool wutil_IsVista() +uint wutil_WindowsVersion() { - debug_assert(versionString[0] != '\0'); - return (versionString[0] >= '6'); + debug_assert(windowsVersion != 0); + return windowsVersion; } + //----------------------------------------------------------------------------- // Wow64 diff --git a/source/lib/sysdep/win/wutil.h b/source/lib/sysdep/win/wutil.h index e3d12a1d4f..33e53571b1 100644 --- a/source/lib/sysdep/win/wutil.h +++ b/source/lib/sysdep/win/wutil.h @@ -99,7 +99,12 @@ extern char win_exe_dir[MAX_PATH+1]; // extern const char* wutil_WindowsVersionString(); -extern bool wutil_IsVista(); + +// (same format as WINVER) +const uint WUTIL_VERSION_XP = 0x0501; +const uint WUTIL_VERSION_VISTA = 0x0600; + +extern uint wutil_WindowsVersion(); // diff --git a/source/lib/timer.cpp b/source/lib/timer.cpp index 93a26b48b6..60a0250110 100644 --- a/source/lib/timer.cpp +++ b/source/lib/timer.cpp @@ -52,7 +52,9 @@ double get_time() { double t; -#if HAVE_CLOCK_GETTIME +#if OS_WIN + t = whrt_Time(); +#elif HAVE_CLOCK_GETTIME struct timespec cur; (void)clock_gettime(CLOCK_REALTIME, &cur); t = (cur.tv_sec - start.tv_sec) + (cur.tv_nsec - start.tv_nsec)*1e-9; @@ -60,8 +62,6 @@ double get_time() struct timeval cur; gettimeofday(&cur, 0); t = (cur.tv_sec - start.tv_sec) + (cur.tv_usec - start.tv_usec)*1e-6; -#elif OS_WIN - t = whrt_Time(); #else # error "get_time: add timer implementation for this platform!" #endif diff --git a/source/tools/atlas/GameInterface/View.h b/source/tools/atlas/GameInterface/View.h index 8e0c4d68ce..5192db2516 100644 --- a/source/tools/atlas/GameInterface/View.h +++ b/source/tools/atlas/GameInterface/View.h @@ -43,7 +43,7 @@ private: CCamera dummyCamera; }; -struct SimState; +class SimState; class ViewGame : public View {