2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2025-04-02 15:49:01 +03:00
metamod-r/metamod/src/osdep.cpp
2016-07-26 15:26:12 +03:00

217 lines
6.9 KiB
C++

// vi: set ts=4 sw=4 :
// vim: set tw=75 :
// osdep.cpp - routines for operating system differences
/*
* Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
*
* This file is part of Metamod.
*
* Metamod is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* Metamod is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Metamod; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game g_engine ("HL
* g_engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL g_engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#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( void )
{
#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=NULL;
char *end=NULL;
char *rest=NULL;
if(s)
begin=s;
else
begin=*ptrptr;
if(!begin)
return(NULL);
end=strpbrk(begin, delim);
if(end) {
*end='\0';
rest=end+1;
*ptrptr=rest+strspn(rest, delim);
}
else
*ptrptr=NULL;
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(void) {
static char buf[MAX_STRBUF_LEN];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //! Default language
(LPTSTR) &buf, MAX_STRBUF_LEN-1, NULL);
return(buf);
}
#endif /* _WIN32 */
// 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;
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];
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;
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(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 1300))
void MM_CDECL meta_new_handler(void) {
// This merely because we don't want the program to exit if new()
// fails..
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);
}
#endif /* _MSC_VER */