00001
00008 #pragma once
00009
00010
00011 #define VMWRPC_PARAMETER_CHECKING
00012
00013
00014 #pragma pack(push, 4)
00016 class VMWareRpcData
00017 {
00018 public:
00019 unsigned m_Cookie1;
00020 unsigned m_Cookie2;
00021 unsigned m_ChannelNumber;
00022
00023 unsigned m_ReplyId;
00024 unsigned m_CachedReplySize;
00025 };
00026 #pragma pack(pop)
00027
00028 #ifdef _AMD64_
00029 extern "C"
00030 {
00031
00032 int VMWareOpenChannel(VMWareRpcData *pChannel);
00033 bool VMWareCloseChannel(VMWareRpcData *pChannel);
00034 bool VMWareSendRequestLength(VMWareRpcData *pChannel, size_t sizeNotCountingNULL);
00035 bool VMWareSendPartialData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, const void *pData);
00036 bool VMWareSendData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, const void *pData);
00037 unsigned VMWareGetReplySize(VMWareRpcData *pChannel);
00038 bool VMWareRecvData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, void *pData);
00039 bool VMWareEndReceive(VMWareRpcData *pChannel);
00040 }
00041 #endif
00042
00044
00045
00046
00047 namespace VMWareRPC
00048 {
00049 #ifndef _AMD64_
00051 static unsigned __declspec(naked) __fastcall OpenChannel(VMWareRpcData *pChannel)
00052 {
00053 __asm
00054 {
00055 pushad
00056 mov eax, 0x564D5868
00057 mov ebx, 0xC9435052
00058 xchg ecx,ebp
00059 mov ecx, 0x0000001E
00060 mov edx, 0x5658
00061 out dx, eax
00062 test ecx, 0x00010000
00063 jz vmware_rpc_open_channel_error
00064 mov [ebp].m_Cookie1, esi
00065 mov [ebp].m_Cookie2, edi
00066 mov [ebp].m_ChannelNumber, edx
00067 popad
00068 xor eax, eax
00069 inc eax
00070 ret
00071 vmware_rpc_open_channel_error:
00072 mov edx, 0x5658
00073 in eax, dx
00074 cmp eax, 'XOBV'
00075 jz vmware_rpc_open_channel_vbox
00076 popad
00077 xor eax, eax
00078 ret
00079 vmware_rpc_open_channel_vbox:
00080 popad
00081 xor eax, eax
00082 add eax, 2
00083 ret
00084 }
00085 }
00086
00088 static bool __declspec(naked) __fastcall CloseChannel(VMWareRpcData *pChannel)
00089 {
00090 __asm
00091 {
00092 pushad
00093 mov eax, 0x564D5868
00094 mov edx, [ecx].m_ChannelNumber
00095 or edx, 0x5658
00096 mov esi, [ecx].m_Cookie1
00097 mov edi, [ecx].m_Cookie2
00098 mov ecx, 0x0006001E
00099 out dx, eax
00100 cmp ecx, 0x00010000
00101 popad
00102 setz al
00103 and eax,1
00104 ret
00105 }
00106 }
00107
00109 static bool __declspec(naked) __fastcall SendRequestLength(VMWareRpcData *pChannel, size_t sizeNotCountingNULL)
00110 {
00111 __asm
00112 {
00113 pushad
00114 mov eax, 0x564D5868
00115 mov ebx, edx
00116 mov edx, [ecx].m_ChannelNumber
00117 or edx, 0x5658
00118 mov esi, [ecx].m_Cookie1
00119 mov edi, [ecx].m_Cookie2
00120 mov ecx, 0x0001001E
00121 out dx, eax
00122 cmp ecx, 0x00810000
00123 jnz vmware_rpc_send_size_error
00124
00125 popad
00126 xor eax,eax
00127 inc eax
00128 ret
00129
00130 vmware_rpc_send_size_error:
00131 popad
00132 xor eax,eax
00133 ret
00134 }
00135 }
00136
00138 static bool __declspec(naked) __fastcall SendPartialData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, const void *pData)
00139 {
00140 __asm
00141 {
00142 pushad
00143 mov eax, 0x564D5868
00144
00145 xchg ecx, edx
00146 mov ebx, 0x00010000
00147 mov esi, [esp+0x24]
00148 mov edi, [edx].m_Cookie2
00149 mov ebp, [edx].m_Cookie1
00150 mov edx, [edx].m_ChannelNumber
00151 or edx, 0x5659
00152 rep outsb
00153
00154 cmp ebx, 0x00010000
00155 jnz vmware_rpc_send_partial_error
00156
00157 popad
00158 xor eax,eax
00159 inc eax
00160 ret 4
00161
00162 vmware_rpc_send_partial_error:
00163 popad
00164 xor eax,eax
00165 ret 4
00166 }
00167 }
00168
00170 static bool __declspec(naked) __fastcall SendData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, const void *pData)
00171 {
00172 __asm
00173 {
00174 pushad
00175 mov eax, 0x564D5868
00176 mov ebx, edx
00177 mov edx, [ecx].m_ChannelNumber
00178 or edx, 0x5658
00179 mov esi, [ecx].m_Cookie1
00180 mov edi, [ecx].m_Cookie2
00181
00182 xchg ebp, ecx
00183 mov ecx, 0x0001001E
00184 out dx, eax
00185 cmp ecx, 0x00810000
00186 jnz vmware_rpc_send_data_error
00187
00188
00189 xchg ecx, ebx
00190 mov ebx, 0x00010000
00191 mov esi, [esp+0x24]
00192 mov edx, [ebp].m_ChannelNumber
00193 or edx, 0x5659
00194 mov edi, [ebp].m_Cookie2
00195 mov ebp, [ebp].m_Cookie1
00196 rep outsb
00197
00198 cmp ebx, 0x00010000
00199 jnz vmware_rpc_send_data_error
00200
00201 popad
00202 xor eax,eax
00203 inc eax
00204 ret 4
00205
00206 vmware_rpc_send_data_error:
00207 popad
00208 xor eax,eax
00209 ret
00210 }
00211 }
00212
00214 static unsigned __declspec(naked) __fastcall GetReplySize(VMWareRpcData *pChannel)
00215 {
00216 __asm
00217 {
00218 push ebx
00219 push esi
00220 push edi
00221 push ebp
00222 mov eax, 0x564D5868
00223 mov edx, [ecx].m_ChannelNumber
00224 or edx, 0x5658
00225 mov esi, [ecx].m_Cookie1
00226 mov edi, [ecx].m_Cookie2
00227 xchg ebp, ecx
00228 mov ecx, 0x0003001E
00229 out dx, eax
00230 mov [ebp].m_ReplyId, edx
00231 cmp ecx, 0x00830000
00232 jz return_from_get_reply_size
00233 or ebx, -1
00234 return_from_get_reply_size:
00235 xchg eax,ebx
00236 pop ebp
00237 pop edi
00238 pop esi
00239 pop ebx
00240 ret
00241 }
00242 }
00243
00245 static bool __declspec(naked) __fastcall RecvData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, void *pData)
00246 {
00247 __asm
00248 {
00249 pushad
00250 mov eax, 0x564D5868
00251 mov ebx, 0x00010000
00252 xchg ecx, edx
00253 mov edi, [esp+0x24]
00254 mov esi, [edx].m_Cookie1
00255 mov ebp, [edx].m_Cookie2
00256 mov edx, [edx].m_ChannelNumber
00257 or edx, 0x5659
00258 rep insb
00259
00260 cmp ebx, 0x00010000
00261 jnz vmware_rpc_recv_data_error
00262
00263 popad
00264 xor eax,eax
00265 inc eax
00266 ret 4
00267
00268 vmware_rpc_recv_data_error:
00269 popad
00270 xor eax,eax
00271 ret 4
00272 }
00273 }
00274
00276 static bool __declspec(naked) __fastcall EndReceive(VMWareRpcData *pChannel)
00277 {
00278 __asm
00279 {
00280 pushad
00281 mov eax, 0x564D5868
00282 mov ebx, [ecx].m_ReplyId
00283 mov edx, [ecx].m_ChannelNumber
00284 or edx, 0x5658
00285 mov esi, [ecx].m_Cookie1
00286 mov edi, [ecx].m_Cookie2
00287 mov ecx, 0x0005001E
00288 out dx, eax
00289 cmp ecx, 0x00010000
00290 popad
00291 setz al
00292 and eax,1
00293 ret
00294 }
00295 }
00296 #else
00297
00298 static inline int OpenChannel(VMWareRpcData *pChannel)
00299 {
00300 return VMWareOpenChannel(pChannel);
00301 }
00302
00303 static inline bool CloseChannel(VMWareRpcData *pChannel)
00304 {
00305 return VMWareCloseChannel(pChannel);
00306 }
00307
00308 static inline bool SendRequestLength(VMWareRpcData *pChannel, size_t sizeNotCountingNULL)
00309 {
00310 return VMWareSendRequestLength(pChannel, sizeNotCountingNULL);
00311 }
00312
00313 static inline bool SendPartialData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, const void *pData)
00314 {
00315 return VMWareSendPartialData(pChannel, sizeNotCountingNULL, pData);
00316 }
00317
00318 static inline bool SendData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, const void *pData)
00319 {
00320 return VMWareSendData(pChannel, sizeNotCountingNULL, pData);
00321 }
00322
00323 static inline unsigned GetReplySize(VMWareRpcData *pChannel)
00324 {
00325 return VMWareGetReplySize(pChannel);
00326 }
00327
00328 static inline bool RecvData(VMWareRpcData *pChannel, size_t sizeNotCountingNULL, void *pData)
00329 {
00330 return VMWareRecvData(pChannel, sizeNotCountingNULL, pData);
00331 }
00332
00333 static inline bool EndReceive(VMWareRpcData *pChannel)
00334 {
00335 return VMWareEndReceive(pChannel);
00336 }
00337 #endif
00338 }
00339
00341
00350 class VMWareRPCChannel : protected VMWareRpcData
00351 {
00352 private:
00353 bool m_bVBoxDetected;
00354
00355 protected:
00356 bool Send(const char *pData, unsigned Size = 0)
00357 {
00358 if (!Size)
00359 Size = strlen(pData);
00360 m_CachedReplySize = -1;
00361 return VMWareRPC::SendData(this, Size, pData);
00362 }
00363
00364 bool Receive(void *pData, unsigned Size)
00365 {
00366 if (m_CachedReplySize == -1)
00367 return false;
00368 if (Size > m_CachedReplySize)
00369 Size = m_CachedReplySize;
00370 if (!Size)
00371 return true;
00372 if (!VMWareRPC::RecvData(this, Size, pData))
00373 {
00374 m_CachedReplySize = m_ChannelNumber = -1;
00375 return false;
00376 }
00377 m_CachedReplySize -= Size;
00378 return true;
00379 }
00380
00381 bool EndReceive()
00382 {
00383 if (!VMWareRPC::EndReceive(this))
00384 return false;
00385 m_CachedReplySize = -1;
00386 return true;
00387 }
00388
00389 unsigned GetReplySize()
00390 {
00391 if (m_CachedReplySize != -1)
00392 return m_CachedReplySize;
00393 m_CachedReplySize = VMWareRPC::GetReplySize(this);
00394 return m_CachedReplySize;
00395 }
00396
00397 public:
00398
00399 VMWareRPCChannel()
00400 : m_bVBoxDetected(false)
00401 {
00402 switch (VMWareRPC::OpenChannel(this))
00403 {
00404 case 1:
00405 break;
00406 case 2:
00407 m_bVBoxDetected = true;
00408
00409 default:
00410 m_ChannelNumber = -1;
00411
00412 }
00413 m_CachedReplySize = -1;
00414 }
00415
00416 ~VMWareRPCChannel()
00417 {
00418 VMWareRPC::CloseChannel(this);
00419 }
00420
00422 unsigned ExecuteCommand(const char *pszRequest, char *pszBuffer, unsigned MaxBufferSize)
00423 {
00424 ASSERT(pszRequest && pszBuffer && (MaxBufferSize > 1));
00425 if (!Send(pszRequest))
00426 return -1;
00427 unsigned size = GetReplySize();
00428 if ((size == -1) || (size >= MaxBufferSize))
00429 return -1;
00430 if (!Receive(pszBuffer, size))
00431 return -1;
00432 pszBuffer[size] = 0;
00433 if (!EndReceive())
00434 return -1;
00435 return size;
00436 }
00437
00438 bool Valid()
00439 {
00440 return m_ChannelNumber != -1;
00441 }
00442
00443 bool IsVBoxDetected()
00444 {
00445 return m_bVBoxDetected;
00446 }
00447 };
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00484 template <char *t_pBuffer, unsigned t_BufferSize> class BufferedRPCChannel : private VMWareRPCChannel
00485 {
00486 private:
00487 unsigned m_BufferPos;
00488 unsigned m_TotalTransferSize;
00489
00490 enum
00491 {
00492 Idle,
00493 Sending,
00494 Sent,
00495 Receiving,
00496 Received,
00497 } m_Phase;
00498
00499 private:
00500 bool SendBufferedData()
00501 {
00502 #ifdef VMWRPC_PARAMETER_CHECKING
00503 if (m_Phase != Sending)
00504 return false;
00505 if (m_BufferPos != m_TotalTransferSize)
00506 return false;
00507 #endif
00508 if (!__super::Send(t_pBuffer, m_TotalTransferSize))
00509 return false;
00510 m_Phase = Sent;
00511 return true;
00512 }
00513
00514 public:
00515 BufferedRPCChannel()
00516 : m_BufferPos(0)
00517 , m_TotalTransferSize(0)
00518 , m_Phase(Idle)
00519 {
00520 }
00521
00522 ~BufferedRPCChannel()
00523 {
00524 }
00525
00526 bool PrepareSend(unsigned SendSize)
00527 {
00528 if ((m_Phase != Idle) || (SendSize > t_BufferSize))
00529 return false;
00530 m_TotalTransferSize = SendSize;
00531 m_Phase = Sending;
00532 m_BufferPos = 0;
00533 return true;
00534 }
00535
00536 bool SendPartial(const void *pData, unsigned Size)
00537 {
00538 if (!Size)
00539 return true;
00540 #ifdef VMWRPC_PARAMETER_CHECKING
00541 if (m_Phase != Sending)
00542 return false;
00543 if (Size > (m_TotalTransferSize - m_BufferPos))
00544 return false;
00545 #endif
00546 memcpy(t_pBuffer + m_BufferPos, pData, Size);
00547 m_BufferPos += Size;
00548 return true;
00549 }
00550
00551 unsigned GetReplySize()
00552 {
00553 if (m_Phase == Receiving)
00554 return m_TotalTransferSize;
00555 if (!SendBufferedData())
00556 return -1;
00557 if (m_Phase != Sent)
00558 return -1;
00559 m_TotalTransferSize = __super::GetReplySize();
00560 if (m_TotalTransferSize && (m_TotalTransferSize != -1) && (m_TotalTransferSize <= t_BufferSize))
00561 {
00562 if (!__super::Receive(t_pBuffer, t_BufferSize))
00563 return -1;
00564 m_Phase = Receiving;
00565 m_BufferPos = 0;
00566 return m_TotalTransferSize;
00567 }
00568 else
00569 return -1;
00570 }
00571
00572 bool Receive(void *pData, unsigned Size)
00573 {
00574 if (!Size)
00575 return true;
00576 #ifdef VMWRPC_PARAMETER_CHECKING
00577 if (m_Phase != Receiving)
00578 return false;
00579 if (Size > (m_TotalTransferSize - m_BufferPos))
00580 return false;
00581 #endif
00582 memcpy(pData, t_pBuffer + m_BufferPos, Size);
00583 m_BufferPos += Size;
00584 if (m_BufferPos == m_TotalTransferSize)
00585 m_Phase = Received;
00586 return true;
00587 }
00588
00589 bool Valid()
00590 {
00591 return __super::Valid();
00592 }
00593
00594 bool EndReceive()
00595 {
00596 if (m_Phase != Received)
00597 return false;
00598 if (!__super::EndReceive())
00599 return false;
00600 m_Phase = Idle;
00601 return true;
00602 }
00603
00604 bool NeedRestartInVBoxMode()
00605 {
00606 return __super::IsVBoxDetected();
00607 }
00608
00609 };