static void OnAttach(void) { gLog.SetPrintLevel(IDebugLog::kLevel_Error); gLog.SetLogLevel(IDebugLog::kLevel_DebugMessage); std::string dllSuffix; bool steamVersion; // paranoia check if(!TestChecksum("oblivion.exe", &dllSuffix, &steamVersion)) { _ERROR("checksum not found"); return; } // /extreme/ paranoia check if(!steamVersion) { _ERROR("not a steam version!?"); return; } // build full path to our dll std::string dllPath; dllPath = GetCWD() + "\\obse_" + dllSuffix + ".dll"; _MESSAGE("dll = %s", dllPath.c_str()); // load it if(!LoadLibrary(dllPath.c_str())) { _ERROR("couldn't load dll"); } }
TEST_F(AndroidWriterSHA1Test, HandlesKernelRamdisk) { static const unsigned char expected[] = { 0xed, 0xe0, 0xeb, 0x80, 0x25, 0x76, 0xb8, 0x9d, 0x2e, 0x8c, 0x1e, 0xfb, 0xec, 0x44, 0x65, 0xf9, 0xc1, 0x62, 0x11, 0xfd, }; TestChecksum(expected, MB_BI_ENTRY_KERNEL | MB_BI_ENTRY_RAMDISK); }
TEST_F(AndroidWriterSHA1Test, HandlesKernel) { static const unsigned char expected[] = { 0xb2, 0x59, 0xf5, 0xff, 0xfb, 0x93, 0x64, 0xab, 0x8c, 0x5f, 0xf7, 0x89, 0x8c, 0x5f, 0xea, 0x7f, 0x47, 0xbc, 0x68, 0x69, }; TestChecksum(expected, MB_BI_ENTRY_KERNEL); }
TEST_F(AndroidWriterSHA1Test, HandlesNothing) { static const unsigned char expected[] = { 0x2c, 0x51, 0x3f, 0x14, 0x9e, 0x73, 0x7e, 0xc4, 0x06, 0x3f, 0xc1, 0xd3, 0x7a, 0xee, 0x9b, 0xea, 0xbc, 0x4b, 0x4b, 0xbf, }; TestChecksum(expected, 0); }
TEST_F(AndroidWriterSHA1Test, HandlesKernelRamdiskSecondbootDT) { static const unsigned char expected[] = { 0xba, 0xf5, 0xf6, 0x39, 0xde, 0xb3, 0x53, 0xeb, 0x29, 0xc2, 0x09, 0x35, 0x85, 0x26, 0x06, 0x36, 0x17, 0xbb, 0x05, 0x20, }; TestChecksum(expected, MB_BI_ENTRY_KERNEL | MB_BI_ENTRY_RAMDISK | MB_BI_ENTRY_SECONDBOOT | MB_BI_ENTRY_DEVICE_TREE); }
TEST_F(AndroidWriterSHA1Test, HandlesKernelRamdiskSecondboot) { static const unsigned char expected[] = { 0xdb, 0xb8, 0x4a, 0x49, 0x68, 0xc2, 0xcb, 0xef, 0xdc, 0x7e, 0x42, 0xe1, 0xaf, 0xe5, 0x4d, 0xa7, 0xc3, 0x16, 0x8f, 0x5e, }; TestChecksum(expected, MB_BI_ENTRY_KERNEL | MB_BI_ENTRY_RAMDISK | MB_BI_ENTRY_SECONDBOOT); }
int main(int argc, char ** argv) { gLog.SetPrintLevel(IDebugLog::kLevel_Error); gLog.SetLogLevel(IDebugLog::kLevel_DebugMessage); if(!g_options.Read(argc, argv)) { PrintError("Couldn't read arguments."); g_options.PrintUsage(); return -1; } if(g_options.m_optionsOnly) { g_options.PrintUsage(); return 0; } if(g_options.m_launchCS) _MESSAGE("launching editor"); if(g_options.m_loadOldblivion) _MESSAGE("loading oldblivion"); // create the process STARTUPINFO startupInfo = { 0 }; PROCESS_INFORMATION procInfo = { 0 }; bool dllHasFullPath = false; startupInfo.cb = sizeof(startupInfo); const char * procName = g_options.m_launchCS ? "TESConstructionSet.exe" : "Oblivion.exe"; const char * baseDllName = g_options.m_launchCS ? "obse_editor" : "obse"; if(g_options.m_altEXE.size()) { procName = g_options.m_altEXE.c_str(); _MESSAGE("launching alternate exe (%s)", procName); } if(g_options.m_altDLL.size()) { baseDllName = g_options.m_altDLL.c_str(); _MESSAGE("launching alternate dll (%s)", baseDllName); dllHasFullPath = true; } std::string dllSuffix; ProcHookInfo procHookInfo; if(!TestChecksum(procName, &dllSuffix, &procHookInfo)) { _ERROR("checksum not found"); return -1; } if(procHookInfo.steamVersion) { // ### maybe check for the loader DLL and just CreateProcess("oblivion.exe") if we can? PrintError("You are trying to use a Steam version of Oblivion. Steam users should launch the game through Steam, not by running obse_loader.exe. If OBSE fails to load, go to Steam > Settings > In Game and check the box marked \"Enable Steam community in game\". Please see the instructions in obse_readme.txt for more information."); return 0; } if(g_options.m_crcOnly) return 0; // build dll path std::string dllPath; if(dllHasFullPath) { dllPath = baseDllName; } else { dllPath = GetCWD() + "\\" + baseDllName + "_" + dllSuffix + ".dll"; } _MESSAGE("dll = %s", dllPath.c_str()); // check to make sure the dll exists { IFileStream tempFile; if(!tempFile.Open(dllPath.c_str())) { PrintError("Couldn't find OBSE DLL (%s). Please make sure you have installed OBSE correctly and are running it from your Oblivion folder.", dllPath.c_str()); return -1; } } bool result = CreateProcess( procName, NULL, // no args NULL, // default process security NULL, // default thread security TRUE, // don't inherit handles CREATE_SUSPENDED, NULL, // no new environment NULL, // no new cwd &startupInfo, &procInfo) != 0; // check for Vista failing to create the process due to elevation requirements if(!result && (GetLastError() == ERROR_ELEVATION_REQUIRED)) { // in theory we could figure out how to UAC-prompt for this process and then run CreateProcess again, but I have no way to test code for that PrintError("Vista has decided that launching Oblivion requires UAC privilege elevation. There is no good reason for this to happen, but to fix it, right-click on obse_loader.exe, go to Properties, pick the Compatibility tab, then turn on \"Run this program as an administrator\"."); return -1; } ASSERT_STR_CODE(result, "Launching Oblivion failed", GetLastError()); if(g_options.m_setPriority) { if(!SetPriorityClass(procInfo.hProcess, g_options.m_priority)) _WARNING("couldn't set process priority"); } result = false; if(g_options.m_launchCS) { if(g_options.m_oldInject) { _MESSAGE("using old editor injection method"); // start the process ResumeThread(procInfo.hThread); // CS needs to run its crt0 code before the DLL is attached, this delays until the message pump is running // note that this method makes it impossible to patch the startup code // this is better than Sleep(1000) but still ugly WaitForInputIdle(procInfo.hProcess, 1000 * 10); // too late if this fails result = InjectDLL(&procInfo, dllPath.c_str(), !g_options.m_noSync); if(!result) PrintError("Couldn't inject dll."); } else { _MESSAGE("using new editor injection method"); result = DoInjectDLL_New(&procInfo, dllPath.c_str(), &procHookInfo); if(!result) PrintError("Couldn't inject dll."); // start the process either way ResumeThread(procInfo.hThread); } } else { result = InjectDLL(&procInfo, dllPath.c_str(), !g_options.m_noSync); if(result) { // try to load oldblivion if requested if(g_options.m_loadOldblivion) { result = LoadOldblivion(&procInfo); if(!result) PrintError("Couldn't load oldblivion."); } } else PrintError("Couldn't inject dll."); if(result) { _MESSAGE("launching oblivion"); // start the process ResumeThread(procInfo.hThread); } else { _ERROR("terminating oblivion process"); // kill the partially-created process TerminateProcess(procInfo.hProcess, 0); g_options.m_waitForClose = false; } } // wait for the process to close if requested if(g_options.m_waitForClose) { WaitForSingleObject(procInfo.hProcess, INFINITE); } // clean up CloseHandle(procInfo.hProcess); CloseHandle(procInfo.hThread); return 0; }