diff --git a/Source/Memory.cc b/Source/Memory.cc index 2b59b02..de5d0d6 100644 --- a/Source/Memory.cc +++ b/Source/Memory.cc @@ -14,6 +14,7 @@ #include #include "Process.h" #include "Memory.h" +#include "System.h" #include using std::search; @@ -31,9 +32,8 @@ using std::unordered_map; #include #include using std::ios; - using std::ifstream; - using std:: fstream; - using std:: getline; + using std::fstream; + using std::getline; #include #include @@ -109,13 +109,6 @@ ROBOT_NS_BEGIN // Locals // //----------------------------------------------------------------------------// -//////////////////////////////////////////////////////////////////////////////// - -static uintptr gMinVM = 0; // Minimum VM address -static uintptr gMaxVM_32 = 0; // Maximum VM address (32-Bit) -static uintptr gMaxVM_64 = 0; // Maximum VM address (64-Bit) -static uintptr gPageSize = 0; // Size of single page - #ifdef ROBOT_OS_LINUX //////////////////////////////////////////////////////////////////////////////// @@ -1173,26 +1166,23 @@ uintptr Memory::GetPtrSize (void) const uintptr Memory::GetMinAddress (void) const { - InitializeVM(); - return gMinVM; + return System::GetMinAddress(); } //////////////////////////////////////////////////////////////////////////////// uintptr Memory::GetMaxAddress (void) const { - InitializeVM(); - // Depends on architecture - return mData->Proc.Is64Bit() ? - gMaxVM_64 : gMaxVM_32; + return mData->Proc.Is64Bit () ? + System::GetMaxAddress64() : + System::GetMaxAddress32(); } //////////////////////////////////////////////////////////////////////////////// uintptr Memory::GetPageSize (void) const { - InitializeVM(); - return gPageSize; + return System::GetPageSize(); } //////////////////////////////////////////////////////////////////////////////// @@ -1604,65 +1594,4 @@ bool Memory::SysWrite (uintptr address, const #endif } -//////////////////////////////////////////////////////////////////////////////// - -void Memory::InitializeVM (void) -{ - // Initialize system info once - static bool initialized = false; - - if (initialized == false) - { - initialized = true; - - #if defined (ROBOT_OS_MAC) || \ - defined (ROBOT_OS_LINUX) - - gMinVM = 0x000000001000; - gMaxVM_32 = 0x0000C0000000; // 3G - - #ifdef ROBOT_ARCH_64 - gMaxVM_64 = 0x7FFFFFFF0000; - #else - // This shouldn't be used - gMaxVM_64 = 0x0000C0000000; - #endif - - #ifdef ROBOT_OS_LINUX - - // Adjust minimum VM value - ifstream file (PROC_PATH - "sys/vm/mmap_min_addr"); - if (file) file >> gMinVM; - - #endif - - gPageSize = sysconf (_SC_PAGESIZE); - - #endif - #ifdef ROBOT_OS_WIN - - SYSTEM_INFO info; - // Retrieve the system info - GetNativeSystemInfo (&info); - - gMinVM = (uintptr) - info.lpMinimumApplicationAddress + 0; - - gMaxVM_64 = (uintptr) - info.lpMaximumApplicationAddress + 1; - - // Always use full low 32-Bit value - gMaxVM_32 = gMaxVM_64 & 0xFFFFFFFF; - - gPageSize = (uintptr) info.dwPageSize; - - #endif - - assert ((gMinVM % gPageSize) == 0); - assert ((gMaxVM_32 % gPageSize) == 0); - assert ((gMaxVM_64 % gPageSize) == 0); - } -} - ROBOT_NS_END diff --git a/Source/Memory.h b/Source/Memory.h index ab66bf9..c823c9e 100644 --- a/Source/Memory.h +++ b/Source/Memory.h @@ -175,8 +175,6 @@ class ROBOT_EXPORT Memory bool SysWrite (uintptr address, const void* data, uintptr length, uintptr* bytes); - static void InitializeVM (void); - private: struct Data; std::shared_ptr mData; // Shared information diff --git a/Source/Process.cc b/Source/Process.cc index 330fe4f..795eba8 100644 --- a/Source/Process.cc +++ b/Source/Process.cc @@ -15,6 +15,7 @@ #include "Memory.h" #include "Module.h" #include "Window.h" +#include "System.h" #include using std::sort; @@ -40,14 +41,12 @@ using std::regex_match; using std:: fstream; using std:: getline; - #include // Path to proc directory #define PROC_PATH "/proc/" #endif #ifdef ROBOT_OS_MAC - #include #include #include @@ -380,8 +379,8 @@ bool Process::Open (int32 pid) // Store the ProcID mData->ProcID = pid; - // Check if system 64-Bit - if (Process::IsSys64Bit()) + // If system is 64-Bit + if (System::Is64Bit()) { BOOL is32Bit = TRUE; // Set whether process is 64-Bit @@ -1086,36 +1085,7 @@ int32 Process::GetCurrentPID (void) bool Process::IsSys64Bit (void) { - // Initialize only once - static int8 is64Bit = -1; - - if (is64Bit == -1) - { - #if defined (ROBOT_OS_MAC) || \ - defined (ROBOT_OS_LINUX) - - utsname unameData; - uname (&unameData); - - is64Bit = !strcmp (unameData. - machine, "x86_64") ? 1:0; - - #endif - #ifdef ROBOT_OS_WIN - - SYSTEM_INFO info; - // Retrieve the system info - GetNativeSystemInfo (&info); - - is64Bit = - info.wProcessorArchitecture == - PROCESSOR_ARCHITECTURE_AMD64 ? - 1 : 0; - - #endif - } - - return is64Bit == 1; + return System::Is64Bit(); } diff --git a/Source/Process.h b/Source/Process.h index 7e8c69e..22240c2 100644 --- a/Source/Process.h +++ b/Source/Process.h @@ -85,7 +85,7 @@ class ROBOT_EXPORT Process static Process GetCurrent (void); static int32 GetCurrentPID (void); - static bool IsSys64Bit (void); + static bool IsSys64Bit (void); // #Deprecated public: bool operator == (const Process& process) const; diff --git a/Source/Robot.h b/Source/Robot.h index 4b19547..800d974 100644 --- a/Source/Robot.h +++ b/Source/Robot.h @@ -19,6 +19,7 @@ #include "Process.h" #include "Module.h" #include "Memory.h" +#include "System.h" #include "Window.h" #include "Screen.h" diff --git a/Source/Robot.vs12.vcxproj b/Source/Robot.vs12.vcxproj index 0c76d3a..8218f1e 100644 --- a/Source/Robot.vs12.vcxproj +++ b/Source/Robot.vs12.vcxproj @@ -52,6 +52,7 @@ + @@ -71,6 +72,7 @@ + @@ -205,7 +207,7 @@ true true MachineX86 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -224,7 +226,7 @@ true true MachineX64 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -237,7 +239,7 @@ Windows true MachineX86 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -250,7 +252,7 @@ Windows true MachineX64 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -328,4 +330,4 @@ - \ No newline at end of file + diff --git a/Source/Robot.vs12.vcxproj.filters b/Source/Robot.vs12.vcxproj.filters index 27ac30b..114f2ac 100644 --- a/Source/Robot.vs12.vcxproj.filters +++ b/Source/Robot.vs12.vcxproj.filters @@ -62,6 +62,9 @@ Types + + Native + Native @@ -115,6 +118,9 @@ Types + + Native + Native @@ -122,4 +128,4 @@ Native - \ No newline at end of file + diff --git a/Source/Robot.vs13.vcxproj b/Source/Robot.vs13.vcxproj index bbefb4c..f42b1ba 100644 --- a/Source/Robot.vs13.vcxproj +++ b/Source/Robot.vs13.vcxproj @@ -52,6 +52,7 @@ + @@ -71,6 +72,7 @@ + @@ -205,7 +207,7 @@ true true MachineX86 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -224,7 +226,7 @@ true true MachineX64 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -237,7 +239,7 @@ Windows true MachineX86 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -250,7 +252,7 @@ Windows true MachineX64 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -328,4 +330,4 @@ - \ No newline at end of file + diff --git a/Source/Robot.vs13.vcxproj.filters b/Source/Robot.vs13.vcxproj.filters index 27ac30b..114f2ac 100644 --- a/Source/Robot.vs13.vcxproj.filters +++ b/Source/Robot.vs13.vcxproj.filters @@ -62,6 +62,9 @@ Types + + Native + Native @@ -115,6 +118,9 @@ Types + + Native + Native @@ -122,4 +128,4 @@ Native - \ No newline at end of file + diff --git a/Source/Robot.vs15.vcxproj b/Source/Robot.vs15.vcxproj index dba8264..e57682f 100644 --- a/Source/Robot.vs15.vcxproj +++ b/Source/Robot.vs15.vcxproj @@ -52,6 +52,7 @@ + @@ -71,6 +72,7 @@ + @@ -205,7 +207,7 @@ true true MachineX86 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -224,7 +226,7 @@ true true MachineX64 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -237,7 +239,7 @@ Windows true MachineX86 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -250,7 +252,7 @@ Windows true MachineX64 - Psapi.lib;%(AdditionalDependencies) + Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) @@ -328,4 +330,4 @@ - \ No newline at end of file + diff --git a/Source/Robot.vs15.vcxproj.filters b/Source/Robot.vs15.vcxproj.filters index 27ac30b..114f2ac 100644 --- a/Source/Robot.vs15.vcxproj.filters +++ b/Source/Robot.vs15.vcxproj.filters @@ -62,6 +62,9 @@ Types + + Native + Native @@ -115,6 +118,9 @@ Types + + Native + Native @@ -122,4 +128,4 @@ Native - \ No newline at end of file + diff --git a/Source/Screen.cc b/Source/Screen.cc index a5e08d3..35f6bf0 100644 --- a/Source/Screen.cc +++ b/Source/Screen.cc @@ -12,6 +12,8 @@ //----------------------------------------------------------------------------// #include "Screen.h" +#include "System.h" + #ifdef ROBOT_OS_LINUX #include @@ -127,45 +129,6 @@ ROBOT_NS_BEGIN //////////////////////////////////////////////////////////////////////////////// - #ifndef DWM_EC_DISABLECOMPOSITION - #define DWM_EC_DISABLECOMPOSITION 0 - #endif - #ifndef DWM_EC_ENABLECOMPOSITION - #define DWM_EC_ENABLECOMPOSITION 1 - #endif - - typedef HRESULT (WINAPI *DWMENABLECOMPOSITION ) (UINT enabled); - typedef HRESULT (WINAPI *DWMISCOMPOSITIONENABLED) (BOOL* enabled); - - static DWMENABLECOMPOSITION gDwmEnableComposition = nullptr; - static DWMISCOMPOSITIONENABLED gDwmIsCompositionEnabled = nullptr; - - //////////////////////////////////////////////////////////////////////////////// - - static void InitializeDWM (void) - { - // Initialize DWM functions once - static bool initialized = false; - - if (!initialized) - { - initialized = true; - // Attempt to load windows DWMAPI DLL library - HMODULE d = LoadLibrary (TEXT ("Dwmapi.dll")); - if (d != nullptr) - { - // Attempt to load the DWM Aero functionality - gDwmEnableComposition = (DWMENABLECOMPOSITION) - GetProcAddress (d, "DwmEnableComposition"); - - gDwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED) - GetProcAddress (d, "DwmIsCompositionEnabled"); - } - } - } - - //////////////////////////////////////////////////////////////////////////////// - static BOOL CALLBACK EnumMonitorsProc (HMONITOR hmon, HDC, LPRECT, LPARAM lParam) { // Retrieve lParam data as a screen deque @@ -684,35 +647,14 @@ Bounds Screen::GetTotalUsable (void) { return mTotalUsable; } bool Screen::IsCompositing (void) { -#if defined (ROBOT_OS_MAC) || \ - defined (ROBOT_OS_LINUX) - - return true; - -#endif -#ifdef ROBOT_OS_WIN - - InitializeDWM(); BOOL enabled = FALSE; - if (gDwmIsCompositionEnabled != nullptr) - gDwmIsCompositionEnabled (&enabled); - return enabled != FALSE; - -#endif + return System::IsCompositing(); } //////////////////////////////////////////////////////////////////////////////// void Screen::SetCompositing (bool enabled) { -#ifdef ROBOT_OS_WIN - - InitializeDWM(); - if (gDwmEnableComposition != nullptr) - gDwmEnableComposition (enabled ? - DWM_EC_ENABLECOMPOSITION : - DWM_EC_DISABLECOMPOSITION); - -#endif + return System::SetCompositing (enabled); } ROBOT_NS_END diff --git a/Source/Screen.h b/Source/Screen.h index 0fadaf1..45fd6f8 100644 --- a/Source/Screen.h +++ b/Source/Screen.h @@ -76,8 +76,8 @@ class ROBOT_EXPORT Screen static Bounds GetTotalBounds (void); static Bounds GetTotalUsable (void); - static bool IsCompositing (void); - static void SetCompositing (bool enabled); + static bool IsCompositing (void); // #Deprecated + static void SetCompositing (bool enabled); // #Deprecated private: Bounds mBounds; // Screen total bounds diff --git a/Source/System.cc b/Source/System.cc new file mode 100644 index 0000000..7d5a867 --- /dev/null +++ b/Source/System.cc @@ -0,0 +1,520 @@ +//////////////////////////////////////////////////////////////////////////////// +// -------------------------------------------------------------------------- // +// // +// (C) 2010-2017 Robot Developers // +// See LICENSE for licensing info // +// // +// -------------------------------------------------------------------------- // +//////////////////////////////////////////////////////////////////////////////// + +//----------------------------------------------------------------------------// +// Prefaces // +//----------------------------------------------------------------------------// + +#include +#include "System.h" + +#ifdef ROBOT_OS_LINUX + + #include + #include + + #include + #include + using std::ifstream; + +#endif +#ifdef ROBOT_OS_MAC + + #include + #include + #include + +#endif +#ifdef ROBOT_OS_WIN + + #define NOMINMAX + #define WIN32_LEAN_AND_MEAN + #include + + // Compositing API + #include + + using std:: string; + using std::wstring; + + #pragma warning (push) + // Ignore deprecation warning + #pragma warning (disable:4995) + +#endif +ROBOT_NS_BEGIN + + + +//----------------------------------------------------------------------------// +// Locals // +//----------------------------------------------------------------------------// + +#ifdef ROBOT_OS_WIN + + //////////////////////////////////////////////////////////////////////////////// + + #ifdef UNICODE + extern string _UTF8Encode (const wstring& value); + extern wstring _UTF8Decode (const string& value); + #else + extern string _UTF8Encode (const string& value); + extern string _UTF8Decode (const string& value); + #endif + +#endif + + + +//----------------------------------------------------------------------------// +// Fields System // +//----------------------------------------------------------------------------// + +//////////////////////////////////////////////////////////////////////////////// + +bool System::mInitialized = false; +bool System::mIs64Bit = true; + +//////////////////////////////////////////////////////////////////////////////// + +uintptr System::mMinAddress = 0; +uintptr System::mMaxAddress32 = 0; +uintptr System::mMaxAddress64 = 0; +uintptr System::mPageSize = 0; + + + +//----------------------------------------------------------------------------// +// Functions System // +//----------------------------------------------------------------------------// + +//////////////////////////////////////////////////////////////////////////////// + +bool System::Is64Bit (void) +{ + if (!mInitialized) + Initialize(); + + return mIs64Bit; +} + +//////////////////////////////////////////////////////////////////////////////// + +bool System::IsUserAdmin (void) +{ +#ifdef ROBOT_OS_LINUX + + return geteuid() == 0; + +#endif +#ifdef ROBOT_OS_MAC + + return geteuid() == 0; + +#endif +#ifdef ROBOT_OS_WIN + + // Based on the following implementation: + // http://support.microsoft.com/kb/118626 + + //----------------------------------------------------------------------------// + + #define ACCESS_READ 1 + #define ACCESS_WRITE 2 + + GENERIC_MAPPING genericMapping = + { + ACCESS_READ, ACCESS_WRITE, 0, + ACCESS_READ | ACCESS_WRITE + }; + + BOOL result = FALSE; + + HANDLE token = nullptr; + HANDLE tokenImp = nullptr; + PSID adminSID = nullptr; + + DWORD status; + SID_IDENTIFIER_AUTHORITY + systemAuthoritySID = + SECURITY_NT_AUTHORITY; + + SECURITY_DESCRIPTOR adminSD; + PACL adminACL = nullptr; + DWORD adminACLSize = 0; + + PRIVILEGE_SET ps; + DWORD psSize = sizeof (PRIVILEGE_SET); + HANDLE processHeap = GetProcessHeap(); + + //----------------------------------------------------------------------------// + + // Attempt to open the thread access token + if (!OpenThreadToken (GetCurrentThread(), + TOKEN_DUPLICATE | TOKEN_QUERY, TRUE, &token)) + { + // Check for errors obtaining a token + if (GetLastError() != ERROR_NO_TOKEN) + return false; + + // Attempt to open the process access token + if (!OpenProcessToken (GetCurrentProcess(), + TOKEN_DUPLICATE | TOKEN_QUERY, &token)) + return false; + } + + // AccessCheck requires impersonation-level token + if (!DuplicateToken (token, SecurityImpersonation, + &tokenImp)) goto exit; + + //----------------------------------------------------------------------------// + + // Create well-known SID that represents the admin group + if (!AllocateAndInitializeSid (&systemAuthoritySID, 2, + SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, &adminSID)) goto exit; + + // Initialize the admin security descriptor + if (!InitializeSecurityDescriptor (&adminSD, + SECURITY_DESCRIPTOR_REVISION)) goto exit; + + adminACLSize = + // Compute size needed for the ACL struct + sizeof (ACL) + sizeof (ACCESS_ALLOWED_ACE) + + GetLengthSid (adminSID) - sizeof (DWORD); + + adminACL = (PACL) HeapAlloc + // Allocate mem for ACL struct + (processHeap, 0, adminACLSize); + if (adminACL == nullptr) goto exit; + + // Initialize the ACL struct + if (!InitializeAcl (adminACL, + adminACLSize, ACL_REVISION)) + goto exit; + + // Add the ACE to the previously initialized ACL + if (!AddAccessAllowedAce (adminACL, ACL_REVISION, + ACCESS_READ | ACCESS_WRITE, adminSID)) + goto exit; + + // Attach ACL to our security descriptor + if (!SetSecurityDescriptorDacl (&adminSD, + TRUE, adminACL, FALSE)) goto exit; + + //----------------------------------------------------------------------------// + + // Setup security descriptor so it passes validation + SetSecurityDescriptorGroup (&adminSD, adminSID, FALSE); + SetSecurityDescriptorOwner (&adminSD, adminSID, FALSE); + if (!IsValidSecurityDescriptor (&adminSD)) goto exit; + + // Perform an access check to determine the result + if (!AccessCheck (&adminSD, tokenImp, ACCESS_READ, + &genericMapping, &ps, &psSize, &status, &result)) + { result = FALSE; goto exit; } + + //----------------------------------------------------------------------------// + +exit: + if (adminACL) HeapFree (processHeap, 0, adminACL); + if (adminSID) FreeSid (adminSID); + if (tokenImp) CloseHandle (tokenImp); + if (token ) CloseHandle (token ); + + // Return check result + return result != FALSE; + +#endif +} + +//////////////////////////////////////////////////////////////////////////////// + +bool System::IsAxEnabled (bool options) +{ +#ifdef ROBOT_OS_LINUX + + return true; + +#endif +#ifdef ROBOT_OS_MAC + + // Load functions just once + static dispatch_once_t once; + dispatch_once (&once, ^{ + // Open the framework + void* handle = dlopen + ("/System/Library/Frameworks/Application" + "Services.framework/ApplicationServices", RTLD_LAZY); + + // Validate the handle + if (handle != nullptr) + { + *(void**) (&gAXIsProcessTrustedWithOptions) = + dlsym (handle, "AXIsProcessTrustedWithOptions"); + + gkAXTrustedCheckOptionPrompt = (CFStringRef*) + dlsym (handle, "kAXTrustedCheckOptionPrompt"); + } + }); + + // Check for new OSX 10.9 function + if (gAXIsProcessTrustedWithOptions) + { + // Check whether to show prompt + auto displayPrompt = options ? + kCFBooleanTrue : kCFBooleanFalse; + + // Convert display prompt value into a dictionary + const void* k[] = { *gkAXTrustedCheckOptionPrompt }; + const void* v[] = { displayPrompt }; + CFDictionaryRef o = CFDictionaryCreate + (nullptr, k, v, 1, nullptr, nullptr); + + // Determine whether the process is actually trusted + bool result = (*gAXIsProcessTrustedWithOptions) (o); + + // Free memory + CFRelease (o); + return result; + } + + else + { + // Ignore deprecated warnings + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + + // Check whether we have accessibility access + return AXAPIEnabled() || AXIsProcessTrusted(); + #pragma clang diagnostic pop + } + +#endif +#ifdef ROBOT_OS_WIN + + return true; + +#endif +} + +//////////////////////////////////////////////////////////////////////////////// + +uintptr System::GetMinAddress (void) +{ + if (!mInitialized) + Initialize(); + + return mMinAddress; +} + +//////////////////////////////////////////////////////////////////////////////// + +uintptr System::GetMaxAddress32 (void) +{ + if (!mInitialized) + Initialize(); + + return mMaxAddress32; +} + +//////////////////////////////////////////////////////////////////////////////// + +uintptr System::GetMaxAddress64 (void) +{ + if (!mInitialized) + Initialize(); + + return mMaxAddress64; +} + +//////////////////////////////////////////////////////////////////////////////// + +uintptr System::GetPageSize (void) +{ + if (!mInitialized) + Initialize(); + + return mPageSize; +} + +//////////////////////////////////////////////////////////////////////////////// + +bool System::IsCompositing (void) +{ +#if defined (ROBOT_OS_MAC) || \ + defined (ROBOT_OS_LINUX) + + return true; + +#endif +#ifdef ROBOT_OS_WIN + + BOOL enabled = FALSE; + DwmIsCompositionEnabled (&enabled); + return enabled != FALSE; + +#endif +} + +//////////////////////////////////////////////////////////////////////////////// + +void System::SetCompositing (bool enabled) +{ +#ifdef ROBOT_OS_WIN + + DwmEnableComposition (enabled ? + DWM_EC_ENABLECOMPOSITION : + DWM_EC_DISABLECOMPOSITION); + +#endif +} + +//////////////////////////////////////////////////////////////////////////////// + +bool System::AdjustPrivilege (const char* privilege, bool enable) +{ +#if defined (ROBOT_OS_MAC) || \ + defined (ROBOT_OS_LINUX) + + return true; + +#endif +#ifdef ROBOT_OS_WIN + + HANDLE token; + TOKEN_PRIVILEGES tp; + bool result = false; + + // Attempt to open the thread access token + if (!OpenThreadToken (GetCurrentThread(), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, + FALSE, &token)) + { + // Check for errors obtaining a token + if (GetLastError() != ERROR_NO_TOKEN) + return false; + + // Attempt to open the process access token + if (!OpenProcessToken (GetCurrentProcess(), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, + &token)) return false; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = enable + ? SE_PRIVILEGE_ENABLED : 0; + + // Attempt to lookup specified privilege value + if (!LookupPrivilegeValue (nullptr, _UTF8Decode + (privilege).data(), &tp.Privileges[0].Luid)) + goto exit; + + // Attempt to adjust requested privilege + if (!AdjustTokenPrivileges (token, FALSE, + &tp, 0, nullptr, nullptr)) goto exit; + + // Ensure the privilege was correctly adjusted + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + goto exit; + + result = true; + +exit: + // Cleanup if needed + CloseHandle (token); + return result; + +#endif +} + + + +//----------------------------------------------------------------------------// +// Internal System // +//----------------------------------------------------------------------------// + +//////////////////////////////////////////////////////////////////////////////// + +void System::Initialize (void) +{ + mInitialized = true; + +#if defined (ROBOT_OS_MAC) || \ + defined (ROBOT_OS_LINUX) + + #ifdef ROBOT_ARCH_32 + + utsname unameData; + uname (&unameData); + + // If system is 64-Bit + if (!strcmp (unameData. + machine, "x86_64")) + mIs64Bit = true; + + #endif + + mMinAddress = 0x000000001000; + mMaxAddress32 = 0x0000C0000000; // 3G + + #ifdef ROBOT_ARCH_64 + mMaxAddress64 = 0x7FFFFFFF0000; + #else + mMaxAddress64 = 0x0000C0000000; + #endif + + #ifdef ROBOT_OS_LINUX + + // Adjust minimum VM value + ifstream file (PROC_PATH + "sys/vm/mmap_min_addr"); + if (file) file >> mMinAddress; + + #endif + + mPageSize = sysconf (_SC_PAGESIZE); + +#endif +#ifdef ROBOT_OS_WIN + + SYSTEM_INFO info; + // Retrieve the system info + GetNativeSystemInfo (&info); + + #ifdef ROBOT_ARCH_32 + + mIs64Bit = + info.wProcessorArchitecture == + PROCESSOR_ARCHITECTURE_AMD64; + + #endif + + mMinAddress = (uintptr) + info.lpMinimumApplicationAddress + 0; + + mMaxAddress64 = (uintptr) + info.lpMaximumApplicationAddress + 1; + + mMaxAddress32 = mMaxAddress64 & 0xFFFFFFFF; + + mPageSize = (uintptr) info.dwPageSize; + +#endif + + assert ((mMinAddress % mPageSize) == 0); + assert ((mMaxAddress32 % mPageSize) == 0); + assert ((mMaxAddress64 % mPageSize) == 0); +} + +ROBOT_NS_END + +#ifdef ROBOT_OS_WIN + #pragma warning (pop) +#endif diff --git a/Source/System.h b/Source/System.h new file mode 100644 index 0000000..4421699 --- /dev/null +++ b/Source/System.h @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////////////////////////// +// -------------------------------------------------------------------------- // +// // +// (C) 2010-2017 Robot Developers // +// See LICENSE for licensing info // +// // +// -------------------------------------------------------------------------- // +//////////////////////////////////////////////////////////////////////////////// + +//----------------------------------------------------------------------------// +// Prefaces // +//----------------------------------------------------------------------------// + +#pragma once + +#include "Types.h" +ROBOT_NS_BEGIN + + + +//----------------------------------------------------------------------------// +// Classes // +//----------------------------------------------------------------------------// + +//////////////////////////////////////////////////////////////////////////////// + +class ROBOT_EXPORT System +{ +private: + System (void); + ~System (void); + System (const System& system); + System ( System&& system); + +public: + static bool Is64Bit (void); + static bool IsUserAdmin (void); + static bool IsAxEnabled (bool options = false); + + static uintptr GetMinAddress (void); + static uintptr GetMaxAddress32 (void); + static uintptr GetMaxAddress64 (void); + static uintptr GetPageSize (void); + + static bool IsCompositing (void); + static void SetCompositing (bool enabled); + + static bool AdjustPrivilege (const char* privilege, + bool enable = true); + +private: + static void Initialize (void); + +private: + System& operator = (const System& system); + System& operator = ( System&& system); + +private: + static bool mInitialized; // Class initialized + static bool mIs64Bit; // System is 64-Bit + + static uintptr mMinAddress; // Minimum address + static uintptr mMaxAddress32; // Maximum address (32-Bit) + static uintptr mMaxAddress64; // Maximum address (64-Bit) + static uintptr mPageSize; // Size of a single page +}; + +ROBOT_NS_END diff --git a/Source/Window.cc b/Source/Window.cc index 3b7ca1e..56ff139 100644 --- a/Source/Window.cc +++ b/Source/Window.cc @@ -12,6 +12,7 @@ //----------------------------------------------------------------------------// #include "Window.h" +#include "System.h" #include "Process.h" using std::string; @@ -1839,70 +1840,7 @@ void Window::SetActive (const Window& window) bool Window::IsAxEnabled (bool options) { -#ifdef ROBOT_OS_LINUX - - return true; - -#endif -#ifdef ROBOT_OS_MAC - - // Statically load all required functions one time - static dispatch_once_t once; - dispatch_once (&once, ^{ - // Open the framework - void* handle = dlopen - ("/System/Library/Frameworks/Application" - "Services.framework/ApplicationServices", RTLD_LAZY); - - // Validate the handle - if (handle != nullptr) - { - *(void**) (&gAXIsProcessTrustedWithOptions) = - dlsym (handle, "AXIsProcessTrustedWithOptions"); - - gkAXTrustedCheckOptionPrompt = (CFStringRef*) - dlsym (handle, "kAXTrustedCheckOptionPrompt"); - } - }); - - // Check for new OSX 10.9 function - if (gAXIsProcessTrustedWithOptions) - { - // Check whether to show prompt - auto displayPrompt = options ? - kCFBooleanTrue : kCFBooleanFalse; - - // Convert display prompt value into a dictionary - const void* k[] = { *gkAXTrustedCheckOptionPrompt }; - const void* v[] = { displayPrompt }; - CFDictionaryRef o = CFDictionaryCreate - (nullptr, k, v, 1, nullptr, nullptr); - - // Determine whether the process is actually trusted - bool result = (*gAXIsProcessTrustedWithOptions) (o); - - // Free memory - CFRelease (o); - return result; - } - - else - { - // Ignore deprecated warnings - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - - // Check whether we have accessibility access - return AXAPIEnabled() || AXIsProcessTrusted(); - #pragma clang diagnostic pop - } - -#endif -#ifdef ROBOT_OS_WIN - - return true; - -#endif + return System::IsAxEnabled (options); } //////////////////////////////////////////////////////////////////////////////// diff --git a/Source/Window.h b/Source/Window.h index 7e06f1e..208a49e 100644 --- a/Source/Window.h +++ b/Source/Window.h @@ -97,7 +97,7 @@ class ROBOT_EXPORT Window static Window GetActive (void); static void SetActive (const Window& window); - static bool IsAxEnabled (bool options = false); + static bool IsAxEnabled (bool options = false); // #Deprecated private: static WindowList GetList (const char* title, int32 pid); diff --git a/Test/Main.cc b/Test/Main.cc index 5c2967d..31b3101 100644 --- a/Test/Main.cc +++ b/Test/Main.cc @@ -52,7 +52,7 @@ int main (int argc, const char* argv[]) #endif #endif - cout << (Process::IsSys64Bit() ? " 64\n" : " 32\n") + cout << (System::Is64Bit() ? " 64\n" : " 32\n") << "------------------------------\n" << "(C) 2010-2017 Robot Developers\n\n" @@ -67,15 +67,16 @@ int main (int argc, const char* argv[]) { cout << "MAIN MENU\n" << "------------------------------\n" - << " 1: Types \n" - << " 2: Timer \n" - << " 3: Keyboard \n" - << " 4: Mouse \n" - << " 5: Process \n" - << " 6: Window \n" - << " 7: Memory \n" - << " 8: Screen \n" - << " 9: Clipboard\n\n"; + << " 1: Types \n" + << " 2: System \n" + << " 3: Timer \n" + << " 4: Keyboard \n" + << " 5: Mouse \n" + << " 6: Process \n" + << " 7: Window \n" + << " 8: Memory \n" + << " 9: Screen \n" + << " 10: Clipboard\n\n"; // Ask the user to make a selection cout << "Enter component(s) to test: "; @@ -89,16 +90,17 @@ int main (int argc, const char* argv[]) bool result; switch (selection) { - case 1: result = TestTypes (); break; - case 2: result = TestTimer (); break; - case 3: result = TestKeyboard (); break; - case 4: result = TestMouse (); break; - case 5: result = TestProcess (); break; - case 6: result = TestWindow (); break; - case 8: result = TestScreen (); break; - case 9: result = TestClipboard(); break; - - case 7: + case 1: result = TestTypes (); break; + case 2: result = TestSystem (); break; + case 3: result = TestTimer (); break; + case 4: result = TestKeyboard (); break; + case 5: result = TestMouse (); break; + case 6: result = TestProcess (); break; + case 7: result = TestWindow (); break; + case 9: result = TestScreen (); break; + case 10: result = TestClipboard(); break; + + case 8: cout << uppercase; result = TestMemory(); cout << nouppercase; diff --git a/Test/Memory.cc b/Test/Memory.cc index 9a52fd5..2454cd4 100644 --- a/Test/Memory.cc +++ b/Test/Memory.cc @@ -469,9 +469,9 @@ static bool TestParams (void) VERIFY (m.GetProcess() == p); cout << "Please verify the following\n" << hex - << "Min VM: 0x" << m.GetMinAddress() << "\n" - << "Max VM: 0x" << m.GetMaxAddress() << "\n" - << "PgSize: 0x" << m.GetPageSize () << "\n\n" << dec; + << "Min VM: 0x" << setw (12) << setfill ('0') << m.GetMinAddress() << "\n" + << "Max VM: 0x" << setw (12) << setfill ('0') << m.GetMaxAddress() << "\n" + << "PgSize: 0x" << setw (12) << setfill ('0') << m.GetPageSize () << "\n\n" << dec; //----------------------------------------------------------------------------// @@ -1703,7 +1703,7 @@ bool TestMemory (void) while (stream >> selection) { // Check for valid selection requirements - if ((selection == 0 || selection >= 9) && + if ((selection == 0 || selection >= 8) && p2.GetName().substr (0, 4) != "Peon") { cout << "This test requires selecting Peon!\n\n"; diff --git a/Test/Peon.vs12.vcxproj b/Test/Peon.vs12.vcxproj index 440ef7f..532e3a7 100644 --- a/Test/Peon.vs12.vcxproj +++ b/Test/Peon.vs12.vcxproj @@ -83,4 +83,4 @@ - \ No newline at end of file + diff --git a/Test/Peon.vs13.vcxproj b/Test/Peon.vs13.vcxproj index 0b7083f..c6c729e 100644 --- a/Test/Peon.vs13.vcxproj +++ b/Test/Peon.vs13.vcxproj @@ -83,4 +83,4 @@ - \ No newline at end of file + diff --git a/Test/Peon.vs15.vcxproj b/Test/Peon.vs15.vcxproj index b3a04b3..6202f68 100644 --- a/Test/Peon.vs15.vcxproj +++ b/Test/Peon.vs15.vcxproj @@ -83,4 +83,4 @@ - \ No newline at end of file + diff --git a/Test/Process.cc b/Test/Process.cc index 83036d2..d3cd3b5 100644 --- a/Test/Process.cc +++ b/Test/Process.cc @@ -110,8 +110,8 @@ static bool TestSelect (void) #endif - int32 pid1 = atoi (input1); VERIFY (pid1 > 0); VERIFY (p1.Open (pid1)); - int32 pid2 = atoi (input2); VERIFY (pid2 > 0); VERIFY (p2.Open (pid2)); + auto pid1 = atoi (input1); VERIFY (pid1 > 0); VERIFY (p1.Open (pid1)); + auto pid2 = atoi (input2); VERIFY (pid2 > 0); VERIFY (p2.Open (pid2)); VERIFY (p1.IsValid()); VERIFY (!p1.HasExited()); VERIFY (p2.IsValid()); VERIFY (!p2.HasExited()); @@ -193,7 +193,7 @@ static bool TestCurrent (void) cout << "Input this application's PID: "; char input[32] = { 0 }; cin.getline (input, 32); - int32 pid = atoi (input); + auto pid = atoi (input); VERIFY (pid > 0); Process p1 (pid); diff --git a/Test/Screen.cc b/Test/Screen.cc index 42029fb..4254ab5 100644 --- a/Test/Screen.cc +++ b/Test/Screen.cc @@ -81,50 +81,6 @@ static bool TestInvalid (void) //////////////////////////////////////////////////////////////////////////////// -static bool TestAero (void) -{ -#if defined (ROBOT_OS_LINUX) || \ - defined (ROBOT_OS_MAC ) - - VERIFY (Screen::IsCompositing()); - - Screen::SetCompositing (false); - VERIFY (Screen::IsCompositing()); - - Screen::SetCompositing (true ); - VERIFY (Screen::IsCompositing()); - -#endif -#ifdef ROBOT_OS_WIN - - cout << "Composition status: " - << (Screen::IsCompositing() ? - "enabled" : "disabled"); - getchar(); - - Screen::SetCompositing (false); - - cout << "Composition status: " - << (Screen::IsCompositing() ? - "enabled" : "disabled"); - getchar(); - - Screen::SetCompositing (true ); - - cout << "Composition status: " - << (Screen::IsCompositing() ? - "enabled" : "disabled"); - getchar(); - - cout << endl; - -#endif - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// - static bool TestSync (void) { VERIFY (Screen::Synchronize()); @@ -150,9 +106,9 @@ static bool TestSync (void) if (i == 0) { VERIFY (list[i] == main); } else { VERIFY (list[i] != main); } - const char* sPort = list[i]->IsPortrait () ? "true" : "false"; - const char* sLand = list[i]->IsLandscape() ? "true" : "false"; - const char* sMain = (list[i] == main ) ? "true" : "false"; + const char* sPort = list[i]->IsPortrait () ? "True" : "False"; + const char* sLand = list[i]->IsLandscape() ? "True" : "False"; + const char* sMain = (list[i] == main ) ? "True" : "False"; cout << "Screen " << i << endl << "Bounds: " << list[i]->GetBounds() << endl @@ -397,10 +353,9 @@ bool TestScreen (void) << "------------------------------\n" << " 0: All \n" << " 1: Invalid\n" - << " 2: Aero \n" - << " 3: Sync \n" - << " 4: Grab \n" - << " 5: Perf \n\n"; + << " 2: Sync \n" + << " 3: Grab \n" + << " 4: Perf \n\n"; // Ask the user to make a selection cout << "Enter component(s) to test: "; @@ -415,7 +370,6 @@ bool TestScreen (void) if (selection == 0) { return TestInvalid() - && TestAero () && TestSync () && TestGrab () && TestPerf (); @@ -424,10 +378,9 @@ bool TestScreen (void) switch (selection) { case 1: if (!TestInvalid()) return false; break; - case 2: if (!TestAero ()) return false; break; - case 3: if (!TestSync ()) return false; break; - case 4: if (!TestGrab ()) return false; break; - case 5: if (!TestPerf ()) return false; break; + case 2: if (!TestSync ()) return false; break; + case 3: if (!TestGrab ()) return false; break; + case 4: if (!TestPerf ()) return false; break; } } diff --git a/Test/System.cc b/Test/System.cc new file mode 100644 index 0000000..64b77ad --- /dev/null +++ b/Test/System.cc @@ -0,0 +1,163 @@ +//////////////////////////////////////////////////////////////////////////////// +// -------------------------------------------------------------------------- // +// // +// (C) 2010-2017 Robot Developers // +// See LICENSE for licensing info // +// // +// -------------------------------------------------------------------------- // +//////////////////////////////////////////////////////////////////////////////// + +//----------------------------------------------------------------------------// +// Prefaces // +//----------------------------------------------------------------------------// + +#include "Test.h" + + + +//----------------------------------------------------------------------------// +// Locals // +//----------------------------------------------------------------------------// + +//////////////////////////////////////////////////////////////////////////////// + +static bool TestGenericInfo (void) +{ + cout << "Is64Bit : " << (System::Is64Bit () ? "True" : "False") << "\n" + << "IsUserAdmin : " << (System::IsUserAdmin() ? "True" : "False") << "\n" + << "IsAxEnabled : " << (System::IsAxEnabled() ? "True" : "False") << "\n\n"; + + cout << uppercase << hex + << "MinAddress : 0x" << setw (12) << setfill ('0') << System::GetMinAddress () << "\n" + << "MaxAddress32: 0x" << setw (12) << setfill ('0') << System::GetMaxAddress32() << "\n" + << "MaxAddress64: 0x" << setw (12) << setfill ('0') << System::GetMaxAddress64() << "\n" + << "PageSize : 0x" << setw (12) << setfill ('0') << System::GetPageSize () << "\n\n" + << nouppercase << dec; + + cout << "Please verify these results\n"; getchar(); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// + +static bool TestCompositing (void) +{ +#if defined (ROBOT_OS_LINUX) || \ + defined (ROBOT_OS_MAC ) + + VERIFY (System::IsCompositing()); + + System::SetCompositing (false); + VERIFY (System::IsCompositing()); + + System::SetCompositing (true ); + VERIFY (System::IsCompositing()); + +#endif +#ifdef ROBOT_OS_WIN + + cout << "Composition status: " + << (System::IsCompositing() ? + "enabled" : "disabled"); + getchar(); + + System::SetCompositing (false); + + cout << "Composition status: " + << (System::IsCompositing() ? + "enabled" : "disabled"); + getchar(); + + System::SetCompositing (true ); + + cout << "Composition status: " + << (System::IsCompositing() ? + "enabled" : "disabled"); + getchar(); + + cout << endl; + +#endif + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// + +static bool TestPrivileges (void) +{ +#if defined (ROBOT_OS_LINUX) || \ + defined (ROBOT_OS_MAC ) + + VERIFY (System::AdjustPrivilege ("")); + +#endif +#ifdef ROBOT_OS_WIN + + cout << "Warning: This test must be ran as a standalone app!\n"; + cout << "Enter PID of an application on another user account: "; + char input[32] = { 0 }; + cin.getline (input, 32); + auto pid = atoi (input); + + cout << endl; + Process process; + VERIFY (pid > 0); + + VERIFY (!process.Open (pid)); process.Close(); + + VERIFY (System::AdjustPrivilege ("SeDebugPrivilege", true )); + VERIFY ( process.Open (pid)); process.Close(); + + VERIFY (System::AdjustPrivilege ("SeDebugPrivilege", false)); + VERIFY (!process.Open (pid)); process.Close(); + +#endif + + return true; +} + + + +//----------------------------------------------------------------------------// +// Functions // +//----------------------------------------------------------------------------// + +//////////////////////////////////////////////////////////////////////////////// + +bool TestSystem (void) +{ + cout << "TEST SYSTEM\n" + << "------------------------------\n" + << " 0: All \n" + << " 1: GenericInfo\n" + << " 2: Compositing\n" + << " 3: Privileges \n\n"; + + // Ask the user to make a selection + cout << "Enter component(s) to test: "; + string input; getline (cin, input); + + int selection; cout << endl; + // Tokenize the input value + stringstream stream (input); + while (stream >> selection) + { + // Test everything + if (selection == 0) + { + return TestGenericInfo() + && TestCompositing() + && TestPrivileges (); + } + + switch (selection) + { + case 1: if (!TestGenericInfo()) return false; break; + case 2: if (!TestCompositing()) return false; break; + case 3: if (!TestPrivileges ()) return false; break; + } + } + + return true; +} diff --git a/Test/Test.h b/Test/Test.h index c17cf18..0e3dd13 100644 --- a/Test/Test.h +++ b/Test/Test.h @@ -174,6 +174,7 @@ inline ostream& operator << (ostream& out, const Bounds& bounds) //----------------------------------------------------------------------------// bool TestTypes (void); +bool TestSystem (void); bool TestTimer (void); bool TestKeyboard (void); bool TestMouse (void); diff --git a/Test/Test.vs12.vcxproj b/Test/Test.vs12.vcxproj index 65fd1e3..95d0d69 100644 --- a/Test/Test.vs12.vcxproj +++ b/Test/Test.vs12.vcxproj @@ -46,6 +46,7 @@ + @@ -255,7 +256,7 @@ true true $(SolutionDir)\Binaries\Win32\ - Robot.lib;Psapi.lib;%(AdditionalDependencies) + Robot.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX86 @@ -279,7 +280,7 @@ true true $(SolutionDir)\Binaries\Win64\ - Robot.lib;Psapi.lib;%(AdditionalDependencies) + Robot.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX64 @@ -297,7 +298,7 @@ Console true $(SolutionDir)\Binaries\Win32\ - Robotd.lib;Psapi.lib;%(AdditionalDependencies) + Robotd.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX86 @@ -315,7 +316,7 @@ Console true $(SolutionDir)\Binaries\Win64\ - Robotd.lib;Psapi.lib;%(AdditionalDependencies) + Robotd.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX64 @@ -325,4 +326,4 @@ - \ No newline at end of file + diff --git a/Test/Test.vs12.vcxproj.filters b/Test/Test.vs12.vcxproj.filters index 65fd334..dc10fa9 100644 --- a/Test/Test.vs12.vcxproj.filters +++ b/Test/Test.vs12.vcxproj.filters @@ -29,6 +29,9 @@ Tests + + Tests + Tests @@ -41,4 +44,4 @@ - \ No newline at end of file + diff --git a/Test/Test.vs13.vcxproj b/Test/Test.vs13.vcxproj index ed5c560..14cf8bd 100644 --- a/Test/Test.vs13.vcxproj +++ b/Test/Test.vs13.vcxproj @@ -46,6 +46,7 @@ + @@ -255,7 +256,7 @@ true true $(SolutionDir)\Binaries\Win32\ - Robot.lib;Psapi.lib;%(AdditionalDependencies) + Robot.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX86 @@ -279,7 +280,7 @@ true true $(SolutionDir)\Binaries\Win64\ - Robot.lib;Psapi.lib;%(AdditionalDependencies) + Robot.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX64 @@ -297,7 +298,7 @@ Console true $(SolutionDir)\Binaries\Win32\ - Robotd.lib;Psapi.lib;%(AdditionalDependencies) + Robotd.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX86 @@ -315,7 +316,7 @@ Console true $(SolutionDir)\Binaries\Win64\ - Robotd.lib;Psapi.lib;%(AdditionalDependencies) + Robotd.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX64 @@ -325,4 +326,4 @@ - \ No newline at end of file + diff --git a/Test/Test.vs13.vcxproj.filters b/Test/Test.vs13.vcxproj.filters index 65fd334..dc10fa9 100644 --- a/Test/Test.vs13.vcxproj.filters +++ b/Test/Test.vs13.vcxproj.filters @@ -29,6 +29,9 @@ Tests + + Tests + Tests @@ -41,4 +44,4 @@ - \ No newline at end of file + diff --git a/Test/Test.vs15.vcxproj b/Test/Test.vs15.vcxproj index 1eb13dc..67d7994 100644 --- a/Test/Test.vs15.vcxproj +++ b/Test/Test.vs15.vcxproj @@ -46,6 +46,7 @@ + @@ -255,7 +256,7 @@ true true $(SolutionDir)\Binaries\Win32\ - Robot.lib;Psapi.lib;%(AdditionalDependencies) + Robot.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX86 @@ -279,7 +280,7 @@ true true $(SolutionDir)\Binaries\Win64\ - Robot.lib;Psapi.lib;%(AdditionalDependencies) + Robot.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX64 @@ -297,7 +298,7 @@ Console true $(SolutionDir)\Binaries\Win32\ - Robotd.lib;Psapi.lib;%(AdditionalDependencies) + Robotd.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX86 @@ -315,7 +316,7 @@ Console true $(SolutionDir)\Binaries\Win64\ - Robotd.lib;Psapi.lib;%(AdditionalDependencies) + Robotd.lib;Dwmapi.lib;Psapi.lib;%(AdditionalDependencies) MachineX64 @@ -325,4 +326,4 @@ - \ No newline at end of file + diff --git a/Test/Test.vs15.vcxproj.filters b/Test/Test.vs15.vcxproj.filters index 65fd334..dc10fa9 100644 --- a/Test/Test.vs15.vcxproj.filters +++ b/Test/Test.vs15.vcxproj.filters @@ -29,6 +29,9 @@ Tests + + Tests + Tests @@ -41,4 +44,4 @@ - \ No newline at end of file + diff --git a/Test/Window.cc b/Test/Window.cc index 22199c8..b08d6c9 100644 --- a/Test/Window.cc +++ b/Test/Window.cc @@ -614,11 +614,8 @@ static bool TestGetList2 (void) bool TestWindow (void) { cout << "TEST WINDOW\n" - << "------------------------------\n"; - - VERIFY (Window::IsAxEnabled()); - - cout << " 0: All \n" + << "------------------------------\n" + << " 0: All \n" << " 1: Invalid \n" << " 2: Select1 \n" << " 3: Select2 \n"