rpcSrv.cpp
5.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
This file is a part of the NVDA project.
URL: http://www.nvda-project.org/
Copyright 2006-2010 NVDA contributers.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.0, as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
This license can be found at:
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
#include <cstdio>
#include <sstream>
#include <rpc.h>
#include <sddl.h>
#include <DbgHelp.h>
#include "nvdaControllerInternal.h"
#include <common/log.h>
#include "vbufRemote.h"
#include "displayModelRemote.h"
#include "NvdaInProcUtils.h"
#include "nvdaControllerInternal.h"
#include "rpcSrv.h"
typedef RPC_STATUS(RPC_ENTRY *RpcServerRegisterIf3_functype)(RPC_IF_HANDLE,UUID __RPC_FAR*,RPC_MGR_EPV __RPC_FAR*,unsigned int,unsigned int,unsigned int,RPC_IF_CALLBACK_FN __RPC_FAR*,void __RPC_FAR*);
RPC_IF_HANDLE availableInterfaces[]={
nvdaInProcUtils_NvdaInProcUtils_v1_0_s_ifspec,
displayModelRemote_DisplayModel_v1_0_s_ifspec,
VBufRemote_VBuf_v2_0_s_ifspec,
};
//memory allocation functions
void* __RPC_USER midl_user_allocate(size_t size) {
return malloc(size);
}
void __RPC_USER midl_user_free(void* p) {
free(p);
}
HANDLE nvdaUnregisteredEvent=NULL;
RPC_BINDING_VECTOR* bindingVector;
UUID nvdaInprocUuid;
RPC_STATUS rpcSrv_initialize() {
nvdaUnregisteredEvent=CreateEvent(NULL,TRUE,true,NULL);
RPC_STATUS status;
//Set the protocol
status=RpcServerUseProtseq((RPC_WSTR)L"ncalrpc",RPC_C_PROTSEQ_MAX_REQS_DEFAULT,NULL);
//We can ignore the error where the endpoint is already set
if(status!=RPC_S_OK&&status!=RPC_S_DUPLICATE_ENDPOINT) {
LOG_ERROR(L"Unable to use RPC endPoint. RPC error "<<status);
return status;
}
if((status=RpcServerInqBindings(&bindingVector))!=RPC_S_OK) {
LOG_ERROR(L"RpcServerInqBindings failed with status "<<status);
return status;
}
UuidCreate(&nvdaInprocUuid);
UUID_VECTOR nvdaInprocUuidVector={1,&nvdaInprocUuid};
//Register the interfaces
for(int i=0;i<ARRAYSIZE(availableInterfaces);++i) {
if((status=RpcServerRegisterIfEx(availableInterfaces[i],NULL,NULL,RPC_IF_AUTOLISTEN,RPC_C_LISTEN_MAX_CALLS_DEFAULT,NULL))!=RPC_S_OK) {
LOG_ERROR(L"RpcServerRegisterIfEx for interface at index "<<i<<L" failed with status "<<status);
continue;
}
if((status=RpcEpRegister(availableInterfaces[i],bindingVector,&nvdaInprocUuidVector,(RPC_WSTR)L"NVDAHelperRemote interface"))!=RPC_S_OK) {
LOG_ERROR(L"RpcEpRegister failed for interface at index "<<i<<L" with status "<<status);
continue;
}
}
RPC_WSTR uuidString;
UuidToString(&nvdaInprocUuid,&uuidString);
RpcBindingSetObject(nvdaControllerInternalBindingHandle,&nvdaInprocUuid);
if((status=nvdaControllerInternal_requestRegistration((wchar_t*)uuidString))!=RPC_S_OK) {
LOG_ERROR(L"nvdaControllerInternal_requestRegistration failed with status "<<status);
}
RpcStringFree(&uuidString);
return status;
}
void rpcSrv_terminate() {
RPC_STATUS status;
CloseHandle(nvdaUnregisteredEvent);
nvdaUnregisteredEvent=NULL;
UUID_VECTOR nvdaInprocUuidVector={1,&nvdaInprocUuid};
for(int i=0;i<ARRAYSIZE(availableInterfaces);++i) {
if((status=RpcEpUnregister(availableInterfaces[i],bindingVector,&nvdaInprocUuidVector))!=RPC_S_OK) {
LOG_ERROR(L"RpcEpUnregister failed for interface at index "<<i<<L" with status "<<status);
}
if((status=RpcServerUnregisterIfEx(availableInterfaces[i],NULL,1))!=RPC_S_OK) {
LOG_ERROR(L"RpcServerUnregisterIfEx for interface at index "<<i<<L" failed with status "<<status);
}
}
RpcBindingVectorFree(&bindingVector);
}
error_status_t nvdaInProcUtils_registerNVDAProcess(handle_t bindingHandle, nvdaRegistrationHandle_t* registrationHandle) {
ResetEvent(nvdaUnregisteredEvent);
*registrationHandle=&nvdaUnregisteredEvent;
return RPC_S_OK;
}
error_status_t nvdaInProcUtils_unregisterNVDAProcess(nvdaRegistrationHandle_t* registrationHandle) {
SetEvent(nvdaUnregisteredEvent);
*registrationHandle=NULL;
return RPC_S_OK;
}
void __RPC_USER nvdaRegistrationHandle_t_rundown(nvdaRegistrationHandle_t registrationHandle) {
nvdaInProcUtils_unregisterNVDAProcess(®istrationHandle);
}
error_status_t nvdaInProcUtils_getActiveObject(handle_t bindingHandle, const wchar_t* progid, IUnknown** ppUnknown) {
if(!progid) {
LOG_DEBUGWARNING(L"NULL progid");
return E_FAIL;
}
IID clsid;
HRESULT res=CLSIDFromString(progid,&clsid);
if(res!=NOERROR) {
LOG_DEBUGWARNING(L"CLSIDFromString for "<<progid<<L" returned "<<res);
return res;
}
return GetActiveObject(clsid,NULL,ppUnknown);
}
std::wstring minidumpPath;
LONG WINAPI crashHandler(LPEXCEPTION_POINTERS exceptionInfo) {
HANDLE mdf = CreateFile(minidumpPath.c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (mdf == INVALID_HANDLE_VALUE)
return EXCEPTION_CONTINUE_SEARCH;
MINIDUMP_EXCEPTION_INFORMATION mdExc;
mdExc.ThreadId = GetCurrentThreadId();
mdExc.ExceptionPointers = exceptionInfo;
mdExc.ClientPointers = FALSE;
MiniDumpWriteDump(
GetCurrentProcess(), GetCurrentProcessId(),
mdf,
MiniDumpNormal,
&mdExc, NULL, NULL);
CloseHandle(mdf);
return EXCEPTION_CONTINUE_SEARCH;
}
error_status_t nvdaInProcUtils_dumpOnCrash(handle_t bindingHandle, const wchar_t* path) {
if (!path)
return E_FAIL;
minidumpPath = path;
SetUnhandledExceptionFilter(crashHandler);
return S_OK;
}