00001
00006 #pragma once
00007
00008 namespace VBoxRPC
00009 {
00010 #ifndef _AMD64_
00011 static void __declspec(naked) __fastcall ExchangeData(ULONG pPhysicalAddr, int)
00012 {
00013 __asm
00014 {
00015 xchg eax, ecx
00016 mov edx, 0x5659
00017 out dx, eax
00018 ret
00019 }
00020 }
00021 #else
00022 extern "C" void VBoxExchangeData(ULONG pPhysicalAddr, int);
00023
00024 static inline void ExchangeData(ULONG pPhysicalAddr, int a)
00025 {
00026 VBoxExchangeData(pPhysicalAddr, a);
00027 }
00028
00029 #endif
00030 }
00031
00033 template <char *t_pBuffer, unsigned t_BufferSize> class BufferedVBoxChannel
00034 {
00035 private:
00036 unsigned m_BufferPos;
00037 unsigned m_TotalTransferSize;
00038 PHYSICAL_ADDRESS m_BufPhysical;
00039
00040 enum {SendHdrSize = 2 * sizeof(unsigned), RecvHdrSize = sizeof(unsigned)};
00041
00042 enum
00043 {
00044 Idle,
00045 Sending,
00046 Receiving,
00047 Received,
00048 } m_Phase;
00049
00050 private:
00051 bool PerformDataExchange()
00052 {
00053 #ifdef VMWRPC_PARAMETER_CHECKING
00054 if (m_Phase != Sending)
00055 return false;
00056 if (m_BufferPos != m_TotalTransferSize)
00057 return false;
00058 #endif
00059 VBoxRPC::ExchangeData(m_BufPhysical.LowPart, 0);
00060 m_TotalTransferSize = ((unsigned *)t_pBuffer)[0] + RecvHdrSize;
00061 m_BufferPos = RecvHdrSize;
00062 m_Phase = Receiving;
00063 return true;
00064 }
00065
00066 public:
00067 BufferedVBoxChannel()
00068 : m_BufferPos(0)
00069 , m_TotalTransferSize(0)
00070 , m_Phase(Idle)
00071 {
00072 m_BufPhysical = MmGetPhysicalAddress(t_pBuffer);
00073 }
00074
00075 ~BufferedVBoxChannel()
00076 {
00077 }
00078
00079 bool PrepareSend(unsigned SendSize)
00080 {
00081 #ifdef VMWRPC_PARAMETER_CHECKING
00082 if ((m_Phase != Idle) || (SendSize > (t_BufferSize - SendHdrSize)))
00083 return false;
00084 #endif
00085 m_TotalTransferSize = SendSize + SendHdrSize;
00086 m_Phase = Sending;
00087 ((unsigned *)t_pBuffer)[0] = SendSize;
00088 ((unsigned *)t_pBuffer)[1] = t_BufferSize;
00089 m_BufferPos = SendHdrSize;
00090 return true;
00091 }
00092
00093 bool SendPartial(const void *pData, unsigned Size)
00094 {
00095 if (!Size)
00096 return true;
00097 #ifdef VMWRPC_PARAMETER_CHECKING
00098 if (m_Phase != Sending)
00099 return false;
00100 if (Size > (m_TotalTransferSize - m_BufferPos))
00101 return false;
00102 #endif
00103 memcpy(t_pBuffer + m_BufferPos, pData, Size);
00104 m_BufferPos += Size;
00105 return true;
00106 }
00107
00108 unsigned GetReplySize()
00109 {
00110 if (m_Phase == Receiving)
00111 return m_TotalTransferSize - RecvHdrSize;
00112 if (!PerformDataExchange())
00113 return -1;
00114 if (m_Phase != Receiving)
00115 return -1;
00116 return m_TotalTransferSize - RecvHdrSize;
00117 }
00118
00119 bool Receive(void *pData, unsigned Size)
00120 {
00121 if (!Size)
00122 return true;
00123 #ifdef VMWRPC_PARAMETER_CHECKING
00124 if (m_Phase != Receiving)
00125 return false;
00126 if (Size > (m_TotalTransferSize - m_BufferPos))
00127 return false;
00128 #endif
00129 memcpy(pData, t_pBuffer + m_BufferPos, Size);
00130 m_BufferPos += Size;
00131 if (m_BufferPos == m_TotalTransferSize)
00132 m_Phase = Received;
00133 return true;
00134 }
00135
00136 bool Valid()
00137 {
00138 return true;
00139 }
00140
00141 bool EndReceive()
00142 {
00143 if (m_Phase != Received)
00144 return false;
00145 m_Phase = Idle;
00146 return true;
00147 }
00148
00149 bool NeedRestartInVBoxMode()
00150 {
00151 return false;
00152 }
00153 };