Przeglądaj źródła

Add Windows support

nosoop 3 lat temu
rodzic
commit
1a732dabe0
2 zmienionych plików z 53 dodań i 11 usunięć
  1. 4 1
      AMBuildScript
  2. 49 10
      mmsplugin.cpp

+ 4 - 1
AMBuildScript

@@ -275,7 +275,10 @@ class MMSConfig(object):
         '-lc++',
         '-mmacosx-version-min=10.9',
       ]
-    # elif builder.target.platform == 'windows': # todo: implement MSVC support
+    elif builder.target.platform == 'windows':
+      cxx.defines += [
+        'WINDOWS',
+      ]
 
   def HL2Compiler(self, context, sdk, arch):
     compiler = context.cxx.clone()

+ 49 - 10
mmsplugin.cpp

@@ -9,13 +9,18 @@
 #include <stdio.h>
 #include "mmsplugin.h"
 
-#include <fcntl.h>
-#include <gelf.h>
 #include <utlmap.h>
 #include <utlstring.h>
 #include <KeyValues.h>
 #include <filesystem.h>
 
+#if WINDOWS
+#include <windows.h>
+#elif _LINUX
+#include <fcntl.h>
+#include <gelf.h>
+#endif
+
 SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
 SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, char const *, char const *, char const *, char const *, bool, bool);
 
@@ -74,6 +79,26 @@ typedef bool (__cdecl *CEconItemAttributeInitFromKV_fn)(CEconItemAttributeDefini
 #endif
 CEconItemAttributeInitFromKV_fn fnItemAttributeInitFromKV = nullptr;
 
+uintptr_t FindPattern(uintptr_t start, uintptr_t end, const char* pattern, size_t length) {
+	uintptr_t ptr = start;
+	bool f;
+	while (ptr < end - length) {
+		f = true;
+		const char* cur = reinterpret_cast<char*>(ptr);
+		for (register size_t i = 0; i < length; i++) {
+			if (pattern[i] != '\x2A' && pattern[i] != cur[i]) {
+				f = false;
+				break;
+			}
+		}
+		if (f) {
+			return ptr;
+		}
+		ptr++;
+	}
+	return 0;
+}
+
 bool DynSchema::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
 {
 	PLUGIN_SAVEVARS();
@@ -86,20 +111,33 @@ bool DynSchema::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, boo
 
 	// get the base address of the server
 	// TODO windows support
+#if WINDOWS
+	MEMORY_BASIC_INFORMATION info;
+	if (!VirtualQuery(server, &info, sizeof(MEMORY_BASIC_INFORMATION))) {
+		return false;
+	}
+	uintptr_t base = reinterpret_cast<uintptr_t>(info.AllocationBase);
+	IMAGE_DOS_HEADER *dos = reinterpret_cast<IMAGE_DOS_HEADER *>(base);
+	IMAGE_NT_HEADERS *pe = reinterpret_cast<IMAGE_NT_HEADERS *>(base + dos->e_lfanew);
+	IMAGE_OPTIONAL_HEADER *opt = &pe->OptionalHeader;
+	size_t size = opt->SizeOfImage;
+	
+	fnGetEconItemSchema = (GetEconItemSchemaFn_t*) (FindPattern(base, base + size, "\xE8\x2A\x2A\x2A\x2A\x83\xC0\x04\xC3", 9));
+	fnItemAttributeInitFromKV = (CEconItemAttributeInitFromKV_fn) (FindPattern(base, base + size, "\x55\x8B\xEC\x53\x8B\x5D\x08\x56\x8B\xF1\x8B\xCB\x57\xE8\x2A\x2A\x2A\x2A", 18));
+#elif _LINUX
 	Dl_info info;
 	if (!dladdr(server, &info)) {
 		return false;
 	}
 	
 	// locate symbols within our server binary
-	Elf_Scn     *scn = NULL;
-	GElf_Shdr   shdr;
-
 	elf_version(EV_CURRENT);
 
 	int fd = open(info.dli_fname, O_RDONLY);
 	Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
 
+	Elf_Scn *scn = NULL;
+	GElf_Shdr shdr;
 	while ((scn = elf_nextscn(elf, scn)) != NULL) {
 		gelf_getshdr(scn, &shdr);
 		if (shdr.sh_type == SHT_SYMTAB) {
@@ -111,9 +149,9 @@ bool DynSchema::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, boo
 	size_t count = shdr.sh_size / shdr.sh_entsize;
 
 	/* print the symbol names */
-	for (size_t ii = 0; ii < count; ++ii) {
+	for (size_t i = 0; i < count; ++i) {
 		GElf_Sym sym;
-		gelf_getsym(data, ii, &sym);
+		gelf_getsym(data, i, &sym);
 		
 		const char *symname = elf_strptr(elf, shdr.sh_link, sym.st_name);
 		if (!strcmp(symname,
@@ -125,9 +163,10 @@ bool DynSchema::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, boo
 	}
 	elf_end(elf);
 	close(fd);
+#endif
 	
 	if (!fnItemAttributeInitFromKV || !fnGetEconItemSchema) {
-		META_CONPRINTF("Failed to get either GEconItemSchema or BInitFromKeyValues\n");
+		META_CONPRINTF("Failed to get GEIS or BIFKV\n");
 		return false;
 	}
 	
@@ -188,7 +227,7 @@ bool DynSchema::Hook_LevelInitPost(const char *pMapName, char const *pMapEntitie
 		}
 		META_CONPRINTF("Successfully injected custom schema %s\n", buffer);
 	} else {
-		META_CONPRINTF("Failed to locate not inject custom schema %s\n", buffer);
+		META_CONPRINTF("Failed to inject custom schema %s\n", buffer);
 	}
 	
 	return true;
@@ -213,7 +252,7 @@ const char *DynSchema::GetLicense() {
 }
 
 const char *DynSchema::GetVersion() {
-	return "1.0.0.0";
+	return "1.0.1";
 }
 
 const char *DynSchema::GetDate() {