/*++ 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 #include #include #include #include #include #include #include #include #include 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