1100 lines
26 KiB
C++
1100 lines
26 KiB
C++
//----------------------------------------------------------------------------
|
|
//
|
|
// Engine interface proxies and stubs.
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 2000.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "ntsdp.hpp"
|
|
|
|
// Generated headers.
|
|
#include "dbgeng_p.hpp"
|
|
#include "dbgeng_s.hpp"
|
|
#include "dbgsvc_p.hpp"
|
|
#include "dbgsvc_s.hpp"
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Initialization.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
DbgRpcInitializeClient(void)
|
|
{
|
|
DbgRpcInitializeStubTables_dbgeng(DBGRPC_SIF_DBGENG_FIRST);
|
|
DbgRpcInitializeStubTables_dbgsvc(DBGRPC_SIF_DBGSVC_FIRST);
|
|
|
|
// Ensure that the V1 interfaces can't change.
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugAdvanced == 19156);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugBreakpoint == 76131);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugClient == 229769);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugControl == 590362);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugDataSpaces == 180033);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugEventCallbacks == 87804);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugInputCallbacks == 10391);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugOutputCallbacks == 9646);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugRegisters == 69746);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugSymbolGroup == 53300);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugSymbols == 376151);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugSystemObjects == 135421);
|
|
|
|
// Ensure that the V2 interfaces can't change.
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugClient2 == 258161);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugControl2 == 635813);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugDataSpaces2 == 231471);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugSymbols2 == 435328);
|
|
C_ASSERT(DBGRPC_UNIQUE_IDebugSystemObjects2 == 155936);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Proxy and stub support.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DbgRpcStubFunction
|
|
DbgRpcGetStub(USHORT StubIndex)
|
|
{
|
|
USHORT If = (USHORT) DBGRPC_STUB_INDEX_INTERFACE(StubIndex);
|
|
USHORT Mth = (USHORT) DBGRPC_STUB_INDEX_METHOD(StubIndex);
|
|
DbgRpcStubFunctionTable* Table;
|
|
|
|
if (If <= DBGRPC_SIF_DBGENG_LAST)
|
|
{
|
|
Table = g_DbgRpcStubs_dbgeng;
|
|
}
|
|
else if (If >= DBGRPC_SIF_DBGSVC_FIRST &&
|
|
If >= DBGRPC_SIF_DBGSVC_LAST)
|
|
{
|
|
Table = g_DbgRpcStubs_dbgsvc;
|
|
If -= DBGRPC_SIF_DBGSVC_FIRST;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
if (Mth >= Table[If].Count)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return Table[If].Functions[Mth];
|
|
}
|
|
|
|
#if DBG
|
|
PCSTR
|
|
DbgRpcGetStubName(USHORT StubIndex)
|
|
{
|
|
USHORT If = (USHORT) DBGRPC_STUB_INDEX_INTERFACE(StubIndex);
|
|
USHORT Mth = (USHORT) DBGRPC_STUB_INDEX_METHOD(StubIndex);
|
|
DbgRpcStubFunctionTable* Table;
|
|
PCSTR** Names;
|
|
|
|
if (If <= DBGRPC_SIF_DBGENG_LAST)
|
|
{
|
|
Table = g_DbgRpcStubs_dbgeng;
|
|
Names = g_DbgRpcStubNames_dbgeng;
|
|
}
|
|
else if (If >= DBGRPC_SIF_DBGSVC_FIRST &&
|
|
If >= DBGRPC_SIF_DBGSVC_LAST)
|
|
{
|
|
Table = g_DbgRpcStubs_dbgsvc;
|
|
Names = g_DbgRpcStubNames_dbgsvc;
|
|
If -= DBGRPC_SIF_DBGSVC_FIRST;
|
|
}
|
|
else
|
|
{
|
|
return "!InvalidInterface!";
|
|
}
|
|
if (Mth >= Table[If].Count)
|
|
{
|
|
return "!InvalidStubIndex!";
|
|
}
|
|
|
|
return Names[If][Mth];
|
|
}
|
|
#endif // #if DBG
|
|
|
|
HRESULT
|
|
DbgRpcPreallocProxy(REFIID InterfaceId, PVOID* Interface,
|
|
DbgRpcProxy** Proxy, PULONG IfUnique)
|
|
{
|
|
HRESULT Status;
|
|
|
|
Status = DbgRpcPreallocProxy_dbgeng(InterfaceId, Interface,
|
|
Proxy, IfUnique);
|
|
|
|
if (Status == E_NOINTERFACE)
|
|
{
|
|
Status = DbgRpcPreallocProxy_dbgsvc(InterfaceId, Interface,
|
|
Proxy, IfUnique);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
void
|
|
DbgRpcDeleteProxy(class DbgRpcProxy* Proxy)
|
|
{
|
|
// All proxies used here are similar simple single
|
|
// vtable proxy objects so IDebugClient can represent them all.
|
|
delete (ProxyIDebugClient*)Proxy;
|
|
}
|
|
|
|
HRESULT
|
|
DbgRpcServerThreadInitialize(void)
|
|
{
|
|
return g_Target->ThreadInitialize();
|
|
}
|
|
|
|
void
|
|
DbgRpcServerThreadUninitialize(void)
|
|
{
|
|
g_Target->ThreadUninitialize();
|
|
}
|
|
|
|
void
|
|
DbgRpcError(char* Format, ...)
|
|
{
|
|
va_list Args;
|
|
|
|
va_start(Args, Format);
|
|
MaskOutVa(DEBUG_OUTPUT_ERROR, Format, Args, TRUE);
|
|
va_end(Args);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Generated RPC proxies and stubs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "dbgeng_p.cpp"
|
|
#include "dbgeng_s.cpp"
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Hand-written proxies and stubs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugClient::CreateClient(
|
|
OUT PDEBUG_CLIENT* Client
|
|
)
|
|
{
|
|
DbgRpcConnection* Conn;
|
|
|
|
// Always look up the owning connection.
|
|
Conn = DbgRpcGetConnection(m_OwningThread);
|
|
if (Conn == NULL)
|
|
{
|
|
return RPC_E_CONNECTION_TERMINATED;
|
|
}
|
|
|
|
if (GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
// The caller wants a new client for a new thread.
|
|
// Create a new RPC connection based on the owning connection.
|
|
DbgRpcTransport* Trans = Conn->m_Trans->Clone();
|
|
if (Trans == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return DbgRpcCreateServerConnection(Trans, &IID_IDebugClient,
|
|
(IUnknown**)Client);
|
|
}
|
|
|
|
//
|
|
// Just creating another client for the owning thread.
|
|
// Normal RPC.
|
|
//
|
|
|
|
HRESULT Status;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
PDEBUG_CLIENT Proxy;
|
|
|
|
if ((Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(m_InterfaceIndex,
|
|
DBGRPC_SMTH_IDebugClient_CreateClient),
|
|
0, sizeof(DbgRpcObjectId))) == NULL)
|
|
{
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
if ((Proxy = DbgRpcPreallocIDebugClientProxy()) == NULL)
|
|
{
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
|
|
if (Status == S_OK)
|
|
{
|
|
*Client = (PDEBUG_CLIENT)
|
|
((ProxyIDebugClient*)Proxy)->
|
|
InitializeProxy(*(DbgRpcObjectId*)Data, Proxy);
|
|
}
|
|
else
|
|
{
|
|
delete Proxy;
|
|
}
|
|
}
|
|
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugClient::StartProcessServer(
|
|
IN ULONG Flags,
|
|
IN PCSTR Options,
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
if (::GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (Reserved != NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
DbgRpcConnection* Conn;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
HRESULT Status;
|
|
ULONG Len = strlen(Options) + 1;
|
|
|
|
if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
|
|
(Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(m_InterfaceIndex,
|
|
DBGRPC_SMTH_IDebugClient_StartProcessServer),
|
|
Len + sizeof(ULONG), 0)) == NULL)
|
|
{
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
PUCHAR InData = Data;
|
|
*(ULONG*)InData = Flags;
|
|
InData += sizeof(ULONG);
|
|
memcpy(InData, Options, Len);
|
|
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugClient2::CreateClient(
|
|
OUT PDEBUG_CLIENT* Client
|
|
)
|
|
{
|
|
DbgRpcConnection* Conn;
|
|
|
|
// Always look up the owning connection.
|
|
Conn = DbgRpcGetConnection(m_OwningThread);
|
|
if (Conn == NULL)
|
|
{
|
|
return RPC_E_CONNECTION_TERMINATED;
|
|
}
|
|
|
|
if (GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
// The caller wants a new client for a new thread.
|
|
// Create a new RPC connection based on the owning connection.
|
|
DbgRpcTransport* Trans = Conn->m_Trans->Clone();
|
|
if (Trans == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return DbgRpcCreateServerConnection(Trans, &IID_IDebugClient,
|
|
(IUnknown**)Client);
|
|
}
|
|
|
|
//
|
|
// Just creating another client for the owning thread.
|
|
// Normal RPC.
|
|
//
|
|
|
|
HRESULT Status;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
PDEBUG_CLIENT Proxy;
|
|
|
|
if ((Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(m_InterfaceIndex,
|
|
DBGRPC_SMTH_IDebugClient2_CreateClient),
|
|
0, sizeof(DbgRpcObjectId))) == NULL)
|
|
{
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
if ((Proxy = DbgRpcPreallocIDebugClientProxy()) == NULL)
|
|
{
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
|
|
if (Status == S_OK)
|
|
{
|
|
*Client = (PDEBUG_CLIENT)
|
|
((ProxyIDebugClient*)Proxy)->
|
|
InitializeProxy(*(DbgRpcObjectId*)Data, Proxy);
|
|
}
|
|
else
|
|
{
|
|
delete Proxy;
|
|
}
|
|
}
|
|
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugClient2::StartProcessServer(
|
|
IN ULONG Flags,
|
|
IN PCSTR Options,
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
if (::GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (Reserved != NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
DbgRpcConnection* Conn;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
HRESULT Status;
|
|
ULONG Len = strlen(Options) + 1;
|
|
|
|
if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
|
|
(Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(m_InterfaceIndex,
|
|
DBGRPC_SMTH_IDebugClient2_StartProcessServer),
|
|
Len + sizeof(ULONG), 0)) == NULL)
|
|
{
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
PUCHAR InData = Data;
|
|
*(ULONG*)InData = Flags;
|
|
InData += sizeof(ULONG);
|
|
memcpy(InData, Options, Len);
|
|
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// The following methods are hand-written to convert
|
|
// varargs output into simple strings before sending
|
|
// them on.
|
|
//
|
|
|
|
STDMETHODIMPV
|
|
ProxyIDebugControl::Output(
|
|
IN ULONG Mask,
|
|
IN PCSTR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list Args;
|
|
HRESULT Status;
|
|
|
|
if (::GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
va_start(Args, Format);
|
|
Status = OutputVaList(Mask, Format, Args);
|
|
va_end(Args);
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugControl::OutputVaList(
|
|
THIS_
|
|
IN ULONG Mask,
|
|
IN PCSTR Format,
|
|
IN va_list Args
|
|
)
|
|
{
|
|
int Len;
|
|
|
|
// Need the engine lock for the global buffers.
|
|
ENTER_ENGINE();
|
|
|
|
if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
|
|
g_FormatBuffer, Args);
|
|
}
|
|
else
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
|
|
}
|
|
if (Len <= 0)
|
|
{
|
|
LEAVE_ENGINE();
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
Len++;
|
|
}
|
|
|
|
DbgRpcConnection* Conn;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
HRESULT Status;
|
|
|
|
if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
|
|
(Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl,
|
|
DBGRPC_SMTH_IDebugControl_OutputVaList),
|
|
Len + sizeof(ULONG), 0)) == NULL)
|
|
{
|
|
LEAVE_ENGINE();
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
PUCHAR InData = Data;
|
|
*(ULONG*)InData = Mask;
|
|
InData += sizeof(ULONG);
|
|
memcpy(InData, g_OutBuffer, Len);
|
|
|
|
LEAVE_ENGINE();
|
|
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMPV
|
|
ProxyIDebugControl::ControlledOutput(
|
|
THIS_
|
|
IN ULONG OutputControl,
|
|
IN ULONG Mask,
|
|
IN PCSTR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list Args;
|
|
HRESULT Status;
|
|
|
|
if (::GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
va_start(Args, Format);
|
|
Status = ControlledOutputVaList(OutputControl, Mask, Format, Args);
|
|
va_end(Args);
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugControl::ControlledOutputVaList(
|
|
THIS_
|
|
IN ULONG OutputControl,
|
|
IN ULONG Mask,
|
|
IN PCSTR Format,
|
|
IN va_list Args
|
|
)
|
|
{
|
|
int Len;
|
|
|
|
// Need the engine lock for the global buffers.
|
|
ENTER_ENGINE();
|
|
|
|
if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
|
|
g_FormatBuffer, Args);
|
|
}
|
|
else
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
|
|
}
|
|
if (Len <= 0)
|
|
{
|
|
LEAVE_ENGINE();
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
Len++;
|
|
}
|
|
|
|
DbgRpcConnection* Conn;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
HRESULT Status;
|
|
|
|
if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
|
|
(Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl,
|
|
DBGRPC_SMTH_IDebugControl_ControlledOutputVaList),
|
|
Len + 2 * sizeof(ULONG), 0)) == NULL)
|
|
{
|
|
LEAVE_ENGINE();
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
PUCHAR InData = Data;
|
|
*(ULONG*)InData = OutputControl;
|
|
InData += sizeof(ULONG);
|
|
*(ULONG*)InData = Mask;
|
|
InData += sizeof(ULONG);
|
|
memcpy(InData, g_OutBuffer, Len);
|
|
|
|
LEAVE_ENGINE();
|
|
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMPV
|
|
ProxyIDebugControl::OutputPrompt(
|
|
IN ULONG OutputControl,
|
|
IN OPTIONAL PCSTR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list Args;
|
|
HRESULT Status;
|
|
|
|
if (::GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
va_start(Args, Format);
|
|
Status = OutputPromptVaList(OutputControl, Format, Args);
|
|
va_end(Args);
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugControl::OutputPromptVaList(
|
|
THIS_
|
|
IN ULONG OutputControl,
|
|
IN OPTIONAL PCSTR Format,
|
|
IN va_list Args
|
|
)
|
|
{
|
|
int Len;
|
|
|
|
if (Format != NULL)
|
|
{
|
|
// Need the engine lock for the global buffers.
|
|
ENTER_ENGINE();
|
|
|
|
if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
|
|
g_FormatBuffer, Args);
|
|
}
|
|
else
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
|
|
}
|
|
if (Len <= 0)
|
|
{
|
|
LEAVE_ENGINE();
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
Len++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Len = 0;
|
|
}
|
|
|
|
DbgRpcConnection* Conn;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
HRESULT Status;
|
|
|
|
// Presence/absence of text will be detected in the stub
|
|
// by checking the input size on the call.
|
|
if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
|
|
(Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl,
|
|
DBGRPC_SMTH_IDebugControl_OutputPromptVaList),
|
|
Len + sizeof(ULONG), 0)) == NULL)
|
|
{
|
|
if (Format != NULL)
|
|
{
|
|
LEAVE_ENGINE();
|
|
}
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
PUCHAR InData = Data;
|
|
*(ULONG*)InData = OutputControl;
|
|
InData += sizeof(ULONG);
|
|
memcpy(InData, g_OutBuffer, Len);
|
|
|
|
if (Format != NULL)
|
|
{
|
|
LEAVE_ENGINE();
|
|
}
|
|
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMPV
|
|
ProxyIDebugControl2::Output(
|
|
IN ULONG Mask,
|
|
IN PCSTR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list Args;
|
|
HRESULT Status;
|
|
|
|
if (::GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
va_start(Args, Format);
|
|
Status = OutputVaList(Mask, Format, Args);
|
|
va_end(Args);
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugControl2::OutputVaList(
|
|
THIS_
|
|
IN ULONG Mask,
|
|
IN PCSTR Format,
|
|
IN va_list Args
|
|
)
|
|
{
|
|
int Len;
|
|
|
|
// Need the engine lock for the global buffers.
|
|
ENTER_ENGINE();
|
|
|
|
if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
|
|
g_FormatBuffer, Args);
|
|
}
|
|
else
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
|
|
}
|
|
if (Len <= 0)
|
|
{
|
|
LEAVE_ENGINE();
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
Len++;
|
|
}
|
|
|
|
DbgRpcConnection* Conn;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
HRESULT Status;
|
|
|
|
if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
|
|
(Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl2,
|
|
DBGRPC_SMTH_IDebugControl2_OutputVaList),
|
|
Len + sizeof(ULONG), 0)) == NULL)
|
|
{
|
|
LEAVE_ENGINE();
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
PUCHAR InData = Data;
|
|
*(ULONG*)InData = Mask;
|
|
InData += sizeof(ULONG);
|
|
memcpy(InData, g_OutBuffer, Len);
|
|
|
|
LEAVE_ENGINE();
|
|
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMPV
|
|
ProxyIDebugControl2::ControlledOutput(
|
|
THIS_
|
|
IN ULONG OutputControl,
|
|
IN ULONG Mask,
|
|
IN PCSTR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list Args;
|
|
HRESULT Status;
|
|
|
|
if (::GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
va_start(Args, Format);
|
|
Status = ControlledOutputVaList(OutputControl, Mask, Format, Args);
|
|
va_end(Args);
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugControl2::ControlledOutputVaList(
|
|
THIS_
|
|
IN ULONG OutputControl,
|
|
IN ULONG Mask,
|
|
IN PCSTR Format,
|
|
IN va_list Args
|
|
)
|
|
{
|
|
int Len;
|
|
|
|
// Need the engine lock for the global buffers.
|
|
ENTER_ENGINE();
|
|
|
|
if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
|
|
g_FormatBuffer, Args);
|
|
}
|
|
else
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
|
|
}
|
|
if (Len <= 0)
|
|
{
|
|
LEAVE_ENGINE();
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
Len++;
|
|
}
|
|
|
|
DbgRpcConnection* Conn;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
HRESULT Status;
|
|
|
|
if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
|
|
(Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl2,
|
|
DBGRPC_SMTH_IDebugControl2_ControlledOutputVaList),
|
|
Len + 2 * sizeof(ULONG), 0)) == NULL)
|
|
{
|
|
LEAVE_ENGINE();
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
PUCHAR InData = Data;
|
|
*(ULONG*)InData = OutputControl;
|
|
InData += sizeof(ULONG);
|
|
*(ULONG*)InData = Mask;
|
|
InData += sizeof(ULONG);
|
|
memcpy(InData, g_OutBuffer, Len);
|
|
|
|
LEAVE_ENGINE();
|
|
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMPV
|
|
ProxyIDebugControl2::OutputPrompt(
|
|
IN ULONG OutputControl,
|
|
IN OPTIONAL PCSTR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list Args;
|
|
HRESULT Status;
|
|
|
|
if (::GetCurrentThreadId() != m_OwningThread)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
va_start(Args, Format);
|
|
Status = OutputPromptVaList(OutputControl, Format, Args);
|
|
va_end(Args);
|
|
return Status;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
ProxyIDebugControl2::OutputPromptVaList(
|
|
THIS_
|
|
IN ULONG OutputControl,
|
|
IN OPTIONAL PCSTR Format,
|
|
IN va_list Args
|
|
)
|
|
{
|
|
int Len;
|
|
|
|
if (Format != NULL)
|
|
{
|
|
// Need the engine lock for the global buffers.
|
|
ENTER_ENGINE();
|
|
|
|
if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
|
|
g_FormatBuffer, Args);
|
|
}
|
|
else
|
|
{
|
|
Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
|
|
}
|
|
if (Len <= 0)
|
|
{
|
|
LEAVE_ENGINE();
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
Len++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Len = 0;
|
|
}
|
|
|
|
DbgRpcConnection* Conn;
|
|
DbgRpcCall Call;
|
|
PUCHAR Data;
|
|
HRESULT Status;
|
|
|
|
// Presence/absence of text will be detected in the stub
|
|
// by checking the input size on the call.
|
|
if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
|
|
(Data = Conn->StartCall(&Call, m_ObjectId,
|
|
DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl2,
|
|
DBGRPC_SMTH_IDebugControl2_OutputPromptVaList),
|
|
Len + sizeof(ULONG), 0)) == NULL)
|
|
{
|
|
if (Format != NULL)
|
|
{
|
|
LEAVE_ENGINE();
|
|
}
|
|
Status = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
PUCHAR InData = Data;
|
|
*(ULONG*)InData = OutputControl;
|
|
InData += sizeof(ULONG);
|
|
memcpy(InData, g_OutBuffer, Len);
|
|
|
|
if (Format != NULL)
|
|
{
|
|
LEAVE_ENGINE();
|
|
}
|
|
|
|
Status = Conn->SendReceive(&Call, &Data);
|
|
Conn->FreeData(Data);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
HRESULT
|
|
SFN_IDebugClient_StartProcessServer(
|
|
IUnknown* __drpc_If,
|
|
DbgRpcConnection* __drpc_Conn,
|
|
DbgRpcCall* __drpc_Call,
|
|
PUCHAR __drpc_InData,
|
|
PUCHAR __drpc_OutData
|
|
)
|
|
{
|
|
ULONG Flags = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
return ((IDebugClient*)__drpc_If)->
|
|
StartProcessServer(Flags, (PSTR)__drpc_InData, NULL);
|
|
}
|
|
|
|
HRESULT
|
|
SFN_IDebugClient2_StartProcessServer(
|
|
IUnknown* __drpc_If,
|
|
DbgRpcConnection* __drpc_Conn,
|
|
DbgRpcCall* __drpc_Call,
|
|
PUCHAR __drpc_InData,
|
|
PUCHAR __drpc_OutData
|
|
)
|
|
{
|
|
ULONG Flags = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
return ((IDebugClient2*)__drpc_If)->
|
|
StartProcessServer(Flags, (PSTR)__drpc_InData, NULL);
|
|
}
|
|
|
|
HRESULT
|
|
SFN_IDebugControl_OutputVaList(
|
|
IUnknown* __drpc_If,
|
|
DbgRpcConnection* __drpc_Conn,
|
|
DbgRpcCall* __drpc_Call,
|
|
PUCHAR __drpc_InData,
|
|
PUCHAR __drpc_OutData
|
|
)
|
|
{
|
|
ULONG Mask = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
return ((IDebugControl*)__drpc_If)->
|
|
Output(Mask, "%s", (PSTR)__drpc_InData);
|
|
}
|
|
|
|
HRESULT
|
|
SFN_IDebugControl_ControlledOutputVaList(
|
|
IUnknown* __drpc_If,
|
|
DbgRpcConnection* __drpc_Conn,
|
|
DbgRpcCall* __drpc_Call,
|
|
PUCHAR __drpc_InData,
|
|
PUCHAR __drpc_OutData
|
|
)
|
|
{
|
|
ULONG OutputControl = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
ULONG Mask = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
return ((IDebugControl*)__drpc_If)->
|
|
ControlledOutput(OutputControl, Mask, "%s", (PSTR)__drpc_InData);
|
|
}
|
|
|
|
HRESULT
|
|
SFN_IDebugControl_OutputPromptVaList(
|
|
IUnknown* __drpc_If,
|
|
DbgRpcConnection* __drpc_Conn,
|
|
DbgRpcCall* __drpc_Call,
|
|
PUCHAR __drpc_InData,
|
|
PUCHAR __drpc_OutData
|
|
)
|
|
{
|
|
ULONG OutputControl = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
if (__drpc_Call->InSize > sizeof(ULONG))
|
|
{
|
|
return ((IDebugControl*)__drpc_If)->
|
|
OutputPrompt(OutputControl, "%s", (PSTR)__drpc_InData);
|
|
}
|
|
else
|
|
{
|
|
return ((IDebugControl*)__drpc_If)->OutputPrompt(OutputControl, NULL);
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
SFN_IDebugControl2_OutputVaList(
|
|
IUnknown* __drpc_If,
|
|
DbgRpcConnection* __drpc_Conn,
|
|
DbgRpcCall* __drpc_Call,
|
|
PUCHAR __drpc_InData,
|
|
PUCHAR __drpc_OutData
|
|
)
|
|
{
|
|
ULONG Mask = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
return ((IDebugControl2*)__drpc_If)->
|
|
Output(Mask, "%s", (PSTR)__drpc_InData);
|
|
}
|
|
|
|
HRESULT
|
|
SFN_IDebugControl2_ControlledOutputVaList(
|
|
IUnknown* __drpc_If,
|
|
DbgRpcConnection* __drpc_Conn,
|
|
DbgRpcCall* __drpc_Call,
|
|
PUCHAR __drpc_InData,
|
|
PUCHAR __drpc_OutData
|
|
)
|
|
{
|
|
ULONG OutputControl = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
ULONG Mask = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
return ((IDebugControl2*)__drpc_If)->
|
|
ControlledOutput(OutputControl, Mask, "%s", (PSTR)__drpc_InData);
|
|
}
|
|
|
|
HRESULT
|
|
SFN_IDebugControl2_OutputPromptVaList(
|
|
IUnknown* __drpc_If,
|
|
DbgRpcConnection* __drpc_Conn,
|
|
DbgRpcCall* __drpc_Call,
|
|
PUCHAR __drpc_InData,
|
|
PUCHAR __drpc_OutData
|
|
)
|
|
{
|
|
ULONG OutputControl = *(ULONG*)__drpc_InData;
|
|
__drpc_InData += sizeof(ULONG);
|
|
if (__drpc_Call->InSize > sizeof(ULONG))
|
|
{
|
|
return ((IDebugControl2*)__drpc_If)->
|
|
OutputPrompt(OutputControl, "%s", (PSTR)__drpc_InData);
|
|
}
|
|
else
|
|
{
|
|
return ((IDebugControl2*)__drpc_If)->OutputPrompt(OutputControl, NULL);
|
|
}
|
|
}
|