Skip to content

Commit 4415eb7

Browse files
authored
Merge 0ddbe45 into 51aacac
2 parents 51aacac + 0ddbe45 commit 4415eb7

12 files changed

Lines changed: 60 additions & 66 deletions

File tree

nvdaHelper/archBuild_sconscript

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,12 @@ mathPlayerRPCStubs=env.SConscript('mathPlayer_sconscript')
200200
if TARGET_ARCH=='x86':
201201
env.Install(sourceTypelibDir,mathPlayerRPCStubs[0]) #typelib
202202

203+
detoursLib = env.SConscript('detours/sconscript')
204+
Export('detoursLib')
205+
206+
apiHookObj = env.Object("apiHook","common/apiHook.cpp")
207+
Export('apiHookObj')
208+
203209
if TARGET_ARCH=='x86':
204210
localLib=env.SConscript('local/sconscript')
205211
Export('localLib')
@@ -224,9 +230,6 @@ if signExec:
224230
env.AddPostAction(clientLib[0],[signExec])
225231
env.Install(clientInstallDir,clientLib)
226232

227-
detoursLib = env.SConscript('detours/sconscript')
228-
Export('detoursLib')
229-
230233
remoteLib=env.SConscript('remote/sconscript')
231234
Export('remoteLib')
232235
if signExec:
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ This license can be found at:
1818
#include <windows.h>
1919
#include <delayimp.h>
2020
#include <detours/src/detours.h>
21-
#include <remote/nvdaControllerInternal.h>
22-
#include <common/log.h>
23-
#include "dllmain.h"
21+
#include "log.h"
2422
#include "apiHook.h"
2523

2624
using namespace std;

nvdaHelper/local/nvdaHelperLocal.cpp

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,25 @@ This license can be found at:
1919
#include <rpc.h>
2020
#include <sddl.h>
2121
#include <common/log.h>
22+
#include <common/apiHook.h>
2223
#include <local/nvdaControllerInternal.h>
2324
#include "nvdaHelperLocal.h"
2425
#include "dllImportTableHooks.h"
2526
#include "rpcsrv.h"
2627

27-
DllImportTableHooks* oleaccHooks = NULL;
28-
DllImportTableHooks* uiaCoreHooks = NULL;
28+
decltype(&SendMessageW) real_SendMessageW = nullptr;
29+
decltype(&SendMessageTimeoutW) real_SendMessageTimeoutW = nullptr;
30+
decltype(&OpenClipboard) real_OpenClipboard = nullptr;
31+
32+
bool isSecureModeNVDAProcess=false;
2933

3034
typedef struct _RPC_SECURITY_QOS_V5_W {
3135
unsigned long Version;
3236
unsigned long Capabilities;
3337
unsigned long IdentityTracking;
3438
unsigned long ImpersonationType;
3539
unsigned long AdditionalSecurityInfoType;
36-
union
40+
union
3741
{
3842
RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials;
3943
} u;
@@ -53,7 +57,7 @@ handle_t createRemoteBindingHandle(wchar_t* uuidString) {
5357
if((rpcStatus=RpcBindingFromStringBinding(stringBinding,&bindingHandle))!=RPC_S_OK) {
5458
LOG_ERROR(L"RpcBindingFromStringBinding failed with status "<<rpcStatus);
5559
return NULL;
56-
}
60+
}
5761
//On Windows 8 we must allow AppContainer servers to communicate back to us
5862
//Detect Windows 8 by looking for RpcServerRegisterIf3
5963
HANDLE rpcrt4Handle=GetModuleHandle(L"rpcrt4.dll");
@@ -106,7 +110,7 @@ DWORD WINAPI bgSendMessageThreadProc(LPVOID param) {
106110
bgSendMessageData.error = ERROR_CANCELLED;
107111
break;
108112
}
109-
if (SendMessageTimeoutW(bgSendMessageData.hwnd, bgSendMessageData.Msg, bgSendMessageData.wParam, bgSendMessageData.lParam, bgSendMessageData.fuFlags, std::min(remainingTimeout, CANCELSENDMESSAGE_CHECK_INTERVAL), &bgSendMessageData.dwResult) != 0) {
113+
if (real_SendMessageTimeoutW(bgSendMessageData.hwnd, bgSendMessageData.Msg, bgSendMessageData.wParam, bgSendMessageData.lParam, bgSendMessageData.fuFlags, std::min(remainingTimeout, CANCELSENDMESSAGE_CHECK_INTERVAL), &bgSendMessageData.dwResult) != 0) {
110114
// Success.
111115
bgSendMessageData.error = 0;
112116
break;
@@ -147,7 +151,7 @@ LRESULT cancellableSendMessageTimeout(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM
147151
DWORD currentThreadId = GetCurrentThreadId();
148152
if (currentThreadId == mainThreadId && GetWindowThreadProcessId(hwnd, NULL) == mainThreadId) {
149153
// We're sending a message to our own thread, so just forward the call.
150-
return SendMessageTimeoutW(hwnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult);
154+
return real_SendMessageTimeoutW(hwnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult);
151155
}
152156

153157
if (currentThreadId != mainThreadId) {
@@ -167,7 +171,7 @@ LRESULT cancellableSendMessageTimeout(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM
167171
SetLastError(ERROR_CANCELLED);
168172
return 0;
169173
}
170-
if ((ret = SendMessageTimeoutW(hwnd, Msg, wParam, lParam, fuFlags, std::min(remainingTimeout, CANCELSENDMESSAGE_CHECK_INTERVAL), lpdwResult)) != 0 || GetLastError() != ERROR_TIMEOUT) {
174+
if ((ret = real_SendMessageTimeoutW(hwnd, Msg, wParam, lParam, fuFlags, std::min(remainingTimeout, CANCELSENDMESSAGE_CHECK_INTERVAL), lpdwResult)) != 0 || GetLastError() != ERROR_TIMEOUT) {
171175
// Success or error other than timeout.
172176
return ret;
173177
}
@@ -232,44 +236,40 @@ LRESULT WINAPI fake_SendMessageTimeoutW(HWND hwnd, UINT Msg, WPARAM wParam, LPAR
232236
return cancellableSendMessageTimeout(hwnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult);
233237
}
234238

235-
void nvdaHelperLocal_initialize() {
239+
//A replacement OpenClipboard function to disable the use of the clipboard in a secure mode NVDA process
240+
//Simply returns false without calling the original OpenClipboard
241+
BOOL WINAPI fake_OpenClipboard(HWND hwndOwner) {
242+
return false;
243+
}
244+
245+
void nvdaHelperLocal_initialize(int secureMode) {
246+
if(secureMode) {
247+
isSecureModeNVDAProcess = true;
248+
}
236249
startServer();
237250
mainThreadId = GetCurrentThreadId();
238251
cancelCallEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
239252
bgSendMessageData.execEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
240253
bgSendMessageData.completeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
241254
bgSendMessageData.isActive = false;
242255
CloseHandle(CreateThread(NULL, 0, bgSendMessageThreadProc, NULL, 0, NULL));
243-
HMODULE oleacc = LoadLibraryA("oleacc.dll");
244-
if (!oleacc)
245-
return;
246-
oleaccHooks = new DllImportTableHooks(oleacc);
247-
oleaccHooks->requestFunctionHook("USER32.dll", "SendMessageW", fake_SendMessageW);
248-
oleaccHooks->requestFunctionHook("USER32.dll", "SendMessageTimeoutW", fake_SendMessageTimeoutW);
249-
oleaccHooks->hookFunctions();
250-
HMODULE uiaCore = LoadLibraryA("UIAutomationCore.dll");
251-
// It is not an error if UIA isn't present.
252-
if (uiaCore) {
253-
uiaCoreHooks = new DllImportTableHooks(uiaCore);
254-
uiaCoreHooks->requestFunctionHook("USER32.dll", "SendMessageW", fake_SendMessageW);
255-
uiaCoreHooks->requestFunctionHook("USER32.dll", "SendMessageTimeoutW", fake_SendMessageTimeoutW);
256-
uiaCoreHooks->hookFunctions();
256+
// Begin API hooking transaction
257+
apiHook_beginTransaction();
258+
// Hook SendMessageW and SendMessageTimeoutW to ensure that
259+
// we can cancel such calls when they would otherwise freeze NVDA's process.
260+
apiHook_hookFunction_safe(SendMessageW, fake_SendMessageW, &real_SendMessageW);
261+
apiHook_hookFunction_safe(SendMessageTimeoutW, fake_SendMessageTimeoutW, &real_SendMessageTimeoutW);
262+
// For secure mode NVDA process, hook OpenClipboard to disable usage of the clipboard
263+
if (isSecureModeNVDAProcess) {
264+
apiHook_hookFunction_safe(OpenClipboard, fake_OpenClipboard, &real_OpenClipboard);
257265
}
266+
// Enable all registered API hooks by committing the transaction
267+
apiHook_commitTransaction();
258268
}
259269

260270
void nvdaHelperLocal_terminate() {
261-
if (uiaCoreHooks) {
262-
uiaCoreHooks->unhookFunctions();
263-
FreeLibrary(uiaCoreHooks->targetModule);
264-
delete uiaCoreHooks;
265-
uiaCoreHooks = NULL;
266-
}
267-
if (oleaccHooks) {
268-
oleaccHooks->unhookFunctions();
269-
FreeLibrary(oleaccHooks->targetModule);
270-
delete oleaccHooks;
271-
oleaccHooks = NULL;
272-
}
271+
// Unregister and terminate API hooks
272+
apiHook_terminate();
273273
// Terminate the background SendMessage thread.
274274
bgSendMessageData.hwnd = NULL;
275275
SetEvent(bgSendMessageData.execEvent);

nvdaHelper/local/nvdaHelperLocal.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ This license can be found at:
1818

1919
handle_t createRemoteBindingHandle(wchar_t* uuidString);
2020
LRESULT cancellableSendMessageTimeout(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD_PTR lpdwResult);
21-
void nvdaHelperLocal_initialize();
21+
/*
22+
* Initializes the NVDAHelper local library
23+
* @param secureMode 1 specifies that the NVDA process initializing NVDAHelper is in secure mode
24+
*/
25+
void nvdaHelperLocal_initialize(int secureMode);
2226
void nvdaHelperLocal_terminate();
2327

2428
#endif

nvdaHelper/local/sconscript

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
Import([
1616
'env',
17+
'detoursLib',
18+
'apiHookObj',
1719
])
1820

1921
winIPCUtilsObj=env.Object("./winIPCUtils","../common/winIPCUtils.cpp")
@@ -71,6 +73,7 @@ localLib=env.SharedLibrary(
7173
target="nvdaHelperLocal",
7274
source=[
7375
env['projectResFile'],
76+
apiHookObj,
7477
"nvdaHelperLocal.cpp",
7578
"beeps.cpp",
7679
vbufRPCClientSource,
@@ -97,6 +100,7 @@ localLib=env.SharedLibrary(
97100
"oleaut32",
98101
"rpcrt4",
99102
"shlwapi",
103+
detoursLib,
100104
],
101105
)
102106

nvdaHelper/remote/gdiHooks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ This license can be found at:
2222
#include <usp10.h>
2323
#include "nvdaHelperRemote.h"
2424
#include "dllmain.h"
25-
#include "apiHook.h"
25+
#include <common/apiHook.h>
2626
#include "displayModel.h"
2727
#include <common/log.h>
2828
#include <remote/nvdaControllerInternal.h>

nvdaHelper/remote/injection.cpp

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ This license can be found at:
2121
#include <shlwapi.h>
2222
#include <sddl.h>
2323
#include <common/log.h>
24-
#include "apiHook.h"
24+
#include <common/apiHook.h>
2525
#include <remote/nvdaController.h>
2626
#include <remote/nvdaControllerInternal.h>
2727
#include <common/lock.h>
@@ -45,7 +45,6 @@ map<long,HHOOK> callWndProcHooksByThread;
4545
map<long,HHOOK> getMessageHooksByThread;
4646
long tlsIndex_inThreadInjectionID=0;
4747
bool isProcessExiting=false;
48-
bool isSecureModeNVDAProcess=false;
4948
SetWindowsHookEx_funcType real_SetWindowsHookExA=NULL;
5049

5150
//Code executed in-process
@@ -128,14 +127,6 @@ void killRunningWindowsHooks() {
128127
}
129128
}
130129

131-
//A replacement OpenClipboard function to disable the use of the clipboard in a secure mode NVDA process
132-
//Simply returns false without calling the original OpenClipboard
133-
typedef BOOL(WINAPI *OpenClipboard_funcType)(HWND);
134-
OpenClipboard_funcType real_OpenClipboard=NULL;
135-
BOOL WINAPI fake_OpenClipboard(HWND hwndOwner) {
136-
return false;
137-
}
138-
139130
//A thread function that runs while NVDA is injected in a process.
140131
//Note that a mutex is used to make sure that there is never more than one copy of this thread in a given process at any given time.
141132
//I.e. Another copy of NVDA is started while the first is still running.
@@ -175,10 +166,6 @@ DWORD WINAPI inprocMgrThreadFunc(LPVOID data) {
175166
// Hook SetWindowsHookExA so that we can juggle hooks around a bit.
176167
// Fixes #2411
177168
apiHook_hookFunction_safe(SetWindowsHookExA, fake_SetWindowsHookExA, &real_SetWindowsHookExA);
178-
// For secure mode NVDA process, hook OpenClipboard to disable usage of the clipboard
179-
if (isSecureModeNVDAProcess) {
180-
apiHook_hookFunction_safe(OpenClipboard, fake_OpenClipboard, &real_OpenClipboard);
181-
}
182169
// Initialize in-process subsystems
183170
inProcess_initialize();
184171
// Enable all registered API hooks by committing the transaction
@@ -339,10 +326,8 @@ BOOL outprocInitialized=FALSE;
339326

340327
/**
341328
* Initializes the out-of-process code for NVDAHelper
342-
* @param secureMode 1 specifies that NVDA is running in seucre mode, 0 says not.
343329
*/
344-
BOOL injection_initialize(int secureMode) {
345-
if(secureMode) isSecureModeNVDAProcess=true;
330+
BOOL injection_initialize() {
346331
if(outprocInitialized) {
347332
MessageBox(NULL,L"Already initialized",L"nvdaHelperRemote (injection_initialize)",0);
348333
return FALSE;

nvdaHelper/remote/nvdaHelperRemote.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,12 @@ This license can be found at:
2121

2222
/**
2323
* Initializes nvdaHelperRemote, and allows it to inject in to processes.
24-
* @param secureMode 1 specifies that the NVDA process initializing NVDAHelper is in secure mode
2524
*/
26-
BOOL injection_initialize(int secureMode);
25+
BOOL injection_initialize();
2726

2827
/**
2928
* Terminates nvdaHelperRemote, allowing it to uninject from any processes.
30-
*/
29+
*/
3130
BOOL injection_terminate();
3231

3332
//Win event registration

nvdaHelper/remote/sconscript

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Import([
1616
'env',
1717
'ia2RPCStubs',
1818
'detoursLib',
19+
'apiHookObj',
1920
])
2021

2122
winIPCUtilsObj=env.Object("./winIPCUtils","../common/winIPCUtils.cpp")
@@ -86,7 +87,7 @@ source = [
8687
"injection.cpp",
8788
"log.cpp",
8889
"inProcess.cpp",
89-
"apiHook.cpp",
90+
apiHookObj,
9091
"inputLangChange.cpp",
9192
"typedCharacter.cpp",
9293
"ime.cpp",

0 commit comments

Comments
 (0)