int EXTThread::start(function_type EntryPoint, void* Arg) { if (EntryPoint) { m_function = EntryPoint; } if (Arg) { m_arg = Arg; } int result = 22; //EINVAL; if (!m_initialised && !m_subsume) { #ifdef _WIN32 std::function<void*()> fn = [=]()->void* { return Trampoline(this); }; m_thread = std::thread(fn); result = 0; #elif __APPLE__ result = pthread_create(&m_thread, NULL, Trampoline, this); #else result = pthread_create(&m_thread, NULL, Trampoline, this); if (!result && !m_name.empty()) { pthread_setname_np(m_thread, m_name.c_str()); } #endif m_initialised = !result; } if(m_subsume && !m_initialised) { m_initialised = true; #ifdef __linux__ if (!result && !m_name.empty()) { pthread_setname_np(m_thread, m_name.c_str()); } #endif // Trampoline here never returns! Trampoline(this); } #ifdef _EXTTHREAD_DEBUG_ if (result) { printf("Error creating thread: %d\n", result); } #endif return result; }
static int Spawn_Program(char *exeFileData, struct Exe_Format *exeFormat) { struct Segment_Descriptor* desc; unsigned long virtSize; unsigned short codeSelector, dataSelector; int i; ulong_t maxva = 0; /* Find maximum virtual address */ for (i = 0; i < exeFormat->numSegments; ++i) { struct Exe_Segment *segment = &exeFormat->segmentList[i]; ulong_t topva = segment->startAddress + segment->sizeInMemory; if (topva > maxva) maxva = topva; } /* setup some memory space for the program */ virtSize = Round_Up_To_Page(maxva) + 4096; /* leave some slack for stack */ virtSpace = Malloc(virtSize); memset((char *) virtSpace, '\0', virtSize); /* Load segment data into memory */ for (i = 0; i < exeFormat->numSegments; ++i) { struct Exe_Segment *segment = &exeFormat->segmentList[i]; memcpy(virtSpace + segment->startAddress, exeFileData + segment->offsetInFile, segment->lengthInFile); } /* allocate and init descriptors and selectors for code and data */ // Kernel code segment. desc = Allocate_Segment_Descriptor(); Init_Code_Segment_Descriptor( desc, (unsigned long)virtSpace, // base address (virtSize/PAGE_SIZE)+10, // num pages 0 // privilege level (0 == kernel) ); codeSelector = Selector( 0, true, Get_Descriptor_Index( desc ) ); // Kernel data segment. desc = Allocate_Segment_Descriptor(); Init_Data_Segment_Descriptor( desc, (unsigned long)virtSpace, // base address (virtSize/PAGE_SIZE)+10, // num pages 0 // privilege level (0 == kernel) ); dataSelector = Selector( 0, true, Get_Descriptor_Index( desc ) ); Install_Interrupt_Handler( 0x90, &Printrap_Handler ); if (lprogdebug) { Print("Spawn_Program(): all structures are set up\n"); Print(" virtSpace = %x\n", (unsigned int) virtSpace); Print(" virtSize = %x\n", (unsigned int) virtSize); Print(" codeSelector = %x\n", codeSelector); Print(" dataSelector = %x\n", dataSelector); Print("Now calling Trampoline()... \n"); } Trampoline(codeSelector, dataSelector, exeFormat->entryAddr); return 0; }
VOID Detour(PSPAWNINFO pChar, PCHAR szFullLine) { DebugSpew("CCommandHook::Detour(%s)",szFullLine); CHAR szFullCommand[MAX_STRING] = {0}; CHAR szCommand[MAX_STRING] = {0}; CHAR szArgs[MAX_STRING] = {0}; CHAR szOrig[MAX_STRING] = {0}; CHAR szSub[MAX_STRING] = {0}; string szSubFullCommand = ""; unsigned int k=0; bool OneCharacterSub = false; PALIAS pLoop = pAliases; PSUB pSubLoop = pSubs; if (szFullLine[0]!=0) { strcpy(szFullCommand,szFullLine); GetArg(szCommand,szFullCommand,1); if (!stricmp(szCommand,"/camp")) { if (gMacroBlock) { WriteChatColor("A macro is currently running. You may wish to /endmacro before you finish camping.", CONCOLOR_YELLOW ); } } szSubFullCommand = szFullCommand; for (unsigned int i=0; i < sizeof(szFullCommand); i++ ) { if (szFullCommand[i] == '%') { if (szFullCommand[i+2] == ' ' || szFullCommand[i+2] == '\0' || !isalnum(szFullCommand[i+2]) ) { if (szFullCommand[i+1] == 'm' || szFullCommand[i+1] == 'M' || szFullCommand[i+1] == 'o' || szFullCommand[i+1] == 'O' || szFullCommand[i+1] == 'p' || szFullCommand[i+1] == 'P' || szFullCommand[i+1] == 'r' || szFullCommand[i+1] == 'R' || szFullCommand[i+1] == 's' || szFullCommand[i+1] == 'S' || szFullCommand[i+1] == 't' || szFullCommand[i+1] == 'T' ) continue; else { szOrig[0] = szFullCommand[i+1]; szOrig[1] = '\0'; k = 1; OneCharacterSub = true; } } if (!OneCharacterSub) { for (unsigned int j=i+1; j < sizeof(szFullCommand); j++ ) { if (szFullCommand[j] == ' ' || szFullCommand[j] == '\0' ) break; else if (!isalnum(szFullCommand[j])) break; szOrig[k] = szFullCommand[j]; k++; } } while (pSubLoop) { if (!stricmp(szOrig, pSubLoop->szOrig)) { sprintf( szSub, "%s", pSubLoop->szSub ); break; } pSubLoop = pSubLoop->pNext; } if (szSub[0] != '\0' ) { szSubFullCommand.replace(i,k+1,szSub); sprintf( szFullCommand, "%s",szSubFullCommand.c_str() ); } szOrig[0] = '\0'; szSub[0] = '\0'; k=0; OneCharacterSub = false; pSubLoop = pSubs; } } sprintf(szFullCommand, "%s", szSubFullCommand.c_str() ); while (pLoop) { if (!stricmp(szCommand,pLoop->szName)) { sprintf(szCommand,"%s%s",pLoop->szCommand,szFullCommand+strlen(pLoop->szName)); strncpy(szFullCommand,szCommand,MAX_STRING); break; } pLoop = pLoop->pNext; } GetArg(szCommand,szFullCommand,1); strcpy(szArgs, GetNextArg(szFullCommand)); PMQCOMMAND pCommand=pCommands; while(pCommand) { if (pCommand->InGameOnly && gGameState!=GAMESTATE_INGAME) { pCommand=pCommand->pNext; continue; } int Pos=strnicmp(szCommand,pCommand->Command,strlen(szCommand)); if (Pos<0) {// command not found break; } if (Pos==0) { if (pCommand->Parse && bAllowCommandParse) ParseMacroParameter(pChar,szArgs); if (pCommand->EQ) { strcat(szCommand," "); strcat(szCommand,szArgs); Trampoline(pChar,szCommand); } else { pCommand->Function(pChar,szArgs); } strcpy(szLastCommand,szFullCommand); return; } pCommand=pCommand->pNext; } } Trampoline(pChar,szFullLine); strcpy(szLastCommand,szFullCommand); }
VOID CEmoteHook::Detour(void) { emotify(); Trampoline(); }
VOID Detour(PSPAWNINFO pChar, PCHAR szFullLine) { lockit lk(ghCCommandLock,"CCommandHook::Detour"); DebugSpew("CCommandHook::Detour(%s)",szFullLine); CHAR szFullCommand[MAX_STRING] = {0}; CHAR szCommand[MAX_STRING] = {0}; CHAR szArgs[MAX_STRING] = {0}; CHAR szOrig[MAX_STRING] = {0}; CHAR szSub[MAX_STRING] = {0}; std::string szSubFullCommand = ""; unsigned int k=0; bool OneCharacterSub = false; PSUB pSubLoop = pSubs; if (szFullLine[0]!=0) { strcpy_s(szFullCommand,szFullLine); GetArg(szCommand,szFullCommand,1); if (!_stricmp(szCommand,"/camp")) { if (GetmacroBlockCount()) { WriteChatColor("A macro is currently running. You may wish to /endmacro before you finish camping.", CONCOLOR_YELLOW ); } } szSubFullCommand = szFullCommand; size_t len = strnlen_s(szFullCommand, MAX_STRING); for (unsigned int i=0; i < sizeof(szFullCommand); i++ ) { if (szFullCommand[i] == '%' && ((i+2)<len)) { if (szFullCommand[i+2] == ' ' || szFullCommand[i+2] == '\0' || !isalnum(szFullCommand[i+2]) ) { if (szFullCommand[i+1] == 'm' || szFullCommand[i+1] == 'M' || szFullCommand[i+1] == 'o' || szFullCommand[i+1] == 'O' || szFullCommand[i+1] == 'p' || szFullCommand[i+1] == 'P' || szFullCommand[i+1] == 'r' || szFullCommand[i+1] == 'R' || szFullCommand[i+1] == 's' || szFullCommand[i+1] == 'S' || szFullCommand[i+1] == 't' || szFullCommand[i+1] == 'T' ) continue; else { szOrig[0] = szFullCommand[i+1]; szOrig[1] = '\0'; k = 1; OneCharacterSub = true; } } if (!OneCharacterSub) { for (unsigned int j=i+1; j < sizeof(szFullCommand); j++ ) { if (szFullCommand[j] == ' ' || szFullCommand[j] == '\0' ) break; else if (!isalnum(szFullCommand[j])) break; szOrig[k] = szFullCommand[j]; k++; } } while (pSubLoop) { if (!_stricmp(szOrig, pSubLoop->szOrig)) { sprintf_s( szSub, "%s", pSubLoop->szSub ); break; } pSubLoop = pSubLoop->pNext; } if (szSub[0] != '\0' ) { szSubFullCommand.replace(i,k+1,szSub); sprintf_s( szFullCommand, "%s",szSubFullCommand.c_str() ); } szOrig[0] = '\0'; szSub[0] = '\0'; k=0; OneCharacterSub = false; pSubLoop = pSubs; } } sprintf_s(szFullCommand, "%s", szSubFullCommand.c_str() ); std::string sName = szCommand; std::transform(sName.begin(), sName.end(), sName.begin(), tolower); if (mAliases.find(sName) != mAliases.end()) { sprintf_s(szCommand,"%s%s",mAliases[sName].c_str(),szFullCommand+sName.size()); strcpy_s(szFullCommand,szCommand); } GetArg(szCommand,szFullCommand,1); strcpy_s(szArgs, GetNextArg(szFullCommand)); PMQCOMMAND pCommand=pCommands; while(pCommand) { if (pCommand->InGameOnly && gGameState!=GAMESTATE_INGAME) { pCommand=pCommand->pNext; continue; } int Pos=_strnicmp(szCommand,pCommand->Command,strlen(szCommand)); if (Pos<0) {// command not found break; } if (Pos==0) { if (pCommand->Parse && bAllowCommandParse) { ParseMacroParameter(pChar, szArgs); } if (pCommand->EQ) { strcat_s(szCommand," "); strcat_s(szCommand,szArgs); Trampoline(pChar,szCommand); } else { pCommand->Function(pChar,szArgs); } strcpy_s(szLastCommand,szFullCommand); return; } pCommand=pCommand->pNext; } PBINDLIST pBind = pBindList; PMACROBLOCK pBlock = GetCurrentMacroBlock(); while( pBind ) { if( gGameState != GAMESTATE_INGAME ) { // Macro Binds only supported in-game pBind = pBind->pNext; continue; } int Pos = _strnicmp( szCommand, pBind->szName, strlen( szCommand ) ); if( Pos == 0 ) { // found it! if( pBind->szFuncName ) { if( PCHARINFO pCharInfo = GetCharInfo() ) { std::string sCallFunc( pBind->szFuncName ); sCallFunc += " "; sCallFunc += szArgs; CHAR szCallFunc[MAX_STRING] = { 0 }; strcpy_s(szCallFunc, sCallFunc.c_str()); ParseMacroData(szCallFunc, MAX_STRING); if (pBlock && !pBlock->BindCmd.size()) { if (!gBindInProgress) { gBindInProgress = true; pBlock->BindCmd = szCallFunc; } else { Beep(1000, 100); WriteChatf("Can't execute bind while another bind is on progress"); } } //CHAR szOrg[MAX_STRING] = {"${Time}"}; //ParseMacroData(szOrg, MAX_STRING); //WriteChatf("[%s] %s called",szOrg, szCallFunc.c_str()); //Beep(1000, 100); } } strcpy_s( szLastCommand, szFullCommand ); return; } pBind = pBind->pNext; } } Trampoline(pChar,szFullLine); strcpy_s(szLastCommand,szFullCommand); }