static cell AMX_NATIVE_CALL n_OnRconLoginAttempt( AMX* amx, cell* params ) { char ip[16], password[64]; amx_GetString( amx, params[1], ip, sizeof(ip) ); amx_GetString( amx, params[2], password, sizeof(password) ); return OnRconLoginAttempt(ip, password, params[3]); }
static cell AMX_NATIVE_CALL n_OnPlayerCommandText( AMX* amx, cell* params ) { char text[1024]; amx_GetString( amx, params[2], text, sizeof(text) ); return OnPlayerCommandText(params[1], text); }
static cell AMX_NATIVE_CALL n_OnDialogResponse( AMX* amx, cell* params ) { char text[1024]; amx_GetString( amx, params[5], text, sizeof(text) ); return OnDialogResponse(params[1], params[2], params[3], params[4], text); }
static cell AMX_NATIVE_CALL n_strfloat(AMX *amx,const cell *params) { /* * params[0] = number of bytes * params[1] = virtual string address to convert to a float */ char szSource[60]; cell *pString; REAL fNum; int nLen; (void)amx; /* They should have sent us 1 cell. */ assert(params[0]/sizeof(cell)==1); /* Get the real address of the string. */ amx_GetAddr(amx,params[1],&pString); /* Find out how long the string is in characters. */ amx_StrLen(pString, &nLen); if (nLen == 0 || nLen >= sizeof szSource) return 0; /* Now convert the Pawn string into a C type null terminated string */ amx_GetString(szSource, pString, 0, sizeof szSource); /* Now convert this to a float. */ fNum = (REAL)atof(szSource); return amx_ftoc(fNum); }
PLUGIN_EXPORT bool PLUGIN_CALL OnPublicCall(AMX *amx, const char *name, cell *params, cell *retval){ sampjs::SAMPJS::amx = amx; if (string(name) == "OnRconCommand"){ cell* maddr = NULL; int len = 0; char* sval; if (amx_GetAddr(amx, params[1], &maddr) != AMX_ERR_NONE){ sjs::logger::error("Can't get string address: %s", name); return 1; } amx_StrLen(maddr, &len); sval = new char[len + 1]; if (amx_GetString(sval, maddr, 0, len + 1) != AMX_ERR_NONE){ sjs::logger::error("Can't get string: %s", name); return 1; } if (RconCommand(sval)){ *retval = true; return true; } } int ret = sampjs::SAMPJS::PublicCall(name, params, retval); return (ret > 0); }
/* sendstring(const message[], const destination[]="") * destination has the format "127.0.0.1:9930"; when set to an empty string, * a broadcast is sent. * To mark the text as a "string", the function inserts a "byte order mark" in * front of it. It does this for Extended ASCII strings too, although this is * not entirely correct. * Returns true on success, false on failure. */ static cell AMX_NATIVE_CALL n_sendstring(AMX *amx, const cell *params) { int r = 0, length; cell *cstr; char *host, *message, *ptr; short port=AMX_DGRAMPORT; cstr = amx_Address(amx, params[1]); amx_UTF8Len(cstr, &length); if ((message = alloca(length + 3 + 1)) != NULL) { /* insert the byte order mark (BOM) */ message[0]='\xef'; message[1]='\xbb'; message[2]='\xbf'; /* if this is a wide string, convert it to UTF-8 */ if ((ucell)*cstr<=UNPACKEDMAX) { ptr=message+3; while (*cstr!=0) amx_UTF8Put(ptr, &ptr, length - (ptr-message), *cstr++); *ptr='\0'; } else { amx_GetString(message+3, cstr, 0, UNLIMITED); } /* if */ amx_StrParam(amx, params[2], host); if (host != NULL && (ptr=strchr(host,':'))!=NULL && isdigit(ptr[1])) { *ptr++='\0'; port=(short)atoi(ptr); } /* if */ r= (udp_Send(host,port,message,strlen(message)+1) > 0); } /* if */ return r; }
void sampgdk_fakeamx_get_string(cell address, char *dest, int size) { assert(is_cell_aligned(address)); assert(dest != NULL); amx_GetString(dest, (cell *)sampgdk_array_get(&global.heap, address / sizeof(cell)), 0, size); }
int main(int argc,char *argv[]) { extern int amx_ConsoleInit(AMX *amx); extern int amx_ConsoleCleanup(AMX *amx); extern int amx_CoreInit(AMX *amx); extern int amx_CoredCleanp(AMX *amx); size_t memsize; void *program; AMX amx; int index, err; cell amx_addr, *phys_addr; char output[128]; if (argc != 4) PrintUsage(argv[0]); if ((memsize = aux_ProgramSize(argv[1])) == 0) PrintUsage(argv[0]); program = malloc(memsize); if (program == NULL) ErrorExit(NULL, AMX_ERR_MEMORY); err = aux_LoadProgram(&amx, argv[1], program); if (err) ErrorExit(&amx, err); amx_ConsoleInit(amx); err = amx_CoreInit(amx); if (err) ErrorExit(&amx, err); err = amx_FindPublic(&amx, argv[2], &index); if (err) ErrorExit(&amx, err); err = amx_Allot(&amx, strlen(argv[3]) + 1, &amx_addr, &phys_addr); if (err) ErrorExit(&amx, err); amx_SetString(phys_addr, argv[3], 0); err = amx_Exec(&amx, NULL, index, 1, amx_addr); if (err) ErrorExit(&amx, err); amx_GetString(output, phys_addr); amx_Release(&amx, amx_addr); printf("%s returns %s\n", argv[1], output); amx_ConsoleCleanup(&amx); amx_CoreCleanup(&amx); amx_Cleanup(&amx); free(program); return 0; }
error_t CellMemory:: GetNextString(char * ret, size_t len) { FAIL(m_cur < m_count, ERROR_OUT_OF_VARIABLES); // 1-indexed array. cell * addr; amx_GetAddr(m_amx, m_params[++m_cur], &addr); amx_GetString(ret, addr, false, len); return OK; }
cell pawn_usbWrite( AMX * amx, const cell * params ) { (void)amx; int length; amx_StrLen( (cell*)params[1], &length ); #define STR_LEN 32 static char stri[ STR_LEN ]; amx_GetString( stri, (cell *)params[1], 0, length ); stri[ STR_LEN-1 ] = '\0'; usbWrite( stri ); return 0; }
static void DoName(AMX * amx, cell playerid, cell name) { cell * str; int len; amx_GetAddr(amx, name, &str); amx_StrLen(str, &len); if ((unsigned int)len >= g_iMaxPlayerName) { len = (int)g_iMaxPlayerName - 1; } amx_GetString(g_szPlayerNames + (g_iMaxPlayerName * playerid), str, 0, len + 1); }
static cell AMX_NATIVE_CALL n_strfixed(AMX *amx,const cell *params) { char str[50],*ptr; cell *cstr,intpart,decimals; long multiplier,divisor; int len,sign=1; cstr=amx_Address(amx,params[1]); amx_StrLen(cstr,&len); if (len>=50) { amx_RaiseError(amx,AMX_ERR_NATIVE); return 0; } /* if */ amx_GetString(str,cstr,0,UNLIMITED); ptr=str; intpart=0; decimals=0; multiplier=MULTIPLIER; divisor=1; while (*ptr!='\0' && *ptr<=' ') ptr++; /* skip whitespace */ if (*ptr=='-') { /* handle sign */ sign=-1; ptr++; } else if (*ptr=='+') { ptr++; } /* if */ while (isdigit(*ptr)) { intpart=intpart*10 + (*ptr-'0'); ptr++; } /* while */ if (*ptr=='.') { ptr++; len=0; while (isdigit(*ptr) && len<8) { decimals=decimals*10 + (*ptr-'0'); if (multiplier>1) multiplier/=10; else divisor*=10; ptr++; len++; } /* while */ } /* if */ return ((intpart*MULTIPLIER) + (decimals*multiplier+(divisor/2))/divisor) * sign; }
cell AMX_NATIVE_CALL kill_proc(AMX *amx, cell *params) { int len; cell *addr = NULL; amx_GetAddr(amx, params [1], &addr); amx_StrLen(addr, &len); char* proc = malloc (++len); amx_GetString(proc, addr, 0, len); int pid = get_process_id (proc); if (pid == 0) { logprintf ("Process %s not found!", proc); free (proc); return 0; } logprintf ("Process %s | ID: %d", proc, pid); kill (pid, SIGKILL) != 0 ? logprintf ("Need root access for kill %s!", proc) : logprintf ("Process %s <%d> was successfully killed!", proc, pid); free (proc); return 1; }
static cell AMX_NATIVE_CALL funcidx(AMX *amx,cell *params) { char name[64]; cell *cstr; int index,err; amx_GetAddr(amx,params[1],&cstr); #if 0 /* if you are paranoia */ amx_StrLen(cstr,&len); if (len>=64) { amx_RaiseError(amx,AMX_ERR_NATIVE); return 0; } /* if */ #endif amx_GetString(name,cstr); err=amx_FindPublic(amx,name,&index); if (err!=AMX_ERR_NONE) index=-1; /* this is not considered a fatal error */ return index; }
string COrm::Variable::GetValueAsString() { string res; switch (m_Type) { case COrm::Variable::Type::INVALID: return "INVALID"; case COrm::Variable::Type::INT: return fmt::FormatInt(*(m_VariableAddr)).str(); case COrm::Variable::Type::FLOAT: ConvertDataToStr(amx_ctof(*m_VariableAddr), res); break; case COrm::Variable::Type::STRING: std::unique_ptr<char[]> buffer(new char[m_VarMaxLen]); amx_GetString(buffer.get(), m_VariableAddr, 0, m_VarMaxLen); buffer[m_VarMaxLen] = '\0'; res.assign(buffer.get()); break; } return res; }
uint32_t CGamemodeManager::OnPlayerText(cell playerid, unsigned char * szText) { if (!gmIsInit) return 0; int idx; cell ret = 1; uint32_t orig_strlen = strlen((char*)szText) + 1; if (!amx_FindPublic(&gmAMX, "OnPlayerText", &idx)) { cell amx_addr, *phys_addr; amx_PushString(&gmAMX, &amx_addr, &phys_addr, (char*)szText, 0, 0); amx_Push(&gmAMX, playerid); amx_Exec(&gmAMX, &ret, idx); amx_GetString((char*)szText, phys_addr, 0, orig_strlen); amx_Release(&gmAMX, amx_addr); } if (ret && __NetGame->playerPool->GetSlotState((_PlayerID)playerid)) { __NetGame->playerPool->GetPlayer((_PlayerID)playerid)->Say((char*)szText, strlen((char*)szText)); } return (uint32_t)ret; }
cell AMX_NATIVE_CALL Natives::CTime_strftime(AMX *pAMX, cell *iParams) { CHECK_PARAMS(4, "strftime"); cell *iPhysAddr ; amx_GetAddr(pAMX, iParams[4], &iPhysAddr); tm tmPtr ; g_CTime->SetTimePointer(&tmPtr, iPhysAddr); int iSize = iParams[2] ; char *szFormat = new char[iSize] ; amx_GetAddr(pAMX, iParams[3], &iPhysAddr); amx_GetString(szFormat, iPhysAddr, 0, iSize); char *szBuf = new char[iSize] ; strftime(szBuf, iSize, szFormat, &tmPtr); amx_GetAddr(pAMX, iParams[1], &iPhysAddr); amx_SetString(iPhysAddr, szBuf, 0, 0, iParams[2]); delete szFormat; delete szBuf; return 1; }
// native mysql_statement_execute(connectionHandle, statementId, callback[], dataId, {Float,_}:...); static cell AMX_NATIVE_CALL n_mysql_statement_execute(AMX* amx, cell* params) { if (params[0] < 4 * sizeof(cell)) { logprintf("SCRIPT: Bad parameter count (%d < 4): ", params[0]); return 0; } ConnectionHost* connection = connectionController->connection(params[1]); const Statement* statement = statementRegistry->At(params[2]); if (connection == nullptr || statement == nullptr) return 0; char* callback; amx_StrParam(amx, params[3], callback); unsigned int dataId = params[4]; const int parameterOffset = 4; if ((statement->Parameters().length() + parameterOffset) * sizeof(cell) != params[0]) { logprintf("[lvp_MySQL] The statement call expected %d parameters, received %d.", statement->Parameters().length() + parameterOffset, params[0] / sizeof(cell)); logprintf("[lvp_MySQL] Statement: [%s].", statement->Query().c_str()); return 0; } std::vector<std::string> parameters; const std::string& parameterTypes = statement->Parameters(); char buffer[256]; cell* address; int length = 0; for (unsigned int index = 0; index < parameterTypes.length(); ++index) { if (amx_GetAddr(amx, params[parameterOffset + 1 + index], &address) != AMX_ERR_NONE) return 0; // this case shouldn't happen. switch (parameterTypes[index]) { case 'i': // integers. snprintf(buffer, sizeof(buffer), "%d", *address); parameters.push_back(buffer); break; case 'f': // floats. snprintf(buffer, sizeof(buffer), "%.4f", amx_ctof(*address)); parameters.push_back(buffer); break; case 's': // strings. amx_StrLen(address, &length); amx_GetString(buffer, address, 0, std::min(static_cast<unsigned int>(length + 1), sizeof(buffer))); buffer[sizeof(buffer)-1] = 0; parameters.push_back(escape_string_parameter(buffer)); break; default: // other (unhandled) types. logprintf("[lvp_MySQL] Unknown parameter type in statement: '%c'. Cannot execute.", parameterTypes[index]); logprintf("[lvp_MySQL] Statement: [%s].", statement->Query().c_str()); return 0; } } std::string query; if (QueryBuilder::Build(statement, parameters, query) == false) { logprintf("[lvp_MySQL] Unable to build the query, cannot execute this statement."); logprintf("[lvp_MySQL] Statement: [%s].", statement->Query().c_str()); return 0; } connection->query(query.c_str(), callback, dataId); return 1; }
cell AMX_NATIVE_CALL amx_RegisterAlt(AMX* amx, cell* params) { int amx_n; for(amx_n=0; amx_n<=lastAMX; ++amx_n) if(amx == amx_List[amx_n].amx) break; if(amx_n>lastAMX) // if amx wasn't found in list return 0; cell *addr; int len; amx_GetAddr(amx, params[1], &addr); amx_StrLen(addr, &len); if(len>31) len=31; ++len; char cmd[32]; amx_GetString(cmd, addr, 0, len); cmd[0] = '_'; // converting string to lower case int pos=0; do{ ++pos; if(('A' <= cmd[pos]) && (cmd[pos] <= 'Z')) cmd[pos] += ('a'-'A'); else if(cmd[pos] == '\0') break; else if((cmd[pos] == ' ') || (cmd[pos] == '\t')) { cmd[pos] = '\0'; break; } }while(1); int pubidx; if(amx_FindPublic(amx, cmd, &pubidx) != AMX_ERR_NONE) { //logprintf((char*)"RegisterAlt: Couldn't find function %s", cmd); return 1; } int alt_n = (params[0]/4), hash; //logprintf("RegisterAlt: alts = %d", alt_n-1); do{ if(amx_GetAddr(amx, params[alt_n], &addr) != AMX_ERR_NONE) continue; amx_StrLen(addr, &len); if(len>31) len=31; // command length must be up to 31 chars ++len; amx_GetString(cmd, addr, 0, len); cmd[0] = '_'; pos = 0; do{ ++pos; if(('A' <= cmd[pos]) && (cmd[pos] <= 'Z')) cmd[pos] += ('a'-'A'); else if(cmd[pos] == '\0') break; else if((cmd[pos] == ' ') || (cmd[pos] == '\t')) { cmd[pos] = '\0'; break; } }while(1); //logprintf((char*)"%s, len = %d", cmd, pos); Murmur3(cmd, pos, &hash); //logprintf("RegisterAlt: Murmur3(%s) = 0x%X", cmd, hash); Alts[amx_n].insert(std::make_pair(hash, pubidx)); Alts_n++; //logprintf((char*)"RegisterAlt: new alt - %s, amx = %d, pubidx = %d", cmd, amx, pubidx); }while(--alt_n > 1); return 1; }
/* libcall(const libname[], const funcname[], const typestring[], ...) * * Loads the DLL or shared library if not yet loaded (the name comparison is * case sensitive). * * typestring format: * Whitespace is permitted between the types, but not inside the type * specification. The string "ii[4]&u16s" is equivalent to "i i[4] &u16 s", * but the latter is easier on the eye. * * types: * i = signed integer, 16-bit in Windows 3.x, else 32-bit in Win32 and Linux * u = unsigned integer, 16-bit in Windows 3.x, else 32-bit in Win32 and Linux * f = IEEE floating point, 32-bit * p = packed string * s = unpacked string * The difference between packed and unpacked strings is only relevant when * the parameter is passed by reference (see below). * * pass-by-value and pass-by-reference: * By default, parameters are passed by value. To pass a parameter by * reference, prefix the type letter with an "&": * &i = signed integer passed by reference * i = signed integer passed by value * Same for '&u' versus 'u' and '&f' versus 'f'. * * Arrays are passed by "copy & copy-back". That is, libcall() allocates a * block of dynamic memory to copy the array into. On return from the foreign * function, libcall() copies the array back to the abstract machine. The * net effect is similar to pass by reference, but the foreign function does * not work in the AMX stack directly. During the copy and the copy-back * operations, libcall() may also transform the array elements, for example * between 16-bit and 32-bit elements. This is done because Pawn only * supports a single cell size, which may not fit the required integer size * of the foreign function. * * See "element ranges" for the syntax of passing an array. * * Strings may either be passed by copy, or by "copy & copy-back". When the * string is an output parameter (for the foreign function), the size of the * array that will hold the return string must be indicated between square * brackets behind the type letter (see "element ranges"). When the string * is "input only", this is not needed --libcall() will determine the length * of the input string itself. * * The tokens 'p' and 's' are equivalent, but 'p[10]' and 's[10]' are not * equivalent: the latter syntaxes determine whether the output from the * foreign function will be stored as a packed or an unpacked string. * * element sizes: * Add an integer behind the type letter; for example, 'i16' refers to a * 16-bit signed integer. Note that the value behind the type letter must * be either 8, 16 or 32. * * You should only use element size specifiers on the 'i' and 'u' types. That * is, do not use these specifiers on 'f', 's' and 'p'. * * element ranges: * For passing arrays, the size of the array may be given behind the type * letter and optional element size. The token 'u[4]' indicates an array of * four unsigned integers, which are typically 32-bit. The token 'i16[8]' * is an array of 8 signed 16-bit integers. Arrays are always passed by * "copy & copy-back" * * When compiled as Unicode, this library converts all strings to Unicode * strings. * * The calling convention for the foreign functions is assumed: * - "__stdcall" for Win32, * - "far pascal" for Win16 * - and the GCC default for Unix/Linux (_cdecl) * * C++ name mangling of the called function is not handled (there is no standard * convention for name mangling, so there is no portable way to convert C++ * function names to mangled names). Win32 name mangling (used by default by * Microsoft compilers on functions declared as __stdcall) is also not handled. * * Returns the value of the called function. */ static cell AMX_NATIVE_CALL n_libcall(AMX *amx, const cell *params) { const TCHAR *libname, *funcname, *typestring; MODLIST *item; int paramidx, typeidx, idx; PARAM ps[MAXPARAMS]; cell *cptr,result; LIBFUNC LibFunc; amx_StrParam(amx, params[1], libname); item = findlib(&ModRoot, amx, libname); if (item == NULL) item = addlib(&ModRoot, amx, libname); if (item == NULL) { amx_RaiseError(amx, AMX_ERR_NATIVE); return 0; } /* if */ /* library is loaded, get the function */ amx_StrParam(amx, params[2], funcname); LibFunc=(LIBFUNC)SearchProcAddress(item->inst, funcname); if (LibFunc==NULL) { amx_RaiseError(amx, AMX_ERR_NATIVE); return 0; } /* if */ #if defined HAVE_DYNCALL_H /* (re-)initialize the dyncall library */ if (dcVM==NULL) { dcVM=dcNewCallVM(4096); dcMode(dcVM,DC_CALL_C_X86_WIN32_STD); } /* if */ dcReset(dcVM); #endif /* decode the parameters */ paramidx=typeidx=0; amx_StrParam(amx, params[3], typestring); while (paramidx < MAXPARAMS && typestring[typeidx]!=__T('\0')) { /* skip white space */ while (typestring[typeidx]!=__T('\0') && typestring[typeidx]<=__T(' ')) typeidx++; if (typestring[typeidx]==__T('\0')) break; /* save "pass-by-reference" token */ ps[paramidx].type=0; if (typestring[typeidx]==__T('&')) { ps[paramidx].type=BYREF; typeidx++; } /* if */ /* store type character */ ps[paramidx].type |= (unsigned char)typestring[typeidx]; typeidx++; /* set default size, then check for an explicit size */ #if defined __WIN32__ || defined _WIN32 || defined WIN32 ps[paramidx].size=32; #elif defined _Windows ps[paramidx].size=16; #endif if (_istdigit(typestring[typeidx])) { ps[paramidx].size=(unsigned char)_tcstol(&typestring[typeidx],NULL,10); while (_istdigit(typestring[typeidx])) typeidx++; } /* if */ /* set default range, then check for an explicit range */ ps[paramidx].range=1; if (typestring[typeidx]=='[') { ps[paramidx].range=_tcstol(&typestring[typeidx+1],NULL,10); while (typestring[typeidx]!=']' && typestring[typeidx]!='\0') typeidx++; ps[paramidx].type |= BYREF; /* arrays are always passed by reference */ typeidx++; /* skip closing ']' too */ } /* if */ /* get pointer to parameter */ cptr=amx_Address(amx,params[paramidx+4]); switch (ps[paramidx].type) { case 'i': /* signed integer */ case 'u': /* unsigned integer */ case 'f': /* floating point */ assert(ps[paramidx].range==1); ps[paramidx].v.val=(int)*cptr; break; case 'i' | BYREF: case 'u' | BYREF: case 'f' | BYREF: ps[paramidx].v.ptr=cptr; if (ps[paramidx].range>1) { /* convert array and pass by address */ ps[paramidx].v.ptr = fillarray(amx, &ps[paramidx], cptr); } /* if */ break; case 'p': case 's': case 'p' | BYREF: case 's' | BYREF: if (ps[paramidx].type=='s' || ps[paramidx].type=='p') { int len; /* get length of input string */ amx_StrLen(cptr,&len); len++; /* include '\0' */ /* check max. size */ if (len<ps[paramidx].range) len=ps[paramidx].range; ps[paramidx].range=len; } /* if */ ps[paramidx].v.ptr=malloc(ps[paramidx].range*sizeof(TCHAR)); if (ps[paramidx].v.ptr==NULL) return amx_RaiseError(amx, AMX_ERR_NATIVE); amx_GetString((char *)ps[paramidx].v.ptr,cptr,sizeof(TCHAR)>1,UNLIMITED); break; default: /* invalid parameter type */ return amx_RaiseError(amx, AMX_ERR_NATIVE); } /* switch */ paramidx++; } /* while */ if ((params[0]/sizeof(cell)) - 3 != (size_t)paramidx) return amx_RaiseError(amx, AMX_ERR_NATIVE); /* format string does not match number of parameters */ #if defined HAVE_DYNCALL_H for (idx = 0; idx < paramidx; idx++) { if ((ps[idx].type=='i' || ps[idx].type=='u' || ps[idx].type=='f') && ps[idx].range==1) { switch (ps[idx].size) { case 8: dcArgChar(dcVM,(unsigned char)(ps[idx].v.val & 0xff)); break; case 16: dcArgShort(dcVM,(unsigned short)(ps[idx].v.val & 0xffff)); break; default: dcArgLong(dcVM,ps[idx].v.val); } /* switch */ } else { dcArgPointer(dcVM,ps[idx].v.ptr); } /* if */ } /* for */ result=(cell)dcCallPointer(dcVM,(void*)LibFunc); #else /* HAVE_DYNCALL_H */ /* push the parameters to the stack (left-to-right in 16-bit; right-to-left * in 32-bit) */ #if defined __WIN32__ || defined _WIN32 || defined WIN32 for (idx=paramidx-1; idx>=0; idx--) { #else for (idx=0; idx<paramidx; idx++) { #endif if ((ps[idx].type=='i' || ps[idx].type=='u' || ps[idx].type=='f') && ps[idx].range==1) { switch (ps[idx].size) { case 8: push((unsigned char)(ps[idx].v.val & 0xff)); break; case 16: push((unsigned short)(ps[idx].v.val & 0xffff)); break; default: push(ps[idx].v.val); } /* switch */ } else { push(ps[idx].v.ptr); } /* if */ } /* for */ /* call the function; all parameters are already pushed to the stack (the * function should remove the parameters from the stack) */ result=LibFunc(); #endif /* HAVE_DYNCALL_H */ /* store return values and free allocated memory */ for (idx=0; idx<paramidx; idx++) { switch (ps[idx].type) { case 'p': case 's': free(ps[idx].v.ptr); break; case 'p' | BYREF: case 's' | BYREF: cptr=amx_Address(amx,params[idx+4]); amx_SetString(cptr,(char *)ps[idx].v.ptr,ps[idx].type==('p'|BYREF),sizeof(TCHAR)>1,UNLIMITED); free(ps[idx].v.ptr); break; case 'i': case 'u': case 'f': assert(ps[idx].range==1); break; case 'i' | BYREF: case 'u' | BYREF: case 'f' | BYREF: cptr=amx_Address(amx,params[idx+4]); if (ps[idx].range==1) { /* modify directly in the AMX (no memory block was allocated */ switch (ps[idx].size) { case 8: *cptr= (ps[idx].type==('i' | BYREF)) ? (long)((signed char)*cptr) : (*cptr & 0xff); break; case 16: *cptr= (ps[idx].type==('i' | BYREF)) ? (long)((short)*cptr) : (*cptr & 0xffff); break; } /* switch */ } else { int i; for (i=0; i<ps[idx].range; i++) { switch (ps[idx].size) { case 8: *cptr= (ps[idx].type==('i' | BYREF)) ? ((signed char*)ps[idx].v.ptr)[i] : ((unsigned char*)ps[idx].v.ptr)[i]; break; case 16: *cptr= (ps[idx].type==('i' | BYREF)) ? ((short*)ps[idx].v.ptr)[i] : ((unsigned short*)ps[idx].v.ptr)[i]; break; default: *cptr= (ps[idx].type==('i' | BYREF)) ? ((long*)ps[idx].v.ptr)[i] : ((unsigned long*)ps[idx].v.ptr)[i]; } /* switch */ } /* for */ free((char *)ps[idx].v.ptr); } /* if */ break; default: assert(0); } /* switch */ } /* for */ return result; } /* bool: libfree(const libname[]="") * When the name is an empty string, this function frees all libraries (for this * abstract machine). The name comparison is case sensitive. * Returns true if one or more libraries were freed. */ static cell AMX_NATIVE_CALL n_libfree(AMX *amx, const cell *params) { const TCHAR *libname; amx_StrParam(amx,params[1],libname); return freelib(&ModRoot,amx,libname) > 0; } #else /* HAVE_DYNCALL_H || WIN32_FFI */ static cell AMX_NATIVE_CALL n_libcall(AMX *amx, const cell *params) { (void)amx; (void)params; return 0; }
cell AMX_NATIVE_CALL amx_DC_CMD(AMX* amx, cell* params) { cell *addr; int len; amx_GetAddr(amx, params[2], &addr); amx_StrLen(addr, &len); if(len>127) len=127; ++len; char cmdtext[128]; amx_GetString(cmdtext, addr, 0, len); cmdtext[0] = '_'; // converting string to lower case int pos=0, cmd_end; do{ ++pos; if(('A' <= cmdtext[pos]) && (cmdtext[pos] <= 'Z')) cmdtext[pos] += ('a'-'A'); else if(cmdtext[pos] == '\0') break; else if(cmdtext[pos] == ' ') { cmd_end = pos; cmdtext[pos++] = '\0'; goto loop1_exit; } }while(1); cmd_end = 0; loop1_exit: // search for command index in all AMX instances int pubidx; cell retval, params_addr; int i; for(i=0; i<=lastAMX; ++i) { if((amx_List[i].amx != NULL) && (amx_FindPublic(amx_List[i].amx, cmdtext, &pubidx) == AMX_ERR_NONE)) { // if current AMX instance has OnPlayerCommandReceived callback - invoke it if(amx_List[i].OPCR != 0x7FFFFFFF) { // restore some symbols in cmdtext cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCR); amx_Release(amx_List[i].amx, params_addr); // if OPCR returned 0 - command execution rejected if(retval == 0) return 1; cmdtext[0] = '_'; // restore AMX-styled command name if(cmd_end>0) // and separate it from parameters (again =/) cmdtext[cmd_end] = ' '; } // remove extra space characters between command name and parameters while(cmdtext[pos] == ' ') pos++; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext+pos, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, pubidx); amx_Release(amx_List[i].amx, params_addr); // if current AMX instance has OnPlayerCommandPerformed callback - invoke it if(amx_List[i].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[i].amx, retval); amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCP); amx_Release(amx_List[i].amx, params_addr); } return 1; } } // if command wasn't found - perhaps this is an alternative command if(Alts_n != 0) { int hash; // remove extra space characters between command name and parameters //logprintf("attempting to find alt %s, len = %d", cmdtext, (cmdtext[pos])?(pos-1):(pos)); Murmur3(cmdtext, (cmdtext[pos])?(pos-1):(pos), &hash); if(cmdtext[pos]) { pos--; while(cmdtext[++pos] == ' '){} } //logprintf((char*)"Murmur3(%s) = 0x%X", cmdtext, hash); boost::unordered_map<int,int>::const_iterator alt; for(i=0; i<=lastAMX; ++i) { if((amx_List[i].amx != NULL) && ((alt = Alts[i].find(hash)) != Alts[i].end())) { pubidx = alt->second; //logprintf("found alt: %s, amx = %d, idx = %d", cmdtext, (int)amx, pubidx); if(amx_List[i].OPCR != 0x7FFFFFFF) { // restore some symbols in cmdtext cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCR); amx_Release(amx_List[i].amx, params_addr); // if OPCR returned 0 - command execution rejected if(retval == 0) return 1; cmdtext[0] = '_'; // restore AMX-styled command name if(cmd_end>0) // and separate it from parameters (again =/) cmdtext[cmd_end] = ' '; } // remove extra space characters between command name and parameters while(cmdtext[pos] == ' ') pos++; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext+pos, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, pubidx); amx_Release(amx_List[i].amx, params_addr); // if current AMX instance has OnPlayerCommandPerformed callback - invoke it if(amx_List[i].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[i].amx, retval); amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCP); amx_Release(amx_List[i].amx, params_addr); } return 1; } } } // if command not found - call OnPlayerCommandPerformed callback in gamemode AMX (success = -1) if(amx_List[0].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[0].amx, -1); amx_PushString(amx_List[0].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[0].amx, params[1]); amx_Exec(amx_List[0].amx, &retval, amx_List[0].OPCP); amx_Release(amx_List[0].amx, params_addr); } return 1; }
int Invoke::callNative(const PAWN::Native * native, ...) { if (amx_list.empty() || amx_map.find(native->name) == amx_map.end()) { return 0; } unsigned int amx_addr = amx_map[native->name], count = strlen(native->data), variables = 0; cell * params = new cell[count + 1], * physAddr[6]; params[0] = count * sizeof(cell); va_list input; va_start(input, native); for (unsigned int i = 0; i < count; ++i) { switch (native->data[i]) { case 'd': case 'i': { params[i + 1] = va_arg(input, int); } break; case 'f': { float value = (float)va_arg(input, double); params[i + 1] = amx_ftoc(value); } break; case 's': { char * string = va_arg(input, char *); amx_Allot(amx_list.front(), strlen(string) + 1, ¶ms[i + 1], &physAddr[variables++]); amx_SetString(physAddr[variables - 1], string, 0, 0, strlen(string) + 1); } break; case 'v': { va_arg(input, void *); amx_Allot(amx_list.front(), 1, ¶ms[i + 1], &physAddr[variables++]); } break; case 'p': { va_arg(input, void *); int size = va_arg(input, int); amx_Allot(amx_list.front(), size, ¶ms[++i], &physAddr[variables++]); params[i + 1] = size; } break; } } va_end(input); amx_Function_t amx_Function = (amx_Function_t)amx_addr; int value = amx_Function(amx_list.front(), params); if (variables) { variables = 0; va_start(input, native); for (unsigned int i = 0; i < count; ++i) { switch (native->data[i]) { case 's': { amx_Release(amx_list.front(), params[i + 1]); } break; case 'v': { unsigned int * value = va_arg(input, unsigned int *), * returnValue = (unsigned int *)physAddr[variables++]; * value = * returnValue; amx_Release(amx_list.front(), params[i + 1]); } break; case 'p': { char * text = va_arg(input, char *); int size = va_arg(input, int); amx_GetString(text, physAddr[variables++], 0, size); amx_Release(amx_list.front(), params[++i]); } break; default: { va_arg(input, void *); } break; } } va_end(input); } delete [] params; return value; }
void FakeAmxGet(cell address, char *value, size_t size) { cell *ptr = reinterpret_cast<cell*>(::fakeAmx.data + address); amx_GetString(value, ptr, 0, size); }