• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

E:/PROJECTS/cvsed/mixed/VIRTUA~1/rpcdispatch/rpcdisp.h

Go to the documentation of this file.
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 };