00001 00007 #pragma once 00008 #include "../kdvm/kdrpc.h" 00009 #include "../kdvm/kdxxx.h" 00010 #include <bzscmn/assert.h> 00011 00013 00016 class IKdComDispatcher 00017 { 00018 public: 00019 virtual KD_RECV_CODE __stdcall KdReceivePacket( 00020 __in ULONG PacketType, 00021 __inout_opt PKD_BUFFER FirstBuffer, 00022 __inout_opt PKD_BUFFER SecondBuffer, 00023 __out_opt PULONG PayloadBytes, 00024 __inout_opt PKD_CONTEXT KdContext)=0; 00025 00026 virtual bool __stdcall KdSendPacket( 00027 __in ULONG PacketType, 00028 __in PKD_BUFFER FirstBuffer, 00029 __in_opt PKD_BUFFER SecondBuffer, 00030 __inout PKD_CONTEXT KdContext)=0; 00031 00032 virtual void ReportProtocolVersionError(int GuestVersion, int HostVersion)=0; 00033 virtual void SetKdDebuggerNotPresent(bool Value)=0; 00034 virtual bool GetKdDebuggerNotPresent()=0; 00035 00036 virtual ~IKdComDispatcher(){} 00037 }; 00038 00040 00046 class KdRpcDispatcher 00047 { 00048 private: 00049 enum {REPLY_BUFFER_BASE = 262144}; 00050 enum {MAX_BUFFER_SIZE = 65536}; 00051 enum {REPLY_BUFFER_SIZE = REPLY_BUFFER_BASE + MAX_BUFFER_SIZE}; 00052 char *m_pReplyBuffer; 00053 00054 private: 00055 IKdComDispatcher *m_pDispatcher; 00056 bool m_bProtocolVersionMatch; 00057 00058 static inline void Serialize(char *pBase, unsigned &offset, const void *pBuffer, unsigned Size) 00059 { 00060 memcpy(pBase + offset, pBuffer, Size); 00061 offset += Size; 00062 } 00063 00064 public: 00065 char szTestReply[KDRPC_TEST_BUFFER_SIZE + sizeof(g_szRPCReplySignature)]; 00066 00067 KdRpcDispatcher(IKdComDispatcher *pDispatcher) 00068 { 00069 m_pDispatcher = pDispatcher; 00070 m_pReplyBuffer = new char[REPLY_BUFFER_SIZE]; 00071 m_bProtocolVersionMatch = false; 00072 } 00073 00074 ~KdRpcDispatcher() 00075 { 00076 delete m_pReplyBuffer; 00077 delete m_pDispatcher; 00078 } 00079 00081 unsigned OnRequest(const char *pRequest, unsigned RequestSize, char **ppReply) 00082 { 00083 ASSERT(pRequest && ppReply); 00084 switch (pRequest[0]) 00085 { 00086 case VersionReport: 00087 *ppReply = m_pReplyBuffer; 00088 if (*((int *)(pRequest + 1)) == KDRPC_PROTOCOL_VERSION) 00089 m_bProtocolVersionMatch = true; 00090 else 00091 { 00092 m_pDispatcher->ReportProtocolVersionError(*((int *)(pRequest + 1)), KDRPC_PROTOCOL_VERSION); 00093 } 00094 memcpy(m_pReplyBuffer, g_szRPCReplySignature, sizeof(g_szRPCReplySignature) - 1); 00095 *((int *)(m_pReplyBuffer + sizeof(g_szRPCReplySignature) - 1)) = KDRPC_PROTOCOL_VERSION; 00096 return sizeof(int) + sizeof(g_szRPCReplySignature) - 1; 00097 case TestConnection: 00098 if (!m_bProtocolVersionMatch) 00099 { 00100 m_pDispatcher->ReportProtocolVersionError(0x100, KDRPC_PROTOCOL_VERSION); 00101 *ppReply = szTestReply; 00102 return 0; 00103 } 00104 *ppReply = szTestReply; 00105 memcpy(szTestReply, g_szRPCReplySignature, sizeof(g_szRPCReplySignature)); 00106 for (int i = 0; i < KDRPC_TEST_BUFFER_SIZE; i++) 00107 szTestReply[i + sizeof(g_szRPCReplySignature) - 1] = (char)(i ^ 0x55); 00108 return sizeof(g_szRPCReplySignature) + KDRPC_TEST_BUFFER_SIZE - 1; 00109 case ReceivePacket: 00110 { 00111 *ppReply = m_pReplyBuffer; 00112 if (RequestSize != (1 + 2 * sizeof(ULONG) + 2 * sizeof(SendableKdBuffer) + sizeof(KD_CONTEXT))) 00113 return 0; 00114 KD_BUFFER Buf1 = {0,}; 00115 KD_BUFFER Buf2 = {0,}; 00116 ULONG globals = *((ULONG *)(pRequest + 1 + sizeof(ULONG))); 00117 m_pDispatcher->SetKdDebuggerNotPresent((globals & 1) != 0); 00118 memcpy(&Buf1, (pRequest + 1 + 2 * sizeof(ULONG)), sizeof(SendableKdBuffer)); 00119 memcpy(&Buf2, (pRequest + 1 + 2 * sizeof(ULONG) + sizeof(SendableKdBuffer)), sizeof(SendableKdBuffer)); 00120 unsigned firstBufOffset = sizeof(g_szRPCReplySignature) + 2 * sizeof(SendableKdBuffer) + KDRPC_RECV_RETURNED_ULONGS * sizeof(ULONG) + sizeof(KD_CONTEXT); 00121 Buf1.pData = (PUCHAR) &m_pReplyBuffer[firstBufOffset]; 00122 Buf2.pData = (PUCHAR) &m_pReplyBuffer[REPLY_BUFFER_BASE]; 00123 PKD_CONTEXT pContext = (PKD_CONTEXT)(pRequest + 1 + 2 * sizeof(ULONG) + 2 * sizeof(SendableKdBuffer)); 00124 00125 ULONG PayloadBytes = 0; 00126 unsigned Status = m_pDispatcher->KdReceivePacket(*((ULONG *)(pRequest + 1)), 00127 Buf1.MaxLength ? &Buf1 : NULL, 00128 Buf2.MaxLength ? &Buf2 : NULL, 00129 &PayloadBytes, 00130 pContext); 00131 unsigned offset = sizeof(g_szRPCReplySignature); 00132 memcpy(m_pReplyBuffer, g_szRPCReplySignature, sizeof(g_szRPCReplySignature) - 1); 00133 m_pReplyBuffer[sizeof(g_szRPCReplySignature)-1] = ReceivePacket; 00134 Serialize(m_pReplyBuffer,offset, &Buf1, sizeof(SendableKdBuffer)); 00135 Serialize(m_pReplyBuffer,offset, &Buf2, sizeof(SendableKdBuffer)); 00136 Serialize(m_pReplyBuffer,offset, pContext, sizeof(KD_CONTEXT)); 00137 00138 unsigned Size1 = Buf1.Length, Size2 = Buf2.Length; 00139 globals = 0; 00140 if (m_pDispatcher->GetKdDebuggerNotPresent()) 00141 globals |= 1; 00142 00143 ULONG *pAdditionalInfo = (ULONG *)(m_pReplyBuffer + offset); 00144 pAdditionalInfo[0] = Status; 00145 pAdditionalInfo[1] = PayloadBytes; 00146 pAdditionalInfo[2] = Size1; 00147 pAdditionalInfo[3] = Size2; 00148 pAdditionalInfo[4] = globals; 00149 offset += KDRPC_RECV_RETURNED_ULONGS * sizeof(ULONG); 00150 ASSERT(offset == firstBufOffset); 00151 offset += Size1; 00152 memcpy(m_pReplyBuffer + offset, &m_pReplyBuffer[REPLY_BUFFER_BASE], Size2); 00153 offset += Size2; 00154 return offset; 00155 } 00156 break; 00157 case SendPacket: 00158 { 00159 *ppReply = m_pReplyBuffer; 00160 unsigned buf1Offset = 1 + sizeof(ULONG) * KDRPC_SEND_PASSED_ULONGS + 2 * sizeof(SendableKdBuffer) + sizeof(KD_CONTEXT); 00161 if (RequestSize < buf1Offset) 00162 return 0; 00163 KD_BUFFER Buf1 = {0,}; 00164 KD_BUFFER Buf2 = {0,}; 00165 memcpy(&Buf1, (pRequest + 1), sizeof(SendableKdBuffer)); 00166 memcpy(&Buf2, (pRequest + 1 + sizeof(SendableKdBuffer)), sizeof(SendableKdBuffer)); 00167 PKD_CONTEXT pContext = (PKD_CONTEXT)(pRequest + 1 + 2 * sizeof(SendableKdBuffer)); 00168 00169 ULONG *pParams = (ULONG *)(pRequest + 1 + 2 * sizeof(SendableKdBuffer) + sizeof(KD_CONTEXT)); 00170 if (RequestSize != (buf1Offset + pParams[1] + pParams[2])) 00171 return 0; 00172 00173 ULONG globals = pParams[3]; 00174 m_pDispatcher->SetKdDebuggerNotPresent((globals & 1) != 0); 00175 00176 00177 Buf1.pData = (PUCHAR) &pRequest[buf1Offset]; 00178 Buf2.pData = (PUCHAR) &pRequest[buf1Offset + pParams[1]]; 00179 00180 bool sendResult = m_pDispatcher->KdSendPacket(pParams[0], 00181 Buf1.Length ? &Buf1 : NULL, 00182 Buf2.Length ? &Buf2 : NULL, 00183 pContext); 00184 00185 unsigned offset = sizeof(g_szRPCReplySignature); 00186 memcpy(m_pReplyBuffer, g_szRPCReplySignature, sizeof(g_szRPCReplySignature) - 1); 00187 m_pReplyBuffer[sizeof(g_szRPCReplySignature)-1] = SendPacket; 00188 Serialize(m_pReplyBuffer,offset, pContext, sizeof(KD_CONTEXT)); 00189 00190 globals = 0; 00191 if (m_pDispatcher->GetKdDebuggerNotPresent()) 00192 globals |= 1; 00193 if (!sendResult) 00194 globals |= (1<<1); 00195 00196 Serialize(m_pReplyBuffer,offset, &globals, sizeof(ULONG)); 00197 return offset; 00198 } 00199 break; 00200 } 00201 return 0; 00202 } 00203 };