| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717 |
- /************************************************************************************
- Filename : Util_SystemInfo.cpp
- Content : Various operations to get information about the system
- Created : September 26, 2014
- Author : Kevin Jenkins
- Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
- Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
- you may not use the Oculus VR Rift SDK except in compliance with the License,
- which is provided at the time of installation or download, or which
- otherwise accompanies this software in either electronic or hard copy form.
- You may obtain a copy of the License at
- http://www.oculusvr.com/licenses/LICENSE-3.2
- Unless required by applicable law or agreed to in writing, the Oculus VR SDK
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ************************************************************************************/
- #include "Util_SystemInfo.h"
- #include "Kernel/OVR_Timer.h"
- #include "Kernel/OVR_Threads.h"
- #include "Kernel/OVR_Log.h"
- #include "Kernel/OVR_Array.h"
- #if defined(OVR_OS_LINUX)
- #include <sys/utsname.h>
- #endif
- // Includes used for GetBaseOVRPath()
- #ifdef OVR_OS_WIN32
- #include "Kernel/OVR_Win32_IncludeWindows.h"
- #include <Shlobj.h>
- #include <Shlwapi.h>
- #pragma comment(lib, "Shlwapi")
- #elif defined(OVR_OS_MS) // Other Microsoft OSs
- // Nothing, thanks.
- #else
- #include <dirent.h>
- #include <sys/stat.h>
- #ifdef OVR_OS_LINUX
- #include <unistd.h>
- #include <pwd.h>
- #endif
- #endif
- namespace OVR { namespace Util {
- // From http://blogs.msdn.com/b/oldnewthing/archive/2005/02/01/364563.aspx
- #if defined (OVR_OS_WIN64) || defined (OVR_OS_WIN32)
- #pragma comment(lib, "version.lib")
- typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
- bool Is64BitWindows()
- {
- #if defined(_WIN64)
- return TRUE; // 64-bit programs run only on Win64
- #elif defined(_WIN32)
- // 32-bit programs run on both 32-bit and 64-bit Windows
- // so must sniff
- BOOL f64 = FALSE;
- LPFN_ISWOW64PROCESS fnIsWow64Process;
- fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process");
- if (NULL != fnIsWow64Process)
- {
- return fnIsWow64Process(GetCurrentProcess(), &f64) && f64;
- }
- return FALSE;
- #else
- return FALSE; // Win64 does not support Win16
- #endif
- }
- #endif
- const char * OSAsString()
- {
- #if defined (OVR_OS_IPHONE)
- return "IPhone";
- #elif defined (OVR_OS_DARWIN)
- return "Darwin";
- #elif defined (OVR_OS_MAC)
- return "Mac";
- #elif defined (OVR_OS_BSD)
- return "BSD";
- #elif defined (OVR_OS_WIN64) || defined (OVR_OS_WIN32)
- if (Is64BitWindows())
- return "Win64";
- else
- return "Win32";
- #elif defined (OVR_OS_ANDROID)
- return "Android";
- #elif defined (OVR_OS_LINUX)
- return "Linux";
- #elif defined (OVR_OS_BSD)
- return "BSD";
- #else
- return "Other";
- #endif
- }
- uint64_t GetGuidInt()
- {
- uint64_t g = Timer::GetTicksNanos();
- uint64_t lastTime, thisTime;
- int j;
- // Sleep a small random time, then use the last 4 bits as a source of randomness
- for (j = 0; j < 8; j++)
- {
- lastTime = Timer::GetTicksNanos();
- Thread::MSleep(1);
- // Note this does not actually sleep for "only" 1 millisecond
- // necessarily. Since we do not call timeBeginPeriod(1) explicitly
- // before invoking this function it may be sleeping for 10+ milliseconds.
- thisTime = Timer::GetTicksNanos();
- uint64_t diff = thisTime - lastTime;
- unsigned int diff4Bits = (unsigned int)(diff & 15);
- diff4Bits <<= 32 - 4;
- diff4Bits >>= j * 4;
- ((char*)&g)[j] ^= diff4Bits;
- }
- return g;
- }
- String GetGuidString()
- {
- uint64_t guid = GetGuidInt();
- char buff[64];
- #if defined(OVR_CC_MSVC)
- OVR_sprintf(buff, sizeof(buff), "%I64u", guid);
- #else
- OVR_sprintf(buff, sizeof(buff), "%llu", (unsigned long long) guid);
- #endif
- return String(buff);
- }
- const char * GetProcessInfo()
- {
- #if defined (OVR_CPU_X86_64 )
- return "64 bit";
- #elif defined (OVR_CPU_X86)
- return "32 bit";
- #else
- return "TODO";
- #endif
- }
- #ifdef OVR_OS_WIN32
- String OSVersionAsString()
- {
- return GetSystemFileVersionStringW(L"\\kernel32.dll");
- }
- String GetSystemFileVersionStringW(wchar_t filePath[MAX_PATH])
- {
- wchar_t strFilePath[MAX_PATH]; // Local variable
- UINT sysDirLen = GetSystemDirectoryW(strFilePath, ARRAYSIZE(strFilePath));
- if (sysDirLen != 0)
- {
- OVR_wcscat(strFilePath, MAX_PATH, filePath);
- return GetFileVersionStringW(strFilePath);
- }
- else
- {
- return "GetSystemDirectoryW failed";
- }
- }
- // See http://stackoverflow.com/questions/940707/how-do-i-programatically-get-the-version-of-a-dll-or-exe-file
- String GetFileVersionStringW(wchar_t filePath[MAX_PATH])
- {
- String result;
- DWORD dwSize = GetFileVersionInfoSizeW(filePath, NULL);
- if (dwSize == 0)
- {
- OVR_DEBUG_LOG(("Error in GetFileVersionInfoSizeW: %d (for %s)", GetLastError(), String(filePath).ToCStr()));
- result = String(filePath) + " not found";
- }
- else
- {
- BYTE* pVersionInfo = new BYTE[dwSize];
- if (!pVersionInfo)
- {
- OVR_DEBUG_LOG(("Out of memory allocating %d bytes (for %s)", dwSize, filePath));
- result = "Out of memory";
- }
- else
- {
- if (!GetFileVersionInfoW(filePath, 0, dwSize, pVersionInfo))
- {
- OVR_DEBUG_LOG(("Error in GetFileVersionInfo: %d (for %s)", GetLastError(), String(filePath).ToCStr()));
- result = "Cannot get version info";
- }
- else
- {
- VS_FIXEDFILEINFO* pFileInfo = NULL;
- UINT pLenFileInfo = 0;
- if (!VerQueryValueW(pVersionInfo, L"\\", (LPVOID*)&pFileInfo, &pLenFileInfo))
- {
- OVR_DEBUG_LOG(("Error in VerQueryValueW: %d (for %s)", GetLastError(), String(filePath).ToCStr()));
- result = "File has no version info";
- }
- else
- {
- int major = (pFileInfo->dwFileVersionMS >> 16) & 0xffff;
- int minor = (pFileInfo->dwFileVersionMS) & 0xffff;
- int hotfix = (pFileInfo->dwFileVersionLS >> 16) & 0xffff;
- int other = (pFileInfo->dwFileVersionLS) & 0xffff;
- char str[128];
- OVR::OVR_sprintf(str, 128, "%d.%d.%d.%d", major, minor, hotfix, other);
- result = str;
- }
- }
- delete[] pVersionInfo;
- }
- }
- return result;
- }
- String GetDisplayDriverVersion()
- {
- if (Is64BitWindows())
- {
- return GetSystemFileVersionStringW(L"\\OVRDisplay64.dll");
- }
- else
- {
- return GetSystemFileVersionStringW(L"\\OVRDisplay32.dll");
- }
- }
- String GetCameraDriverVersion()
- {
- return GetSystemFileVersionStringW(L"\\drivers\\OCUSBVID.sys");
- }
- // From http://stackoverflow.com/questions/9524309/enumdisplaydevices-function-not-working-for-me
- void GetGraphicsCardList( Array< String > &gpus)
- {
- gpus.Clear();
- DISPLAY_DEVICEW dd;
- dd.cb = sizeof(dd);
- DWORD deviceNum = 0;
- while( EnumDisplayDevicesW(NULL, deviceNum, &dd, 0) )
- {
- if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
- gpus.PushBack(String(dd.DeviceString));
- deviceNum++;
- }
- }
- String GetProcessorInfo()
- {
- char brand[0x40] = {};
- int cpui[4] = { -1 };
- __cpuidex(cpui, 0x80000002, 0);
- //unsigned int blocks = cpui[0];
- for (int i = 0; i <= 2; ++i)
- {
- __cpuidex(cpui, 0x80000002 + i, 0);
- *reinterpret_cast<int*>(brand + i * 16) = cpui[0];
- *reinterpret_cast<int*>(brand + 4 + i * 16) = cpui[1];
- *reinterpret_cast<int*>(brand + 8 + i * 16) = cpui[2];
- *reinterpret_cast<int*>(brand + 12 + i * 16) = cpui[3];
- }
- return String(brand, 0x40);
- }
- #else
- #ifdef OVR_OS_MAC
- //use objective c source
- // used for driver files
- String GetFileVersionString(String /*filePath*/)
- {
- return String();
- }
- String GetSystemFileVersionString(String /*filePath*/)
- {
- return String();
- }
- String GetDisplayDriverVersion()
- {
- return String();
- }
- String GetCameraDriverVersion()
- {
- return String();
- }
- #else
- String GetDisplayDriverVersion()
- {
- char info[256] = { 0 };
- FILE *file = popen("/usr/bin/glxinfo", "r");
- if (file)
- {
- int status = 0;
- while (status == 0)
- {
- status = fscanf(file, "%*[^\n]\n"); // Read up till the end of the current line, leaving the file pointer at the beginning of the next line (skipping any leading whitespace).
- OVR_UNUSED(status); // Prevent GCC compiler warning: "ignoring return value of ‘int fscanf(FILE*, const char*, ...)"
- status = fscanf(file, "OpenGL version string: %255[^\n]", info);
- }
- pclose(file);
- if (status == 1)
- {
- return String(info);
- }
- }
- return String("No graphics driver details found.");
- }
- String GetCameraDriverVersion()
- {
- struct utsname kver;
- if (uname(&kver))
- {
- return String();
- }
- return String(kver.release);
- }
- void GetGraphicsCardList(OVR::Array< OVR::String > &gpus)
- {
- gpus.Clear();
- char info[256] = { 0 };
- FILE *file = popen("/usr/bin/lspci", "r");
- if (file)
- {
- int status = 0;
- while (status >= 0)
- {
- status = fscanf(file, "%*[^\n]\n"); // Read up till the end of the current line, leaving the file pointer at the beginning of the next line (skipping any leading whitespace).
- OVR_UNUSED(status); // Prevent GCC compiler warning: "ignoring return value of ‘int fscanf(FILE*, const char*, ...)"
- status = fscanf(file, "%*[^ ] VGA compatible controller: %255[^\n]", info);
- if (status == 1)
- {
- gpus.PushBack(String(info));
- }
- }
- pclose(file);
- }
- if (gpus.GetSizeI() <= 0)
- {
- gpus.PushBack(String("No video card details found."));
- }
- }
- String OSVersionAsString()
- {
- char info[256] = { 0 };
- FILE *file = fopen("/etc/issue", "r");
- if (file)
- {
- int status = fscanf(file, "%255[^\n\\]", info);
- fclose(file);
- if (status == 1)
- {
- return String(info);
- }
- }
- return String("No OS version details found.");
- }
- String GetProcessorInfo()
- {
- char info[256] = { 0 };
- FILE *file = fopen("/proc/cpuinfo", "r");
- if (file)
- {
- int status = 0;
- while (status == 0)
- {
- status = fscanf(file, "%*[^\n]\n"); // Read up till the end of the current line, leaving the file pointer at the beginning of the next line (skipping any leading whitespace).
- OVR_UNUSED(status); // Prevent GCC compiler warning: "ignoring return value of ‘int fscanf(FILE*, const char*, ...)"
- status = fscanf(file, "model name : %255[^\n]", info);
- }
- fclose(file);
- if (status == 1)
- {
- return String(info);
- }
- }
- return String("No processor details found.");
- }
- #endif //OVR_OS_MAC
- #endif // WIN32
- //-----------------------------------------------------------------------------
- // Get the path for local app data.
- String GetBaseOVRPath(bool create_dir)
- {
- #if defined(OVR_OS_WIN32)
- wchar_t path[MAX_PATH];
- ::SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA, NULL, 0, path);
- OVR_wcscat(path, MAX_PATH, L"\\Oculus");
- if (create_dir)
- { // Create the Oculus directory if it doesn't exist
- DWORD attrib = ::GetFileAttributesW(path);
- bool exists = attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY);
- if (!exists)
- {
- ::CreateDirectoryW(path, NULL);
- }
- }
- #elif defined(OVR_OS_MS) // Other Microsoft OSs
- // TODO: figure this out.
- OVR_UNUSED ( create_dir );
- path = "";
-
- #elif defined(OVR_OS_MAC)
- const char* home = getenv("HOME");
- path = home;
- path += "/Library/Preferences/Oculus";
- if (create_dir)
- { // Create the Oculus directory if it doesn't exist
- DIR* dir = opendir(path);
- if (dir == NULL)
- {
- mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
- }
- else
- {
- closedir(dir);
- }
- }
- #else
- const char* home = getenv("HOME");
- String path = home;
- path += "/.config/Oculus";
- if (create_dir)
- { // Create the Oculus directory if it doesn't exist
- DIR* dir = opendir(path);
- if (dir == NULL)
- {
- mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
- }
- else
- {
- closedir(dir);
- }
- }
- #endif
- return String(path);
- }
- #ifdef OVR_OS_MS
- //widechar functions are Windows only for now
- bool GetRegistryStringW(const wchar_t* pSubKey, const wchar_t* stringName, wchar_t out[MAX_PATH], bool wow64value, bool currentUser)
- {
- HKEY root = currentUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
- DWORD dwType = REG_SZ;
- HKEY hKey = 0;
- wchar_t value[MAX_PATH + 1]; // +1 because RegQueryValueEx doesn't necessarily 0-terminate.
- DWORD value_length = MAX_PATH;
- if ((RegOpenKeyExW(root, pSubKey, 0, KEY_QUERY_VALUE | (wow64value ? KEY_WOW64_32KEY : 0), &hKey) != ERROR_SUCCESS) ||
- (RegQueryValueExW(hKey, stringName, NULL, &dwType, (LPBYTE)&value, &value_length) != ERROR_SUCCESS) || (dwType != REG_SZ))
- {
- out[0] = L'\0';
- RegCloseKey(hKey);
- return false;
- }
- RegCloseKey(hKey);
- value[value_length] = L'\0';
- wcscpy_s(out, MAX_PATH, value);
- return true;
- }
- bool GetRegistryDwordW(const wchar_t* pSubKey, const wchar_t* stringName, DWORD& out, bool wow64value, bool currentUser)
- {
- HKEY root = currentUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
- DWORD dwType = REG_DWORD;
- HKEY hKey = 0;
- DWORD value_length = sizeof(DWORD);
- if ((RegOpenKeyExW(root, pSubKey, 0, KEY_QUERY_VALUE | (wow64value ? KEY_WOW64_32KEY : 0), &hKey) != ERROR_SUCCESS) ||
- (RegQueryValueExW(hKey, stringName, NULL, &dwType, (LPBYTE)&out, &value_length) != ERROR_SUCCESS) || (dwType != REG_DWORD))
- {
- out = 0;
- RegCloseKey(hKey);
- return false;
- }
- RegCloseKey(hKey);
- return true;
- }
- bool GetRegistryBinaryW(const wchar_t* pSubKey, const wchar_t* stringName, LPBYTE out, DWORD* size, bool wow64value, bool currentUser)
- {
- HKEY root = currentUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
- DWORD dwType = REG_BINARY;
- HKEY hKey = 0;
- if ((RegOpenKeyExW(root, pSubKey, 0, KEY_QUERY_VALUE | (wow64value ? KEY_WOW64_32KEY : 0), &hKey) != ERROR_SUCCESS) ||
- (RegQueryValueExW(hKey, stringName, NULL, &dwType, out, size) != ERROR_SUCCESS) || (dwType != REG_BINARY))
- {
- *out = 0;
- RegCloseKey(hKey);
- return false;
- }
- RegCloseKey(hKey);
- return true;
- }
- // When reading Oculus registry keys, we recognize that the user may have inconsistently
- // used a DWORD 1 vs. a string "1", and so we support either when checking booleans.
- bool GetRegistryBoolW(const wchar_t* pSubKey, const wchar_t* stringName, bool defaultValue, bool wow64value, bool currentUser)
- {
- wchar_t out[MAX_PATH];
- if (GetRegistryStringW(pSubKey, stringName, out, wow64value, currentUser))
- {
- return (_wtoi64(out) != 0);
- }
- DWORD dw;
- if (GetRegistryDwordW(pSubKey, stringName, dw, wow64value, currentUser))
- {
- return (dw != 0);
- }
- return defaultValue;
- }
- bool SetRegistryBinaryW(const wchar_t* pSubKey, const wchar_t* stringName, LPBYTE value, DWORD size, bool wow64value, bool currentUser)
- {
- HKEY root = currentUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
- HKEY hKey = 0;
- if ((RegCreateKeyExW(root, pSubKey, 0, nullptr, 0, KEY_CREATE_SUB_KEY | KEY_SET_VALUE | (wow64value ? KEY_WOW64_32KEY : 0), nullptr, &hKey, nullptr) != ERROR_SUCCESS) ||
- (RegSetValueExW(hKey, stringName, 0, REG_BINARY, value, size) != ERROR_SUCCESS))
- {
- RegCloseKey(hKey);
- return false;
- }
- RegCloseKey(hKey);
- return true;
- }
- bool DeleteRegistryValue(const wchar_t* pSubKey, const wchar_t* stringName, bool wow64value, bool currentUser)
- {
- HKEY root = currentUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
- HKEY hKey = 0;
- if (RegOpenKeyExW(root, pSubKey, 0, KEY_ALL_ACCESS | (wow64value ? KEY_WOW64_32KEY : 0), &hKey) != ERROR_SUCCESS)
- {
- RegCloseKey(hKey);
- return false;
- }
- bool result = (RegDeleteValueW(hKey, stringName) == ERROR_SUCCESS);
- RegCloseKey(hKey);
- return result;
- }
- bool GetOVRRuntimePathW(wchar_t out[MAX_PATH])
- {
- if (Is64BitWindows())
- {
- if (!GetRegistryStringW(L"Software\\Wow6432Node\\Oculus VR, LLC\\Oculus Runtime", L"Location", out))
- {
- return false;
- }
- }
- else if (!GetRegistryStringW(L"Software\\Oculus VR, LLC\\Oculus Runtime", L"Location", out))
- {
- return false;
- }
- return true;
- }
- #endif // OVR_OS_MS
- bool GetOVRRuntimePath(String& runtimePath)
- {
- runtimePath = "";
- #ifdef OVR_OS_MS
- wchar_t path[MAX_PATH];
- if (GetOVRRuntimePathW(path))
- {
- runtimePath = String(path);
- return true;
- }
- #endif // OVR_OS_MS
- //mac/linux uses environment variables
- return false;
- }
- bool GetDefaultFirmwarePath(String& firmwarePath)
- {
- if (!GetOVRRuntimePath(firmwarePath))
- {
- return false;
- }
- else
- {
- firmwarePath + "\\Tools\\FirmwareBundle.json";
- return true;
- }
- }
- bool GetFirmwarePathFromService(OVR::String& firmwarePath, int numSearchDirs)
- {
- #ifdef OVR_OS_MS
- firmwarePath = "";
- //Try relative file locations
- wchar_t path[MAX_PATH]; // FIXME: This is Windows-specific.
- // Get full path to our module.
- int pathlen = ::GetModuleFileNameW(nullptr, path, MAX_PATH);
- OVR_ASSERT_AND_UNUSED(pathlen, pathlen);
- //try the registry default
- if (GetOVRRuntimePath(firmwarePath) && !firmwarePath.IsEmpty())
- {
- if (OVR_strncmp(OVR::String(path), firmwarePath, firmwarePath.GetSize()) == 0)
- {
- //we are in the default runtime directory.
- firmwarePath += "/Tools/Firmware/";
- return true;
- }
- else
- {
- firmwarePath = "";
- }
- }
- if (firmwarePath.IsEmpty())
- {
- //try internal path.
- wchar_t relpath[MAX_PATH];
- relpath[0] = L'\0';
- for (int i = 0; i < numSearchDirs; i++)
- {
- wchar_t* trailingSlash = wcsrchr(path, L'\\');
- if (trailingSlash == nullptr)
- {
- break; // no more paths to traverse
- }
- *(trailingSlash + 1) = L'\0'; //delete after the last trailing slash
- //Then attach this prefix
- OVR_wcscat(path, MAX_PATH, L"Firmware\\");
- //And attempt to find the path
- if (::PathFileExistsW(path))
- {
- firmwarePath = String(path);
- return true;
- }
- else
- {
- *trailingSlash = L'\0'; //remove trailing slash, traversing up 1 directory
- }
- }
- }
- firmwarePath = L"";
- #else
- OVR_UNUSED2(firmwarePath, numSearchDirs);
- //#error "FIXME"
- #endif
- return false;
- }
- }} // namespace OVR::Util
|