00001 #include "stdafx.h"
00002 #include "../rpcdispatch/rpcdisp.h"
00003 #include "../rpcdispatch/kdcomdisp.h"
00004 #include "../rpcdispatch/reporter.h"
00005 #include "VBoxCmdLine.h"
00006
00007 #include <VBox/mm.h>
00008
00009 static bool s_bVMWareOpenChannelDetected = false;
00010 static bool s_bChannelDetectSuccessful = false;
00011
00012 static unsigned KDRPCDirectHandler(char *pCommandBody, unsigned CommandBodyLength, char **ppReply);
00013 static unsigned KDRPCProxyHandler(char *pCommandBody, unsigned CommandBodyLength, char **ppReply);
00014
00015 int VirtualKDPortOutHandler( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb )
00016 {
00017 struct
00018 {
00019 unsigned RequestSize;
00020 unsigned MaxReplySize;
00021 } RequestHeader = {0, };
00022 static char CmdBody[262144];
00023 if (Port == 0x5659)
00024 {
00025 int rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)u32, &RequestHeader, sizeof(RequestHeader));
00026 if (!RT_SUCCESS(rc) || !RequestHeader.RequestSize)
00027 return VINF_SUCCESS;
00028 rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)(u32 + sizeof(RequestHeader)), CmdBody, RequestHeader.RequestSize);
00029 if (!RT_SUCCESS(rc))
00030 return VINF_SUCCESS;
00031 ASSERT(!memcmp(CmdBody, g_szRPCCommandHeader, sizeof(g_szRPCCommandHeader) - 1));
00032
00033 char *pReply = NULL;
00034 #ifdef KDVMWARE_USE_PROXY
00035 unsigned done = KDRPCProxyHandler(CmdBody + sizeof(g_szRPCCommandHeader) - 1, RequestHeader.RequestSize - (sizeof(g_szRPCCommandHeader) - 1), &pReply);
00036 #else
00037 unsigned done = KDRPCDirectHandler(CmdBody + sizeof(g_szRPCCommandHeader) - 1, RequestHeader.RequestSize - (sizeof(g_szRPCCommandHeader) - 1), &pReply);
00038 #endif
00039
00040 if (!pReply)
00041 done = 0;
00042
00043 char Prefix[sizeof(done) + 2];
00044 ((unsigned *)Prefix)[0] = done + 2;
00045 Prefix[sizeof(unsigned)] = '1';
00046 Prefix[sizeof(unsigned) + 1] = ' ';
00047
00048 rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)u32, Prefix, sizeof(Prefix));
00049 if (!RT_SUCCESS(rc))
00050 return VINF_SUCCESS;
00051 if (done)
00052 {
00053 rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)(u32 + sizeof(Prefix)), pReply, done);
00054 if (!RT_SUCCESS(rc))
00055 return VINF_SUCCESS;
00056 }
00057 return VINF_SUCCESS;
00058 }
00059 else
00060 {
00061 if ((Port == 0x5658) && (u32 == 0x564D5868))
00062 s_bVMWareOpenChannelDetected = true;
00063 else
00064 s_bVMWareOpenChannelDetected = false;
00065 return VINF_SUCCESS;
00066 }
00067 }
00068
00069 int VirtualKDPortInHandler( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb )
00070 {
00071 if (s_bVMWareOpenChannelDetected)
00072 {
00073 *pu32 = 'XOBV';
00074 s_bVMWareOpenChannelDetected = false;
00075 s_bChannelDetectSuccessful = true;
00076 }
00077 else
00078 *pu32 = -1;
00079 return VINF_SUCCESS;
00080 }
00081
00082
00083
00084
00085 #ifdef KDVMWARE_USE_PROXY
00086
00087 int MaxDelay = 0;
00088 static char ReplyBuffer[262144];
00089
00090 static unsigned KDRPCProxyHandler(char *pCommandBody, unsigned CommandBodyLength, char **ppReply)
00091 {
00092 DWORD done = 0;
00093 DWORD tick = GetTickCount();
00094 for (;;)
00095 {
00096 BOOL b = CallNamedPipe(_T("\\\\.\\pipe\\kdvmware_proxypipe"), pCommandBody, CommandBodyLength, ReplyBuffer, sizeof(ReplyBuffer), &done, INFINITE);
00097 if (b)
00098 {
00099 int delay = (int)(GetTickCount() - tick);
00100 if (delay > MaxDelay)
00101 MaxDelay = delay;
00102 break;
00103 }
00104 int er = GetLastError();
00105 if ((GetTickCount() - tick) > 1000)
00106 return 0;
00107 }
00108 *ppReply = ReplyBuffer;
00109 return done;
00110 }
00111
00112 #else
00113
00114 static KdRpcDispatcher *s_pClient = NULL;
00115
00116 static unsigned KDRPCDirectHandler(char *pCommandBody, unsigned CommandBodyLength, char **ppReply)
00117 {
00118 if (!s_pClient)
00119 return false;
00120 return s_pClient->OnRequest(pCommandBody, CommandBodyLength, ppReply);
00121 }
00122
00123 #endif
00124
00125 void InitializeRpcDispatcher()
00126 {
00127 #ifndef KDVMWARE_USE_PROXY
00128 LPWSTR lpCmdLine = GetCommandLineW();
00129 wchar_t wszPipeName[MAX_PATH] = {0,};
00130 if (!VBoxCmdLineToPipeNameW(lpCmdLine, wszPipeName, __countof(wszPipeName)))
00131 return;
00132 ASSERT(g_pReporter);
00133 wcsncpy(g_pReporter->GetStatusPointer()->PipeName, wszPipeName, __countof(g_pReporter->GetStatusPointer()->PipeName));
00134 s_pClient = new KdRpcDispatcher(new KdComDispatcher(wszPipeName));
00135 #else
00136 wcsncpy(g_pReporter->GetStatusPointer()->PipeName, L"\\\\.\\pipe\\kdvmware_proxypipe", __countof(g_pReporter->GetStatusPointer()->PipeName));
00137 #endif
00138 g_pReporter->GetStatusPointer()->PatchErrorPlus1 = 1;
00139 }