amx_header.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Copyright (C) 2012 Zeex
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the "Software"),
  5. // to deal in the Software without restriction, including without limitation
  6. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  7. // and/or sell copies of the Software, and to permit persons to whom the
  8. // Software is furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  14. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  19. // DEALINGS IN THE SOFTWARE.
  20. #if defined AMX_HEADER_INC
  21. #endinput
  22. #endif
  23. #define AMX_HEADER_INC
  24. #include <a_samp>
  25. #include "amx_memory"
  26. #define AMX_HDR_BYTES (60)
  27. #define AMX_HDR_CELLS (AMX_HDR_BYTES / 4)
  28. enum AMX_HDR {
  29. AMX_HDR_SIZE,
  30. AMX_HDR_MAGIC,
  31. AMX_HDR_FILE_VERSION,
  32. AMX_HDR_AMX_VERSION,
  33. AMX_HDR_FLAGS,
  34. AMX_HDR_DEFSIZE,
  35. AMX_HDR_COD,
  36. AMX_HDR_DAT,
  37. AMX_HDR_HEA,
  38. AMX_HDR_STP,
  39. AMX_HDR_CIP,
  40. AMX_HDR_PUBLICS,
  41. AMX_HDR_NATIVES,
  42. AMX_HDR_LIBRARIES,
  43. AMX_HDR_PUBVARS,
  44. AMX_HDR_TAGS,
  45. AMX_HDR_NAMETABLE
  46. }
  47. const AMX_HDR_OFFSET_SIZE = 0;
  48. const AMX_HDR_OFFSET_MAGIC = 4;
  49. const AMX_HDR_OFFSET_FILE_VERSION = 6;
  50. const AMX_HDR_OFFSET_AMX_VERSION = 7;
  51. const AMX_HDR_OFFSET_FLAGS = 8;
  52. const AMX_HDR_OFFSET_DEFSIZE = 10;
  53. const AMX_HDR_OFFSET_COD = 12;
  54. const AMX_HDR_OFFSET_DAT = 16;
  55. const AMX_HDR_OFFSET_HEA = 20;
  56. const AMX_HDR_OFFSET_STP = 24;
  57. const AMX_HDR_OFFSET_CIP = 28;
  58. const AMX_HDR_OFFSET_PUBLICS = 32;
  59. const AMX_HDR_OFFSET_NATIVES = 36;
  60. const AMX_HDR_OFFSET_LIBRARIES = 40;
  61. const AMX_HDR_OFFSET_PUBVARS = 44;
  62. const AMX_HDR_OFFSET_TAGS = 48;
  63. const AMX_HDR_OFFSET_NAMETABLE = 52;
  64. enum AMX_FUNCSTUBNT {
  65. AMX_FUNCSTUBNT_ADDRESS,
  66. AMX_FUNCSTUBNT_NAMEOFS
  67. }
  68. // Publics
  69. forward GetPublicIndexFromAddress(address);
  70. forward GetPublicIndexFromName(const name[]);
  71. forward bool:GetPublicInfo(index, info[AMX_FUNCSTUBNT]);
  72. forward GetPublicAddressFromName(const name[]);
  73. forward GetPublicAddressFromIndex(index);
  74. forward bool:GetPublicNameFromIndex(index, name[], size = sizeof(name));
  75. forward bool:GetPublicNameFromAddress(address, name[], size = sizeof(name));
  76. forward HookPublic(index, address);
  77. // Natives
  78. forward GetNativeIndexFromAddress(address);
  79. forward GetNativeIndexFromName(const name[]);
  80. forward bool:GetNativeInfo(index, info[AMX_FUNCSTUBNT]);
  81. forward GetNativeAddressFromName(const name[]);
  82. forward GetNativeAddressFromIndex(index);
  83. forward bool:GetNativeNameFromIndex(index, name[], size = sizeof(name));
  84. forward bool:GetNativeNameFromAddress(address, name[], size = sizeof(name));
  85. forward HookNative(index, address);
  86. // Public Variables
  87. forward bool:GetPubVarInfo(index, info[AMX_FUNCSTUBNT]);
  88. forward GetPubVarIndexFromName(const name[]);
  89. forward GetPubVarIndexFromAddress(address);
  90. forward GetPubVarAddressFromName(const name[]);
  91. forward GetPubVarAddressFromIndex(index);
  92. forward bool:GetPubVarNameFromIndex(index, name[], size = sizeof(name));
  93. forward bool:GetPubVarNameFromAddress(address, name[], size = sizeof(name));
  94. // General
  95. forward GetRawAmxHeader(plain_amxhdr[AMX_HDR_CELLS]);
  96. forward GetAmxHeaderNow(amxhdr[AMX_HDR]);
  97. forward GetAmxHeader(amxhdr[AMX_HDR]);
  98. forward GetAmxHeaderComponent(AMX_HDR:comp);
  99. forward PrintAmxHeader();
  100. stock GetRawAmxHeader(plain_amxhdr[AMX_HDR_CELLS]) {
  101. new address;
  102. #emit lctrl 1 // DAT
  103. #emit neg // -DAT
  104. #emit stor.s.pri address
  105. for (new i = 0; i < AMX_HDR_CELLS; i++) {
  106. plain_amxhdr[i] = ReadAmxMemory(address);
  107. address += 4;
  108. }
  109. }
  110. static stock copy_1(&dest, const source[], start) {
  111. #emit load.s.pri source
  112. #emit load.s.alt start
  113. #emit add
  114. #emit load.s.alt dest
  115. #emit movs 1
  116. }
  117. static stock copy_2(&dest, const source[], start) {
  118. #emit load.s.pri source
  119. #emit load.s.alt start
  120. #emit add
  121. #emit load.s.alt dest
  122. #emit movs 2
  123. }
  124. static stock copy_4(&dest, const source[], start) {
  125. #emit load.s.pri source
  126. #emit load.s.alt start
  127. #emit add
  128. #emit load.s.alt dest
  129. #emit movs 4
  130. }
  131. stock GetAmxHeaderNow(amxhdr[AMX_HDR]) {
  132. new plain_amxhdr[AMX_HDR_CELLS];
  133. GetRawAmxHeader(plain_amxhdr);
  134. copy_4(amxhdr[AMX_HDR_SIZE], plain_amxhdr, AMX_HDR_OFFSET_SIZE);
  135. copy_2(amxhdr[AMX_HDR_MAGIC], plain_amxhdr, AMX_HDR_OFFSET_MAGIC);
  136. copy_1(amxhdr[AMX_HDR_FILE_VERSION], plain_amxhdr, AMX_HDR_OFFSET_FILE_VERSION);
  137. copy_1(amxhdr[AMX_HDR_AMX_VERSION], plain_amxhdr, AMX_HDR_OFFSET_AMX_VERSION);
  138. copy_2(amxhdr[AMX_HDR_FLAGS], plain_amxhdr, AMX_HDR_OFFSET_FLAGS);
  139. copy_2(amxhdr[AMX_HDR_DEFSIZE], plain_amxhdr, AMX_HDR_OFFSET_DEFSIZE);
  140. copy_4(amxhdr[AMX_HDR_COD], plain_amxhdr, AMX_HDR_OFFSET_COD);
  141. copy_4(amxhdr[AMX_HDR_DAT], plain_amxhdr, AMX_HDR_OFFSET_DAT);
  142. copy_4(amxhdr[AMX_HDR_HEA], plain_amxhdr, AMX_HDR_OFFSET_HEA);
  143. copy_4(amxhdr[AMX_HDR_STP], plain_amxhdr, AMX_HDR_OFFSET_STP);
  144. copy_4(amxhdr[AMX_HDR_CIP], plain_amxhdr, AMX_HDR_OFFSET_CIP);
  145. copy_4(amxhdr[AMX_HDR_PUBLICS], plain_amxhdr, AMX_HDR_OFFSET_PUBLICS);
  146. copy_4(amxhdr[AMX_HDR_NATIVES], plain_amxhdr, AMX_HDR_OFFSET_NATIVES);
  147. copy_4(amxhdr[AMX_HDR_LIBRARIES], plain_amxhdr, AMX_HDR_OFFSET_LIBRARIES);
  148. copy_4(amxhdr[AMX_HDR_PUBVARS], plain_amxhdr, AMX_HDR_OFFSET_PUBVARS);
  149. copy_4(amxhdr[AMX_HDR_TAGS], plain_amxhdr, AMX_HDR_OFFSET_TAGS);
  150. copy_4(amxhdr[AMX_HDR_NAMETABLE], plain_amxhdr, AMX_HDR_OFFSET_NAMETABLE);
  151. }
  152. static gHdr[AMX_HDR];
  153. static bool:gInitialized = false;
  154. stock ResetStaticAmxHeader() {
  155. GetAmxHeaderNow(gHdr);
  156. gInitialized = true;
  157. }
  158. stock GetAmxHeader(amxhdr[AMX_HDR]) {
  159. if (!gInitialized) {
  160. ResetStaticAmxHeader();
  161. }
  162. amxhdr = gHdr;
  163. }
  164. stock GetAmxHeaderComponent(AMX_HDR:comp) {
  165. if (!gInitialized) {
  166. ResetStaticAmxHeader();
  167. }
  168. return gHdr[comp];
  169. }
  170. stock PrintAmxHeader() {
  171. if (!gInitialized) {
  172. ResetStaticAmxHeader();
  173. }
  174. printf("------------------------");
  175. printf("AMX Header:");
  176. printf("------------------------");
  177. printf("size %d", gHdr[AMX_HDR_SIZE]);
  178. printf("magic %x", gHdr[AMX_HDR_MAGIC]);
  179. printf("file_version %d", gHdr[AMX_HDR_FILE_VERSION]);
  180. printf("amx_version %d", gHdr[AMX_HDR_AMX_VERSION]);
  181. printf("flags %d", gHdr[AMX_HDR_FLAGS]);
  182. printf("defsize %d", gHdr[AMX_HDR_DEFSIZE]);
  183. printf("cod 0x%08x", gHdr[AMX_HDR_COD]);
  184. printf("dat 0x%08x", gHdr[AMX_HDR_DAT]);
  185. printf("hea 0x%08x", gHdr[AMX_HDR_HEA]);
  186. printf("stp 0x%08x", gHdr[AMX_HDR_STP]);
  187. printf("cip 0x%08x", gHdr[AMX_HDR_CIP]);
  188. printf("publics 0x%08x", gHdr[AMX_HDR_PUBLICS]);
  189. printf("natives 0x%08x", gHdr[AMX_HDR_NATIVES]);
  190. printf("libraries 0x%08x", gHdr[AMX_HDR_LIBRARIES]);
  191. printf("pubvars 0x%08x", gHdr[AMX_HDR_PUBVARS]);
  192. printf("tags 0x%08x", gHdr[AMX_HDR_TAGS]);
  193. printf("nametable 0x%08x", gHdr[AMX_HDR_NAMETABLE]);
  194. printf("------------------------");
  195. }
  196. // Compares a string stored in the name table starting at "s1" (packed)
  197. // with another string "s2" (unpacked).
  198. static stock NtCompare(s1, const s2[]) {
  199. new index;
  200. new c1, c2;
  201. new diff;
  202. do {
  203. c1 = ReadAmxMemory(s1++) & 0xFF;
  204. c2 = s2[index++];
  205. diff = c1 - c2;
  206. if (diff != 0) {
  207. break;
  208. }
  209. } while (!(c1 & c2 == 0));
  210. return diff;
  211. }
  212. // Copies a name from the name table to a string. Returns the number
  213. // of characters copied.
  214. static stock NtCopy(src, dest[], size = sizeof(dest)) {
  215. new i = 0;
  216. new c;
  217. do {
  218. c = ReadAmxMemory(src++) & 0xFF;
  219. dest[i++] = c;
  220. } while (c != '\0' && i <= size);
  221. dest[i] = '\0'; // terminator
  222. return i;
  223. }
  224. stock GetNumPublics(amxhdr[AMX_HDR]) {
  225. new num_publics = (amxhdr[AMX_HDR_NATIVES] - amxhdr[AMX_HDR_PUBLICS]) / amxhdr[AMX_HDR_DEFSIZE];
  226. return num_publics;
  227. }
  228. stock GetPublicIndexFromAddress(address) {
  229. new amxhdr[AMX_HDR];
  230. GetAmxHeader(amxhdr);
  231. new num_publics = GetNumPublics(amxhdr);
  232. new off = amxhdr[AMX_HDR_PUBLICS] - amxhdr[AMX_HDR_DAT];
  233. // Linear search
  234. for (new i = 0; i < num_publics; i++) {
  235. if (ReadAmxMemory(off) == address) {
  236. return i;
  237. }
  238. off += amxhdr[AMX_HDR_DEFSIZE];
  239. }
  240. return -1;
  241. }
  242. stock bool:GetPublicInfo(index, info[AMX_FUNCSTUBNT]) {
  243. new amxhdr[AMX_HDR];
  244. GetAmxHeader(amxhdr);
  245. new num_publics = GetNumPublics(amxhdr);
  246. if (index < 0 || index >= num_publics) {
  247. return false;
  248. }
  249. new off = amxhdr[AMX_HDR_PUBLICS] - amxhdr[AMX_HDR_DAT] + index * amxhdr[AMX_HDR_DEFSIZE];
  250. info[AMX_FUNCSTUBNT_ADDRESS] = ReadAmxMemory(off);
  251. info[AMX_FUNCSTUBNT_NAMEOFS] = ReadAmxMemory(off + 4);
  252. return true;
  253. }
  254. stock GetPublicIndexFromName(const name[]) {
  255. new amxhdr[AMX_HDR];
  256. GetAmxHeader(amxhdr);
  257. new num_publics = GetNumPublics(amxhdr);
  258. // Binary search
  259. new first = 0;
  260. new last = num_publics - 1;
  261. new mid;
  262. while (first <= last) {
  263. mid = (first + last) / 2;
  264. new off = amxhdr[AMX_HDR_PUBLICS] - amxhdr[AMX_HDR_DAT] + mid * amxhdr[AMX_HDR_DEFSIZE];
  265. new nameofs = ReadAmxMemory(off + 4) - amxhdr[AMX_HDR_DAT];
  266. new diff = NtCompare(nameofs, name);
  267. if (diff < 0) {
  268. first = mid + 1;
  269. } else if (diff > 0) {
  270. last = mid - 1;
  271. } else {
  272. return mid;
  273. }
  274. }
  275. return -1;
  276. }
  277. stock GetPublicAddressFromIndex(index) {
  278. new info[AMX_FUNCSTUBNT];
  279. GetPublicInfo(index, info);
  280. return info[AMX_FUNCSTUBNT_ADDRESS];
  281. }
  282. stock GetPublicAddressFromName(const name[]) {
  283. return GetPublicAddressFromIndex(GetPublicIndexFromName(name));
  284. }
  285. stock bool:GetPublicNameFromIndex(index, name[], size = sizeof(name)) {
  286. new info[AMX_FUNCSTUBNT];
  287. if (!GetPublicInfo(index, info)) {
  288. return false;
  289. }
  290. return (NtCopy(info[AMX_FUNCSTUBNT_NAMEOFS]
  291. - GetAmxHeaderComponent(AMX_HDR_DAT), name, size) > 0);
  292. }
  293. stock bool:GetPublicNameFromAddress(address, name[], size = sizeof(name)) {
  294. return GetPublicNameFromIndex(GetPublicIndexFromAddress(address), name, size);
  295. }
  296. stock HookPublic(index, address) {
  297. new amxhdr[AMX_HDR];
  298. GetAmxHeader(amxhdr);
  299. new num_publics = GetNumPublics(amxhdr);
  300. if (index < 0 || index >= num_publics) {
  301. return 0;
  302. }
  303. new off = amxhdr[AMX_HDR_PUBLICS] - amxhdr[AMX_HDR_DAT] + index * amxhdr[AMX_HDR_DEFSIZE];
  304. new old_address = ReadAmxMemory(off);
  305. WriteAmxMemory(off, address);
  306. return old_address;
  307. }
  308. stock GetNumNatives(amxhdr[AMX_HDR]) {
  309. return (amxhdr[AMX_HDR_LIBRARIES] - amxhdr[AMX_HDR_NATIVES]) / amxhdr[AMX_HDR_DEFSIZE];
  310. }
  311. stock GetNativeIndexFromAddress(address) {
  312. new amxhdr[AMX_HDR];
  313. GetAmxHeader(amxhdr);
  314. new num_natives = GetNumNatives(amxhdr);
  315. new off = amxhdr[AMX_HDR_NATIVES] - amxhdr[AMX_HDR_DAT];
  316. // Linear search
  317. for (new i = 0; i < num_natives; i++) {
  318. if (ReadAmxMemory(off) == address) {
  319. return i;
  320. }
  321. off += amxhdr[AMX_HDR_DEFSIZE];
  322. }
  323. return -1;
  324. }
  325. stock bool:GetNativeInfo(index, info[AMX_FUNCSTUBNT]) {
  326. new amxhdr[AMX_HDR];
  327. GetAmxHeader(amxhdr);
  328. // For when "index" is not valid
  329. info[AMX_FUNCSTUBNT_ADDRESS] = -1;
  330. new num_natives = GetNumNatives(amxhdr);
  331. if (index < 0 || index >= num_natives) {
  332. return false;
  333. }
  334. new off = amxhdr[AMX_HDR_NATIVES] - amxhdr[AMX_HDR_DAT] + index * amxhdr[AMX_HDR_DEFSIZE];
  335. info[AMX_FUNCSTUBNT_ADDRESS] = ReadAmxMemory(off);
  336. info[AMX_FUNCSTUBNT_NAMEOFS] = ReadAmxMemory(off + 4);
  337. return true;
  338. }
  339. stock GetNativeIndexFromName(const name[]) {
  340. new amxhdr[AMX_HDR];
  341. GetAmxHeader(amxhdr);
  342. new num_natives = GetNumNatives(amxhdr);
  343. new off = amxhdr[AMX_HDR_NATIVES] - amxhdr[AMX_HDR_DAT];
  344. // Linear search
  345. for (new i = 0; i < num_natives; i++) {
  346. new nameofs = ReadAmxMemory(off + 4) - amxhdr[AMX_HDR_DAT];
  347. new diff = NtCompare(nameofs, name);
  348. if (diff == 0) {
  349. return i;
  350. }
  351. off += amxhdr[AMX_HDR_DEFSIZE];
  352. }
  353. return -1;
  354. }
  355. stock GetNativeAddressFromIndex(index) {
  356. new info[AMX_FUNCSTUBNT];
  357. GetNativeInfo(index, info);
  358. return info[AMX_FUNCSTUBNT_ADDRESS];
  359. }
  360. stock GetNativeAddressFromName(const name[]) {
  361. return GetNativeAddressFromIndex(GetNativeIndexFromName(name));
  362. }
  363. stock bool:GetNativeNameFromIndex(index, name[], size = sizeof(name)) {
  364. new info[AMX_FUNCSTUBNT];
  365. if (!GetNativeInfo(index, info)) {
  366. return false;
  367. }
  368. return (NtCopy(info[AMX_FUNCSTUBNT_NAMEOFS]
  369. - GetAmxHeaderComponent(AMX_HDR_DAT), name, size) > 0);
  370. }
  371. stock bool:GetNativeNameFromAddress(address, name[], size = sizeof(name)) {
  372. return GetNativeNameFromIndex(GetNativeIndexFromAddress(address), name, size);
  373. }
  374. stock HookNative(index, address) {
  375. new amxhdr[AMX_HDR];
  376. GetAmxHeader(amxhdr);
  377. new num_natives = GetNumNatives(amxhdr);
  378. if (index < 0 || index >= num_natives) {
  379. return 0;
  380. }
  381. new off = amxhdr[AMX_HDR_NATIVES] - amxhdr[AMX_HDR_DAT] + index * amxhdr[AMX_HDR_DEFSIZE];
  382. new old_address = ReadAmxMemory(off);
  383. WriteAmxMemory(off, address);
  384. return old_address;
  385. }
  386. stock GetNumPubVars(amxhdr[AMX_HDR]) {
  387. return (amxhdr[AMX_HDR_TAGS] - amxhdr[AMX_HDR_PUBVARS]) / amxhdr[AMX_HDR_DEFSIZE];
  388. }
  389. stock bool:GetPubVarInfo(index, info[AMX_FUNCSTUBNT]) {
  390. new amxhdr[AMX_HDR];
  391. GetAmxHeader(amxhdr);
  392. new num_pubvars = GetNumPubVars(amxhdr);
  393. if (index < 0 || index >= num_pubvars) {
  394. return false;
  395. }
  396. new off = amxhdr[AMX_HDR_PUBVARS] - amxhdr[AMX_HDR_DAT] + index * amxhdr[AMX_HDR_DEFSIZE];
  397. info[AMX_FUNCSTUBNT_ADDRESS] = ReadAmxMemory(off);
  398. info[AMX_FUNCSTUBNT_NAMEOFS] = ReadAmxMemory(off + 4);
  399. return true;
  400. }
  401. stock GetPubVarIndexFromName(const name[]) {
  402. new amxhdr[AMX_HDR];
  403. GetAmxHeader(amxhdr);
  404. new num_pubvars = GetNumPubVars(amxhdr);
  405. // Binary search
  406. new first = 0;
  407. new last = num_pubvars - 1;
  408. new mid;
  409. while (first <= last) {
  410. mid = (first + last) / 2;
  411. new off = amxhdr[AMX_HDR_PUBVARS] - amxhdr[AMX_HDR_DAT] + mid * amxhdr[AMX_HDR_DEFSIZE];
  412. new nameofs = ReadAmxMemory(off + 4) - amxhdr[AMX_HDR_DAT];
  413. new diff = NtCompare(nameofs, name);
  414. if (diff < 0) {
  415. first = mid + 1;
  416. } else if (diff > 0) {
  417. last = mid - 1;
  418. } else {
  419. return mid;
  420. }
  421. }
  422. return -1;
  423. }
  424. stock GetPubVarIndexFromAddress(address) {
  425. new amxhdr[AMX_HDR];
  426. GetAmxHeader(amxhdr);
  427. new num_pubvars = GetNumPubVars(amxhdr);
  428. new off = amxhdr[AMX_HDR_PUBVARS] - amxhdr[AMX_HDR_DAT];
  429. // Linear search
  430. for (new i = 0; i < num_pubvars; i++) {
  431. if (ReadAmxMemory(off) == address) {
  432. return i;
  433. }
  434. off += amxhdr[AMX_HDR_DEFSIZE];
  435. }
  436. return -1;
  437. }
  438. stock GetPubVarAddressFromIndex(index) {
  439. new info[AMX_FUNCSTUBNT];
  440. GetPubVarInfo(index, info);
  441. return info[AMX_FUNCSTUBNT_ADDRESS];
  442. }
  443. stock GetPubVarAddressFromName(const name[]) {
  444. return GetPubVarAddressFromIndex(GetPubVarIndexFromName(name));
  445. }
  446. stock bool:GetPubVarNameFromIndex(index, name[], size = sizeof(name)) {
  447. new info[AMX_FUNCSTUBNT];
  448. if (!GetPubVarInfo(index, info)) {
  449. return false;
  450. }
  451. return (NtCopy(info[AMX_FUNCSTUBNT_NAMEOFS]
  452. - GetAmxHeaderComponent(AMX_HDR_DAT), name, size) > 0);
  453. }
  454. stock bool:GetPubVarNameFromAddress(address, name[], size = sizeof(name)) {
  455. return GetPubVarNameFromIndex(GetPubVarIndexFromAddress(address), name, size);
  456. }