|
@@ -187,15 +187,54 @@ HRESULT CheckModuleAddress(HANDLE process, LPCVOID remoteImageBase, LPCVOID loca
|
|
|
return S_OK;
|
|
return S_OK;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+HRESULT
|
|
|
|
|
+ServerConnectProcess(
|
|
|
|
|
+ handle_t binding,
|
|
|
|
|
+#ifdef USE_RPC_HANDLE_MARSHALLING
|
|
|
|
|
+ HANDLE processHandle,
|
|
|
|
|
+#endif
|
|
|
|
|
+ intptr_t chakraBaseAddress,
|
|
|
|
|
+ intptr_t crtBaseAddress
|
|
|
|
|
+)
|
|
|
|
|
+{
|
|
|
|
|
+ DWORD clientPid;
|
|
|
|
|
+ HRESULT hr = HRESULT_FROM_WIN32(I_RpcBindingInqLocalClientPID(binding, &clientPid));
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ return hr;
|
|
|
|
|
+ }
|
|
|
|
|
+#ifdef USE_RPC_HANDLE_MARSHALLING
|
|
|
|
|
+ HANDLE targetHandle;
|
|
|
|
|
+ if (!DuplicateHandle(GetCurrentProcess(), processHandle, GetCurrentProcess(), &targetHandle, 0, false, DUPLICATE_SAME_ACCESS))
|
|
|
|
|
+ {
|
|
|
|
|
+ return E_ACCESSDENIED;
|
|
|
|
|
+ }
|
|
|
|
|
+#else
|
|
|
|
|
+ HANDLE targetHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_LIMITED_INFORMATION, false, clientPid);
|
|
|
|
|
+ if (!targetHandle)
|
|
|
|
|
+ {
|
|
|
|
|
+ return E_ACCESSDENIED;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+ hr = CheckModuleAddress(targetHandle, (LPCVOID)chakraBaseAddress, (LPCVOID)AutoSystemInfo::Data.dllLoadAddress);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ return hr;
|
|
|
|
|
+ }
|
|
|
|
|
+ hr = CheckModuleAddress(targetHandle, (LPCVOID)crtBaseAddress, (LPCVOID)AutoSystemInfo::Data.GetCRTHandle());
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ return hr;
|
|
|
|
|
+ }
|
|
|
|
|
+ return ProcessContextManager::RegisterNewProcess(clientPid, targetHandle, chakraBaseAddress, crtBaseAddress);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#pragma warning(push)
|
|
#pragma warning(push)
|
|
|
#pragma warning(disable:6387 28196) // PREFast does not understand the out context can be null here
|
|
#pragma warning(disable:6387 28196) // PREFast does not understand the out context can be null here
|
|
|
HRESULT
|
|
HRESULT
|
|
|
ServerInitializeThreadContext(
|
|
ServerInitializeThreadContext(
|
|
|
/* [in] */ handle_t binding,
|
|
/* [in] */ handle_t binding,
|
|
|
/* [in] */ __RPC__in ThreadContextDataIDL * threadContextData,
|
|
/* [in] */ __RPC__in ThreadContextDataIDL * threadContextData,
|
|
|
-#ifdef USE_RPC_HANDLE_MARSHALLING
|
|
|
|
|
- /* [in] */ __RPC__in HANDLE processHandle,
|
|
|
|
|
-#endif
|
|
|
|
|
/* [out] */ __RPC__deref_out_opt PPTHREADCONTEXT_HANDLE threadContextInfoAddress,
|
|
/* [out] */ __RPC__deref_out_opt PPTHREADCONTEXT_HANDLE threadContextInfoAddress,
|
|
|
/* [out] */ __RPC__out intptr_t *prereservedRegionAddr,
|
|
/* [out] */ __RPC__out intptr_t *prereservedRegionAddr,
|
|
|
/* [out] */ __RPC__out intptr_t *jitThunkAddr)
|
|
/* [out] */ __RPC__out intptr_t *jitThunkAddr)
|
|
@@ -218,28 +257,23 @@ ServerInitializeThreadContext(
|
|
|
{
|
|
{
|
|
|
return hr;
|
|
return hr;
|
|
|
}
|
|
}
|
|
|
-#ifdef USE_RPC_HANDLE_MARSHALLING
|
|
|
|
|
- HANDLE targetHandle;
|
|
|
|
|
- if (!DuplicateHandle(GetCurrentProcess(), processHandle, GetCurrentProcess(), &targetHandle, 0, false, DUPLICATE_SAME_ACCESS))
|
|
|
|
|
- {
|
|
|
|
|
- return E_ACCESSDENIED;
|
|
|
|
|
- }
|
|
|
|
|
-#else
|
|
|
|
|
- HANDLE targetHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_LIMITED_INFORMATION, false, clientPid);
|
|
|
|
|
- if (!targetHandle)
|
|
|
|
|
|
|
+ ProcessContext* processContext = ProcessContextManager::GetProcessContext(clientPid);
|
|
|
|
|
+ if (processContext == nullptr)
|
|
|
{
|
|
{
|
|
|
return E_ACCESSDENIED;
|
|
return E_ACCESSDENIED;
|
|
|
}
|
|
}
|
|
|
-#endif
|
|
|
|
|
try
|
|
try
|
|
|
{
|
|
{
|
|
|
AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory));
|
|
AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory));
|
|
|
- contextInfo = HeapNew(ServerThreadContext, threadContextData, targetHandle);
|
|
|
|
|
|
|
+ contextInfo = HeapNew(ServerThreadContext, threadContextData, processContext);
|
|
|
ServerContextManager::RegisterThreadContext(contextInfo);
|
|
ServerContextManager::RegisterThreadContext(contextInfo);
|
|
|
}
|
|
}
|
|
|
catch (Js::OutOfMemoryException)
|
|
catch (Js::OutOfMemoryException)
|
|
|
{
|
|
{
|
|
|
- CloseHandle(targetHandle);
|
|
|
|
|
|
|
+ if (!contextInfo)
|
|
|
|
|
+ {
|
|
|
|
|
+ processContext->Release();
|
|
|
|
|
+ }
|
|
|
return E_OUTOFMEMORY;
|
|
return E_OUTOFMEMORY;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -249,16 +283,6 @@ ServerInitializeThreadContext(
|
|
|
{
|
|
{
|
|
|
return E_ACCESSDENIED;
|
|
return E_ACCESSDENIED;
|
|
|
}
|
|
}
|
|
|
- hr = CheckModuleAddress(targetHandle, (LPCVOID)contextInfo->GetRuntimeChakraBaseAddress(), (LPCVOID)AutoSystemInfo::Data.dllLoadAddress);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- return hr;
|
|
|
|
|
- }
|
|
|
|
|
- hr = CheckModuleAddress(targetHandle, (LPCVOID)contextInfo->GetRuntimeCRTBaseAddress(), (LPCVOID)contextInfo->GetJITCRTBaseAddress());
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- return hr;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
*threadContextInfoAddress = (PTHREADCONTEXT_HANDLE)EncodePointer(contextInfo);
|
|
*threadContextInfoAddress = (PTHREADCONTEXT_HANDLE)EncodePointer(contextInfo);
|
|
|
|
|
|
|
@@ -834,6 +858,60 @@ JsUtil::BaseHashSet<ServerThreadContext*, HeapAllocator> ServerContextManager::t
|
|
|
JsUtil::BaseHashSet<ServerScriptContext*, HeapAllocator> ServerContextManager::scriptContexts(&HeapAllocator::Instance);
|
|
JsUtil::BaseHashSet<ServerScriptContext*, HeapAllocator> ServerContextManager::scriptContexts(&HeapAllocator::Instance);
|
|
|
CriticalSection ServerContextManager::cs;
|
|
CriticalSection ServerContextManager::cs;
|
|
|
|
|
|
|
|
|
|
+BaseDictionary<DWORD, ProcessContext*, HeapAllocator> ProcessContextManager::ProcessContexts(&HeapAllocator::Instance);
|
|
|
|
|
+CriticalSection ProcessContextManager::cs;
|
|
|
|
|
+
|
|
|
|
|
+HRESULT
|
|
|
|
|
+ProcessContextManager::RegisterNewProcess(DWORD pid, HANDLE processHandle, intptr_t chakraBaseAddress, intptr_t crtBaseAddress)
|
|
|
|
|
+{
|
|
|
|
|
+ AutoCriticalSection autoCS(&cs);
|
|
|
|
|
+ auto iter = ProcessContexts.GetIteratorWithRemovalSupport();
|
|
|
|
|
+ while (iter.IsValid())
|
|
|
|
|
+ {
|
|
|
|
|
+ ProcessContext* context = iter.CurrentValue();
|
|
|
|
|
+ // We can delete a ProcessContext if no ThreadContexts refer to it and the process is terminated
|
|
|
|
|
+ if (!context->HasRef() && WaitForSingleObject(context->processHandle, 0) != WAIT_TIMEOUT)
|
|
|
|
|
+ {
|
|
|
|
|
+ iter.RemoveCurrent();
|
|
|
|
|
+ HeapDelete(context);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // We cannot register multiple ProcessContexts for a single process
|
|
|
|
|
+ if (ProcessContexts.ContainsKey(pid))
|
|
|
|
|
+ {
|
|
|
|
|
+ return E_ACCESSDENIED;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
|
|
+ AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory));
|
|
|
|
|
+
|
|
|
|
|
+ ProcessContext* context = HeapNew(ProcessContext, processHandle, chakraBaseAddress, crtBaseAddress);
|
|
|
|
|
+ ProcessContexts.Add(pid, context);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (Js::OutOfMemoryException)
|
|
|
|
|
+ {
|
|
|
|
|
+ return E_OUTOFMEMORY;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return S_OK;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+ProcessContext*
|
|
|
|
|
+ProcessContextManager::GetProcessContext(DWORD pid)
|
|
|
|
|
+{
|
|
|
|
|
+ AutoCriticalSection autoCS(&cs);
|
|
|
|
|
+ ProcessContext* context = nullptr;
|
|
|
|
|
+ // It is possible that we don't have a ProcessContext for a pid in case ProcessContext initialization failed,
|
|
|
|
|
+ // or if the calling process terminated and the ProcessContext was already cleaned up before we got here
|
|
|
|
|
+ if (ProcessContexts.ContainsKey(pid))
|
|
|
|
|
+ {
|
|
|
|
|
+ context = ProcessContexts.Item(pid);
|
|
|
|
|
+ context->AddRef();
|
|
|
|
|
+ }
|
|
|
|
|
+ return context;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#ifdef STACK_BACK_TRACE
|
|
#ifdef STACK_BACK_TRACE
|
|
|
SList<ServerContextManager::ClosedContextEntry<ServerThreadContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedThreadContextList(&NoThrowHeapAllocator::Instance);
|
|
SList<ServerContextManager::ClosedContextEntry<ServerThreadContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedThreadContextList(&NoThrowHeapAllocator::Instance);
|
|
|
SList<ServerContextManager::ClosedContextEntry<ServerScriptContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedScriptContextList(&NoThrowHeapAllocator::Instance);
|
|
SList<ServerContextManager::ClosedContextEntry<ServerScriptContext>*, NoThrowHeapAllocator> ServerContextManager::ClosedScriptContextList(&NoThrowHeapAllocator::Instance);
|