~stomato463/+junk/nvdajp

« back to all changes in this revision

Viewing changes to nvdaHelper/remote/inProcess.cpp

  • Committer: Masataka Shinke
  • Date: 2011-10-25 12:35:26 UTC
  • mfrom: (4185 jpmain)
  • mto: This revision was merged to the branch mainline in revision 4211.
  • Revision ID: mshinke@users.sourceforge.jp-20111025123526-ze527a2rl3z0g2ky
lp:~nishimotz/nvdajp/main : 4185 をマージ

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//nvdaHelper.cpp
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.
 
1
/*
 
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
 
13
*/
5
14
 
6
15
#include <cstdio>
7
 
#include <cassert>
8
16
#include <list>
9
17
#include <set>
10
18
#include <map>
 
19
#define WIN32_LEAN_AND_MEAN 
11
20
#include <windows.h>
12
 
#include <shlwapi.h>
13
21
#include "rpcSrv.h"
 
22
#include "winword.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>
 
27
#include "log.h"
 
28
#include "gdiHooks.h"
22
29
#include "nvdaHelperRemote.h"
 
30
#include "inProcess.h"
23
31
 
24
32
using namespace std;
25
33
 
26
34
typedef map<WINEVENTPROC,size_t> winEventHookRegistry_t;
27
35
typedef map<HOOKPROC,size_t> windowsHookRegistry_t;
28
36
 
29
 
#pragma data_seg(".remoteShared")
30
 
        wchar_t dllDirectory[MAX_PATH]={0};
31
 
#pragma data_seg()
32
 
#pragma comment(linker, "/section:.remoteShared,rws")
33
 
 
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;
45
40
 
46
41
void inProcess_initialize() {
47
 
        #ifndef NDEBUG
48
 
        Beep(220,35);
49
 
        #endif
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();
58
49
}
59
50
 
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;
69
 
        #ifndef NDEBUG
70
 
        Beep(440,35);
71
 
        #endif
72
59
}
73
60
 
74
61
bool registerWinEventHook(WINEVENTPROC hookProc) {
82
69
        if(i->second>1) {
83
70
                i->second-=1;
84
71
        } else {
85
 
                assert(i->second==1);
 
72
                nhAssert(i->second==1);
86
73
                inProcess_registeredWinEventHooks.erase(i);
87
74
        }
88
75
        return true;
113
100
        if(i->second>1) {
114
101
                i->second-=1;
115
102
        } else {
116
 
                assert(i->second==1);
 
103
                nhAssert(i->second==1);
117
104
                r->erase(i);
118
105
        }
119
106
        return true;
120
107
}
121
108
 
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);
134
 
        }
135
 
        return TRUE;
136
 
}
137
 
 
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) {
140
111
        if(code<0) {
141
112
                return CallNextHookEx(0,code,wParam,lParam);
142
113
        }
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);
148
 
                }
149
 
                for(list<windowsHookRegistry_t::key_type>::iterator j=hookProcList.begin();j!=hookProcList.end();j++) {
150
 
                        (*j)(code,wParam,lParam);
151
 
                }
 
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);
152
118
        }
153
119
        return CallNextHookEx(0,code,wParam,lParam);
154
120
}
155
121
 
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) {
158
124
        if(code<0) {
159
125
                return CallNextHookEx(0,code,wParam,lParam);
160
126
        }
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);
166
 
                }
167
 
                for(list<windowsHookRegistry_t::key_type>::iterator j=hookProcList.begin();j!=hookProcList.end();j++) {
168
 
                        (*j)(code,wParam,lParam);
169
 
                }
 
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);
170
131
        }
171
132
        return CallNextHookEx(0,code,wParam,lParam);
172
133
}
173
134
 
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();
183
 
                        }
184
 
                }
185
 
        } 
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);
191
 
                }
192
 
                for(list<winEventHookRegistry_t::key_type>::iterator j=hookProcList.begin();j!=hookProcList.end();j++) {
193
 
                        (*j)(hookID, eventID, hwnd, objectID, childID, threadID, time);
194
 
                }
195
 
        }
196
 
}
197
 
 
198
 
int nvdaHelper_initialize() {
199
 
        if(isInitialized) {
200
 
                MessageBox(NULL,L"Already initialized",L"nvdaHelperRemote (nvdaHelper_initialize)",0);
201
 
                return -1;
202
 
        }
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);
209
 
                return -1;
210
 
        }
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);
213
 
                return -1;
214
 
        }
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);
217
 
                return -1;
218
 
        }
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);
221
 
                return -1;
222
 
        }
223
 
        isInitialized=TRUE;
224
 
        return 0;
225
 
}
226
 
 
227
 
int nvdaHelper_terminate() {
228
 
        if(!isInitialized) {
229
 
                fprintf(stderr,"Error: not initialized yet\n");
230
 
                return -1;
231
 
        }
232
 
        if(UnhookWindowsHookEx(getMessageHookID)==0) {
233
 
                fprintf(stderr,"Error unhooking getMessage hook\n");
234
 
                return -1;
235
 
        }
236
 
        if(UnhookWindowsHookEx(callWndProcHookID)==0) {
237
 
                fprintf(stderr,"Error unhooking callWndProc hook\n");
238
 
                return -1;
239
 
        }
240
 
        if(UnhookWinEvent(winEventHookID)==FALSE) {
241
 
                fprintf(stderr,"Error unregistering foreground winEvent\n");
242
 
                return -1;
243
 
        }
244
 
        if(!IA2Support_terminate()) {
245
 
                fprintf(stderr,"Error terminating IA2 support");
246
 
                return -1;
247
 
        }
248
 
        isInitialized=FALSE;
249
 
        return 0;
 
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);
 
143
        }
250
144
}