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.
Related
I have the below example. (My actual project is a multi-threaded one and I have the terminate handler set for all of them.) I have a couple of questions here.
My terminate handler doesn't do anything fancy. It just says that an error occured and exits. I read that it i good practice to add the handler. Why is that so and do I really need in this case ?
If I don't have the handler, I get the type of exception thrown. terminate called after throwing an instance of 'char const*' But when I use the handler, I am unable to get it. Even if I use current_exception, I am unable to get the type of exception. (Here its obviously char* but in my case it could be anything so I can't catch correctly. Even if I use catch{...}, the message and type are lost). Is there anyway to get the message. If not message, atleast can I get type of the exception thrown ?
// set_terminate example
#include <iostream>
#include <exception>
#include <cstdlib>
using namespace std;
void myterminate () {
cerr << "terminate handler called\n";
abort(); // forces abnormal termination
}
int main (void) {
//set_terminate (myterminate);
throw "TEST"; // unhandled exception: calls terminate handler
return 0;
If you can live with the portability restriction implied by <cxxabi.h>1,
then you might be OK with the backstop() terminate-handler below:
main.cpp
#include <iostream>
#include <exception>
#include <stdexcept>
#include <cstdlib>
#include <cxxabi.h>
void backstop()
{
auto const ep = std::current_exception();
if (ep) {
try {
int status;
auto const etype = abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), 0, 0, &status);
std::cerr << "Terminating with uncaught exception of type `" << etype << "`";
std::rethrow_exception(ep);
} catch(const std::exception& e) {
std::cerr << " with `what()` = \"" << e.what() << "\"";
} catch(...) {}
std::cerr << std::endl;
}
std::abort();
}
int main(int argc, char *argv[])
{
std::set_terminate(backstop);
if (argc > 1) {
throw argv[1];
} else {
throw std::runtime_error("I am too tired to carry on");
}
return 0;
}
This will always report the type of the uncaught exception, and if that type derives from
std::exception, it will also report the what() of that exception. E.g.
$ g++ --version
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
...
$ g++ -Wall -Wextra -pedantic main.cpp; ./a.out Whoops!
Terminating with uncaught exception of type `char*`
Aborted (core dumped)
$ clang++ --version
clang version 10.0.0-4ubuntu1
...
$ clang++ -Wall -Wextra -pedantic main.cpp; ./a.out
Terminating with uncaught exception of type `std::runtime_error` with `what()` = "I am too tired to carry on"
Aborted (core dumped)
Note that you might avoid calling set_terminate(backstop) - which conceivably might be
countermanded someplace else in a big complicated program - and ensure that any
exception escaping the body of main is caught in a function try-block, i.e.
replace main with:
int main(int argc, char *argv[]) try
{
if (argc > 1) {
throw argv[1];
} else {
throw std::runtime_error("I am too tired to carry on");
}
return 0;
}
catch(...) {
backstop();
}
This program will behave just as before.
[1] You'll have at least g++, clang++, icc; you won't have MS C++
As your metioned, If you want to let your terminate do something fancy, you could write a terminate handler function and call it as a parameter of std::set_terminate.And I think it might be useful to add a backtrace in this function to give more information.Although the name of functions is mangled by the compiler, but still you could see where this error occurred.
And if you want to show the exception, you can add a try-catch block in terminate-handler function.
By the way, I think it may be necessary to using signal function to deal with segmental default error, by doing this your program is more complete in exception handle.
In utils.h file :
#include <stdexcept>
#include <execinfo.h>
#include <exception>
#include <stdexcept>
#include <cstdlib>
#include <csignal>
// This function is used for handle segmental fault
inline void segfaultHandler(int signal __attribute__((unused)))
{
void *stackArray[20];
size_t size = backtrace(stackArray, 10);
std::cerr << "Segmentation fault! backtrace: ";
char** backtrace = backtrace_symbols(stackArray, size);
for (size_t i = 0; i < size; i++)
{
std::cerr << "\t" << backtrace[i]
}
abort();
}
// This is terminate handle function
inline void exceptionHandler()
{
static bool triedThrow = false;
try
{
if(!triedThrow)
{
triedThrow = true;
throw;
}
}
catch( const std::exception &e)
{
std::cerr << "Caught unhandled exception: " << e.what();
}
catch(...){}
void *stackArray[20];
size_t size = backtrace(stackArray, 10);
std::cerr << "Segmentation fault! backtrace: ";
char** backtrace = backtrace_symbols(stackArray, size);
for (size_t i = 0; i < size; i++)
{
std::cerr << "\t" << backtrace[i]
}
abort();
}
And in main, Using Mike Kinghan's code for example
#include <iostream>
#include "utils.h"
int main(int argc, char *argv[])
{
signal(SIGSEGV, segfaultHandler);
std::set_terminate(exceptionHandler);
if (argc > 1) {
throw argv[1];
} else {
throw std::runtime_error("I am too tired to carry on");
}
return 0;
}
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
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;
}
When I try to attach to Microsoft Text Services Framework (TSF) outside the context of a text service, I can't retrieve the information I need to interact with the active application's text.
#include <SDKDDKVer.h>
#include <stdio.h>
#include <tchar.h>
#include <msctf.h>
#include <atlbase.h>
#include <iostream>
// Macro throws a descriptive WCHAR* exception if(FAILED(hr))
#define OK(hrExpr) do{std::cout<<"IN: "<<#hrExpr<<std::endl; HRESULT returnCode = hrExpr; if( FAILED(returnCode) ){std::cout<<std::endl<<"ERROR! "<<#hrExpr<<" #"<<__FILE__<<":"<<__LINE__<<" returned "<<returnCode<<std::endl; throw L#hrExpr; }else{std::cout << "OK: " << #hrExpr << std::endl;}}while(0)
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(0);
ITfThreadMgr* pThreadMgr = NULL;
TfClientId clientId = NULL;
ITfDocumentMgr* docMgr = NULL;
ITfContext* pContext = NULL;
try
{
std::cout << "Use the next 5 seconds to switch to a TSF-enabled application and make a text selection." << std::endl;
Sleep(5000);
OK( CoCreateInstance( CLSID_TF_ThreadMgr,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITfThreadMgr,
(void**)&pThreadMgr) );
OK( pThreadMgr->Activate(&clientId) );
OK( pThreadMgr->GetFocus(&docMgr) );
if (docMgr == NULL)
{
throw L"NULL document manager";
}
OK( docMgr->GetTop(&pContext) );
// TODO: use ITfContext to get selection or make document edits
}
catch(LPCSTR msg)
{
std::wcout << L"Exception: " << msg << std::endl;
}
catch(LPCWSTR msg)
{
std::wcout << L"Exception: " << msg << std::endl;
}
if (pContext)
pContext->Release();
if (docMgr)
docMgr->Release();
::CoUninitialize();
return 0;
}
I am using WordPad on Windows 7 as my target test application, and I make sure to have focus on WordPad by the time the TSF methods execute.
The program gets as far as trying to get the currently focused ITfDocumentMgr (ITfThreadMgr::GetFocus), but the returned document manager is NULL. According to the API documentation this means there is no currently focused ITfDocumentMgr, however:
If I take a completely different approach: register a custom text service and receive a ITfThreadMgr reference through ITfTextInputProcessor::Activate, I am able to retrieve the focused ITfDocumentMgr for WordPad via ITfThreadMgr::GetFocus. However for various reasons I would prefer not to install a custom inproc text service.
Is there any way to hook into the TSF API across process boundaries, as is possible with AutomationElement.FocusedElement, IUIAutomation::GetFocusedElement or AccessibleObjectFromWindow?
Text Services Framework doesn't work cross-process. There's neither proxies nor stubs available. Sorry.
Incidentally, your code is trying to get the focused doc manager for your process. You create the ITfThreadMgr using CLSCTX_INPROC_SERVER, which starts the thread manager in your process, not in the target.
how can i check whether a specific window is open or not. I only got part of the window's name. i thinking of using EnumWindows() in QT console app but i get a few errors stating "main.obj:-1: error: unresolved external symbol imp__GetWindowTextW#12 referenced in function "int __stdcall EnumWindowsProc(struct HWND *,long)" (?EnumWindowsProc##YGHPAUHWND__##J#Z)"
Below is my sample code
BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam) {
char buff[255];
if (IsWindowVisible(hWnd)) {
GetWindowText(hWnd, (LPWSTR) buff, 254);
}
return TRUE;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
EnumWindows(EnumWindowsProc, 0);
return 0;
}
That's a linker error rather than a compile error.
You have correctly included windows.h but you also need to add the import libraries to your linker options. All three Win32 functions in your sample code require you to link user32.lib.
EnumWindowsProc is not from Qt, it's a windows API function, you need to include windows.h
I did not use Qt, and the code can pass complie, but the output seems NOT right. Anyway, here's my code
#include <conio.h>
#include <iostream>
#include <windows.h>
using namespace std;
char buff[255];
BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam)
{
if (IsWindowVisible(hWnd))
{
GetWindowText(hWnd, (LPWSTR) buff, 254);
}
return TRUE;
}
int main()
{
EnumWindows(EnumWindowsProc, 0);
for(int i = 0; i != 254; ++i)
cout << buff[i];
getch();
return 0;
}
You can use:
Application.OpenForms["FormName"]
To check if the form is open or not.