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;
}
Related
here is code snippet i try to compile, which result to compile error:
convert const char * to int is invalid;
can anyone help debug this code ?
thanks in advance!
#include <iostream>
#include <typeinfo>
using namespace std;
int sums() { return 0; }
template <typename Type, typename... T>
int sums(const Type s, const T... args)
{
int res = 0;
if (typeid(s) == typeid(int))
{
res += s;
}
else
{
cout << "not int" << s << endl;
}
res += sums(args...);
return res;
}
int main()
{
cout << sums(1,"sir", 4) << endl;
return 0;
}
You try to do different things for different types, but a normal if in combination with typeid is evaluated at runtime. That mean that the compiler must generate code for both cases, because the evaluation which is executed is not clear at compiler time.
To fix this problem you must bring the decision from runtime to compile time.
Thats what if constexpr is for. It is evaluated at compile time and there you can write code in one branch that would not compile if the condition is not fulfilled
I am trying to experiment bind in C++. Basically I have two class - Invokee. The invokee class registers a test handler that needs to be invoked upon some callbacks. The method here is -
void RegisterTestHandler(int id, TestFunction handler, std::string summary, std::string details);
Similarly, I have another method that actually invokes what has been registered -
void callHandler(int id);
Another class Test which has a function that needs to be invoked on callHandler.
unsigned int globalReset(int val);
In the main function, I am doing the nullptr for the second parameter in the bind. However, it still works and I don't get any crashes. Is it something working because of the compiler optimisation or undefined behaviour or it is something to do with bind concept.
Here is the entire experimental code.
// main.cpp
#include <iostream>
#include "test.h"
#include "invokee.h"
#include <memory>
#include <functional>
// beautify using clang-format in Vscode.
int main(int argc, char **argv)
{
auto *invokeTest = new Invokee();
Test *test = new Test();
std::string summary = "global reset summary";
std::string details = "global reset details";
//Basically there are two object from different class - InvokeTest --> does the registration of the handler.
// Now the InvokeTest has to call the member function of class object - Test.
// ?? How it can do - it can do using bind - basically, the this pointer of Test class is available to invokeTest
// therefore invokeTest can simply invoke the member function of test object.
// until the test point is valid, it can use it to invoke the method of it ?? --> Is it really correct?
delete(test); //experiment deleted the test pointer.
test= nullptr; // explicity set to nullptr
// still it works?? how come ??
invokeTest->RegisterTestHandler(1, std::bind(&Test::globalReset, test, std::placeholders::_1), summary, details);
invokeTest->callHandler(1);
return 0;
}
Here is the invokee.cpp -
#include "invokee.h"
void Invokee::RegisterTestHandler(int id, TestFunction handler, std::string summary, std::string details)
{
this->handlers[id] = handler;
this->summary[id] = summary;
this->details[id] = details;
}
void Invokee::callHandler(int id)
{
auto handler = handlers.find(id);
if (handler != handlers.end())
{
std::cout << "Found the handler --" << std::endl;
handler->second(1);
}
}
Here is the test.cpp
#include <iostream>
#include "test.h"
unsigned int Test::globalReset(int val)
{
std::cout << "global Reset invoked" << std::endl;
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
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.
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.