예제 #1
0
void PlayerSlots::Unpatch()
{
    L4D_DEBUG_LOG("PlayersSlots - Unpatching ...");

    //jl around the string "Human player limit reached (%d/%d)"
    // Windows only

#if defined PLATFORM_WINDOWS
    if(humanLimitSig)
    {
        ApplyPatch(humanLimitSig, /*offset*/0, &humanLimitRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("PlayerSlots -- 'HumanPlayerLimitReached' jl(e) restored");
    }
#endif

    //jz around the string "#Valve_Reject_Server_Full"

    if(lobbyConnectSig)
    {
        ApplyPatch(lobbyConnectSig, /*offset*/0, &lobbyConnectRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("PlayerSlots -- 'ConnectClientLobbyCheck' restored");
    }

    PlayerSlots::UnpatchSlotCheckOnly();
    PlayerSlots::UnpatchGetMaxHumanPlayers();
    //PlayerSlots::UnpatchGetTotalNumPlayersSupported();
}
예제 #2
0
void CommandTable::Init(void)
{
	// read in the console commands
	g_consoleCommands.SetBaseID(0x0100);
	g_consoleCommands.Read((CommandInfo *)g_offsetConsoleCommandsStart, (CommandInfo *)g_offsetConsoleCommandsLast);

	// read in the script commands
	g_scriptCommands.SetBaseID(0x1000);
	g_scriptCommands.Read((CommandInfo *)g_offsetScriptCommandsStart, (CommandInfo *)g_offsetScriptCommandsLast);

	// pad to opcode 0x1400 to give Bethesda lots of room
	g_scriptCommands.PadTo(kNVSEOpcodeStart);

	// Add NVSE Commands
	g_scriptCommands.AddCommandsV1();

#if _DEBUG
	g_scriptCommands.AddDebugCommands();
#endif

	// register plugins
	g_pluginManager.Init();

	ApplyPatch(kPatch_ScriptCommands_Start, (UInt32)g_scriptCommands.GetStart());
	ApplyPatch(kPatch_ScriptCommands_End, (UInt32)g_scriptCommands.GetEnd());
	ApplyPatch(kPatch_ScriptCommands_MaxIdx, g_scriptCommands.GetMaxID());

	_MESSAGE("max id = %08X", g_scriptCommands.GetMaxID());

	g_scriptCommands.Dump();

	_MESSAGE("patched");
}
예제 #3
0
void CommandTable::Init(void)
{
	static CommandInfo* kCmdInfo_Unused_1;
#if RUNTIME
#if RUNTIME_VERSION == RUNTIME_VERSION_1_4_0_525
	kCmdInfo_Unused_1 = (CommandInfo*)0x0118E4F8;
#elif RUNTIME_VERSION == RUNTIME_VERSION_1_4_0_525ng
	kCmdInfo_Unused_1 = (CommandInfo*)0x0118E4F8;
#else
#error
#endif
#else
	kCmdInfo_Unused_1 = (CommandInfo*)0x00E9D7A0;
#endif

	// read in the console commands
	g_consoleCommands.SetBaseID(0x0100);
	g_consoleCommands.Read((CommandInfo *)g_offsetConsoleCommandsStart, (CommandInfo *)g_offsetConsoleCommandsLast);

	// read in the script commands
	g_scriptCommands.SetBaseID(0x1000);
	g_scriptCommands.Read((CommandInfo *)g_offsetScriptCommandsStart, (CommandInfo *)g_offsetScriptCommandsLast);

	// blocktype "Unused_1" becomes "Function"
	UInt16 onUnused_1Opcode = kCmdInfo_Unused_1->opcode;
	*kCmdInfo_Unused_1 = kCommandInfo_Function;
	kCmdInfo_Unused_1->opcode = onUnused_1Opcode;

	// pad to opcode 0x1400 to give Bethesda lots of room
	g_scriptCommands.PadTo(kNVSEOpcodeStart);

	// Add NVSE Commands
	g_scriptCommands.AddCommandsV1();
	g_scriptCommands.AddCommandsV3s();
	g_scriptCommands.AddCommandsV4();

#if _DEBUG
	g_scriptCommands.AddDebugCommands();
#endif

	// register plugins
	g_pluginManager.Init();

	// patch the code
	ApplyPatch(kPatch_ScriptCommands_Start, (UInt32)g_scriptCommands.GetStart());
	ApplyPatch(kPatch_ScriptCommands_End, (UInt32)g_scriptCommands.GetEnd());
	ApplyPatch(kPatch_ScriptCommands_MaxIdx, g_scriptCommands.GetMaxID());

	ApplyPatchEditorOpCodeDataList();

	_MESSAGE("max id = %08X", g_scriptCommands.GetMaxID());

	_MESSAGE("console commands");
	g_consoleCommands.Dump();
	_MESSAGE("script commands");
	g_scriptCommands.Dump();

	_MESSAGE("patched");
}
예제 #4
0
/*
	Patch CTerrorGameRules::GetMaxHumanPlayers(void) to always return our own value

	This will cause server browsers to display our own 'max players' value (Linux only)

	On Windows overriding it does nothing at first..
	  but actually it breaks scavenge mode which is stuck in a 'scavenge versus' type mode
	  so it should NEVER BE PATCHED FOR WINDOWS EVER

	On Linux just overriding ServerPlayerCounts isn't enough (it only fixes 'status' command)
	  but overwriting GetMaxHumanPlayers works great
*/
void PlayerSlots::PatchGetMaxHumanPlayers()
{
#if !defined PLATFORM_WINDOWS

    bool firstTime = (getMaxHumanPlayersSig == NULL);

    if(firstTime)
    {
        if (!g_pGameConf->GetMemSig("GetMaxHumanPlayers", &getMaxHumanPlayersSig) || !getMaxHumanPlayersSig)
        {
            g_pSM->LogError(myself, "PlayerSlots -- Could not find 'GetMaxHumanPlayers' signature");
            return;
        }
    }

    /*
    Normally CTerrorGameRules::GetMaxHumanRules(void)
    	returns CTerrorGameRules::IsVersusMode() ? 8 : 4
    we just want it to return our own PLAYER_SLOTS_MAX always though
    */

    /*
    The trick here is just to patch the function to:

    	mov eax, PLAYER_SLOTS_MAX
    	retn

    Now it will always return our value instead of 4 or 8
    */

    patch_t getMaxHumanPlayersPatch;
    getMaxHumanPlayersPatch.bytes = OP_MOV_EAX_IMM32_SIZE + OP_RETN_SIZE;

    // mov eax, PLAYER_SLOTS_MAX
    getMaxHumanPlayersPatch.patch[0] = OP_MOV_EAX_IMM32;
    *(uint32_t*)(getMaxHumanPlayersPatch.patch+sizeof(uint8_t)) = (uint32_t)PLAYER_SLOTS_MAX;

    // retn
    getMaxHumanPlayersPatch.patch[OP_MOV_EAX_IMM32_SIZE] = OP_RETN;

    if(firstTime)
    {
        ApplyPatch(getMaxHumanPlayersSig, /*offset*/0, &getMaxHumanPlayersPatch, &getMaxHumanPlayersRestore);
    }
    else
    {
        ApplyPatch(getMaxHumanPlayersSig, /*offset*/0, &getMaxHumanPlayersPatch, /*restore*/NULL);
    }

    L4D_DEBUG_LOG("PlayerSlots -- 'GetMaxHumanPlayers' patched to MOV eax, %d; retn", PLAYER_SLOTS_MAX);

#endif
}
예제 #5
0
//=--------------------------------------------------------------------------=
// CPatchDialog::PatchUpdateThreadProc
//=--------------------------------------------------------------------------=
// Thread procedure for applying the patch
//
// Parameters:
//	lpParameter  Thread parameter
//
// Output:
//	DWORD	    
//
// Notes:
//
DWORD WINAPI CPatchDialog::PatchUpdateThreadProc(LPVOID lpParameter)
{
    CPatchDialog* pDlg = (CPatchDialog *) lpParameter;
    
    g_pDlg = pDlg;

    BOOL bSuccess = FALSE;

    do
    {
	// Check if download has been cancelled
	if (WAIT_OBJECT_0 == WaitForSingleObject(pDlg->m_hCancelEvent, 0))
	    break;

	bSuccess = ApplyPatch(m_szDirectory, m_szOptions, PatchUpdateCallBack);
    }
    while (0);


    // Post message to main thread to dis-miss dialog if users haven't hit cancel
    //
    if (WAIT_OBJECT_0 != WaitForSingleObject(pDlg->m_hCancelEvent, 0))
    {
	if (bSuccess)
	    ::PostMessage(pDlg->m_hWnd, WM_COMMAND, IDOK, NULL);
	else
	    ::PostMessage(pDlg->m_hWnd, WM_COMMAND, IDCANCEL, NULL);
    }


    // Signal main thread
    ::SetEvent(pDlg->m_hPatchUpdateThreadExitEvent);   

    return 0;
}
예제 #6
0
void SysCoreThread::GameStartingInThread()
{
	GetMTGS().SendGameCRC(ElfCRC);

	if (EmuConfig.EnablePatches) ApplyPatch(0);
	if (EmuConfig.EnableCheats)  ApplyCheat(0);
}
예제 #7
0
bool ApplyPatch(PatchTree *child, bool success, Sequence *branchTree, DWORD dwVersionLS, bool isMorrowind, int hInstanceOffset) {
	PatchTree *patch = child;
	if(!patch) return success;
	do {
		if( !( (patch->FileVersion?(*patch->FileVersion)!=dwVersionLS:DEFAULTFILEVER!=dwVersionLS) ||
			(patch->Removed?(*patch->Removed):false) || (patch->Checked?!(*patch->Checked):false) ) ) {
			char *message = NULL;
			Sequence **branch = NULL;
			if(patch->Original ? !MachineCode::CompareOriginal(patch->Original, hInstanceOffset) : false) {
				message = strcat(strcat(strcpy(new char[MAX_PATH], "Patch: Original code is different for section \""), patch->Section), "\"");
			}else if(patch->Attach ? !(branch = MachineCode::SetAttach(patch->Attach, &branchTree, hInstanceOffset)) : false) {
				message = strcat(strcat(strcpy(new char[MAX_PATH], "Patch: Problems in section \""), patch->Attach->String), "\"");
			}else if(patch->Patch ? !MachineCode::SetPatch(patch->Patch, branchTree, hInstanceOffset) : false) {
				message = strcat(strcat(strcpy(new char[MAX_PATH], "Patch: Problems with patch applying in section \""), patch->Section), "\"");
			}else success = ApplyPatch(patch->Child, success, branchTree, dwVersionLS, isMorrowind, hInstanceOffset) ? success : false;
			if(message) {
				if(success && !isMorrowind) Logger::CreateLogFile(PATCH_LOG_NAME);
				_LogLine(message);
				success = false;
				delete[] message;
			}
			if(branch) {
				delete (*branch);
				(*branch) = NULL;
			}
		}
	}while(patch = patch->Next);
	return success;
}
예제 #8
0
int TestPatchInMemory(int argc,char *argv[])
{
	FILE *patchFile, *newFile, *oldFile;
	char *patch,*_new,*old;
	unsigned patchSize, oldSize;
	unsigned int newSize;
	int res;
	if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);

	patchFile=fopen(argv[3], "rb");
	newFile=fopen(argv[2], "wb");
	oldFile=fopen(argv[1], "rb");
	fseeko(patchFile, 0, SEEK_END);
	fseeko(oldFile, 0, SEEK_END);
	patchSize=ftell(patchFile);
	oldSize=ftell(oldFile);
	fseeko(patchFile, 0, SEEK_SET);
	fseeko(oldFile, 0, SEEK_SET);
	patch = new char [patchSize];
	old = new char [oldSize];
	fread(patch, patchSize, 1, patchFile);
	fread(old, oldSize, 1, oldFile);

	res = ApplyPatch( old, oldSize, &_new, &newSize,patch, patchSize);
	fwrite(_new, newSize, 1, newFile);

	fclose(patchFile);
	fclose(newFile);
	fclose(oldFile);

	return res;
}
예제 #9
0
void PlayerSlots::UnpatchGetMaxHumanPlayers()
{
    if(getMaxHumanPlayersSig)
    {
        ApplyPatch(getMaxHumanPlayersSig, /*offset*/0, &getMaxHumanPlayersRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("PlayerSlots -- 'GetMaxHumanPlayers' restored");
    }
}
예제 #10
0
void CDetour::DisableDetour()
{
	if (detoured)
	{
		/* Remove the patch */
		ApplyPatch(detour_address, 0, &detour_restore, NULL);
		detoured = false;
	}
}
예제 #11
0
void AddonsDisabler::Unpatch()
{
    L4D_DEBUG_LOG("AddonsDisabler - Unpatching ...");

    if (vanillaModeSig)
    {
        ApplyPatch(vanillaModeSig, /*offset*/4, &vanillaModeSigRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("AddonsDisabler -- 'VanillaModeOffset' restored");
    }
}
예제 #12
0
void PlayerSlots::UnpatchSlotCheckOnly()
{
    //cmp around the string "#Valve_Reject_Server_Full"

    if(lobbyConnectSig && serverFullOffset != -1)
    {
        ApplyPatch(lobbyConnectSig, serverFullOffset, &serverFullRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("PlayerSlots -- 'ValveRejectServerFullFirst' restored");
    }
}
예제 #13
0
파일: main.cpp 프로젝트: NightQuest/SKSE
void GameplayPatches(void)
{
	// originally supposed to be 100 /decimal/ but oops
	UInt8	kPickpocketChance[] =
	{
		0xB8, 0x00, 0x01, 0x00, 0x00,	// mov eax, 0x0100
		0xC3							// retn
	};

	ApplyPatch(0x00598DB0, kPickpocketChance, sizeof(kPickpocketChance));

	SafeWrite8(0x008F0850, 0xC3);	// disable achievements
}
예제 #14
0
void PatchModuleMemory(HINSTANCE hModule, LPSTR lpFilename, bool isMorrowind) {
	if(!lpPatchTree || !hModule || !lpFilename) return;
	PatchTree *file = lpPatchTree;
	do {
		if((_stricmp(lpFilename, file->Section)==0)&&(file->Removed?!(*file->Removed):true)&&(file->Checked?(*file->Checked):true)&&file->Child) {
			if(ApplyPatch(file->Child, true, NULL, GetModuleNameAndVersion(hModule,NULL,NULL), isMorrowind, DWORD(hModule)-DEFAULT_INSTANCE_DLL)) {
				if(isMorrowind) _LogLine("Patch has been applied to %s successfully", file->Section);
			}
			break;
		}
	}while(file = file->Next);
	return;
}
예제 #15
0
void CriticalHitManager::DisableCriticalDetour()
{
	if (critical_callback)
	{
		/* Remove the patch */
		ApplyPatch(critical_address, 0, &critical_restore, NULL);
		detoured = false;
	}

	if (melee_callback)
	{
		/* Remove the patch */
		ApplyPatch(melee_address, 0, &melee_restore, NULL);
		detoured = false;
	}

	if (knife_callback)
	{
		/* Remove the patch */
		ApplyPatch(knife_address, 0, &knife_restore, NULL);
		detoured = false;
	}
}
예제 #16
0
void PatchProcessMemory(HINSTANCE hModule, LPSTR origFilename, DWORD dwVersionLS, bool isMorrowind) {
	HINSTANCE hInstance = hModule;//GetModuleHandleA(NULL);
	if(lpPatchTree && hInstance && hModule && origFilename) {} else return;
	PatchTree *file = lpPatchTree;
	do {
		HINSTANCE hModuleInstance = _stricmp(origFilename, file->Section)==0 ? hModule : GetModuleHandleA(file->Section);
		if(hModule == hInstance && (_stricmp(TEXT_DLL_NAME, file->Section)==0 || _stricmp(MWE_DLL_NAME, file->Section)==0)) continue;
		if(hModuleInstance && (file->Removed?!(*file->Removed):true) && (file->Checked?(*file->Checked):true) && file->Child) {
			if(ApplyPatch(file->Child, true, NULL, 
				hModuleInstance == hInstance ? dwVersionLS : GetModuleNameAndVersion(hModuleInstance, NULL, NULL), isMorrowind,
				DWORD(hModuleInstance) - (hModuleInstance == hInstance ? DEFAULT_INSTANCE_EXE : DEFAULT_INSTANCE_DLL ))) {
				if(isMorrowind) _LogLine("Patch has been applied to %s successfully", file->Section);
			}
		}
	}while(file = file->Next);
	return;
}
예제 #17
0
int __cdecl EnableucrtFreadWorkaround()
{
	// This patches ucrtbase such that fseek will always
	// synchronize the file object's internal buffer.

	bool applied_at_least_one = false;
	for (const auto &patch : s_patches) {
		if (ApplyPatch(patch)) {
			applied_at_least_one = true;
		}
	}

	/* For forward compat, do not fail if patches don't apply (e.g. version mismatch)
	if (!applied_at_least_one) {
		std::abort();
	}
	//*/

	return 0;
}
예제 #18
0
void AddonsDisabler::Patch()
{
    L4D_DEBUG_LOG("AddonsDisabler - Patching ...");
    
    bool firstTime = (vanillaModeSig == NULL);
    if (firstTime)
    {
        if (!g_pGameConf->GetMemSig("VanillaModeOffset", &vanillaModeSig) || !vanillaModeSig) 
        { 
            g_pSM->LogError(myself, "AddonsDisabler -- Could not find 'VanillaModeOffset' signature");
            return;
        } 
    }
    patch_t vanillaModePatch;
    vanillaModePatch.bytes = 3;

    // mov esi+19h -> NOP
    vanillaModePatch.patch[0] = 0x0f;
    vanillaModePatch.patch[1] = 0x1f;
    vanillaModePatch.patch[2] = 0x00;

    ApplyPatch(vanillaModeSig, /*offset*/4, &vanillaModePatch, /*restore*/firstTime ? &vanillaModeSigRestore : NULL);
    L4D_DEBUG_LOG("AddonsDisabler -- 'VanillaModeOffset' patched to NOP");
}
예제 #19
0
void PlayerSlots::Patch()
{
#if defined PLATFORM_WINDOWS
    bool firstTime = !(humanLimitSig && lobbyConnectSig);
#else
    bool firstTime = !(lobbyConnectSig);
#endif
    L4D_DEBUG_LOG("PlayerSlots - Patching ...");

    /*
    Server patch
    ** Needed on windows only. On Linux, this called GetMaxHumanPlayers
    L4DToolZ doesn't patch this anymore?
    */

#if defined PLATFORM_WINDOWS
    if(firstTime)
    {
        if (!g_pGameConf->GetMemSig("HumanPlayerLimitReached", &humanLimitSig) || !humanLimitSig)
        {
            g_pSM->LogError(myself, "PlayerSlots -- Could not find 'HumanPlayerLimitReached' signature");
            return;
        }
    }
    //code pages can't be written to by default, so ApplyPatch changes that ;)

    /*
    jl around the string "Human player limit reached (%d/%d)"

    	jl -> jmp (Windows)
    	jle -> nop (Linux)

    we never check if the human player limit has been reached
    */
    patch_t humanLimitPatch;

//#if defined PLATFORM_WINDOWS
    humanLimitPatch.bytes = 1;
    humanLimitPatch.patch[0] = OP_JMP_REL8;
//#else //PLATFORM_LINUX
//	humanLimitPatch.bytes = OP_JLE_REL8_SIZE;
//	fill_nop(humanLimitPatch.patch, humanLimitPatch.bytes);
//#endif


    ApplyPatch(humanLimitSig, /*offset*/0, &humanLimitPatch, firstTime ? &humanLimitRestore : NULL);

    L4D_DEBUG_LOG("PlayerSlots -- 'HumanPlayerLimitReached' jl(e) patched to jmp");
#endif

    /*
    Engine patch
    */
    if (!g_pGameConf->GetMemSig("ConnectClientLobbyCheck", &lobbyConnectSig) || !lobbyConnectSig)
    {
        g_pSM->LogError(myself, "PlayerSlots -- Could not find 'ConnectClientLobbyCheck' signature");
        return;
    }
#if defined PLATFORM_WINDOWS

    /*
    jz around the string "#Valve_Reject_Server_Full"

    	jz -> nop (linux or windows)

     do not skip to the server is full code when sv_allow_lobby_connect is 0
    */
    patch_t lobbyConnectPatch;
    lobbyConnectPatch.bytes = OP_JZ_REL8_SIZE;
    fill_nop(lobbyConnectPatch.patch, OP_JZ_REL8_SIZE);
    ApplyPatch(lobbyConnectSig, /*offset*/0, &lobbyConnectPatch, firstTime ? &lobbyConnectRestore : NULL);

    unsigned char oldValue2 = lobbyConnectRestore.patch[0];
    L4D_DEBUG_LOG("PlayerSlots -- 'ConnectClientLobbyCheck' jz(%x) patched to 2 nops", oldValue2);
#endif
}
예제 #20
0
// This is called from the PS2 VM at the start of every vsync (either 59.94 or 50 hz by PS2
// clock scale, which does not correlate to the actual host machine vsync).
//
// Default tasks: Updates PADs and applies vsync patches.  Derived classes can override this
// to change either PAD and/or Patching behaviors.
//
// [TODO]: Should probably also handle profiling and debugging updates, once those are
// re-implemented.
//
void SysCoreThread::VsyncInThread()
{
	if (EmuConfig.EnablePatches) ApplyPatch();
	if (EmuConfig.EnableCheats)  ApplyCheat();
}
예제 #21
0
void PlayerSlots::PatchSlotCheckOnly()
{
    if(!lobbyConnectSig) return; //avoid a null dereference if we failed to lookup the sig

    bool firstTime = (serverFullOffset == -1);

    if(firstTime)
    {
        //////////////////////////
        //valve reject server full

        if (!g_pGameConf->GetOffset("ValveRejectServerFullFirst", &serverFullOffset))
        {
            g_pSM->LogError(myself, "PlayerSlots -- Could not find 'ValveRejectServerFullFirst' offset");
            return;
        }

        //the offset should point to the cmp eax, [esi+180h]... first byte incorrect => wrong offset

        if(*((uint8_t*)lobbyConnectSig + serverFullOffset) != OP_CMP_R32_RM32)
        {
            g_pSM->LogError(myself, "PlayerSlots -- Offset for 'ValveRejectServerFullFirst' is incorrect");
            return;
        }
    }

    /*
    cmp around the string "#Valve_Reject_Server_Full"

     cmp eax, [esi+180h] -> cmp eax, IMM32(PLAYER_SLOTS_MAX)        (Windows)
     cmp esi, [ebx+17Ch] -> cmp esi, IMM32(PLAYER_SLOTS_MAX)        (Linux)

    we effectively change how many max players we allow
    */

    patch_t serverFullPatch;

#if defined PLATFORM_LINUX
    serverFullPatch.bytes  = OP_CMP_RM32_IMM32_SIZE;
    serverFullPatch.patch[0] = OP_CMP_RM32_IMM32;
    serverFullPatch.patch[MODRM_BYTE] = MODRM_MOD_DIRECT | OP_CMP_RM32_IMM32_MODRM_DIGIT | MODRM_RM_ESI; //0xFF
    *(uint32_t*)(serverFullPatch.patch+MODRM_BYTE+sizeof(uint8_t)) = (uint32_t)PLAYER_SLOTS_MAX;

#else //PLATFORM_WINDOWS
    serverFullPatch.bytes = OP_CMP_R32_RM32_SIZE;

    //replace the first part of cmp eax, [esi+180h] with cmp eax, IMM32(player_slots_max)

    serverFullPatch.patch[0] = OP_CMP_EAX_IMM32;
    *(uint32_t*)(serverFullPatch.patch+sizeof(uint8_t)) = (uint32_t)PLAYER_SLOTS_MAX;

    //fill in the rest of the patch size with nops

    fill_nop(serverFullPatch.patch + OP_CMP_EAX_IMM32_SIZE, OP_CMP_R32_RM32_SIZE - OP_CMP_EAX_IMM32_SIZE);
#endif

    if(firstTime)
    {
        ApplyPatch(lobbyConnectSig, serverFullOffset, &serverFullPatch, &serverFullRestore);
    }
    else
    {
        ApplyPatch(lobbyConnectSig, serverFullOffset, &serverFullPatch, /*restore*/NULL);
    }
    L4D_DEBUG_LOG("PlayerSlots -- 'ValveRejectServerFullFirst' patched to CMP eax, %d", PLAYER_SLOTS_MAX);
//	L4D_DEBUG_LOG("PlayerSlots -- CBaseServer player limit: %d", *(unsigned int *)((int)g_pServer+ 0x17C));
}
예제 #22
0
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
                                HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
{
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
    HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
#else
    HRESULT hRes = CoInitialize(NULL);
#endif
    _ASSERTE(SUCCEEDED(hRes));
    _Module.Init(ObjectMap, hInstance, NULL);

    int nRet = 0;

    // Various mode of operation
    BOOL bSilentMode = FALSE;


    TCHAR szTargetBaseVersionInfo[256];
    TCHAR szTargetNewVersionInfo[256];

    // Open patch trace file
    OPEN_PATCH_TRACEFILE();

    do
    {
        TCHAR szDirectory[BUFFER_SIZE];
        szDirectory[0] = NULL;

        //---------------------------------------------------
        // Parse parameters from command line
        //
        if ((__argc == 2) ||
                (__argc == 3 && lstrcmpi(__argv[1], TEXT("-s")) == 0))
        {
            // jupdate [-s] dir (Apply patch)
            //
            wsprintf(szDirectory, "%s", __argv[__argc - 1]);

            //---------------------------------------------------
            // Remove trailing '\' in path (#4689837)
            //
            int iPathLen = lstrlen(szDirectory);

            if (szDirectory[iPathLen - 1] == '\\' || szDirectory[iPathLen - 1] == '\"')
                szDirectory[iPathLen - 1] = NULL;

            if (__argc == 3)
                bSilentMode = TRUE;
        }
        else
        {
            // Invalid options
            nRet = UPDATE_ERROR_OPTIONS;
            break;
        }

        //---------------------------------------------------
        // Check if VM is running
        //
        UINT uRet = IDRETRY;

        while (IsVMRunning(szDirectory) && uRet == IDRETRY)
        {
            /*
            	    // Should not ask user if we are in silent mode
            	    if (bSilentMode)
            	    {
            		nRet = UPDATE_ERROR_VM_RUNNING;
            		break;
            	    }
            	    else
            */	    {
                TCHAR szBuffer[BUFFER_SIZE], szMessage[BUFFER_SIZE], szCaption[BUFFER_SIZE];
                ::LoadString(_Module.GetResourceInstance(), IDS_ERROR_VM_RUNNING, szBuffer, BUFFER_SIZE);
                ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_WARNING, szCaption, BUFFER_SIZE);

                wsprintf(szMessage, szBuffer, NEW_IMAGE_FULLVERSION);

                uRet = MessageBox(NULL, szMessage, szCaption, MB_RETRYCANCEL | MB_ICONWARNING);
            }
        }

        // Make sure we break out of the loop
        if (nRet == UPDATE_ERROR_VM_RUNNING)
            break;

        if (uRet == IDCANCEL)
        {
            nRet = UPDATE_ERROR_VM_RUNNING;
            break;
        }


        //---------------------------------------------------
        // Retrieve version info of patched image and base image
        //
        // Retrieve version info of base image
        if (RetrievePatchInfo(szDirectory, szTargetBaseVersionInfo) == FALSE)
        {
            // Cannot locate version.dat
            nRet = UPDATE_ERROR_VERSIONINFO;
            break;
        }

        wsprintf(szTargetNewVersionInfo, "%s", szTargetBaseVersionInfo);

        // Check if directory has been patched
        //
        /*	if (stricmp(szTargetNewVersionInfo, NEW_IMAGE_FULLVERSION) == 0)
        	{
        	    nRet = UPDATE_ERROR_SAME_VERSION_INSTALLED;
        	    break;

        	    // Check if a newer patch has been installed
        	    else if (stricmp(szTargetNewBuildNumber, NEW_IMAGE_BUILD_NUMBER) > 0)
        	    {
        		nRet = UPDATE_ERROR_NEWER_VERSION_INSTALLED;
        		break;
        	    }
        	}
        */

        //-----------------------------------------
        // Perform actual patching
        //

        // If we can't found the base image, see if the targeted directory
        // can be used as the base image
        if (stricmp(szTargetBaseVersionInfo, BASE_IMAGE_FULLVERSION) != 0
                && stricmp(szTargetBaseVersionInfo, NEW_IMAGE_FULLVERSION) != 0)
        {
            // Cannot locate any valid base image
            nRet = UPDATE_ERROR_INVALID_BASE_IMAGE;
            break;
        }


        if (bSilentMode)
        {
            // Patch silently
            if (ApplyPatch(szDirectory, "", SilentUpdateCallBack) == FALSE)
            {
                nRet = UPDATE_ERROR_PATCH;
                break;
            }
        }
        else
        {
            // Patch installer dialog
            CPatchDialog dlg;

            // Set directory to apply the patch
            dlg.setCommandLine(szDirectory, NULL);

            // Execute Installation ...
            if (dlg.DoModal() != IDOK)
            {
                nRet = UPDATE_ERROR_PATCH;
                break;
            }
        }
    }
    while (0);


    // Show dialogs for success/failure
    //
    TCHAR szBuffer[BUFFER_SIZE], szMessage[BUFFER_SIZE], szCaption[BUFFER_SIZE];

    switch (nRet)
    {
    case 0:
    {
        ::LoadString(_Module.GetResourceInstance(), IDS_INSTALL_SUCCESS, szBuffer, BUFFER_SIZE);
        ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_SUCCEEDED, szCaption, BUFFER_SIZE);

        wsprintf(szMessage, szBuffer, NEW_IMAGE_FULLVERSION);

        DisplayInfo(bSilentMode, szMessage, szCaption);

        break;
    }
    case UPDATE_ERROR_OPTIONS:
    {
        ::LoadString(_Module.GetResourceInstance(), IDS_OPTIONS, szBuffer, BUFFER_SIZE);
        ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_ERROR, szCaption, BUFFER_SIZE);

        char* lpszPath = strrchr(__argv[0], '\\');

        if (lpszPath != NULL)
            wsprintf(szMessage, szBuffer, lpszPath + 1);
        else
            wsprintf(szMessage, szBuffer, __argv[0]);

        DisplayError(bSilentMode, szMessage, szCaption);

        break;
    }

    case UPDATE_ERROR_PATCH:
    {
        ::LoadString(_Module.GetResourceInstance(), IDS_ERROR_UPDATE, szMessage, BUFFER_SIZE);
        ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_ERROR, szCaption, BUFFER_SIZE);

        DisplayError(bSilentMode, szMessage, szCaption);

        break;
    }
    case UPDATE_ERROR_VERSIONINFO:
    {
        ::LoadString(_Module.GetResourceInstance(), IDS_ERROR_VERSIONINFO, szMessage, BUFFER_SIZE);
        ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_ERROR, szCaption, BUFFER_SIZE);

        DisplayError(bSilentMode, szMessage, szCaption);

        break;
    }
    case UPDATE_ERROR_INVALID_BASE_IMAGE:
    {
        ::LoadString(_Module.GetResourceInstance(), IDS_ERROR_BASE_IMAGE_NOT_FOUND, szBuffer, BUFFER_SIZE);
        ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_ERROR, szCaption, BUFFER_SIZE);

        wsprintf(szMessage, szBuffer, NEW_IMAGE_FULLVERSION, BASE_IMAGE_FULLVERSION);

        DisplayError(bSilentMode, szMessage, szCaption);

        break;
    }
    case UPDATE_ERROR_SAME_VERSION_INSTALLED:
    {
        ::LoadString(_Module.GetResourceInstance(), IDS_ERROR_INSTALLED_SAME_VERSION, szBuffer, BUFFER_SIZE);
        ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_SUCCEEDED, szCaption, BUFFER_SIZE);

        wsprintf(szMessage, szBuffer, NEW_IMAGE_FULLVERSION);

        DisplayInfo(bSilentMode, szMessage, szCaption);

        break;
    }
    case UPDATE_ERROR_NEWER_VERSION_INSTALLED:
    {
        ::LoadString(_Module.GetResourceInstance(), IDS_ERROR_INSTALLED_NEWER_VERSION, szBuffer, BUFFER_SIZE);
        ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_ERROR, szCaption, BUFFER_SIZE);

        wsprintf(szMessage, szBuffer, NEW_IMAGE_FULLVERSION, szTargetNewVersionInfo);

        DisplayError(bSilentMode, szMessage, szCaption);

        break;
    }
    case UPDATE_ERROR_WRONG_VERSION_UNINSTALLED:
    {
        ::LoadString(_Module.GetResourceInstance(), IDS_ERROR_UNINSTALL_WRONG_VERSION, szBuffer, BUFFER_SIZE);
        ::LoadString(_Module.GetResourceInstance(), IDS_CAPTION_ERROR, szCaption, BUFFER_SIZE);

        wsprintf(szMessage, szBuffer, NEW_IMAGE_FULLVERSION, szTargetNewVersionInfo);

        DisplayError(bSilentMode, szMessage, szCaption);

        break;
    }
    case UPDATE_ERROR_VM_RUNNING:
    {
        PATCH_TRACE("FAIL: VM is currently running.\n");
        break;
    }
    };


    // Close patch trace file
    CLOSE_PATCH_TRACEFILE();


    _Module.Term();
    CoUninitialize();

    if (nRet == 0)
        return 0;
    else
        return ERROR_INSTALL_FAILURE;
}