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

E:/PROJECTS/cvsed/mixed/VIRTUA~1/kdclient/tablemgr.cpp

Go to the documentation of this file.
00001 
00007 #include "stdafx.h"
00008 #include "tablemgr.h"
00009 #include <list>
00010 #include <bzscmn/bzscmn.h>
00011 #include <bzscmn/textfile.h>
00012 #include <bzscmn/textser.h>
00013 #include <bzswin/registry.h>
00014 #include "../rpcdispatch/reporter.h"
00015 
00016 using namespace BazisLib;
00017 
00018 PatchInfoDatabase::PatchInfoDatabase(const BazisLib::FilePath &directory)
00019         : m_Directory(directory)
00020 {
00021         Directory dir(m_Directory);
00022         ManagedPointer<AIDirectoryIterator> pIter = dir.FindFirstFile(_T("*.vmpatch"));
00023         while (pIter && pIter->Valid())
00024         {
00025                 PatchInfoRecord rec;
00026                 memset(&rec, 0, sizeof(rec));
00027                 ManagedPointer<TextUnicodeFileReader> pReader = new TextUnicodeFileReader(new OSFile(pIter->GetFullPath()));
00028                 TextFileDeserializer ds(pReader);
00029                 if (ds.DeserializeObject(rec))
00030                         m_Records.Add(rec);
00031                 pIter->FindNextFile();
00032         }
00033 }
00034 
00035 PatchInfoDatabase::~PatchInfoDatabase()
00036 {
00037 }
00038 
00039 bool PatchInfoDatabase::QueryLoadedImage(void *pPEHeader, PatchInfoRecord &rec)
00040 {
00041         if (!pPEHeader)
00042                 return false;
00043         PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((char *)pPEHeader + ((PIMAGE_DOS_HEADER)pPEHeader)->e_lfanew);
00044         PIMAGE_SECTION_HEADER pSections = (PIMAGE_SECTION_HEADER)&pNtHdr[1];
00045         rec.TimeStamp = pNtHdr->FileHeader.TimeDateStamp;
00046         rec.FirstSectionSize = pSections[0].Misc.VirtualSize;
00047         rec.FileSize = 0;
00048         TCHAR tsz[MAX_PATH];
00049         ULONGLONG fsize = 0;
00050         GetModuleFileName((HMODULE)pPEHeader, tsz, __countof(tsz));
00051         {
00052                 File f(tsz);
00053                 fsize = f.GetSize();
00054         }
00055         if (!fsize || (fsize == -1LL))
00056                 return false;
00057         rec.FileSize = (unsigned)fsize;
00058         return true;
00059 }
00060 
00061 bool PatchInfoDatabase::FindRecord(void *pPEHeader, PatchInfoRecord &record)
00062 {
00063         PatchInfoRecord curmod;
00064         if (!QueryLoadedImage(pPEHeader, curmod))
00065                 return false;
00066         for (size_t i = 0; i < m_Records.Count(); i++)
00067         {
00068                 if ((m_Records[i].FileSize == curmod.FileSize) &&
00069                         (m_Records[i].TimeStamp == curmod.TimeStamp) &&
00070                         (m_Records[i].FirstSectionSize == curmod.FirstSectionSize))
00071                 {
00072                         record = m_Records[i];
00073                         return true;
00074                 }
00075         }
00076         return false;
00077 }
00078 
00079 bool PatchInfoDatabase::AddRecord(void *pPEHeader, LPVOID lpDispatcherTable, unsigned EntryCount)
00080 {
00081         PatchInfoRecord rec;
00082         bool Exists = false;
00083         if (FindRecord(pPEHeader, rec))
00084                 Exists = true;
00085         QueryLoadedImage(pPEHeader, rec);
00086         rec.DispatcherTableOffset = (char *)lpDispatcherTable - (char *)pPEHeader;
00087         rec.EntryCount = EntryCount;
00088         if (Exists)
00089         {
00090                 for (size_t i = 0; i < m_Records.Count(); i++)
00091                 {
00092                         if (((m_Records[i].FileSize) == rec.FileSize) &&
00093                                 ((m_Records[i].FirstSectionSize) == rec.FirstSectionSize) &&
00094                                 ((m_Records[i].TimeStamp) == rec.TimeStamp))
00095                         {
00096                                 m_Records[i] = rec;
00097                                 break;
00098                         }
00099                 }
00100         }
00101         else
00102                 m_Records.Add(rec);
00103         TCHAR tsz[MAX_PATH];
00104         _sntprintf(tsz, __countof(tsz), _T("%08X.vmpatch"), rec.TimeStamp);
00105         FilePath fp = m_Directory + (FilePath)tsz;
00106         unsigned n = 0;
00107         while (File::Exists(fp) && !Exists)
00108         {
00109                 n++;
00110                 _sntprintf(tsz, __countof(tsz), _T("%08X (%d).vmpatch"), rec.TimeStamp, n);
00111                 fp = m_Directory + (FilePath)tsz;
00112         }
00113         ManagedPointer<AIFile> pFile = OSFile::Create(fp);
00114         pFile->Write(L"\xfeff", 2);
00115         TextFileSerializer ser(pFile);
00116         ser.SerializeObject(rec);
00117         return true;
00118 }
00119 
00120 //-----------------------------------------------------------------------------------
00121 
00122 enum
00123 {
00124         MinStringLength = 10,
00125         MaxStringLength = 100,
00126         MaxRpcHandlers = 1024,
00127 };
00128 
00129 static inline bool IsValidStringChar(unsigned char ch)
00130 {
00131         if ((ch >= 'a') && (ch <= 'z'))
00132                 return true;
00133         if ((ch >= 'A') && (ch <= 'Z'))
00134                 return true;
00135         if ((ch >= '0') && (ch <= '9'))
00136                 return true;
00137         if ((ch == '_') || (ch == '.'))
00138                 return true;
00139         return false;
00140 }
00141 
00142 void RPCTableManager::FindSections(char *lpMainExe, std::list<AddressRange> &dataRanges, std::list<AddressRange> &codeRanges)
00143 {
00144         PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(lpMainExe + ((PIMAGE_DOS_HEADER)lpMainExe)->e_lfanew);
00145         PIMAGE_SECTION_HEADER pSections = (PIMAGE_SECTION_HEADER)&pNtHdr[1];
00146 
00147         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00148                 g_pReporter->LogLineIfEnabled(_T("Building list of EXE sections... "));
00149 
00150         size_t totalSize = 0;
00151         for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++)
00152         {
00153                 if (!(pSections[i].Characteristics & IMAGE_SCN_CNT_CODE))
00154                 {
00155                         AddressRange range (lpMainExe + pSections[i].VirtualAddress, lpMainExe + pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize);
00156                         totalSize += range.GetSize();
00157                         dataRanges.push_back(range);
00158                 }
00159                 else
00160                 {
00161                         AddressRange range (lpMainExe + pSections[i].VirtualAddress, lpMainExe + pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize);
00162                         totalSize += range.GetSize();
00163                         codeRanges.push_back(range);
00164                 }
00165         }
00166 
00167         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00168         {
00169                 TCHAR tsz[512];
00170                 _sntprintf(tsz, __countof(tsz), _T("%dK of data found.\r\nScanning for RPC command name strings...\r\n"), totalSize / 1024);
00171                 g_pReporter->LogLineIfEnabled(tsz);
00172         }
00173 }
00174 
00175 void RPCTableManager::MakeListOfStrings(const std::list<AddressRange> &dataRanges, BazisLib::SingleMallocVector<StringPointer> &strings, bool FullMode)
00176 {
00177         for (std::list<AddressRange>::const_iterator it = dataRanges.begin(); it != dataRanges.end(); it++)
00178         {
00179                 const AddressRange &range = *it;
00180                 char *pPossibleStart = NULL;
00181 
00182                 for (char *p = range.lpStart; p < range.lpEnd; p++)
00183                 {
00184                         if (pPossibleStart)
00185                         {
00186                                 if (p[0])
00187                                 {
00188                                         if (!IsValidStringChar(*p))
00189                                                 pPossibleStart = NULL;
00190                                 }
00191                                 else
00192                                 {
00193                                         size_t len = p - pPossibleStart;
00194                                         if ((len >= MinStringLength) && (len <= MaxStringLength))
00195                                         {
00196                                                 if ((FullMode && strchr(pPossibleStart, '.')) || (!FullMode && (!memcmp(pPossibleStart, "tools.", 6))))
00197                                                         strings.Add(StringPointer(pPossibleStart, len));
00198                                         }
00199                                         pPossibleStart = NULL;
00200                                 }
00201                         }
00202                         else
00203                         {
00204                                 if (IsValidStringChar(*p))
00205                                         pPossibleStart = p;
00206                         }
00207                 }
00208         }
00209 
00210         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00211         {
00212                 TCHAR tsz[512];
00213                 _sntprintf(tsz, __countof(tsz), _T("Finished scanning. Found %d strings.\r\nSearching for string references...\r\n"), strings.Count());
00214                 g_pReporter->LogLineIfEnabled(tsz);
00215         }
00216 }
00217 
00218 void RPCTableManager::FindStringRefs(const std::list<AddressRange> &dataRanges,
00219                                                    const BazisLib::SingleMallocVector<StringPointer> &strings,
00220                                                    BazisLib::SingleMallocVector<StringReferenceDescriptor> &stringRefs)
00221 {
00222         char *pMinPtr = 0, *pMaxPtr = 0;
00223         for (unsigned i = 0; i < strings.Count(); i++)
00224         {
00225                 if ((strings[i].pszData < pMinPtr) || !pMinPtr)
00226                         pMinPtr = strings[i].pszData;
00227                 if ((strings[i].pszData > pMaxPtr) || !pMaxPtr)
00228                         pMaxPtr = strings[i].pszData;
00229         }
00230 
00231         for (std::list<AddressRange>::const_iterator it = dataRanges.begin(); it != dataRanges.end(); it++)
00232         {
00233                 const AddressRange &range = *it;
00234 
00235                 for (char **p = (char **)range.lpStart; p < (char **)range.lpEnd; p++)
00236                 {
00237                         if ((*p < pMinPtr) || (*p > pMaxPtr))
00238                                 continue;
00239                         for (unsigned i = 0; i < strings.Count(); i++)
00240                                 if (*p == strings[i].pszData)
00241                                 {
00242                                         stringRefs.Add(StringReferenceDescriptor(p));
00243                                         break;
00244                                 }
00245                 }
00246         }
00247         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00248         {
00249                 TCHAR tsz[512];
00250                 _sntprintf(tsz, __countof(tsz), _T("Found %d string references.\r\n"), stringRefs.Count());
00251                 g_pReporter->LogLineIfEnabled(tsz);
00252         }
00253 }
00254 
00255 void RPCTableManager::GroupStringRefs(BazisLib::SingleMallocVector<StringReferenceDescriptor> &stringRefs,
00256                                                         BazisLib::SingleMallocVector<RefGroupDescriptor> &groups)
00257 {
00258         unsigned GroupCount = 0;
00259 
00260         for (unsigned i = 0; i < stringRefs.Count(); i++)
00261         {
00262                 if (!stringRefs[i].GroupID)
00263                         stringRefs[i].GroupID = ++GroupCount;
00264                 for (unsigned j = i + 1; j < stringRefs.Count(); j++)
00265                 {
00266                         size_t dist = 0;
00267                         if (stringRefs[i].pAddress > stringRefs[j].pAddress)
00268                                 dist = (size_t)stringRefs[i].pAddress - (size_t)stringRefs[j].pAddress;
00269                         else
00270                                 dist = (size_t)stringRefs[j].pAddress - (size_t)stringRefs[i].pAddress;
00271                         if ((dist < (sizeof(RPCHandlerRecord) * MaxRpcHandlers)) && !(dist % sizeof(RPCHandlerRecord)))
00272                         {
00273                                 stringRefs[j].GroupID = stringRefs[i].GroupID;
00274                         }
00275                 }
00276         }
00277 
00278         groups.EnsureCapacity(GroupCount);
00279         groups.SetElementCount(GroupCount);
00280         memset(groups.GetRawPointer(), 0, sizeof(RefGroupDescriptor) * GroupCount);
00281 
00282         for (unsigned j = 0; j < stringRefs.Count(); j++)
00283         {
00284                 if (stringRefs[j].GroupID)
00285                 {
00286                         groups[stringRefs[j].GroupID - 1].pAddr = stringRefs[j].pAddress;
00287                         groups[stringRefs[j].GroupID - 1].RefCount++;
00288                 }
00289         }
00290 
00291         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00292         {
00293                 TCHAR tsz[512];
00294                 _sntprintf(tsz, __countof(tsz), _T("Found %d structures resemblant to RPC dispatcher table.\r\n"), GroupCount);
00295                 g_pReporter->LogLineIfEnabled(tsz);
00296                 if (GroupCount < 30)
00297                 {
00298                         for (unsigned i = 0; i < GroupCount; i++)
00299                         {
00300                                 _sntprintf(tsz, __countof(tsz), _T("(address %08X, matched pointers: %d)\r\n"), groups[i].pAddr, groups[i].RefCount);
00301                                 g_pReporter->LogLineIfEnabled(tsz);
00302                         }
00303                 }
00304                 g_pReporter->LogLineIfEnabled(_T("Analyzing potential RPC dispatcher tables...\r\n"));
00305         }
00306 }
00307 
00308 bool RPCTableManager::ScanPotentialRPCTable(void *pAddr,
00309                                                                   std::list<AddressRange> &dataRanges,
00310                                                                   std::list<AddressRange> &codeRanges,
00311                                                                   RPCTableInfo &info)
00312 {
00313         RPCHandlerRecord *pRec = (RPCHandlerRecord *)pAddr;
00314         RPCHandlerRecord *pFirst = pRec, *pLast = pRec;
00315         for (unsigned i = 0; i < MaxRpcHandlers; i++)
00316         {
00317                 if (!VerifyEntry(pFirst, dataRanges, codeRanges))
00318                         break;
00319                 pFirst--;
00320         }
00321         do {pFirst++;}
00322                 while (!pFirst->Enabled && (pFirst < pRec));
00323         for (unsigned i = 0; i < MaxRpcHandlers; i++)
00324         {
00325                 if (!VerifyEntry(pLast, dataRanges, codeRanges))
00326                         break;
00327                 pLast++;
00328         }
00329         do {pLast--;}
00330                 while (!pLast->Enabled && (pLast > pRec));
00331         if (pFirst >= pLast)
00332                 return false;
00333         info.pAddr = pFirst;
00334         info.EntryCount = (unsigned)(pLast - pFirst);
00335         info.UsedEntries = info.FreeEntries = 0;
00336         for (pRec = pFirst; pRec <= pLast; pRec++)
00337         {
00338                 if (pRec->Enabled)
00339                         info.UsedEntries++;
00340                 else
00341                         info.FreeEntries++;
00342         }
00343         return true;
00344 }
00345 
00346 
00347 bool RPCTableManager::FindHandlerTable(bool FullMode)
00348 {
00349         char *lpMainExe = (char *)GetModuleHandle(NULL);
00350         if (!lpMainExe)
00351                 return false;
00352 
00353         std::list<AddressRange> dataRanges, codeRanges;
00354         BazisLib::SingleMallocVector<StringPointer> strings;
00355         BazisLib::SingleMallocVector<StringReferenceDescriptor> stringRefs;
00356         BazisLib::SingleMallocVector<RefGroupDescriptor> groups;
00357 
00358         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00359                 g_pReporter->LogLineIfEnabled(_T("Analyzing VMWARE-VMX executable...\r\n"));
00360 
00361         FindSections(lpMainExe, dataRanges, codeRanges);
00362         MakeListOfStrings(dataRanges, strings, FullMode);
00363         FindStringRefs(dataRanges, strings, stringRefs);
00364         GroupStringRefs(stringRefs, groups);
00365 
00366         unsigned matchCount = 0;
00367         for (unsigned i = 0; i < groups.Count(); i++)
00368         {
00369                 if (!ScanPotentialRPCTable(groups[i].pAddr, dataRanges, codeRanges, groups[i].info))
00370                         groups[i].info.pAddr = NULL;
00371                 else
00372                         matchCount++;
00373         }
00374 
00375         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00376         {
00377                 TCHAR tsz[512];
00378                 _sntprintf(tsz, __countof(tsz), _T("Potential RPC table analyzis complete. Found %d candidates.\r\n"), matchCount);
00379                 g_pReporter->LogLineIfEnabled(tsz);
00380                 if (matchCount < 30)
00381                 {
00382                         for (unsigned i = 0; i < groups.Count(); i++)
00383                         {
00384                                 if (!groups[i].info.pAddr)
00385                                         continue;
00386                                 _sntprintf(tsz, __countof(tsz), _T("(address %08X, entries: %d, free entries: %d)\r\n"), groups[i].info.pAddr, groups[i].info.EntryCount, groups[i].info.FreeEntries);
00387                                 g_pReporter->LogLineIfEnabled(tsz);
00388                         }
00389                 }
00390         }
00391 
00392         unsigned maxMatchID = -1;
00393         for (unsigned i = 0; i < groups.Count(); i++)
00394         {
00395                 if (!groups[i].info.pAddr)
00396                         continue;
00397                 if ((maxMatchID == -1) || (groups[i].info.EntryCount > groups[maxMatchID].info.EntryCount))
00398                         maxMatchID = i;
00399         }
00400 
00401         if (maxMatchID == -1)
00402                 return false;
00403 
00404         m_Database.AddRecord(lpMainExe, groups[maxMatchID].info.pAddr, groups[maxMatchID].info.EntryCount);
00405         return true;
00406 }
00407 
00408 static inline FilePath GetDLLDirectory(HINSTANCE hDLL)
00409 {
00410         TCHAR tsz[MAX_PATH];
00411         GetModuleFileName(hDLL, tsz, __countof(tsz));
00412         FilePath fp(tsz);
00413         return fp.GetParentPath();
00414 }
00415 
00416 RPCTableManager::RPCTableManager(HINSTANCE hThisDLL)
00417         : m_Database(GetDLLDirectory(hThisDLL))
00418         , m_pPatchedEntry(NULL)
00419 {
00420         const TCHAR tszRegistryPath[] = _T("SOFTWARE\\BazisSoft\\KDVMWare\\Patcher");
00421         RegistryKey key(HKEY_LOCAL_MACHINE, tszRegistryPath);
00422         key.DeserializeObject(m_Params);
00423         key.SerializeObject(m_Params);
00424 }
00425 
00426 bool RPCTableManager::InstallHandler(const char *pszPrefix, size_t prefixLen, RPCTableManager::GRPCHANDLER pHandler, void *pContext, bool ForceReinstall)
00427 {
00428         if (m_pPatchedEntry && !ForceReinstall)
00429                 return false;
00430         PatchInfoRecord rec;
00431 
00432         char *lpMainExe = (char *)GetModuleHandle(NULL);
00433         if (!lpMainExe)
00434                 return false;
00435 
00436         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00437         {
00438                 g_pReporter->LogLineIfEnabled(_T("*******************************************************************************\r\n"));
00439                 g_pReporter->LogLineIfEnabled(_T("*VirtualKD patcher DLL successfully loaded. Patching the GuestRPC mechanism...*\r\n"));
00440                 g_pReporter->LogLineIfEnabled(_T("*******************************************************************************\r\n"));
00441                 g_pReporter->LogLineIfEnabled(_T("Searching patch database for information about current executable...\r\n"));
00442         }
00443         if (!m_Database.FindRecord(lpMainExe, rec) || !rec.DispatcherTableOffset)
00444         {
00445                 if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00446                         g_pReporter->LogLineIfEnabled(_T("No information found.\r\n"));
00447                 FILETIME ftStart, ftUnused;
00448                 if (GetProcessTimes(GetCurrentProcess(), &ftStart, &ftUnused, &ftUnused, &ftUnused))
00449                 {
00450                         TimeSpan elapsed = DateTime::Now() - ftStart;
00451                         unsigned msPassed = (unsigned)elapsed.GetTotalMilliseconds();
00452                         if (msPassed < m_Params.MinRunTimeBeforePatch)
00453                         {
00454                                 int toWait = m_Params.MinRunTimeBeforePatch - msPassed;
00455                                 if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00456                                 {
00457                                         TCHAR tsz[512];
00458                                         _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("Waiting for VMWare to initialize (%d ms more to wait)\r\n"), toWait);
00459                                         g_pReporter->LogLineIfEnabled(tsz);
00460                                 }
00461                                 if (toWait > 0)
00462                                         Sleep(toWait);
00463                         }
00464                 }
00465                 if (!FindHandlerTable(false))
00466                 {
00467                         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00468                                 g_pReporter->LogLineIfEnabled(_T("Cannot determine RPC dispatcher table location.\r\nPerforming additional analyzis.\r\n"));
00469                         if (!FindHandlerTable(true))
00470                         {
00471                                 if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00472                                         g_pReporter->LogLineIfEnabled(_T("Still cannot find RPC dispatcher table. Try another VMWare version :-(\r\n"));
00473                                 return false;
00474                         }
00475                 }
00476         }
00477 
00478         if (!m_Database.FindRecord(lpMainExe, rec) || !rec.DispatcherTableOffset)
00479                 return false;
00480 
00481         PVOID pDispatcherTable = (char *)lpMainExe + rec.DispatcherTableOffset;
00482 
00483         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00484         {
00485                 TCHAR tsz[512];
00486                 _sntprintf(tsz, __countof(tsz), _T("Using RPC dispatcher table at 0x%08I64X (%d entries)\r\n"), (ULONGLONG)pDispatcherTable, rec.EntryCount);
00487                 g_pReporter->LogLineIfEnabled(tsz);
00488         }
00489 
00490         RPCHandlerRecord *pFirst = (RPCHandlerRecord *)pDispatcherTable;
00491         RPCHandlerRecord *pLast = pFirst + rec.EntryCount;
00492 
00493         if (m_Params.WaitForNonZeroFirstCommand)
00494         {
00495                 if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00496                 {
00497                         TCHAR tsz[512];
00498                         _sntprintf(tsz, __countof(tsz), _T("Waiting for RPC table to be initialized by VMWare..."));
00499                         g_pReporter->LogLineIfEnabled(tsz);
00500                 }
00501                 while (!pFirst->Enabled || !pFirst->CommandPrefixLength || !pFirst->pCommandPrefix || !pFirst->pHandler)
00502                 {
00503                         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00504                                 g_pReporter->LogLineIfEnabled(_T("."));
00505                         Sleep(200);
00506                 }
00507                 Sleep(200);
00508                 if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00509                         g_pReporter->LogLineIfEnabled(_T("\r\nRPC table initialized. Patching it...\r\n"));
00510         }
00511 
00512         memset(&m_OriginalHandler, 0, sizeof(RPCHandlerRecord));
00513 
00514         if (!m_Params.DefaultPatchingAtTableStart)
00515         {
00516                 for (RPCHandlerRecord *pRec = pFirst; pRec < pLast; pRec++)
00517                 {
00518                         if (!pRec->Enabled)
00519                         {
00520                                 DoPatch(pRec, pszPrefix, prefixLen, pHandler, pContext);
00521                                 if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00522                                 {
00523                                         TCHAR tsz[512];
00524                                         _sntprintf(tsz, __countof(tsz), _T("Successfully patched entry #%d\r\n"), pRec - pFirst);
00525                                         g_pReporter->LogLineIfEnabled(tsz);
00526                                 }
00527                                 return true;
00528                         }
00529                 }
00530         }
00531 
00532         if (m_Params.DefaultPatchingAtTableStart || m_Params.AllowPatchingAtTableStart) 
00533         {
00534                 if (!memcmp(&m_OriginalHandler, &pFirst[-1], sizeof(RPCHandlerRecord)))
00535                 {
00536                         DoPatch(--pFirst, pszPrefix, prefixLen, pHandler, pContext);
00537                         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00538                         {
00539                                 TCHAR tsz[512];
00540                                 _sntprintf(tsz, __countof(tsz), _T("Successfully patched entry before the first used one (0x%08X)\r\n"), &pFirst[-1]);
00541                                 g_pReporter->LogLineIfEnabled(tsz);
00542                         }
00543                         return true;
00544                 }
00545         }
00546 
00547         if (m_Params.AllowReplacingFirstCommand)
00548         {
00549                 if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00550                 {
00551                         TCHAR tsz[512];
00552                         _sntprintf(tsz, __countof(tsz), _T("No suitable free entries found. Replaced handler for %s\r\n"), ANSIStringToString(std::string(pFirst->CommandPrefixLength, pFirst->CommandPrefixLength)).c_str());
00553                         g_pReporter->LogLineIfEnabled(tsz);
00554                 }
00555                 DoPatch(pFirst, pszPrefix, prefixLen, pHandler, pContext);
00556                 return true;
00557         }
00558         if (s_EnableLogging && (g_pReporter->GetStatusPointer()->DebugLevel >= DebugLevelTracePatching))
00559                 g_pReporter->LogLineIfEnabled(_T("Cannot found a usable entry to patch! Exitting.\r\n"));
00560         return false;
00561 }
00562 
00563 void RPCTableManager::RestoreOriginalHandler()
00564 {
00565         if (m_pPatchedEntry)
00566         {
00567                 *m_pPatchedEntry = m_OriginalHandler;
00568                 m_pPatchedEntry = NULL;
00569         }
00570 }