static void EnterMemoryScope(ke::Vector<MemoryScope>& frame) { if (frame.empty()) frame.append(MemoryScope{0}); else frame.append(MemoryScope{frame.back().scope_id + 1}); }
//Makes a new menu handle (-1 for failure) //native csdm_makemenu(title[]); static cell AMX_NATIVE_CALL menu_create(AMX *amx, cell *params) { int len; char *title = get_amxstring(amx, params[1], 0, len); validate_menu_text(title); char *handler = get_amxstring(amx, params[2], 1, len); int func = registerSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_CELL, FP_DONE); if (func == -1) { LogError(amx, AMX_ERR_NOTFOUND, "Invalid function \"%s\"", handler); return 0; } Menu *pMenu = new Menu(title, amx, func); if (g_MenuFreeStack.empty()) { g_NewMenus.append(pMenu); pMenu->thisId = (int)g_NewMenus.length() - 1; } else { int pos = g_MenuFreeStack.front(); g_MenuFreeStack.pop(); g_NewMenus[pos] = pMenu; pMenu->thisId = pos; } return pMenu->thisId; }
// native Array:ArrayClone(Array:which); static cell AMX_NATIVE_CALL ArrayClone(AMX* amx, cell* params) { CellArray* vec = HandleToVector(amx, params[1]); if (vec == NULL) { return 0; } CellArray *clonevec = vec->clone(); // Scan through the vector list to see if any are NULL. // NULL means the vector was previously destroyed. for (unsigned int i = 0; i < VectorHolder.length(); ++i) { if (VectorHolder[i] == NULL) { VectorHolder[i] = clonevec; return i + 1; } } VectorHolder.append(clonevec); return VectorHolder.length(); }
pstruct_t* pstructs_add(const char *name) { auto p = ke::MakeUnique<pstruct_t>(name); sStructs.append(ke::Move(p)); return sStructs.back().get(); }
funcenum_t *funcenums_add(const char *name) { auto e = ke::MakeUnique<funcenum_t>(); strcpy(e->name, name); e->tag = gTypes.defineFunction(name, e.get())->tagid(); sFuncEnums.append(ke::Move(e)); return sFuncEnums.back().get(); }
int GetPEL() { for (int i=0; i<(int)PEL.length(); i++) { if (PEL[i]->isFree()) return i; } RegEx *x = new RegEx(); PEL.append(x); return (int)PEL.length() - 1; }
//register_native(const name[], const handler[]) static cell AMX_NATIVE_CALL register_native(AMX *amx, cell *params) { if (!g_Initialized) amxx_DynaInit((void *)(amxx_DynaCallback)); g_Initialized = true; int len; char *name = get_amxstring(amx, params[1], 0, len); char *func = get_amxstring(amx, params[2], 1, len); int idx, err; if ( (err=amx_FindPublic(amx, func, &idx)) != AMX_ERR_NONE) { LogError(amx, err, "Function \"%s\" was not found", func); return 0; } regnative *pNative = new regnative; pNative->amx = amx; pNative->func = idx; //we'll apply a safety buffer too //make our function int size = amxx_DynaCodesize(); #if defined(_WIN32) DWORD temp; pNative->pfn = new char[size + 10]; VirtualProtect(pNative->pfn, size+10, PAGE_EXECUTE_READWRITE, &temp); #elif defined(__GNUC__) # if defined(__APPLE__) pNative->pfn = (char *)valloc(size+10); # else pNative->pfn = (char *)memalign(sysconf(_SC_PAGESIZE), size+10); # endif mprotect((void *)pNative->pfn, size+10, PROT_READ|PROT_WRITE|PROT_EXEC); #endif int id = (int)g_RegNatives.length(); amxx_DynaMake(pNative->pfn, id); pNative->func = idx; pNative->style = params[3]; g_RegNatives.append(pNative); pNative->name = name; return 1; }
static cell AMX_NATIVE_CALL free_kvd(AMX *amx, cell *params) { if (params[1] == 0) { return 0; } KVD_Wrapper *kvdw = reinterpret_cast<KVD_Wrapper *>(params[1]); for (size_t i = 0; i < g_KVDWs.length(); ++i) { if (g_KVDWs[i] == kvdw) { g_KVDWs.remove(i); g_FreeKVDWs.append(kvdw); return 1; } } return 0; }
methodmap_t* methodmap_add(methodmap_t* parent, LayoutSpec spec, const char* name) { auto map = ke::MakeUnique<methodmap_t>(parent, spec, name); if (spec == Layout_MethodMap && parent) { if (parent->nullable) map->nullable = parent->nullable; if (parent->keyword_nullable) map->keyword_nullable = parent->keyword_nullable; } if (spec == Layout_MethodMap) map->tag = gTypes.defineMethodmap(name, map.get())->tagid(); else map->tag = gTypes.defineObject(name)->tagid(); sMethodmaps.append(ke::Move(map)); return sMethodmaps.back().get(); }
static cell AMX_NATIVE_CALL create_kvd(AMX *amx, cell *params) { KVD_Wrapper *kvdw; if (g_FreeKVDWs.empty()) { kvdw = new KVD_Wrapper; } else { kvdw = g_FreeKVDWs.popCopy(); } kvdw->cls = ""; kvdw->kvd.szClassName = const_cast<char*>(kvdw->cls.chars()); kvdw->key = ""; kvdw->kvd.szKeyName = const_cast<char*>(kvdw->key.chars()); kvdw->val = ""; kvdw->kvd.szValue = const_cast<char*>(kvdw->val.chars()); kvdw->kvd.fHandled = 0; g_KVDWs.append(kvdw); return reinterpret_cast<cell>(kvdw); }
// Array:ArrayCreate(cellsize=1, reserved=32); static cell AMX_NATIVE_CALL ArrayCreate(AMX* amx, cell* params) { // params[1] (cellsize) is how big in cells each element is. // this MUST be greater than 0! int cellsize = params[1]; // params[2] (reserved) is how many elements to allocate // immediately when the list is created. int reserved = params[2]; if (cellsize <= 0) { LogError(amx, AMX_ERR_NATIVE, "Invalid array size (%d)", cellsize); return -1; } if (reserved < 0) { reserved = 0; } // Scan through the vector list to see if any are NULL. // NULL means the vector was previously destroyed. for (unsigned int i=0; i < VectorHolder.length(); ++i) { if (VectorHolder[i]==NULL) { VectorHolder[i] = new CellArray(cellsize, reserved); return i + 1; } } // None are NULL, create a new vector CellArray* NewVector = new CellArray(cellsize, reserved); VectorHolder.append(NewVector); return VectorHolder.length(); }
void InitDetours() { IsValidTargetDetour = DETOUR_CREATE_MEMBER_FIXED(Observer_IsValidTarget, Util::FindAddress(FUNC_ISVALIDTARGET)); ObserverSetModeDetour = DETOUR_CREATE_MEMBER_FIXED(Observer_SetMode , Util::FindAddress(FUNC_SETMODE)); #if defined(KE_LINUX) void *SetModePart2Address = Util::FindAddress(FUNC_SETMODE2); if (ObserverSetModeDetour && IsValidTargetDetour && SetModePart2Address) { SetModePart2 = reinterpret_cast<SetModePart2Fn>(SetModePart2Address); #elif defined(KE_WINDOWS) || defined(KE_MACOSX) if (ObserverSetModeDetour && IsValidTargetDetour) { #endif IsValidTargetDetour->EnableDetour(); ObserverSetModeDetour->EnableDetour(); } else { if (!IsValidTargetDetour) { ErrorLogs.append("CBasePlayer::Observer_IsValidTarget is not available."); } if (!ObserverSetModeDetour) { ErrorLogs.append("CBasePlayer::Observer_SetMode is not available."); } #if defined(KE_LINUX) if (!SetModePart2Address) { ErrorLogs.append("CBasePlayer::Observer_SetMode (second part) is not available."); } #endif ErrorLogs.append("Some functions are not availble, module has been disabled."); DestroyDetours(); } } void DestroyDetours() { if (IsValidTargetDetour) { IsValidTargetDetour->Destroy(); IsValidTargetDetour = nullptr; } if (ObserverSetModeDetour) { ObserverSetModeDetour->Destroy(); ObserverSetModeDetour = nullptr; } }
bool loadDatabase() { const auto isDatabaseLoaded = HandleDB.filename != nullptr; if (isDatabaseLoaded) { return true; } const char *databases[] = { "City", "Country" // Is the default shipped database with AMXX. }; const auto modName = MF_GetModname(); const auto dataDir = MF_GetLocalInfo("amxx_datadir", "addons/amxmodx/data"); char file[260]; auto status = -1; for (auto& database : databases) { // MF_BuildPathname not used because backslash // makes CreateFileMapping failing under windows. ke::SafeSprintf(file, sizeof file, "%s/%s/GeoLite2-%s.mmdb", modName, dataDir, database); status = MMDB_open(file, MMDB_MODE_MMAP, &HandleDB); if (status == MMDB_SUCCESS) { break; } if (status != MMDB_FILE_OPEN_ERROR) { MF_Log("Could not open %s - %s", file, MMDB_strerror(status)); if (status == MMDB_IO_ERROR) { MF_Log(" IO error: %s", strerror(errno)); } } } if (status != MMDB_SUCCESS) { MF_Log("Could not find GeoIP2 databases. Disabled natives."); return false; } MF_Log("Database info: %s %i.%i", HandleDB.metadata.description.descriptions[0]->description, HandleDB.metadata.binary_format_major_version, HandleDB.metadata.binary_format_minor_version); // Retrieve supported languages. for (size_t i = 0; i < HandleDB.metadata.languages.count; i++) { LangList.append(ke::AString(HandleDB.metadata.languages.names[i])); } return true; }