void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly) { sp_native_t *native; uint32_t i, native_count; IPluginContext *pContext; pContext = pPlugin->GetBaseContext(); /* Generate a new serial ID, mark our dependencies with it. */ g_mark_serial++; pPlugin->PropagateMarkSerial(g_mark_serial); native_count = pContext->GetNativesNum(); for (i = 0; i < native_count; i++) { if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE) continue; // If we're already bound, no need to do anything else. if (native->status == SP_NATIVE_BOUND) continue; /* Otherwise, the native must be in our cache. */ Ref<Native> pEntry = FindNative(native->name); if (!pEntry) continue; if (bCoreOnly && pEntry->owner != &g_CoreNatives) continue; BindNativeToPlugin(pPlugin, native, i, pEntry); } }
void CNativeOwner::UnbindWeakRef(const WeakNative &ref) { IPluginContext *pContext; pContext = ref.pl->GetBaseContext(); pContext->GetRuntime()->UpdateNativeBinding( ref.idx, nullptr, 0, nullptr); }
void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly) { NativeEntry *pEntry; sp_native_t *native; uint32_t i, native_count; IPluginContext *pContext; pContext = pPlugin->GetBaseContext(); /* Generate a new serial ID, mark our dependencies with it. */ g_mark_serial++; pPlugin->PropogateMarkSerial(g_mark_serial); native_count = pContext->GetNativesNum(); for (i = 0; i < native_count; i++) { if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE) { continue; } /* If we're bound, check if there is a replacement available. * If not, this native is totally finalized. */ if (native->status == SP_NATIVE_BOUND) { pEntry = (NativeEntry *)native->user; assert(pEntry != NULL); if (pEntry->replacement.owner == NULL || (pEntry->replacement.owner != NULL && pEntry->replacement.func == native->pfn)) { continue; } } /* Otherwise, the native must be in our cache. */ else if ((pEntry = FindNative(native->name)) == NULL) { continue; } if (bCoreOnly && pEntry->owner != g_pCoreNatives) { continue; } BindNativeToPlugin(pPlugin, native, i, pEntry); } }
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, const Ref<Native> &entry) { if (!entry->owner) return; IPluginContext *pContext = pPlugin->GetBaseContext(); uint32_t i; if (pContext->FindNativeByName(entry->name(), &i) != SP_ERROR_NONE) return; sp_native_t *native; if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE) return; if (native->status == SP_NATIVE_BOUND) return; BindNativeToPlugin(pPlugin, native, i, entry); }
char * GetMyinfoVar(char *var) { unsigned int idx = NULL; if (strcmp(var, "name") == 0) idx = cinfo->name; else if (strcmp(var, "description") == 0) idx = cinfo->description; else if (strcmp(var, "author") == 0) idx = cinfo->author; else if (strcmp(var, "version") == 0) idx = cinfo->version; else if (strcmp(var, "url") == 0) idx = cinfo->url; char *value = new char[512]; IPluginContext *ctx = g_Plugin->GetDefaultContext(); ctx->LocalToString(idx, (char **)&value); return value; }
int sort2d_amx_custom(const void *elem1, const void *elem2) { cell_t c1 = *(cell_t *)elem1; cell_t c2 = *(cell_t *)elem2; cell_t c1_addr = g_SortInfo.array_addr + (c1 * sizeof(cell_t)) + g_SortInfo.array_remap[c1]; cell_t c2_addr = g_SortInfo.array_addr + (c2 * sizeof(cell_t)) + g_SortInfo.array_remap[c2]; IPluginContext *pContext = g_SortInfo.pFunc->GetParentContext(); cell_t *c1_r, *c2_r; pContext->LocalToPhysAddr(c1_addr, &c1_r); pContext->LocalToPhysAddr(c2_addr, &c2_r); cell_t result = 0; g_SortInfo.pFunc->PushCell(c1_addr); g_SortInfo.pFunc->PushCell(c2_addr); g_SortInfo.pFunc->PushCell(g_SortInfo.array_addr); g_SortInfo.pFunc->PushCell(g_SortInfo.hndl); g_SortInfo.pFunc->Execute(&result); return result; }
void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist) { List<CmdHook *>::iterator iter = cmdlist.begin(); while (iter != cmdlist.end()) { CmdHook *pHook = (*iter); IPluginContext *pContext = pHook->pf->GetParentContext(); IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); CmdList *pList = NULL; //gaben if (!pPlugin->GetProperty("CommandList", (void **)&pList, false) || !pList) { continue; } CmdList::iterator p_iter = pList->begin(); while (p_iter != pList->end()) { PlCmdInfo &cmd = (*p_iter); if (cmd.pHook == pHook) { p_iter = pList->erase(p_iter); } else { p_iter++; } } delete pHook->pAdmin; delete pHook; iter = cmdlist.erase(iter); } }
void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) { /* Whoa, first get its information struct */ ConCmdInfo *pInfo; if (!m_Cmds.retrieve(name, &pInfo)) return; CmdHookList::iterator iter = pInfo->hooks.begin(); while (iter != pInfo->hooks.end()) { CmdHook *hook = *iter; IPluginContext *pContext = hook->pf->GetParentContext(); IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); // The list is guaranteed to exist. PluginHookList *list; pPlugin->GetProperty("CommandList", (void **)&list, false); for (PluginHookList::iterator hiter = list->begin(); hiter != list->end(); hiter++) { if (*hiter == hook) { list->erase(hiter); break; } } if (hook->admin) hook->admin->group->hooks.remove(hook); iter = pInfo->hooks.erase(iter); delete hook; } RemoveConCmd(pInfo, name, is_read_safe, false); }
void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction) { ConVarInfo *pInfo; IChangeableForward *pForward; IPluginContext *pContext = pFunction->GetParentContext(); /* Find the convar in the lookup trie */ if (convar_cache_lookup(pConVar->GetName(), &pInfo)) { /* Get the forward */ pForward = pInfo->pChangeForward; /* If the forward doesn't exist, we can't unhook anything */ if (!pForward) { pContext->ThrowNativeError("Convar \"%s\" has no active hook", pConVar->GetName()); return; } /* Remove the function from the forward's list */ if (!pForward->RemoveFunction(pFunction)) { pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", pConVar->GetName()); return; } /* If the forward now has 0 functions in it... */ if (pForward->GetFunctionCount() == 0 && !ConVarReentrancyGuard::IsCvarInChain(pConVar)) { /* Free this forward */ forwardsys->ReleaseForward(pForward); pInfo->pChangeForward = NULL; } } }
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry) { uint32_t i; sp_native_t *native; IPluginContext *pContext; pContext = pPlugin->GetBaseContext(); if (pContext->FindNativeByName(pEntry->name, &i) != SP_ERROR_NONE) { return; } if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE) { return; } if (native->status == SP_NATIVE_BOUND) { return; } BindNativeToPlugin(pPlugin, native, i, pEntry); }
int NativeInvoker::Invoke(cell_t *result) { int err = SP_ERROR_NONE; if (pContext == NULL) { return SP_ERROR_INVALID_NATIVE; } if (m_errorstate != SP_ERROR_NONE) { err = m_errorstate; Cancel(); return err; } cell_t tresult; if (result == NULL) { result = &tresult; } //This is for re-entrancy! IPluginContext *ctx = pContext; cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1]; cell_t *temp_params = &_temp_params[1]; ParamInfo temp_info[SP_MAX_EXEC_PARAMS]; unsigned int numparams = m_curparam; unsigned int i; bool docopies = true; if (numparams) { //Save the info locally, then reset it for re-entrant calls. memcpy(temp_info, m_info, numparams * sizeof(ParamInfo)); } m_curparam = 0; pContext = NULL; /* Initialize 0th parameter */ _temp_params[0] = numparams; /* Browse the parameters and build arrays */ for (i = 0; i < numparams; i++) { /* Is this marked as an array? */ if (temp_info[i].marked) { if (!temp_info[i].str.is_sz) { /* Allocate a normal/generic array */ if ((err = ctx->HeapAlloc(temp_info[i].size, &temp_info[i].local_addr, &temp_info[i].phys_addr)) != SP_ERROR_NONE) { break; } if (temp_info[i].orig_addr) { memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size); } } else { /* Calculate cells required for the string */ size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t); /* Allocate the buffer */ if ((err = ctx->HeapAlloc(cells, &temp_info[i].local_addr, &temp_info[i].phys_addr)) != SP_ERROR_NONE) { break; } /* Copy original string if necessary */ if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL)) { /* Cut off UTF-8 properly */ if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8) { if ((err = ctx->StringToLocalUTF8(temp_info[i].local_addr, temp_info[i].size, (const char *)temp_info[i].orig_addr, NULL)) != SP_ERROR_NONE) { break; } } /* Copy a binary blob */ else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY) { memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size); } /* Copy ASCII characters */ else { if ((err = ctx->StringToLocal(temp_info[i].local_addr, temp_info[i].size, (const char *)temp_info[i].orig_addr)) != SP_ERROR_NONE) { break; } } } } /* End array/string calculation */ /* Update the pushed parameter with the byref local address */ temp_params[i] = temp_info[i].local_addr; } else { /* Just copy the value normally */ temp_params[i] = m_params[i]; } } /* Make the call if we can */ if (err == SP_ERROR_NONE) { *result = native(ctx, _temp_params); if (ctx->GetLastNativeError() != SP_ERROR_NONE) { docopies = false; ctx->ClearLastNativeError(); } } else { docopies = false; } /* i should be equal to the last valid parameter + 1 */ while (i--) { if (!temp_info[i].marked) { continue; } if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK)) { if (temp_info[i].orig_addr) { if (temp_info[i].str.is_sz) { memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size); } else { if (temp_info[i].size == 1) { *temp_info[i].orig_addr = *(temp_info[i].phys_addr); } else { memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size * sizeof(cell_t)); } } } } if ((err = ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE) { return err; } } return err; }
void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *results) { if (!m_pVoteResults) { /* Call MenuAction_VoteEnd instead. See if there are any extra winners. */ unsigned int num_items = 1; for (unsigned int i=1; i<results->num_items; i++) { if (results->item_list[i].count != results->item_list[0].count) { break; } num_items++; } /* See if we need to pick a random winner. */ unsigned int winning_item; if (num_items > 1) { /* Yes, we do. */ srand(time(NULL)); winning_item = rand() % num_items; winning_item = results->item_list[winning_item].item; } else { /* No, take the first. */ winning_item = results->item_list[0].item; } unsigned int total_votes = results->num_votes; unsigned int winning_votes = results->item_list[0].count; DoAction(menu, MenuAction_VoteEnd, winning_item, (total_votes << 16) | (winning_votes & 0xFFFF)); } else { IPluginContext *pContext = m_pVoteResults->GetParentContext(); bool no_call = false; int err; /* First array */ cell_t client_array_address = -1; cell_t *client_array_base = NULL; cell_t client_array_size = results->num_clients + (results->num_clients * 2); if (client_array_size) { if ((err = pContext->HeapAlloc(client_array_size, &client_array_address, &client_array_base)) != SP_ERROR_NONE) { logicore.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for client list.", client_array_size * sizeof(cell_t)); no_call = true; } else { cell_t target_offs = sizeof(cell_t) * results->num_clients; cell_t *cur_index = client_array_base; cell_t *cur_array; for (unsigned int i=0; i<results->num_clients; i++) { /* Copy the array index */ *cur_index = target_offs; /* Get the current array address */ cur_array = (cell_t *)((char *)cur_index + target_offs); /* Store information */ cur_array[0] = results->client_list[i].client; cur_array[1] = results->client_list[i].item; /* Adjust for the new target by subtracting one indirection * and adding one array. */ target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t); cur_index++; } } } /* Second array */ cell_t item_array_address = -1; cell_t *item_array_base = NULL; cell_t item_array_size = results->num_items + (results->num_items * 2); if (item_array_size) { if ((err = pContext->HeapAlloc(item_array_size, &item_array_address, &item_array_base)) != SP_ERROR_NONE) { logicore.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for item list.", item_array_size); no_call = true; } else { cell_t target_offs = sizeof(cell_t) * results->num_items; cell_t *cur_index = item_array_base; cell_t *cur_array; for (unsigned int i=0; i<results->num_items; i++) { /* Copy the array index */ *cur_index = target_offs; /* Get the current array address */ cur_array = (cell_t *)((char *)cur_index + target_offs); /* Store information */ cur_array[0] = results->item_list[i].item; cur_array[1] = results->item_list[i].count; /* Adjust for the new target by subtracting one indirection * and adding one array. */ target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t); cur_index++; } } } /* Finally, push everything */ if (!no_call) { m_pVoteResults->PushCell(menu->GetHandle()); m_pVoteResults->PushCell(results->num_votes); m_pVoteResults->PushCell(results->num_clients); m_pVoteResults->PushCell(client_array_address); m_pVoteResults->PushCell(results->num_items); m_pVoteResults->PushCell(item_array_address); m_pVoteResults->Execute(NULL); } /* Free what we allocated, in reverse order as required */ if (item_array_address != -1) { pContext->HeapPop(item_array_address); } if (client_array_address != -1) { pContext->HeapPop(client_array_address); } } }