Index: src/OFSystemInfo.h ================================================================== --- src/OFSystemInfo.h +++ src/OFSystemInfo.h @@ -35,10 +35,13 @@ @property (class, readonly, nonatomic) unsigned short ObjFWVersionMajor; @property (class, readonly, nonatomic) unsigned short ObjFWVersionMinor; @property (class, readonly, nullable, nonatomic) OFString *operatingSystemName; @property (class, readonly, nullable, nonatomic) OFString *operatingSystemVersion; +#if defined(OF_WINDOWS) || defined(DOXYGEN) +@property (class, readonly, nullable, nonatomic) OFString *wineVersion; +#endif @property (class, readonly, nullable, nonatomic) OFIRI *userDataIRI; @property (class, readonly, nullable, nonatomic) OFIRI *userConfigIRI; @property (class, readonly, nullable, nonatomic) OFIRI *temporaryDirectoryIRI; @property (class, readonly, nullable, nonatomic) OFString *CPUVendor; @property (class, readonly, nullable, nonatomic) OFString *CPUModel; @@ -144,10 +147,23 @@ * running on. * * @return The version of the operating system the application is running on */ + (nullable OFString *)operatingSystemVersion; + +#if defined(OF_WINDOWS) || defined(DOXYGEN) +/** + * @brief Returns the version of Wine the application is running on, or `nil` + * if not running on Wine (e.g. on Windows natively). + * + * @note This is only available on Windows. + * + * @return The version of Wine the application is running on, or `nil` if not + * running on Wine (e.g. on Windows natively) + */ ++ (nullable OFString *)wineVersion; +#endif /** * @brief Returns the path where user data for the application can be stored. * * On UNIX systems, this adheres to the XDG Base Directory specification.@n Index: src/OFSystemInfo.m ================================================================== --- src/OFSystemInfo.m +++ src/OFSystemInfo.m @@ -156,10 +156,14 @@ static size_t pageSize = 4096; static size_t numberOfCPUs = 1; static OFString *operatingSystemName = nil; static OFString *operatingSystemVersion = nil; + +#ifdef OF_WINDOWS +static const char *(*wine_get_version)(void); +#endif static void initOperatingSystemName(void) { #if defined(OF_IOS) @@ -389,14 +393,20 @@ */ SSETest(); #endif #if defined(OF_WINDOWS) + HANDLE module; + SYSTEM_INFO si; GetSystemInfo(&si); pageSize = si.dwPageSize; numberOfCPUs = si.dwNumberOfProcessors; + + if ((module = GetModuleHandle("ntdll.dll")) != NULL) + wine_get_version = (const char *(*)(void)) + GetProcAddress(module, "wine_get_version"); #elif defined(OF_QNX) if ((tmp = sysconf(_SC_PAGESIZE)) > 0) pageSize = tmp; numberOfCPUs = _syspage_ptr->num_cpu; #else @@ -456,10 +466,21 @@ static OFOnceControl onceControl = OFOnceControlInitValue; OFOnce(&onceControl, initOperatingSystemVersion); return operatingSystemVersion; } + +#ifdef OF_WINDOWS ++ (OFString *)wineVersion +{ + if (wine_get_version != NULL) + return [OFString stringWithCString: wine_get_version() + encoding: [OFLocale encoding]]; + + return nil; +} +#endif + (OFIRI *)userDataIRI { #ifdef OF_HAVE_FILES # if defined(OF_MACOS) || defined(OF_IOS) Index: tests/OFSystemInfoTests.m ================================================================== --- tests/OFSystemInfoTests.m +++ tests/OFSystemInfoTests.m @@ -63,10 +63,13 @@ ADD(@"ObjFW version", [OFSystemInfo ObjFWVersion]) ADD_UINT(@"ObjFW version major", [OFSystemInfo ObjFWVersionMajor]) ADD_UINT(@"ObjFW version minor", [OFSystemInfo ObjFWVersionMinor]) ADD(@"Operating system name", [OFSystemInfo operatingSystemName]); ADD(@"Operating system version", [OFSystemInfo operatingSystemVersion]); +#ifdef OF_WINDOWS + ADD(@"Wine version", [OFSystemInfo wineVersion]); +#endif ADD_ULONGLONG(@"Page size", [OFSystemInfo pageSize]); ADD_ULONGLONG(@"Number of CPUs", [OFSystemInfo numberOfCPUs]); ADD(@"User config IRI", [OFSystemInfo userConfigIRI].string); ADD(@"User data IRI", [OFSystemInfo userDataIRI].string); ADD(@"Temporary directory IRI",