How to detect screen lock (Qt5, C++, Windows, OSX) - windows

In my Qt5 C++ client, I'm wanting to detect when a user running Windows or OSX has locked the screen, then simultaneously lock my client application.
I have yet to come across a Qt5 class that provides this function, so I'm wondering if I'll need to write an OS-specific library. Does anyone have any experience doing something like this?
Thanks!

On windows you can use below code:
mywidget.cpp
#include "mywidget.h"
#include <Windows.h>
#include <WtsApi32.h>
#include <QDebug>
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
WTSRegisterSessionNotification((HWND)this->winId(), NOTIFY_FOR_THIS_SESSION);
}
MyWidget::~MyWidget()
{
WTSUnRegisterSessionNotification((HWND)this->winId());
}
bool MyWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
if (eventType != "windows_generic_MSG") return false;
MSG *msg = static_cast<MSG*>(message);
switch (msg->message) {
case WM_WTSSESSION_CHANGE:
qDebug() << "session change: " << msg->wParam;
}
return false;
}
project.pro
...
LIBS += -lwtsapi32
...
reference1
reference2

Related

What changes between C++98 and C++11 show difference in behavior?

I was reading the following post:
What changes introduced in C++14 can potentially break a program written in C++11?
and also the isocpp page:
https://isocpp.org/files/papers/p0636r0.html
So I became curious, according to the Standard: What changes introduced in C++11 can potentially break a program written in C++98?
Big one that stands out -- throwing exceptions from destructors.
In C++98 you can have programs that do this and work fine if you are careful.
In C++11 you will often have to explicitly declare the dtor noexcept(false).
Nice blog post here, on Andrzej's C++ blog.
In short, the following program used to run successfully in C++03 (under some definition of “success”):
struct S
{
~S() { throw runtime_error(""); } // bad, but acceptable
};
int main()
{
try { S s; }
catch (...) {
cerr << "exception occurred";
}
cout << "success";
}
In C++11, the same program will trigger the call to std::terminate.
Here is another case related to destructors are noexcept(true) in C++11:
// A simple program that demonstrates how C++11 and pthread_cancel don't play
// nicely together.
//
// If you build without C++11 support (g++ threadkill.cpp -lpthread), the
// application will work as expected. After 5 seconds, main() will cancel the
// thread it created and the program will successfully exit.
//
// If you build with C++11 support(g++ -std=c++11 threadkill.cpp -lpthread),
// the program will crash because the abi::__forced_unwind exception will
// escape the destructor, which is implicitly marked as noexcept(true) in
// C++11. If you mark the destructor as noexcept(false), the program does
// not crash.
#include <iostream>
#include <unistd.h>
#include <string.h>
class sleepyDestructorObject
{
public:
~sleepyDestructorObject() //noexcept(false)
{
std::cout << "sleepy destructor invoked" << std::endl;
while(true)
{
std::cout << "." << std::flush;
sleep(1);
}
}
};
void* threadFunc( void* lpParam )
{
sleepyDestructorObject sleepy;
return NULL;
}
int main(int argc, char** argv)
{
pthread_t tThreadID;
pthread_create(&tThreadID, NULL, threadFunc, NULL);
sleep(5);
pthread_cancel(tThreadID);
pthread_join(tThreadID, NULL);
return 0;
}
Original reference:
https://gcc.gnu.org/ml/gcc-help/2015-08/msg00036.html

Regarding CFLocaleCopyCurrent API incorrect return value

At my workplace, we are in a situation where following standalone code below,
#include <CoreFoundation/CoreFoundation.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <boost/cast.hpp>
// Reference release
struct reference_close
{
void operator()(const void *ref) const
{
CFRelease(static_cast<CFTypeRef>(ref));
}
}; // end of reference_close structure
typedef std::unique_ptr<const void, reference_close> reference_uptr;
std::string get_user_locale()
{
reference_uptr ref_ptr(CFLocaleCopyCurrent());
CFLocaleRef locale_ref(static_cast<CFLocaleRef>(ref_ptr.get()));
if (locale_ref == nullptr)
{
return std::string();
}
const size_t default_size(128);
std::vector<char> buff(default_size);
CFStringRef str_ref(CFLocaleGetIdentifier(locale_ref));
// CFStringRef str_ref((CFStringRef)CFLocaleGetValue(locale_ref,kCFLocaleLanguageCode));
if (str_ref != nullptr)
{
CFIndex len(CFStringGetLength(str_ref) + 1);
if (len > boost::numeric_cast<CFIndex>(default_size))
{
buff.resize(len);
}
buff[0] = 0;
if (!CFStringGetCString(str_ref, &buff[0], len, kCFStringEncodingISOLatin1))
{
return std::string();
}
}
return std::string(&buff[0]);
} // end of get_user_locale()
int main()
{
std::cout << "get_user_locale() : "<<get_user_locale() << std::endl;
return 0;
}
gives us a different output on OS X 10.12 and 10.13 beta.
This is what we do in a nutshell.
On 10.12 machine
1) Set the preference language as ru and region as RU
2) Restart the machine
3) Get the output of "defaults read -g AppleLocale" to make sure that output is
{
ru_RU
}
4) Compile the code, run the exe. We get the output as { ru_RU }.
We then repeat the steps 1) to 3) on OS X 10.13 (beta) machine and then run the same exe (created on 10.12, you might ask why, its because of some our internal build system restrictions ) on 10.13 machine and the output we get is "en_RU" which is not correct.
Are we missing something here ? Or is this a known problem in OS X 10.13 (beta) ? If so, how do we fix this ?
UPDATE
We also wrote a following Objective-C code to use NSLocale interface and that too gave us same results i.e ru_RU on 10.12 and en_RU on 10.13 (beta)
#import <Foundation/Foundation.h>
int main()
{
#autoreleasepool
{
NSLog(#"localeIdentifier: %#", [[NSLocale currentLocale] localeIdentifier]);
}
}
The reason we were getting an incorrect value is because our app was not localized into the locale we expected e.g ru.
We corrected this by adding an empty ru.lproj directory into our app's Contents/Resources directory and the API started giving us the correct answer.

LoadLibrary("bthprops.dll") fails, file not found

The Microsoft documentation for Bluetooth APIs such as BluetoothGetDeviceInfo provide instructions for calling these functions using either static or dynamic imports.
The static import, linking with bthprops.lib, works fine.
#include <windows.h>
#include <BluetoothAPIs.h>
#include <iostream>
int main(int argc, char** argv)
{
BLUETOOTH_DEVICE_INFO binfo = {};
binfo.dwSize = sizeof binfo;
binfo.Address.ullLong = 0xBAADDEADF00Dull;
auto result = ::BluetoothGetDeviceInfo(nullptr, &binfo);
std::wcout << L"BluetoothGetDeviceInfo returned " << result
<< L"\nand the name is \"" << binfo.szName << "\"\n";
return 0;
}
But this isn't ideal in ultra-portable code, because the documentation says they are not supported prior to Windows XP SP2. So one should use dynamic linking and recover from missing functions. However, dynamic loading bthprops.dll as instructed by the MSDN docs fails:
decltype(::BluetoothGetDeviceInfo)* pfnBluetoothGetDeviceInfo;
bool LoadBthprops( void )
{
auto dll = ::LoadLibraryW(L"bthprops.dll");
if (!dll) return false;
pfnBluetoothGetDeviceInfo = reinterpret_cast<decltype(pfnBluetoothGetDeviceInfo)>(::GetProcAddress(dll, "BluetoothGetDeviceInfo"));
return pfnBluetoothGetDeviceInfo != nullptr;
}
How should one dynamically link to these functions?
Apparently this fact is pretty well known to Google but not to MSDN. If you want to dynamically load these functions, use LoadLibrary("bthprops.cpl") which is the correct DLL name, contrary to the nice table in the function documentation.
This works:
decltype(::BluetoothGetDeviceInfo)* pfnBluetoothGetDeviceInfo;
bool LoadBthprops( void )
{
auto dll = ::LoadLibraryW(L"bthprops.cpl");
if (!dll) return false;
pfnBluetoothGetDeviceInfo = reinterpret_cast<decltype(pfnBluetoothGetDeviceInfo)>(::GetProcAddress(dll, "BluetoothGetDeviceInfo"));
return pfnBluetoothGetDeviceInfo != nullptr;
}

How to get the name of a console in Windows?

Is possible to get the name of a console in Windows? Just like is done by the C function ttyname in Unix systems
You can use the WinAPI GetConsoleTitle function to retrieve it.
You might find links to all of the console functions useful.
You didn't specify a language, so here's the one in C++ from MSDN
#include <windows.h>
#include <tchar.h>
#include <conio.h>
#include <strsafe.h>
int main( void )
{
TCHAR szOldTitle[MAX_PATH];
TCHAR szNewTitle[MAX_PATH];
// Save current console title.
if( GetConsoleTitle(szOldTitle, MAX_PATH) )
{
// Build new console title string.
StringCchPrintf(szNewTitle, MAX_PATH, TEXT("TEST: %s"), szOldTitle);
// Set console title to new title
if( !SetConsoleTitle(szNewTitle) )
{
_tprintf(TEXT("SetConsoleTitle failed (%d)\n"), GetLastError());
return 1;
}
else
{
_tprintf(TEXT("SetConsoleTitle succeeded.\n"));
}
}
return 0;
}

SetWindowsHookEx, CBTProc and g++3.4.5 (mingw)

I'm currently working on an application that needs to add a menu
to each application's system menu. I can accomplish that for the existing
windows with the EnumWindows function.
For the new windows (applications starting up after mine)
I'm trying to do this with windows hooks. More specifically with CBTProc.
This is where I'm stuck.
I've stripped about everything possible in the app,
but I've got the impression the procedure in my dll just doesn't
get called at all.
Here's the code for the dll:
#include <string>
using std::string;
#include <fstream>
using std::ofstream;
#include <windows.h>
// ---------------------------------------------------
extern "C"
{
void log(const string & msg)
{
ofstream out("out.log", std::ios_base::app);
out << msg;
out.flush();
out.close();
}
// ---------------------------------------------------
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
log("CBTProc");
return CallNextHookEx(0, nCode, wParam, lParam);
}
// ---------------------------------------------------
}
I compile this with g++ 3.4.5 on a windows xp sp3 32bit machine:
g++ -shared -otest.dll test_dll.cpp
And here's the code for the application
#include <iostream>
using std::cout;
using std::cin;
using std::cerr;
using std::endl;
#include <string>
using std::string;
#include <windows.h>
typedef void (*func)();
void run()
{
cout << "press enter to exit" << endl;
cin.get();
}
void * loadProc(HMODULE mod, const char * procname)
{
void * retval = (void *)GetProcAddress(mod, procname);
if (retval == NULL)
cerr << "GetProcAddress(" << procname << ") failed" << endl;
return retval;
}
int main(int argc, char ** argv)
{
HMODULE dll = LoadLibrary("test.dll");
if (dll == NULL)
{
cerr << "LoadLibrary failed" << endl;
return 1;
}
HOOKPROC proc = (HOOKPROC)loadProc(dll, "CBTProc#12");
if (!proc)
return 1;
HHOOK callwnd = SetWindowsHookEx(WH_CBT, proc, dll, 0);
if (callwnd == NULL)
{
cerr << "SetWindowsHookEx failed for CBTProc" << endl;
return 1;
}
run();
UnhookWindowsHookEx(callwnd);
return 0;
}
I compile this with the same setup:
g++ -otest.exe test.cpp
When I run, I get no errors, but when I start up new applications I get nothing
in my logfile.
Any ideas?
gr,
ldx
Edit: spelling errors
I'd suggest you to check the following:
ensure that your DLL has an export
(can be checked with dumpbin tool). I
don't know about g++, but in MSVC it
is necessary to either use
__declspec(dllexport) or explicitly state exports in DEF file.
ensure that your host application
uses the correct name of the
exported function (the same as
"dumpbin /EXPORTS test.dll"
displays)
keep in mind that you are are using relative file name out.log - when DLL gets loaded to other processes it would write relatively to the host process' current directory. For testing purposes it would be better to use OutputDebugString API and inspect results with DbgView tool.
Chances are that your solution works already.
PS: it's not generally a good idea to use STL in an injected DLL. Make sure you are aware of the risks.

Resources