mirror of
https://github.com/rehlds/metamod-r.git
synced 2025-04-02 15:49:01 +03:00
193 lines
5.3 KiB
C++
193 lines
5.3 KiB
C++
#include "precompiled.h"
|
|
|
|
mBOOL dlclose_handle_invalid;
|
|
|
|
// To keep the rest of the sources clean and keep not only OS but also
|
|
// compiler dependant differences in this file, we define a local function
|
|
// to set the new handler.
|
|
void mm_set_new_handler()
|
|
{
|
|
#if defined(_MSC_VER) && (_MSC_VER < 1300)
|
|
_set_new_handler(meta_new_handler);
|
|
#else
|
|
std::set_new_handler(meta_new_handler);
|
|
#endif
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
// Since windows doesn't provide a verison of strtok_r(), we include one
|
|
// here. This may or may not operate exactly like strtok_r(), but does
|
|
// what we need it it do.
|
|
char *my_strtok_r(char *s, const char *delim, char **ptrptr)
|
|
{
|
|
char *begin = nullptr;
|
|
char *end = nullptr;
|
|
char *rest = nullptr;
|
|
if (s)
|
|
begin = s;
|
|
else
|
|
begin = *ptrptr;
|
|
if (!begin)
|
|
return nullptr;
|
|
|
|
end = strpbrk(begin, delim);
|
|
if (end)
|
|
{
|
|
*end = '\0';
|
|
rest = end + 1;
|
|
*ptrptr = rest + strspn(rest, delim);
|
|
}
|
|
else
|
|
*ptrptr = nullptr;
|
|
|
|
return begin;
|
|
}
|
|
#endif // _WIN32
|
|
|
|
#ifdef _WIN32
|
|
// Windows doesn't provide a functon analagous to dlerr() that returns a
|
|
// string describing the error, so we include one here, as exampled at:
|
|
// http://msdn.microsoft.com/library/en-us/debug/errors_0sdh.asp
|
|
// except without FORMAT_MESSAGE_ALLOCATE_BUFFER, since we use a local
|
|
// static buffer.
|
|
const char *str_GetLastError()
|
|
{
|
|
static char buf[MAX_STRBUF_LEN];
|
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, MAX_STRBUF_LEN - 1, NULL);
|
|
return buf;
|
|
}
|
|
#endif
|
|
|
|
// Find the filename of the DLL/shared-lib where the given memory location
|
|
// exists.
|
|
#if defined(linux) || defined(__APPLE__)
|
|
// Errno values:
|
|
// - ME_NOTFOUND couldn't find a sharedlib that contains memory location
|
|
const char *DLFNAME(void *memptr)
|
|
{
|
|
Dl_info dli;
|
|
Q_memset(&dli, 0, sizeof(dli));
|
|
if (dladdr(memptr, &dli))
|
|
return dli.dli_fname;
|
|
else
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
}
|
|
#elif defined(_WIN32)
|
|
// Implementation for win32 provided by Jussi Kivilinna <kijuhe00@rhea.otol.fi>:
|
|
//
|
|
// 1. Get memory location info on memptr with VirtualQuery.
|
|
// 2. Check if memory location info is valid and use MBI.AllocationBase
|
|
// as module start point.
|
|
// 3. Get module file name with GetModuleFileName.
|
|
//
|
|
// Simple and should work pretty much same way as 'dladdr' in linux.
|
|
// VirtualQuery and GetModuleFileName work even with win32s.
|
|
//
|
|
// Note that GetModuleFileName returns longfilenames rather than 8.3.
|
|
//
|
|
// Note also, the returned filename is local static storage, and should be
|
|
// copied by caller if it needs to keep it around.
|
|
//
|
|
// Also note, normalize_pathname() should really be done by the caller, but
|
|
// is done here to preserve "const char *" return consistent with linux
|
|
// version.
|
|
//
|
|
// Errno values:
|
|
// - ME_NOTFOUND couldn't find a DLL that contains memory location
|
|
const char *DLFNAME(void *memptr)
|
|
{
|
|
MEMORY_BASIC_INFORMATION MBI;
|
|
static char fname[PATH_MAX];
|
|
|
|
Q_memset(fname, 0, sizeof(fname));
|
|
|
|
if (!VirtualQuery(memptr, &MBI, sizeof(MBI)))
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
if (MBI.State != MEM_COMMIT)
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
if (!MBI.AllocationBase)
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
// MSDN indicates that GetModuleFileName will leave string
|
|
// null-terminated, even if it's truncated because buffer is too small.
|
|
if (!GetModuleFileName((HMODULE)MBI.AllocationBase, fname,
|
|
sizeof(fname)-1))
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
if (!fname[0])
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
normalize_pathname(fname);
|
|
return fname;
|
|
}
|
|
#endif // _WIN32
|
|
|
|
|
|
// Determine whether the given memory location is valid (ie whether we
|
|
// should expect to be able to reference strings or functions at this
|
|
// location without segfaulting).
|
|
#if defined(linux) || defined(__APPLE__)
|
|
// Simulate this with dladdr. I'm not convinced this will be as generally
|
|
// applicable as the native windows routine below, but it should do what
|
|
// we need it for in this particular situation.
|
|
// meta_errno values:
|
|
// - ME_NOTFOUND couldn't find a matching sharedlib for this ptr
|
|
mBOOL IS_VALID_PTR(void *memptr)
|
|
{
|
|
Dl_info dli;
|
|
Q_memset(&dli, 0, sizeof(dli));
|
|
if (dladdr(memptr, &dli))
|
|
return mTRUE;
|
|
else
|
|
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
|
}
|
|
#elif defined(_WIN32)
|
|
// Use the native windows routine IsBadCodePtr.
|
|
// meta_errno values:
|
|
// - ME_BADMEMPTR not a valid memory pointer
|
|
mBOOL IS_VALID_PTR(void *memptr)
|
|
{
|
|
if (IsBadCodePtr((FARPROC) memptr))
|
|
RETURN_ERRNO(mFALSE, ME_BADMEMPTR);
|
|
else
|
|
return mTRUE;
|
|
}
|
|
#endif // _WIN32
|
|
|
|
// This used to be OS-dependent, as it used a SEGV signal handler under
|
|
// linux, but that was removed because (a) it masked legitimate segfaults
|
|
// in plugin commands and produced confusing output ("plugin has been
|
|
// unloaded", when really it segfaultd), and (b) wasn't necessary since
|
|
// IS_VALID_PTR() should cover the situation.
|
|
mBOOL os_safe_call(REG_CMD_FN pfn)
|
|
{
|
|
// try and see if this is a valid memory location
|
|
if (!IS_VALID_PTR((void *)pfn))
|
|
// meta_errno should be already set in is_valid_ptr()
|
|
return mFALSE;
|
|
|
|
pfn();
|
|
return mTRUE;
|
|
}
|
|
|
|
// See comments in osdep.h.
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1300)
|
|
void __cdecl meta_new_handler()
|
|
{
|
|
return;
|
|
}
|
|
#elif defined(_MSC_VER)
|
|
int meta_new_handler(size_t size)
|
|
{
|
|
// This merely because we don't want the program to exit if new()
|
|
// fails..
|
|
return 0;
|
|
}
|
|
#else
|
|
void meta_new_handler()
|
|
{
|
|
return;
|
|
}
|
|
#endif
|