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

E:/PROJECTS/cvsed/mixed/VIRTUA~1/rpcdispatch/PacketLog.cpp

Go to the documentation of this file.
00001 
00007 #include "stdafx.h"
00008 #include "PacketLog.h"
00009 #include <bzscmn/bzscmn.h>
00010 
00011 static const char szHTMLPreambleFormat[] = "<html><head><title>KDVMWare Packet Log - %S</title>\r\n\
00012 <style>table {font-family: Courier New} tr.recv {color: red; } tr.send {color: green; }</style>\r\n\
00013 </head>\r\n<body><center><h1>KDVMWare Packet Log - %S</h1></center>\r\n";
00014 
00015 static const char szLegend[] = "Legend: <b><font color = red>Debugger-to-kernel packets are in red</font>; <font color = green>Kernel-to-debugger packets are in green</font></b><br/>\r\n";
00016 static const char szTableHeader[] = "<table border><tr><td>#</td><td>Time</td><td>Type</td><td>Data</td></tr>";
00017 
00018 static const char szTerminationSimulationNotification[] = "</table><br/><center><font color = \"blue\"><b>----- Simulating session termination -----</b></font></center><br/>";
00019 static const char szTerminationSimulationEndFmt[] = "</table><br/><center><font color = \"blue\"><b>----- Session termination simulated: %s -----</b></font></center><br/>";
00020 
00021 static const char szHTMLFooter[] = "\r\n</table></body></html>";
00022 
00023 PacketLogger::PacketLogger( const TCHAR *pszKdPipeName )
00024         : m_LogFilePath(_T(""))
00025         , m_SendPacketNumber(0)
00026         , m_RecvPacketNumber(0)
00027         , m_bTableHeaderPrinted(false)
00028 {
00029         if (!pszKdPipeName)
00030                 return;
00031         const TCHAR *p = _tcsrchr(pszKdPipeName, '\\');
00032         if (!p)
00033                 return;
00034         
00035         TCHAR tsz[MAX_PATH];
00036 #ifdef _USRDLL
00037         extern HMODULE g_hThisDll;
00038         GetModuleFileName(g_hThisDll, tsz, sizeof(tsz)/sizeof(tsz[0]));
00039 #else
00040         GetModuleFileName(GetModuleHandle(NULL), tsz, sizeof(tsz)/sizeof(tsz[0]));
00041 #endif
00042 
00043         TCHAR *p2 = _tcsrchr(tsz, '\\');
00044         if (p2)
00045                 p2[0] = 0;
00046 
00047         m_LogFilePath = tsz;
00048         m_LogFilePath.AppendPath(p + 1);
00049 
00050         if (!memcmp(p + 1, L"kd_", 3 * sizeof(TCHAR)))
00051                 p += 3;
00052 
00053         m_SessionName = (p + 1);
00054 
00055         m_LogFilePath.append(_T(".html"));
00056 }
00057 
00058 #pragma region Helpers for displaying various constants from windbgkd.h
00059 static const char *GetPacketTypeName(int PacketType)
00060 {
00061         switch(PacketType)
00062         {
00063         case 1:
00064                 return " KD_STATE_CHANGE32";
00065         case 2:
00066                 return " KD_STATE_MANIPULATE";
00067         case 3:
00068                 return " KD_DEBUG_IO";
00069         case 4:
00070                 return " KD_ACKNOWLEDGE";
00071         case 5:
00072                 return " KD_RESEND";
00073         case 6:
00074                 return " KD_RESET";
00075         case 7:
00076                 return " KD_STATE_CHANGE64";
00077         case 8:
00078                 return " KD_POLL_BREAKIN";
00079         case 9:
00080                 return " KD_TRACE_IO";
00081         case 10:
00082                 return " KD_CONTROL_REQUEST";
00083         case 11:
00084                 return " KD_FILE_IO";
00085         default:
00086                 return "";
00087         }
00088 }
00089 
00090 static const char *GetApiTypeName(int ApiType)
00091 {
00092         switch (ApiType)
00093         {
00094         case 0x00003030:
00095                 return "DbgKdExceptionStateChange";
00096         case 0x00003031:
00097                 return "DbgKdLoadSymbolsStateChange";
00098         case 0x00003032:
00099                 return "DbgKdCommandStringStateChange";
00100         case 0x00003033:
00101                 return "DbgKdMaximumStateChange";
00102         case 0x00003130:
00103                 return "DbgKdReadVirtualMemoryApi";
00104         case 0x00003131:
00105                 return "DbgKdWriteVirtualMemoryApi";
00106         case 0x00003132:
00107                 return "DbgKdGetContextApi";
00108         case 0x00003133:
00109                 return "DbgKdSetContextApi";
00110         case 0x00003134:
00111                 return "DbgKdWriteBreakPointApi";
00112         case 0x00003135:
00113                 return "DbgKdRestoreBreakPointApi";
00114         case 0x00003136:
00115                 return "DbgKdContinueApi";
00116         case 0x00003137:
00117                 return "DbgKdReadControlSpaceApi";
00118         case 0x00003138:
00119                 return "DbgKdWriteControlSpaceApi";
00120         case 0x00003139:
00121                 return "DbgKdReadIoSpaceApi";
00122         case 0x0000313A:
00123                 return "DbgKdWriteIoSpaceApi";
00124         case 0x0000313B:
00125                 return "DbgKdRebootApi";
00126         case 0x0000313C:
00127                 return "DbgKdContinueApi2";
00128         case 0x0000313D:
00129                 return "DbgKdReadPhysicalMemoryApi";
00130         case 0x0000313E:
00131                 return "DbgKdWritePhysicalMemoryApi";
00132         case 0x0000313F:
00133                 return "DbgKdQuerySpecialCallsApi";
00134         case 0x00003140:
00135                 return "DbgKdSetSpecialCallApi";
00136         case 0x00003141:
00137                 return "DbgKdClearSpecialCallsApi";
00138         case 0x00003142:
00139                 return "DbgKdSetInternalBreakPointApi";
00140         case 0x00003143:
00141                 return "DbgKdGetInternalBreakPointApi";
00142         case 0x00003144:
00143                 return "DbgKdReadIoSpaceExtendedApi";
00144         case 0x00003145:
00145                 return "DbgKdWriteIoSpaceExtendedApi";
00146         case 0x00003146:
00147                 return "DbgKdGetVersionApi";
00148         case 0x00003147:
00149                 return "DbgKdWriteBreakPointExApi";
00150         case 0x00003148:
00151                 return "DbgKdRestoreBreakPointExApi";
00152         case 0x00003149:
00153                 return "DbgKdCauseBugCheckApi";
00154         case 0x00003150:
00155                 return "DbgKdSwitchProcessor";
00156         case 0x00003151:
00157                 return "DbgKdPageInApi";
00158         case 0x00003152:
00159                 return "DbgKdReadMachineSpecificRegister";
00160         case 0x00003153:
00161                 return "DbgKdWriteMachineSpecificRegister";
00162         case 0x00003154:
00163                 return "OldVlm1";
00164         case 0x00003155:
00165                 return "OldVlm2";
00166         case 0x00003156:
00167                 return "DbgKdSearchMemoryApi";
00168         case 0x00003157:
00169                 return "DbgKdGetBusDataApi";
00170         case 0x00003158:
00171                 return "DbgKdSetBusDataApi";
00172         case 0x00003159:
00173                 return "DbgKdCheckLowMemoryApi";
00174         case 0x0000315A:
00175                 return "DbgKdClearAllInternalBreakpointsApi";
00176         case 0x0000315B:
00177                 return "DbgKdFillMemoryApi";
00178         case 0x0000315C:
00179                 return "DbgKdQueryMemoryApi";
00180         case 0x0000315D:
00181                 return "DbgKdSwitchPartition";
00182         case 0x0000315E:
00183                 return "DbgKdMaximumManipulate";
00184         default:
00185                 return NULL;
00186         }
00187 }
00188 #pragma endregion
00189 
00190 static void DumpHexA(const void *pBuffer, size_t length, BazisLib::ConstManagedPointer<BazisLib::AIFile> &pFile, size_t BytesPerLine = 16, const char *pLineBreak = "<br/>\r\n")
00191 {
00192         PBYTE pBuf = (PBYTE)pBuffer;
00193         std::string strBuf;
00194         strBuf.reserve(1024);
00195 
00196         char sz[32];
00197         for (size_t i = 0; i < length;)
00198         {
00199                 size_t todo = length - i;
00200                 if (todo > BytesPerLine)
00201                         todo = BytesPerLine;
00202 
00203                 strBuf.erase();
00204                 
00205                 for (size_t j = 0; j < BytesPerLine; j++)
00206                 {
00207                         if (j < todo)
00208                                 _snprintf(sz, sizeof(sz), "%02X&nbsp;", pBuf[i + j]);
00209                         else
00210                                 strncpy(sz, "&nbsp;&nbsp;&nbsp;", sizeof(sz));
00211                         strBuf += sz;
00212                 }
00213 
00214                 strBuf += "&nbsp;&nbsp;&nbsp;&nbsp;";
00215 
00216                 sz[1] = 0;
00217                 for (size_t j = 0; j < todo; j++)
00218                 {
00219                         BYTE byte = pBuf[i + j];
00220                         if ((byte >= 0x20) && (byte <= 0x7F))
00221                                 sz[0] = byte;
00222                         else
00223                                 sz[0] = '.';
00224                         strBuf += sz;
00225                 }
00226 
00227                 i += todo;
00228                 pFile->Write(strBuf.c_str(), strBuf.length());
00229                 
00230                 if (i < length)
00231                         pFile->Write(pLineBreak, strlen(pLineBreak));
00232 
00233         }
00234 }
00235 
00236 void PacketLogger::OnSendReceivePacket( bool bLoggingEnabled, bool bSendPacket, ULONG PacketType, PKD_BUFFER FirstBuffer, PKD_BUFFER SecondBuffer, PKD_CONTEXT KdContext )
00237 {
00238         if (!bLoggingEnabled)
00239         {
00240                 if (m_pFile && m_pFile->Valid())
00241                         m_pFile->Write(szHTMLFooter, sizeof(szHTMLFooter) - 1);
00242                 if (m_pFile)
00243                         m_pFile = NULL;
00244                 return;
00245         }
00246         if (!m_pFile)
00247         {
00248                 m_pFile = new BazisLib::OSFile(m_LogFilePath, BazisLib::FastFileFlags::CreateOrTruncateRW);
00249                 if (!m_pFile || !m_pFile->Valid())
00250                         return;
00251                 m_StartTime = BazisLib::DateTime::Now();
00252                 m_RecvPacketNumber = m_SendPacketNumber = 1;
00253                 char szTmp[sizeof(szHTMLPreambleFormat) + MAX_PATH * 2];
00254                 _snprintf(szTmp, sizeof(szTmp), szHTMLPreambleFormat, m_SessionName.c_str(), m_SessionName.c_str());
00255                 m_pFile->Write(szTmp, strlen(szTmp));
00256                 m_pFile->Write(szLegend, sizeof(szLegend) - 1);
00257                 m_bTableHeaderPrinted = false;
00258         }
00259         if (!m_pFile || !m_pFile->Valid())
00260                 return;
00261 
00262         if (!m_bTableHeaderPrinted)
00263         {
00264                 m_pFile->Write(szTableHeader, sizeof(szTableHeader) - 1);
00265                 m_bTableHeaderPrinted = true;
00266         }
00267 
00268         char sz[512];
00269         ULONGLONG t = (BazisLib::DateTime::Now() - m_StartTime).GetTotalMilliseconds();
00270 
00271         unsigned msec = (unsigned)(t % 1000);
00272         unsigned tsec = (unsigned)(t / 1000);
00273 
00274         unsigned sec = tsec % 60;
00275         unsigned min = tsec / 60;
00276         unsigned hr = min / 60;
00277         min %= 60;
00278 
00279         unsigned &num = bSendPacket ? m_SendPacketNumber : m_RecvPacketNumber;
00280         _snprintf(sz, sizeof(sz), "<tr class=\"%s\"><td>%d</td><td>+%d:%02d:%02d.%04d</td><td>%d%s</td><td>\r\n", bSendPacket ? "send" : "recv", num++, hr, min, sec, msec, PacketType, GetPacketTypeName(PacketType));
00281         m_pFile->Write(sz, strlen(sz));
00282 
00283         if (FirstBuffer && FirstBuffer->Length)
00284         {
00285                 _snprintf(sz, sizeof(sz), "Buf1: Size = %d (0x%X)", FirstBuffer->Length, FirstBuffer->Length);
00286                 m_pFile->Write(sz, strlen(sz));
00287 
00288                 const char *pApi = GetApiTypeName(*((unsigned *)FirstBuffer->pData));
00289                 if (pApi)
00290                         _snprintf(sz, sizeof(sz), "; Api# = %s<br/>\r\n", pApi);
00291                 else
00292                         _snprintf(sz, sizeof(sz), "<br/>\r\n");
00293                 m_pFile->Write(sz, strlen(sz));
00294 
00295                 DumpHexA(FirstBuffer->pData, FirstBuffer->Length, m_pFile);
00296         }
00297 
00298         if (SecondBuffer && SecondBuffer->Length)
00299         {
00300                 _snprintf(sz, sizeof(sz), "<br/><br/>Buf2: Size = %d (0x%X)<br/>", SecondBuffer->Length, SecondBuffer->Length);
00301                 m_pFile->Write(sz, strlen(sz));
00302 
00303                 DumpHexA(SecondBuffer->pData, SecondBuffer->Length, m_pFile);
00304         }
00305         _snprintf(sz, sizeof(sz), "</td></tr>\r\n");
00306         m_pFile->Write(sz, strlen(sz));
00307 }
00308 
00309 PacketLogger::~PacketLogger()
00310 {
00311         if (m_pFile && m_pFile->Valid())
00312                 m_pFile->Write(szHTMLFooter, sizeof(szHTMLFooter) - 1);
00313 }
00314 
00315 void PacketLogger::OnWindowsTerminationSimulated()
00316 {
00317         if (!m_pFile)
00318                 return;
00319         m_pFile->Write(szTerminationSimulationNotification, sizeof(szTerminationSimulationNotification) - 1);
00320         m_bTableHeaderPrinted = false;
00321 }
00322 
00323 void PacketLogger::OnWindowsTerminationSimDone( char *pDebugMsg )
00324 {
00325         if (!m_pFile)
00326                 return;
00327         char szMsg[1024];
00328         _snprintf(szMsg, sizeof(szMsg), szTerminationSimulationEndFmt, pDebugMsg ? pDebugMsg : "(no additional info)");
00329         m_pFile->Write(szMsg, strlen(szMsg));
00330         m_bTableHeaderPrinted = false;
00331 }