Microsoft TSF - Using ITfThreadMgr::GetFocus like IUIAutomation::GetFocusedElement - windows

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.

Related

async_write_some callback not called after delay

My callback for async_write_some is not called after a one second sleep. If I am starting an io_service worker thread for every write, why is the callback not being called?
header
boost::system::error_code error_1;
boost::shared_ptr <boost::asio::io_service> io_service_1;
boost::shared_ptr <boost::asio::ip::tcp::socket> socket_1;
connect
void eth_socket::open_eth_socket (void)
{
// 1. reset io services
io_service_1.reset();
io_service_1 = boost::make_shared <boost::asio::io_service> ();
// 2. create endpoint
boost::asio::ip::tcp::endpoint remote_endpoint(
boost::asio::ip::address::from_string("10.0.0.3"),
socket_1_port
);
// 3. reset socket
socket_1.reset(new boost::asio::ip::tcp::socket(*io_service_1));
// 4. connect socket
socket_1->async_connect(remote_endpoint,
boost::bind(
&eth_socket::socket_1_connect_callback,
this, boost::asio::placeholders::error
)
);
// 5. start io_service_1 run thread after giving it work
boost::thread t(boost::bind(&boost::asio::io_service::run, *&io_service_1));
return;
}
write
void eth_socket::write_data (std::string data)
{
// 1. check socket status
if (!socket_1->is_open())
{
WARNING << "socket_1 is not open";
throw -3;
}
// 2. start asynchronous write
socket_1->async_write_some(
boost::asio::buffer(data.c_str(), data.size()),
boost::bind(
&eth_socket::socket_1_write_data_callback,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
// 3. start io_service_1 run thread after giving it work
boost::thread t(boost::bind(&boost::asio::io_service::run, *&io_service_1));
return;
}
callback
void eth_socket::socket_1_write_data_callback (const boost::system::error_code& error, size_t bytes_transferred)
{
// 1. check for errors
if (error)
{
ERROR << "error.message() >> " << error.message().c_str();
return;
}
if (socket_1.get() == NULL || !socket_1->is_open())
{
WARNING << "serial_port_1 is not open";
return;
}
INFO << "data written to 10.0.0.3:1337 succeeded; bytes_transferred = " << bytes_transferred;
return;
}
test
open_eth_socket();
write_data("Hello"); // callback called
write_data("Hello"); // callback called
write_data("Hello"); // callback called
sleep(1);
write_data("Hello"); // callback not called after sleep
boost::thread t(boost::bind(&boost::asio::io_service::run, *&io_service_1));
That's weird for a number of reasons.
You should not "run" io_services for each operation. Instead, run them steadily while operations may be posted. Optionally use io_service::work to prevent run from returning.
You should not (have to) create threads for each operation. If anything, it's recipe for synchronization issues (Why do I need strand per connection when using boost::asio?)
When running io_service again after it returned (without error) you should call reset() first, as per documentation (Why must io_service::reset() be called?)
You destruct a non-detached thread - likely before it had completed. If you had used std::thread this would even have caused immediate abnormal program termination. It's bad practice to not-join non-detached threads (and I'd add it's iffy to use detached threads without explicit synchronization on thread termination). See Why is destructor of boost::thread detaching joinable thread instead of calling terminate() as standard suggests?
I'd add to these top-level concerns
the smell from using names like socket_1 (just call it socket_ and instantiate another object with a descriptive name to contain the other socket_). I'm not sure, but the question does raise suspicion these might even be global variables. (I hope that's not the case)
throw-ing raw integers, really?
You are risking full on data-races by destructing io_service while never checking that worker threads had completed.
More Undefined Behaviour here:
_sock.async_write_some(
ba::buffer(data.c_str(), data.size()),
You pass a reference to the parameter data which goes out of scope. When the async operation completes, it will be a dangling reference
There's some obvious copy/paste trouble going on here:
if (socket_1.get() == NULL || !socket_1->is_open())
{
WARNING << "serial_port_1 is not open";
return;
}
I'd actually say this stems from precisely the same source that lead to the variable names being serial_port_1 and socket_1
Some Cleanup
Simplify. There wasn't self-contained code, so nothing complete here, but at least see the many points of simplification:
Live On Coliru
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <iostream>
namespace ba = boost::asio;
using ba::ip::tcp;
using boost::system::error_code;
#define ERROR std::cerr
#define WARNING std::cerr
#define INFO std::cerr
struct eth_socket {
~eth_socket() {
_work.reset();
if (_worker.joinable())
_worker.join(); // wait
}
void open(std::string address);
void write_data(std::string data);
private:
void connected(error_code error) {
if (error)
ERROR << "Connect failed: " << error << "\n";
else
INFO << "Connected to " << _sock.remote_endpoint() << "\n";
}
void written(error_code error, size_t bytes_transferred);
private:
ba::io_service _svc;
boost::optional<ba::io_service::work> _work{ _svc };
boost::thread _worker{ [this] { _svc.run(); } };
std::string _data;
unsigned short _port = 6767;
tcp::socket _sock{ _svc };
};
void eth_socket::open(std::string address) {
tcp::endpoint remote_endpoint(ba::ip::address::from_string(address), _port);
_sock.async_connect(remote_endpoint, boost::bind(&eth_socket::connected, this, _1));
}
void eth_socket::write_data(std::string data) {
_data = data;
_sock.async_write_some(ba::buffer(_data), boost::bind(&eth_socket::written, this, _1, _2));
}
void eth_socket::written(error_code error, size_t bytes_transferred) {
INFO << "data written to " << _sock.remote_endpoint() << " " << error.message() << ";"
<< "bytes_transferred = " << bytes_transferred << "\n";
}
int main() {
{
eth_socket s;
s.open("127.0.0.1");
s.write_data("Hello"); // callback called
s.write_data("Hello"); // callback called
s.write_data("Hello"); // callback called
boost::this_thread::sleep_for(boost::chrono::seconds(1));
s.write_data("Hello"); // callback not called after sleep
} // orderly worker thread join here
}
My problems are now fixed thanks to sehe's help and prayer.
This line in open_eth_socket:
boost::thread t(boost::bind(&boost::asio::io_service::run, *&io_service_1));
is now this:
boost::shared_ptr <boost::thread> io_service_1_thread; // in header
if (io_service_1_thread.get()) io_service_1_thread->interrupt();
io_service_1_thread.reset(new boost::thread (boost::bind(&eth_socket::run_io_service_1, this)));
I added this function:
void eth_socket::run_io_service_1 (void)
{
while (true) // work forever
{
boost::asio::io_service::work work(*io_service_1);
io_service_1->run();
io_service_1->reset(); // not sure if this will cause problems yet
INFO << "io_service_1 run complete";
boost::this_thread::sleep (boost::posix_time::milliseconds (100));
}
return;
}

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;
}

trying to understand gsoap

I am creating my first web service client using gsoap. I was able to the run the calc example provided with gsoap.
Now I am trying to access String GetData() function from WCF Webservice. I did the wsdl2h and soapcpp2 steps and have generated the .h file. In xxxxproxy.h I see that the prototype of GetData is as follows
/// Web service operation 'GetData' (returns error code or SOAP_OK)
virtual int GetData(_ns1__GetData *ns1__GetData, _ns1__GetDataResponse *ns1__GetDataResponse);
Can someone tell me what should I write in my main.cpp to access GetData. I have following code in main.cpp
#include <QtCore/QCoreApplication>
#include "soapWSHttpBinding_USCOREIAquaLinkProxy.h"
#include "WSHttpBinding_USCOREIAquaLink.nsmap"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WSHttpBinding_USCOREIAquaLinkProxy webService;
std::cout <<"Sent request"<<std::endl;
std::string result;
if(webService.GetData(?????? )==SOAP_OK)
{
std::cout << "Returned "<< ????? <<std::endl;
}
else
{
webService.soap_stream_fault(std::cerr);
}
return a.exec();
}
Thanks.
The first argument _ns1__GetData in the function GetData is the request argument, the second is the response argument. You should try following:
_ns1__GetData request;
request.???? = ???? // I don't know the WCF Webservice
_ns1__GetDataResponse response;
if(webService.GetData(&request, &response) == SOAP_OK)
{
std::cout << "Returned " << response.????;
}
I don't know the WCF Webservice. But I guess that you have to fill the request instance with some values. What makes me wonder is, that the class names _ns1__GetData and _ns1__GetDataResponse begin with an underscore. I'm using gSoap for a long time and the names were always without beginning underscore.

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.

InternetCheckConnection always return false

I want to use the Wininet function InternetCheckConnection to check whenever the machine is connected to the internet and can access a specific host.
The problem is that this function is always returning false, no matter the URL I put on it.
MSDN link
Following combination works for me on Windows 7 and Windows XP SP3:
InternetCheckConnection("http://www.google.com", FLAG_ICC_FORCE_CONNECTION, 0) ;
GetLastError() returns 0 if the connexion is possible and it returns
12029 (The attempt to connect to the server failed) if not.
Following combonations don't work for me :
InternetCheckConnection(NULL, FLAG_ICC_FORCE_CONNECTION, 0) ;
GetLastError() returns 12016 (The requested operation is invalid).
InternetCheckConnection(NULL, 0, 0) ;
InternetCheckConnection(("http://www.google.com", 0, 0) ;
for both GetLastError() returns 2250 (The network connection could not be found).
Have you checked GetLastError() ? If I read MSDN correctly, you would need to check for ERROR_NOT_CONNECTED to determine whether you're truly offline.
Just a wild guess, but perhaps this is due to a personal firewall blocking all outgoing connections for one of the Windows DLLs and / or your application?
According to Microsoft API document InternetCheckConnection is deprecated.
[InternetCheckConnection is available for use in the operating systems specified in the Requirements section. It may be altered or unavailable in subsequent versions. Instead, use NetworkInformation.GetInternetConnectionProfile or the NLM Interfaces. ]
Instead of this API we can use INetworkListManager interface to check whether Internet is connected or not for windows platform.
Here below is the win32 codebase :
#include <iostream>
#include <ObjBase.h> // include the base COM header
#include <Netlistmgr.h>
// Instruct linker to link to the required COM libraries
#pragma comment(lib, "ole32.lib")
using namespace std;
enum class INTERNET_STATUS
{
CONNECTED,
DISCONNECTED,
CONNECTED_TO_LOCAL,
CONNECTION_ERROR
};
INTERNET_STATUS IsConnectedToInternet();
int main()
{
INTERNET_STATUS connectedStatus = INTERNET_STATUS::CONNECTION_ERROR;
connectedStatus = IsConnectedToInternet();
switch (connectedStatus)
{
case INTERNET_STATUS::CONNECTED:
cout << "Connected to the internet" << endl;
break;
case INTERNET_STATUS::DISCONNECTED:
cout << "Internet is not available" << endl;
break;
case INTERNET_STATUS::CONNECTED_TO_LOCAL:
cout << "Connected to the local network." << endl;
break;
case INTERNET_STATUS::CONNECTION_ERROR:
default:
cout << "Unknown error has been occurred." << endl;
break;
}
}
INTERNET_STATUS IsConnectedToInternet()
{
INTERNET_STATUS connectedStatus = INTERNET_STATUS::CONNECTION_ERROR;
HRESULT hr = S_FALSE;
try
{
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
INetworkListManager* pNetworkListManager;
hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, __uuidof(INetworkListManager), (LPVOID*)&pNetworkListManager);
if (SUCCEEDED(hr))
{
NLM_CONNECTIVITY nlmConnectivity = NLM_CONNECTIVITY::NLM_CONNECTIVITY_DISCONNECTED;
VARIANT_BOOL isConnected = VARIANT_FALSE;
hr = pNetworkListManager->get_IsConnectedToInternet(&isConnected);
if (SUCCEEDED(hr))
{
if (isConnected == VARIANT_TRUE)
connectedStatus = INTERNET_STATUS::CONNECTED;
else
connectedStatus = INTERNET_STATUS::DISCONNECTED;
}
if (isConnected == VARIANT_FALSE && SUCCEEDED(pNetworkListManager->GetConnectivity(&nlmConnectivity)))
{
if (nlmConnectivity & (NLM_CONNECTIVITY_IPV4_LOCALNETWORK | NLM_CONNECTIVITY_IPV4_SUBNET | NLM_CONNECTIVITY_IPV6_LOCALNETWORK | NLM_CONNECTIVITY_IPV6_SUBNET))
{
connectedStatus = INTERNET_STATUS::CONNECTED_TO_LOCAL;
}
}
pNetworkListManager->Release();
}
}
CoUninitialize();
}
catch (...)
{
connectedStatus = INTERNET_STATUS::CONNECTION_ERROR;
}
return connectedStatus;
}

Resources