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 }