2
//Copyright (c) 2007 Michael Curran <mick@kulgan.net>
3
//This file is covered by the GNU General Public Licence
4
//See the file Copying for details.
2
This file is a part of the NVDA project.
3
URL: http://www.nvda-project.org/
4
Copyright 2006-2010 NVDA contributers.
5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License version 2.0, as published by
7
the Free Software Foundation.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
This license can be found at:
12
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19
#define WIN32_LEAN_AND_MEAN
11
20
#include <windows.h>
13
21
#include "rpcSrv.h"
14
23
#include "inputLangChange.h"
15
24
#include "typedCharacter.h"
16
25
#include "IA2Support.h"
17
26
#include "ia2LiveRegions.h"
18
#include "nvdaController.h"
19
#include "nvdaControllerInternal.h"
20
#include <common/winIPCUtils.h>
21
#include <common/log.h>
22
29
#include "nvdaHelperRemote.h"
30
#include "inProcess.h"
24
32
using namespace std;
26
34
typedef map<WINEVENTPROC,size_t> winEventHookRegistry_t;
27
35
typedef map<HOOKPROC,size_t> windowsHookRegistry_t;
29
#pragma data_seg(".remoteShared")
30
wchar_t dllDirectory[MAX_PATH]={0};
32
#pragma comment(linker, "/section:.remoteShared,rws")
34
BOOL isInitialized=FALSE;
35
HINSTANCE moduleHandle;
36
BOOL inProcess_wasInitializedOnce=false;
37
BOOL inProcess_isRunning=false;
38
37
winEventHookRegistry_t inProcess_registeredWinEventHooks;
39
38
windowsHookRegistry_t inProcess_registeredCallWndProcWindowsHooks;
40
39
windowsHookRegistry_t inProcess_registeredGetMessageWindowsHooks;
41
HHOOK getMessageHookID=0;
42
HHOOK callWndProcHookID=0;
43
HWINEVENTHOOK winEventHookID=0;
44
DWORD desktopProcessID=0;
46
41
void inProcess_initialize() {
50
assert(!inProcess_isRunning);
51
assert(!inProcess_wasInitializedOnce);
52
rpcSrv_inProcess_initialize();
53
42
IA2Support_inProcess_initialize();
54
43
ia2LiveRegions_inProcess_initialize();
55
44
typedCharacter_inProcess_initialize();
56
45
inputLangChange_inProcess_initialize();
57
inProcess_isRunning=inProcess_wasInitializedOnce=true;
46
winword_inProcess_initialize();
47
gdiHooks_inProcess_initialize();
48
rpcSrv_inProcess_initialize();
60
51
void inProcess_terminate() {
61
assert(inProcess_isRunning);
62
assert(inProcess_wasInitializedOnce);
52
rpcSrv_inProcess_terminate();
53
gdiHooks_inProcess_terminate();
54
winword_inProcess_terminate();
63
55
inputLangChange_inProcess_terminate();
64
56
typedCharacter_inProcess_terminate();
65
57
ia2LiveRegions_inProcess_terminate();
66
58
IA2Support_inProcess_terminate();
67
rpcSrv_inProcess_terminate();
68
inProcess_isRunning=false;
74
61
bool registerWinEventHook(WINEVENTPROC hookProc) {
113
100
if(i->second>1) {
116
assert(i->second==1);
103
nhAssert(i->second==1);
122
BOOL WINAPI DllMain(HINSTANCE hModule,DWORD reason,LPVOID lpReserved) {
123
if((reason==DLL_PROCESS_ATTACH)&&(moduleHandle==NULL)) {
124
moduleHandle=hModule;
125
GetWindowThreadProcessId(GetDesktopWindow(),&desktopProcessID);
126
wchar_t endpointString[64];
127
getNVDAControllerNcalrpcEndpointString(endpointString,64,TRUE);
128
RpcBindingFromStringBinding((RPC_WSTR)endpointString,&nvdaControllerBindingHandle);
129
RpcBindingFromStringBinding((RPC_WSTR)endpointString,&nvdaControllerInternalBindingHandle);
130
} else if(reason==DLL_PROCESS_DETACH) {
131
if(inProcess_isRunning) inProcess_terminate();
132
RpcBindingFree(&nvdaControllerBindingHandle);
133
RpcBindingFree(&nvdaControllerInternalBindingHandle);
138
109
//GetMessage hook callback
139
LRESULT CALLBACK getMessageHook(int code, WPARAM wParam, LPARAM lParam) {
110
LRESULT CALLBACK inProcess_getMessageHook(int code, WPARAM wParam, LPARAM lParam) {
141
112
return CallNextHookEx(0,code,wParam,lParam);
143
if(inProcess_isRunning) {
144
//Hookprocs may unregister or register hooks themselves, so we must copy the hookprocs before executing
145
list<windowsHookRegistry_t::key_type> hookProcList;
146
for(windowsHookRegistry_t::iterator i=inProcess_registeredGetMessageWindowsHooks.begin();i!=inProcess_registeredGetMessageWindowsHooks.end();i++) {
147
hookProcList.push_back(i->first);
149
for(list<windowsHookRegistry_t::key_type>::iterator j=hookProcList.begin();j!=hookProcList.end();j++) {
150
(*j)(code,wParam,lParam);
114
//Hookprocs may unregister or register hooks themselves, so we must copy the hookprocs before executing
115
windowsHookRegistry_t hookProcs=inProcess_registeredGetMessageWindowsHooks;
116
for(windowsHookRegistry_t::iterator i=hookProcs.begin();i!=hookProcs.end();++i) {
117
i->first(code,wParam,lParam);
153
119
return CallNextHookEx(0,code,wParam,lParam);
156
122
//callWndProc hook callback
157
LRESULT CALLBACK callWndProcHook(int code, WPARAM wParam,LPARAM lParam) {
123
LRESULT CALLBACK inProcess_callWndProcHook(int code, WPARAM wParam,LPARAM lParam) {
159
125
return CallNextHookEx(0,code,wParam,lParam);
161
if(inProcess_isRunning) {
162
//Hookprocs may unregister or register hooks themselves, so we must copy the hookprocs before executing
163
list<windowsHookRegistry_t::key_type> hookProcList;
164
for(windowsHookRegistry_t::iterator i=inProcess_registeredCallWndProcWindowsHooks.begin();i!=inProcess_registeredCallWndProcWindowsHooks.end();i++) {
165
hookProcList.push_back(i->first);
167
for(list<windowsHookRegistry_t::key_type>::iterator j=hookProcList.begin();j!=hookProcList.end();j++) {
168
(*j)(code,wParam,lParam);
127
//Hookprocs may unregister or register hooks themselves, so we must copy the hookprocs before executing
128
windowsHookRegistry_t hookProcs=inProcess_registeredCallWndProcWindowsHooks;
129
for(windowsHookRegistry_t::iterator i=hookProcs.begin();i!=hookProcs.end();++i) {
130
i->first(code,wParam,lParam);
171
132
return CallNextHookEx(0,code,wParam,lParam);
174
135
//winEvent callback
175
void CALLBACK winEventHook(HWINEVENTHOOK hookID, DWORD eventID, HWND hwnd, long objectID, long childID, DWORD threadID, DWORD time) {
176
if(!inProcess_wasInitializedOnce) {
177
assert(!inProcess_isRunning);
178
DWORD curProcessID=0;
179
if(eventID==EVENT_SYSTEM_FOREGROUND||eventID==EVENT_OBJECT_FOCUS) {
180
GetWindowThreadProcessId(hwnd,&curProcessID);
181
if(curProcessID!=desktopProcessID) {
182
inProcess_initialize();
186
if(inProcess_isRunning) {
187
//Hookprocs may unregister or register hooks themselves, so we must copy the hookprocs before executing
188
list<winEventHookRegistry_t::key_type> hookProcList;
189
for(winEventHookRegistry_t::iterator i=inProcess_registeredWinEventHooks.begin();i!=inProcess_registeredWinEventHooks.end();i++) {
190
hookProcList.push_back(i->first);
192
for(list<winEventHookRegistry_t::key_type>::iterator j=hookProcList.begin();j!=hookProcList.end();j++) {
193
(*j)(hookID, eventID, hwnd, objectID, childID, threadID, time);
198
int nvdaHelper_initialize() {
200
MessageBox(NULL,L"Already initialized",L"nvdaHelperRemote (nvdaHelper_initialize)",0);
203
//Find the directory name of this dll
204
assert(moduleHandle);
205
GetModuleFileName(moduleHandle,dllDirectory,MAX_PATH);
206
PathRemoveFileSpec(dllDirectory);
207
if(!IA2Support_initialize()) {
208
MessageBox(NULL,L"Error initializing IA2 support",L"nvdaHelperRemote (nvdaHelper_initialize)",0);
211
if((getMessageHookID=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)getMessageHook,moduleHandle,0))==0) {
212
MessageBox(NULL,L"Error registering getMessage Windows hook",L"nvdaHelperRemote (nvdaHelper_initialize)",0);
215
if((callWndProcHookID=SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)callWndProcHook,moduleHandle,0))==0) {
216
MessageBox(NULL,L"Error registering callWndProc Windows hook",L"nvdaHelperRemote (nvdaHelper_initialize)",0);
219
if((winEventHookID=SetWinEventHook(0,0xFFFFFFFF,moduleHandle,(WINEVENTPROC)winEventHook,0,0,WINEVENT_INCONTEXT))==0) {
220
MessageBox(NULL,L"Error registering winEvent hook",L"nvdaHelperRemote (nvdaHelper_initialize)",0);
227
int nvdaHelper_terminate() {
229
fprintf(stderr,"Error: not initialized yet\n");
232
if(UnhookWindowsHookEx(getMessageHookID)==0) {
233
fprintf(stderr,"Error unhooking getMessage hook\n");
236
if(UnhookWindowsHookEx(callWndProcHookID)==0) {
237
fprintf(stderr,"Error unhooking callWndProc hook\n");
240
if(UnhookWinEvent(winEventHookID)==FALSE) {
241
fprintf(stderr,"Error unregistering foreground winEvent\n");
244
if(!IA2Support_terminate()) {
245
fprintf(stderr,"Error terminating IA2 support");
136
void CALLBACK inProcess_winEventCallback(HWINEVENTHOOK hookID, DWORD eventID, HWND hwnd, long objectID, long childID, DWORD threadID, DWORD time) {
137
//We are not at all interested in out-of-context winEvents, even if they were accidental.
138
if(threadID!=GetCurrentThreadId()) return;
139
//Hookprocs may unregister or register hooks themselves, so we must copy the hookprocs before executing
140
winEventHookRegistry_t hookProcs=inProcess_registeredWinEventHooks;
141
for(winEventHookRegistry_t::iterator i=hookProcs.begin();i!=hookProcs.end();++i) {
142
i->first(hookID, eventID, hwnd, objectID, childID, threadID, time);