windows-nt/Source/XPSP1/NT/com/rpc/runtime/epmap/dbgsvr.cxx
2020-09-26 16:20:57 +08:00

716 lines
22 KiB
C++

/*++
Copyright (C) Microsoft Corporation, 1996 - 1999
Module Name:
DbgSvr.cxx
Abstract:
The debugging support interfaces in RPCSS
Author:
Kamen Moutafov [KamenM]
Revision History:
KamenM Dec 99 Creation
--*/
#include <sysinc.h>
#include <wincrypt.h>
#include <wtypes.h>
#include <rpc.h>
#include <rpcdcep.h>
#include <rpcerrp.h>
#include <rpctrans.hxx>
#include <objidl.h>
#include <CellDef.hxx>
#include <DbgIdl.h>
START_C_EXTERN
RPC_STATUS RPC_ENTRY
DebugServerSecurityCallback (
IN RPC_IF_HANDLE InterfaceUuid,
IN void *Context
)
{
RPC_STATUS Status, TempStatus;
HANDLE TempHandle;
PVOID SectionPointer;
// Context is an SCALL
Status = RpcImpersonateClient(Context);
if (Status != RPC_S_OK)
{
return Status;
}
// try to open our own section - this is protected by ACL for admins & local system
// only, so this should filter out unauthorized access
Status = OpenDbgSection(&TempHandle, &SectionPointer, GetCurrentProcessId(), NULL);
if (Status == RPC_S_OK)
{
CloseDbgSection(TempHandle, SectionPointer);
}
TempStatus = RpcRevertToSelfEx(Context);
ASSERT(TempStatus == RPC_S_OK);
return Status;
}
////////////////////////////////////////////////////////////////////
/// Local representation to wire representation translation routines
////////////////////////////////////////////////////////////////////
void TranslateLocalCallInfoToRemoteCallInfo(IN DebugCallInfo *LocalDebugInfo,
OUT RemoteDebugCallInfo *RemoteCallInfo)
{
RemoteCallInfo->Type = LocalDebugInfo->Type;
RemoteCallInfo->Status = LocalDebugInfo->Status;
RemoteCallInfo->ProcNum = LocalDebugInfo->ProcNum;
RemoteCallInfo->InterfaceUUIDStart = LocalDebugInfo->InterfaceUUIDStart;
RemoteCallInfo->ServicingTID = LocalDebugInfo->ServicingTID;
RemoteCallInfo->CallFlags = LocalDebugInfo->CallFlags;
RemoteCallInfo->CallID = LocalDebugInfo->CallID;
RemoteCallInfo->LastUpdateTime = LocalDebugInfo->LastUpdateTime;
if (LocalDebugInfo->CallFlags & DBGCELL_LRPC_CALL)
{
RemoteCallInfo->ConnectionType = crtLrpcConnection;
RemoteCallInfo->connInfo.Connection = LocalDebugInfo->Connection;
}
else
{
RemoteCallInfo->ConnectionType = crtOsfConnection;
RemoteCallInfo->connInfo.Caller.PID = LocalDebugInfo->PID;
RemoteCallInfo->connInfo.Caller.TID = LocalDebugInfo->TID;
}
}
void TranslateLocalEndpointInfoToRemoteEndpointInfo(IN DebugEndpointInfo *LocalDebugInfo,
OUT RemoteDebugEndpointInfo *RemoteEndpointInfo)
{
RemoteEndpointInfo->Type = LocalDebugInfo->Type;
RemoteEndpointInfo->ProtseqType = LocalDebugInfo->ProtseqType;
RemoteEndpointInfo->Status = LocalDebugInfo->Status;
// the endpoint name in the debug cell is not null terminated - process it specially
RemoteEndpointInfo->EndpointNameLength = 0;
RemoteEndpointInfo->EndpointName
= (unsigned char *)MIDL_user_allocate(DebugEndpointNameLength + 1);
if (RemoteEndpointInfo->EndpointName != NULL)
{
memcpy(RemoteEndpointInfo->EndpointName,
LocalDebugInfo->EndpointName, DebugEndpointNameLength);
RemoteEndpointInfo->EndpointName[DebugEndpointNameLength] = 0;
RemoteEndpointInfo->EndpointNameLength
= strlen((const char *) RemoteEndpointInfo->EndpointName) + 1;
}
}
void TranslateLocalThreadInfoToRemoteThreadInfo(IN DebugThreadInfo *LocalDebugInfo,
OUT RemoteDebugThreadInfo *RemoteThreadInfo)
{
RemoteThreadInfo->Type = LocalDebugInfo->Type;
RemoteThreadInfo->Status = LocalDebugInfo->Status;
RemoteThreadInfo->LastUpdateTime = LocalDebugInfo->LastUpdateTime;
RemoteThreadInfo->TID = LocalDebugInfo->TID;
RemoteThreadInfo->Endpoint = LocalDebugInfo->Endpoint;
}
void TranslateLocalClientCallInfoToRemoteClientCallInfo(IN DebugClientCallInfo *LocalDebugInfo,
OUT RemoteDebugClientCallInfo *RemoteClientCallInfo)
{
RemoteClientCallInfo->Type = LocalDebugInfo->Type;
RemoteClientCallInfo->ProcNum = LocalDebugInfo->ProcNum;
RemoteClientCallInfo->ServicingThread = LocalDebugInfo->ServicingThread;
RemoteClientCallInfo->IfStart = LocalDebugInfo->IfStart;
RemoteClientCallInfo->CallID = LocalDebugInfo->CallID;
RemoteClientCallInfo->CallTargetID = LocalDebugInfo->CallTargetID;
// the endpoint in the debug cell is not null terminated - process it specially
RemoteClientCallInfo->EndpointLength = 0;
RemoteClientCallInfo->Endpoint
= (unsigned char *)MIDL_user_allocate(ClientCallEndpointLength + 1);
if (RemoteClientCallInfo->Endpoint != NULL)
{
memcpy(RemoteClientCallInfo->Endpoint,
LocalDebugInfo->Endpoint, ClientCallEndpointLength);
RemoteClientCallInfo->Endpoint[ClientCallEndpointLength] = 0;
RemoteClientCallInfo->EndpointLength
= strlen((const char *) RemoteClientCallInfo->Endpoint) + 1;
}
}
void TranslateLocalConnectionInfoToRemoteConnectionInfo(IN DebugConnectionInfo *LocalDebugInfo,
OUT RemoteDebugConnectionInfo *RemoteConnectionInfo)
{
RemoteConnectionInfo->Type = LocalDebugInfo->Type;
RemoteConnectionInfo->Flags = LocalDebugInfo->Flags;
RemoteConnectionInfo->LastTransmitFragmentSize
= LocalDebugInfo->LastTransmitFragmentSize;
RemoteConnectionInfo->Endpoint = LocalDebugInfo->Endpoint;
RemoteConnectionInfo->ConnectionID[0]
= HandleToUlong(LocalDebugInfo->ConnectionID[0]);
RemoteConnectionInfo->ConnectionID[1]
= HandleToUlong(LocalDebugInfo->ConnectionID[1]);
RemoteConnectionInfo->LastSendTime = LocalDebugInfo->LastSendTime;
RemoteConnectionInfo->LastReceiveTime = LocalDebugInfo->LastReceiveTime;
}
void TranslateLocalCallTargetInfoToRemoteCallTargetInfo(IN DebugCallTargetInfo *LocalDebugInfo,
OUT RemoteDebugCallTargetInfo *RemoteCallTargetInfo)
{
RemoteCallTargetInfo->Type = LocalDebugInfo->Type;
RemoteCallTargetInfo->ProtocolSequence = LocalDebugInfo->ProtocolSequence;
RemoteCallTargetInfo->LastUpdateTime = LocalDebugInfo->LastUpdateTime;
// the target server name in the debug cell is not null terminated - process it specially
RemoteCallTargetInfo->TargetServerLength = 0;
RemoteCallTargetInfo->TargetServer
= (unsigned char *)MIDL_user_allocate(TargetServerNameLength + 1);
if (RemoteCallTargetInfo->TargetServer != NULL)
{
memcpy(RemoteCallTargetInfo->TargetServer,
LocalDebugInfo->TargetServer, TargetServerNameLength);
RemoteCallTargetInfo->TargetServer[TargetServerNameLength] = 0;
RemoteCallTargetInfo->TargetServerLength
= strlen((const char *) RemoteCallTargetInfo->TargetServer) + 1;
}
}
////////////////////////////////////////////////////////////////////
/// Remote get cell info routine
////////////////////////////////////////////////////////////////////
/* [fault_status][comm_status] */ error_status_t RemoteGetCellByDebugCellID(
/* [in] */ handle_t IDL_handle,
/* [in] */ DWORD ProcessID,
/* [in] */ DebugCellID CellID,
/* [in, out, unique] */ RemoteDebugCellUnion __RPC_FAR *__RPC_FAR *debugInfo)
{
DebugCellUnion Container;
RemoteDebugCellUnion *ActualDebugInfo;
RPC_STATUS Status;
if (debugInfo == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
*debugInfo = NULL;
ActualDebugInfo = (RemoteDebugCellUnion *) MIDL_user_allocate(sizeof(RemoteDebugCellUnion));
if (ActualDebugInfo == NULL)
return RPC_S_OUT_OF_MEMORY;
Status = GetCellByDebugCellID(ProcessID, CellID, &Container);
if (Status != RPC_S_OK)
{
MIDL_user_free(ActualDebugInfo);
return Status;
}
ActualDebugInfo->UnionType = Container.callInfo.Type;
if ((ActualDebugInfo->UnionType < dctFirstEntry) || (ActualDebugInfo->UnionType > dctLastEntry)
|| (ActualDebugInfo->UnionType == dctInvalid) || (ActualDebugInfo->UnionType == dctFree)
|| (ActualDebugInfo->UnionType == dctUsedGeneric))
{
MIDL_user_free(ActualDebugInfo);
return RPC_S_OBJECT_NOT_FOUND;
}
switch(ActualDebugInfo->UnionType)
{
case dctCallInfo:
TranslateLocalCallInfoToRemoteCallInfo(&Container.callInfo,
&ActualDebugInfo->debugInfo.callInfo);
break;
case dctThreadInfo:
TranslateLocalThreadInfoToRemoteThreadInfo(&Container.threadInfo,
&ActualDebugInfo->debugInfo.threadInfo);
break;
case dctEndpointInfo:
TranslateLocalEndpointInfoToRemoteEndpointInfo(&Container.endpointInfo,
&ActualDebugInfo->debugInfo.endpointInfo);
break;
case dctClientCallInfo:
TranslateLocalClientCallInfoToRemoteClientCallInfo(&Container.clientCallInfo,
&ActualDebugInfo->debugInfo.clientCallInfo);
break;
case dctConnectionInfo:
TranslateLocalConnectionInfoToRemoteConnectionInfo(&Container.connectionInfo,
&ActualDebugInfo->debugInfo.connectionInfo);
break;
case dctCallTargetInfo:
TranslateLocalCallTargetInfoToRemoteCallTargetInfo(&Container.callTargetInfo,
&ActualDebugInfo->debugInfo.callTargetInfo);
break;
default:
ASSERT(0);
}
*debugInfo = ActualDebugInfo;
return RPC_S_OK;
}
////////////////////////////////////////////////////////////////////
/// Remote call enumeration routines
////////////////////////////////////////////////////////////////////
typedef enum tagRemoteEnumerationHandleType
{
rehtCallInfo,
rehtEndpointInfo,
rehtThreadInfo,
rehtClientCallInfo
} RemoteEnumerationHandleType;
typedef struct tagRemoteCallInfoEnumerationHandle
{
RemoteEnumerationHandleType ThisHandleType;
CallInfoEnumerationHandle h;
} RemoteCallInfoEnumerationHandle;
error_status_t RemoteOpenRPCDebugCallInfoEnumeration(
/* [in] */ handle_t IDL_handle,
/* [out] */ DbgCallEnumHandle __RPC_FAR *h,
/* [in] */ DWORD CallID,
/* [in] */ DWORD IfStart,
/* [in] */ int ProcNum,
/* [in] */ DWORD ProcessID)
{
RemoteCallInfoEnumerationHandle *rh;
RPC_STATUS Status;
*h = NULL;
rh = new RemoteCallInfoEnumerationHandle;
if (rh == NULL)
return RPC_S_OUT_OF_MEMORY;
rh->ThisHandleType = rehtCallInfo;
Status = OpenRPCDebugCallInfoEnumeration(CallID, IfStart, ProcNum, ProcessID, &rh->h);
if (Status != RPC_S_OK)
{
delete rh;
return Status;
}
*h = rh;
return RPC_S_OK;
}
error_status_t RemoteGetNextRPCDebugCallInfo(
/* [in] */ DbgCallEnumHandle h,
/* [unique][out][in] */ RemoteDebugCallInfo __RPC_FAR *__RPC_FAR *debugInfo,
/* [out] */ DebugCellID __RPC_FAR *CellID,
/* [out] */ DWORD __RPC_FAR *ProcessID)
{
RemoteCallInfoEnumerationHandle *rh;
RPC_STATUS Status;
DebugCallInfo *NextCall;
if (debugInfo == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
*debugInfo = NULL;
CellID->SectionID = 0;
CellID->CellID = 0;
rh = (RemoteCallInfoEnumerationHandle *)h;
if (rh->ThisHandleType != rehtCallInfo)
return ERROR_INVALID_HANDLE;
Status = GetNextRPCDebugCallInfo(rh->h, &NextCall, CellID, ProcessID);
if (Status == RPC_S_OK)
{
*debugInfo = (RemoteDebugCallInfo *) MIDL_user_allocate(sizeof(RemoteDebugCallInfo));
if (*debugInfo != NULL)
{
TranslateLocalCallInfoToRemoteCallInfo(NextCall, *debugInfo);
}
else
Status = RPC_S_OUT_OF_MEMORY;
}
return Status;
}
error_status_t RemoteFinishRPCDebugCallInfoEnumeration(
/* [out][in] */ DbgCallEnumHandle __RPC_FAR *h)
{
RemoteCallInfoEnumerationHandle *rh;
rh = (RemoteCallInfoEnumerationHandle *)*h;
if (rh == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
if (rh->ThisHandleType != rehtCallInfo)
return ERROR_INVALID_HANDLE;
DbgCallEnumHandle_rundown(*h);
*h = NULL;
return RPC_S_OK;
}
void __RPC_USER DbgCallEnumHandle_rundown(DbgCallEnumHandle h)
{
RemoteCallInfoEnumerationHandle *rh;
rh = (RemoteCallInfoEnumerationHandle *)h;
FinishRPCDebugCallInfoEnumeration(&rh->h);
delete rh;
}
////////////////////////////////////////////////////////////////////
/// Remote endpoint enumeration routines
////////////////////////////////////////////////////////////////////
typedef struct tagRemoteEndpointInfoEnumerationHandle
{
RemoteEnumerationHandleType ThisHandleType;
EndpointInfoEnumerationHandle h;
} RemoteEndpointInfoEnumerationHandle;
error_status_t RemoteOpenRPCDebugEndpointInfoEnumeration(
/* [in] */ handle_t IDL_handle,
/* [out] */ DbgEndpointEnumHandle __RPC_FAR *h,
/* [in] */ short EndpointSize,
/* [size_is][in] */ unsigned char __RPC_FAR *Endpoint)
{
RemoteEndpointInfoEnumerationHandle *rh;
RPC_STATUS Status;
*h = NULL;
rh = new RemoteEndpointInfoEnumerationHandle;
if (rh == NULL)
return RPC_S_OUT_OF_MEMORY;
rh->ThisHandleType = rehtEndpointInfo;
Status = OpenRPCDebugEndpointInfoEnumeration((EndpointSize > 0) ? (char *)Endpoint : NULL, &rh->h);
if (Status != RPC_S_OK)
{
delete rh;
return Status;
}
*h = rh;
return RPC_S_OK;
}
error_status_t RemoteGetNextRPCDebugEndpointInfo(
/* [in] */ DbgEndpointEnumHandle h,
/* [unique][out][in] */ RemoteDebugEndpointInfo __RPC_FAR *__RPC_FAR *debugInfo,
/* [out] */ DebugCellID __RPC_FAR *CellID,
/* [out] */ DWORD __RPC_FAR *ProcessID)
{
RemoteEndpointInfoEnumerationHandle *rh;
RPC_STATUS Status;
DebugEndpointInfo *NextEndpoint;
if (debugInfo == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
*debugInfo = NULL;
CellID->SectionID = 0;
CellID->CellID = 0;
rh = (RemoteEndpointInfoEnumerationHandle *)h;
if (rh->ThisHandleType != rehtEndpointInfo)
return ERROR_INVALID_HANDLE;
Status = GetNextRPCDebugEndpointInfo(rh->h, &NextEndpoint, CellID, ProcessID);
if (Status == RPC_S_OK)
{
*debugInfo = (RemoteDebugEndpointInfo *) MIDL_user_allocate(sizeof(RemoteDebugEndpointInfo));
if (*debugInfo != NULL)
{
TranslateLocalEndpointInfoToRemoteEndpointInfo(NextEndpoint, *debugInfo);
}
else
Status = RPC_S_OUT_OF_MEMORY;
}
return Status;
}
error_status_t RemoteFinishRPCDebugEndpointInfoEnumeration(
/* [out][in] */ DbgEndpointEnumHandle __RPC_FAR *h)
{
RemoteEndpointInfoEnumerationHandle *rh;
rh = (RemoteEndpointInfoEnumerationHandle *)*h;
if (rh == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
if (rh->ThisHandleType != rehtEndpointInfo)
return ERROR_INVALID_HANDLE;
DbgEndpointEnumHandle_rundown(*h);
*h = NULL;
return RPC_S_OK;
}
void __RPC_USER DbgEndpointEnumHandle_rundown(DbgEndpointEnumHandle h)
{
RemoteEndpointInfoEnumerationHandle *rh;
rh = (RemoteEndpointInfoEnumerationHandle *)h;
FinishRPCDebugEndpointInfoEnumeration(&rh->h);
delete rh;
}
////////////////////////////////////////////////////////////////////
/// Remote thread enumeration routines
////////////////////////////////////////////////////////////////////
typedef struct tagRemoteThreadInfoEnumerationHandle
{
RemoteEnumerationHandleType ThisHandleType;
ThreadInfoEnumerationHandle h;
} RemoteThreadInfoEnumerationHandle;
error_status_t RemoteOpenRPCDebugThreadInfoEnumeration(
/* [in] */ handle_t IDL_handle,
/* [out] */ DbgThreadEnumHandle __RPC_FAR *h,
/* [in] */ DWORD ProcessID,
/* [in] */ DWORD ThreadID)
{
RemoteThreadInfoEnumerationHandle *rh;
RPC_STATUS Status;
*h = NULL;
rh = new RemoteThreadInfoEnumerationHandle;
if (rh == NULL)
return RPC_S_OUT_OF_MEMORY;
rh->ThisHandleType = rehtThreadInfo;
Status = OpenRPCDebugThreadInfoEnumeration(ProcessID, ThreadID, &rh->h);
if (Status != RPC_S_OK)
{
delete rh;
return Status;
}
*h = rh;
return RPC_S_OK;
}
error_status_t RemoteGetNextRPCDebugThreadInfo(
/* [in] */ DbgThreadEnumHandle h,
/* [unique][out][in] */ RemoteDebugThreadInfo __RPC_FAR *__RPC_FAR *debugInfo,
/* [out] */ DebugCellID __RPC_FAR *CellID,
/* [out] */ DWORD __RPC_FAR *ProcessID)
{
RemoteThreadInfoEnumerationHandle *rh;
RPC_STATUS Status;
DebugThreadInfo *NextThread;
if (debugInfo == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
*debugInfo = NULL;
CellID->SectionID = 0;
CellID->CellID = 0;
rh = (RemoteThreadInfoEnumerationHandle *)h;
if (rh->ThisHandleType != rehtThreadInfo)
return ERROR_INVALID_HANDLE;
Status = GetNextRPCDebugThreadInfo(rh->h, &NextThread, CellID, ProcessID);
if (Status == RPC_S_OK)
{
*debugInfo = (RemoteDebugThreadInfo *) MIDL_user_allocate(sizeof(RemoteDebugThreadInfo));
if (*debugInfo != NULL)
{
TranslateLocalThreadInfoToRemoteThreadInfo(NextThread, *debugInfo);
}
else
Status = RPC_S_OUT_OF_MEMORY;
}
return Status;
}
error_status_t RemoteFinishRPCDebugThreadInfoEnumeration(
/* [out][in] */ DbgThreadEnumHandle __RPC_FAR *h)
{
RemoteThreadInfoEnumerationHandle *rh;
rh = (RemoteThreadInfoEnumerationHandle *)*h;
if (rh == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
if (rh->ThisHandleType != rehtThreadInfo)
return ERROR_INVALID_HANDLE;
DbgThreadEnumHandle_rundown(*h);
*h = NULL;
return RPC_S_OK;
}
void __RPC_USER DbgThreadEnumHandle_rundown(DbgThreadEnumHandle h)
{
RemoteThreadInfoEnumerationHandle *rh;
rh = (RemoteThreadInfoEnumerationHandle *)h;
FinishRPCDebugThreadInfoEnumeration(&rh->h);
delete rh;
}
////////////////////////////////////////////////////////////////////
/// Remote client call enumeration routines
////////////////////////////////////////////////////////////////////
typedef struct tagRemoteClientCallInfoEnumerationHandle
{
RemoteEnumerationHandleType ThisHandleType;
ClientCallInfoEnumerationHandle h;
} RemoteClientCallInfoEnumerationHandle;
error_status_t RemoteOpenRPCDebugClientCallInfoEnumeration(
/* [in] */ handle_t IDL_handle,
/* [out] */ DbgClientCallEnumHandle __RPC_FAR *h,
/* [in] */ DWORD CallID,
/* [in] */ DWORD IfStart,
/* [in] */ int ProcNum,
/* [in] */ DWORD ProcessID)
{
RemoteClientCallInfoEnumerationHandle *rh;
RPC_STATUS Status;
*h = NULL;
rh = new RemoteClientCallInfoEnumerationHandle;
if (rh == NULL)
return RPC_S_OUT_OF_MEMORY;
rh->ThisHandleType = rehtClientCallInfo;
Status = OpenRPCDebugClientCallInfoEnumeration(CallID, IfStart, ProcNum, ProcessID, &rh->h);
if (Status != RPC_S_OK)
{
delete rh;
return Status;
}
*h = rh;
return RPC_S_OK;
}
error_status_t RemoteGetNextRPCDebugClientCallInfo(
/* [in] */ DbgClientCallEnumHandle h,
/* [unique][out][in] */ RemoteDebugClientCallInfo __RPC_FAR *__RPC_FAR *debugInfo,
/* [unique][out][in] */ RemoteDebugCallTargetInfo __RPC_FAR *__RPC_FAR *CallTargetDebugInfo,
/* [out] */ DebugCellID __RPC_FAR *CellID,
/* [out] */ DWORD __RPC_FAR *ProcessID)
{
RemoteClientCallInfoEnumerationHandle *rh;
RPC_STATUS Status;
DebugClientCallInfo *NextClientCall;
DebugCallTargetInfo *NextCallTarget;
if (debugInfo == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
if (CallTargetDebugInfo == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
*debugInfo = NULL;
*CallTargetDebugInfo = NULL;
CellID->SectionID = 0;
CellID->CellID = 0;
rh = (RemoteClientCallInfoEnumerationHandle *)h;
if (rh->ThisHandleType != rehtClientCallInfo)
return ERROR_INVALID_HANDLE;
Status = GetNextRPCDebugClientCallInfo(rh->h, &NextClientCall, &NextCallTarget,
CellID, ProcessID);
if (Status == RPC_S_OK)
{
*debugInfo = (RemoteDebugClientCallInfo *) MIDL_user_allocate(sizeof(RemoteDebugClientCallInfo));
if (*debugInfo != NULL)
{
TranslateLocalClientCallInfoToRemoteClientCallInfo(NextClientCall, *debugInfo);
*CallTargetDebugInfo
= (RemoteDebugCallTargetInfo *)MIDL_user_allocate(sizeof(RemoteDebugCallTargetInfo));
if (*CallTargetDebugInfo != NULL)
{
if ((NextCallTarget != NULL) && (NextCallTarget->Type != dctCallTargetInfo))
{
// inconsistent info - return NULL for call target
MIDL_user_free(*CallTargetDebugInfo);
*CallTargetDebugInfo = NULL;
NextCallTarget = NULL;
}
else
{
TranslateLocalCallTargetInfoToRemoteCallTargetInfo(NextCallTarget, *CallTargetDebugInfo);
}
}
// else - don't care - this is a best effort. We will return what we
// can. Client is prepared to handle NULL in the call target
}
else
Status = RPC_S_OUT_OF_MEMORY;
}
return Status;
}
error_status_t RemoteFinishRPCDebugClientCallInfoEnumeration(
/* [out][in] */ DbgClientCallEnumHandle __RPC_FAR *h)
{
RemoteClientCallInfoEnumerationHandle *rh;
rh = (RemoteClientCallInfoEnumerationHandle *)*h;
if (rh == NULL)
RpcRaiseException(ERROR_INVALID_PARAMETER);
if (rh->ThisHandleType != rehtClientCallInfo)
return ERROR_INVALID_HANDLE;
DbgClientCallEnumHandle_rundown(*h);
*h = NULL;
return RPC_S_OK;
}
void __RPC_USER DbgClientCallEnumHandle_rundown(DbgClientCallEnumHandle h)
{
RemoteClientCallInfoEnumerationHandle *rh;
rh = (RemoteClientCallInfoEnumerationHandle *)h;
FinishRPCDebugClientCallInfoEnumeration(&rh->h);
delete rh;
}
END_C_EXTERN