static cell_t sm_RemoveFromForward(IPluginContext *pContext, const cell_t *params) { Handle_t fwdHandle = static_cast<Handle_t>(params[1]); Handle_t plHandle = static_cast<Handle_t>(params[2]); HandleError err; IChangeableForward *pForward; IPlugin *pPlugin; if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward)) != HandleError_None) { return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err); } if (plHandle == 0) { pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext()); } else { pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err); if (!pPlugin) { return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err); } } IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]); if (!pFunction) { return pContext->ThrowNativeError("Invalid function id (%X)", params[3]); } return pForward->RemoveFunction(pFunction); }
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; } } }