tinymux/mux/modules/engine/log.cpp

1889 lines
42 KiB
C++
Raw Permalink Normal View History

/*! \file log.cpp
* \brief Logging routines.
*
*/
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"
// Factory class declarations — internal to engine.so (no DCL_EXPORT).
//
class CLogFactory : public mux_IClassFactory
{
public:
virtual MUX_RESULT QueryInterface(MUX_IID iid, void **ppv);
virtual uint32_t AddRef(void);
virtual uint32_t Release(void);
virtual MUX_RESULT CreateInstance(mux_IUnknown *pUnknownOuter, MUX_IID iid, void **ppv);
virtual MUX_RESULT LockServer(bool bLock);
CLogFactory(void);
virtual ~CLogFactory();
private:
uint32_t m_cRef;
};
class CLogPSFactory : public mux_IPSFactoryBuffer, public mux_IClassFactory
{
public:
virtual MUX_RESULT QueryInterface(MUX_IID iid, void **ppv);
virtual uint32_t AddRef(void);
virtual uint32_t Release(void);
virtual MUX_RESULT CreateProxy(mux_IUnknown *pUnknownOuter, MUX_IID riid, mux_IRpcProxyBuffer **ppProxy, void **ppv);
virtual MUX_RESULT CreateStub(MUX_IID riid, mux_IUnknown *pUnknownOuter, mux_IRpcStubBuffer **ppStub);
virtual MUX_RESULT CreateInstance(mux_IUnknown *pUnknownOuter, MUX_IID iid, void **ppv);
virtual MUX_RESULT LockServer(bool bLock);
CLogPSFactory(void);
virtual ~CLogPSFactory();
private:
uint32_t m_cRef;
};
NAMETAB logdata_nametab[] =
{
{T("flags"), 1, 0, LOGOPT_FLAGS},
{T("location"), 1, 0, LOGOPT_LOC},
{T("owner"), 1, 0, LOGOPT_OWNER},
{T("timestamp"), 1, 0, LOGOPT_TIMESTAMP},
{ nullptr, 0, 0, 0}
};
NAMETAB logoptions_nametab[] =
{
{T("accounting"), 2, 0, LOG_ACCOUNTING},
{T("all_commands"), 2, 0, LOG_ALLCOMMANDS},
{T("bad_commands"), 2, 0, LOG_BADCOMMANDS},
{T("buffer_alloc"), 3, 0, LOG_ALLOCATE},
{T("bugs"), 3, 0, LOG_BUGS},
{T("checkpoints"), 2, 0, LOG_DBSAVES},
{T("config_changes"), 2, 0, LOG_CONFIGMODS},
{T("create"), 2, 0, LOG_PCREATES},
{T("debug"), 1, 0, LOG_DEBUG},
{T("killing"), 1, 0, LOG_KILLS},
{T("logins"), 1, 0, LOG_LOGIN},
{T("network"), 1, 0, LOG_NET},
{T("problems"), 1, 0, LOG_PROBLEMS},
{T("security"), 2, 0, LOG_SECURITY},
{T("shouts"), 2, 0, LOG_SHOUTS},
{T("startup"), 2, 0, LOG_STARTUP},
{T("suspect"), 2, 0, LOG_SUSPECTCMDS},
{T("time_usage"), 1, 0, LOG_TIMEUSE},
{T("wizard"), 1, 0, LOG_WIZARD},
{ nullptr, 0, 0, 0}
};
/* ---------------------------------------------------------------------------
* start_log: see if it is OK to log something, and if so, start writing the
* log entry.
*/
bool start_log(const UTF8 * primary, const UTF8 * secondary)
{
mudstate.logging++;
if ( 1 <= mudstate.logging
&& mudstate.logging <= 2)
{
if (!mudstate.bStandAlone)
{
// Format the timestamp.
//
UTF8 buffer[256];
buffer[0] = '\0';
if (mudconf.log_info & LOGOPT_TIMESTAMP)
{
CLinearTimeAbsolute ltaNow;
ltaNow.GetLocal();
FIELDEDTIME ft;
ltaNow.ReturnFields(&ft);
mux_sprintf(buffer, sizeof(buffer),
T("%d.%02d%02d:%02d%02d%02d "), ft.iYear, ft.iMonth,
ft.iDayOfMonth, ft.iHour, ft.iMinute, ft.iSecond);
}
// Write the header to the log.
//
if ( secondary
&& *secondary)
{
Log.tinyprintf(T("%s%s %3s/%-5s: "), buffer, mudconf.mud_name,
primary, secondary);
}
else
{
Log.tinyprintf(T("%s%s %-9s: "), buffer, mudconf.mud_name,
primary);
}
}
// If a recursive call, log it and return indicating no log.
//
if (mudstate.logging == 1)
{
return true;
}
Log.WriteString(T("Recursive logging request." ENDLINE));
}
mudstate.logging--;
return false;
}
/* ---------------------------------------------------------------------------
* end_log: Finish up writing a log entry
*/
void end_log(void)
{
Log.WriteString( reinterpret_cast<const UTF8 *>(ENDLINE));
Log.Flush();
mudstate.logging--;
}
/* ---------------------------------------------------------------------------
* log_perror: Write perror message to the log
*/
void log_perror(const UTF8 * primary, const UTF8 * secondary,
const UTF8 * extra, const UTF8 * failing_object)
{
start_log(primary, secondary);
if (extra && *extra)
{
log_text(T("("));
log_text(extra);
log_text(T(") "));
}
// <Failing_object text>: <strerror() text>
//
Log.WriteString(failing_object);
Log.WriteString(T(": "));
Log.WriteString(mux_strerror(errno));
#ifndef WIN32
Log.WriteString( reinterpret_cast<const UTF8 *>(ENDLINE));
#endif // !WIN32
Log.Flush();
mudstate.logging--;
}
/* ---------------------------------------------------------------------------
* log_text, log_number: Write text or number to the log file.
*/
void log_text(const UTF8 * text)
{
Log.WriteString(strip_color(text));
}
void log_number(int num)
{
Log.WriteInteger(num);
}
2025-03-24 14:53:29 -06:00
void DCL_CDECL log_printf(const UTF8 * fmt, ...)
{
va_list ap;
va_start(ap, fmt);
UTF8 aTempBuffer[SIZEOF_LOG_BUFFER];
size_t nString = mux_vsnprintf(aTempBuffer, SIZEOF_LOG_BUFFER, fmt, ap);
va_end(ap);
Log.WriteBuffer(nString, aTempBuffer);
}
/* ---------------------------------------------------------------------------
* log_name: write the name, db number, and flags of an object to the log.
* If the object does not own itself, append the name, db number, and flags
* of the owner.
*/
void log_name(dbref target)
{
if (mudstate.bStandAlone)
{
Log.tinyprintf(T("%s(#%d)"), PureName(target), target);
}
else
{
UTF8 *tp;
if (mudconf.log_info & LOGOPT_FLAGS)
{
tp = unparse_object(GOD, target, false);
}
else
{
tp = unparse_object_numonly(target);
}
Log.WriteString(strip_color(tp));
free_lbuf(tp);
if ( (mudconf.log_info & LOGOPT_OWNER)
&& target != Owner(target))
{
if (mudconf.log_info & LOGOPT_FLAGS)
{
tp = unparse_object(GOD, Owner(target), false);
}
else
{
tp = unparse_object_numonly(Owner(target));
}
Log.tinyprintf(T("[%s]"), strip_color(tp));
free_lbuf(tp);
}
}
}
/* ---------------------------------------------------------------------------
* log_name_and_loc: Log both the name and location of an object
*/
void log_name_and_loc(dbref player)
{
log_name(player);
if ( (mudconf.log_info & LOGOPT_LOC)
&& Has_location(player))
{
log_text(T(" in "));
log_name(Location(player));
}
return;
}
static const UTF8 *OBJTYP(dbref thing)
{
if (!Good_dbref(thing))
{
return T("??OUT-OF-RANGE??");
}
switch (Typeof(thing))
{
case TYPE_PLAYER:
return T("PLAYER");
case TYPE_THING:
return T("THING");
case TYPE_ROOM:
return T("ROOM");
case TYPE_EXIT:
return T("EXIT");
case TYPE_GARBAGE:
return T("GARBAGE");
default:
return T("??ILLEGAL??");
}
}
void log_type_and_name(dbref thing)
{
Log.tinyprintf(T("%s #%d(%s)"), OBJTYP(thing), thing,
Good_obj(thing) ? PureName(thing) : T(""));
return;
}
void do_log
(
dbref executor,
dbref caller,
dbref enactor,
int eval,
int key,
int nargs,
UTF8 *whichlog,
UTF8 *logtext,
const UTF8 *cargs[],
int ncargs
)
{
UNUSED_PARAMETER(caller);
UNUSED_PARAMETER(enactor);
UNUSED_PARAMETER(eval);
UNUSED_PARAMETER(key);
UNUSED_PARAMETER(nargs);
UNUSED_PARAMETER(cargs);
UNUSED_PARAMETER(ncargs);
bool bValid = true;
// Strip the filename of all ANSI.
//
UTF8 *pFilename = strip_color(whichlog);
// Restrict filename to a subdirectory to reduce the possibility
// of a security hole.
//
UTF8 *temp_ptr = reinterpret_cast<UTF8 *>(strrchr( reinterpret_cast<char *>(pFilename), '/'));
if (temp_ptr)
{
pFilename = ++temp_ptr;
}
temp_ptr = reinterpret_cast<UTF8 *>(strrchr( reinterpret_cast<char *>(pFilename), '\\'));
if (temp_ptr)
{
pFilename = ++temp_ptr;
}
// Check for and disallow leading periods, empty strings
// and filenames over 30 characters.
//
size_t n = strlen( reinterpret_cast<char *>(pFilename));
if ( n == 0
|| 30 < n)
{
bValid = false;
}
else
{
unsigned int i;
for (i = 0; i < n; i++)
{
if (!mux_isalnum(pFilename[i]))
{
bValid = false;
break;
}
}
}
LBuf pFullName = LBuf_Src("do_log_filename");
const UTF8 *pMessage = T("");
if (bValid)
{
mux_sprintf(pFullName, LBUF_SIZE, T("logs/M-%s.log"), pFilename);
// Strip the message of all ANSI.
//
pMessage = strip_color(logtext);
// Check for and disallow empty messages.
//
if (pMessage[0] == '\0')
{
bValid = false;
}
}
if (!bValid)
{
notify(executor, M_("Syntax: @log file=message"));
return;
}
FILE *hFile;
if (mux_fopen(&hFile, pFullName, T("r")))
{
mux_fclose(hFile);
if (mux_fopen(&hFile, pFullName, T("a")))
{
// Okay, at this point, the file exists.
//
2009-01-02 09:16:25 -08:00
mux_fprintf(hFile, T("%s" ENDLINE), pMessage);
mux_fclose(hFile);
return;
}
}
notify(executor, M_("Not a valid log file."));
return;
}
2009-02-28 18:09:33 -08:00
CLogFile Log;
void CLogFile::WriteInteger(int iNumber)
{
UTF8 aTempBuffer[I32BUF_SIZE];
size_t nTempBuffer = mux_ltoa(iNumber, aTempBuffer);
WriteBuffer(nTempBuffer, aTempBuffer);
}
void CLogFile::WriteBuffer(size_t nString, const UTF8 * pString)
2009-02-28 18:09:33 -08:00
{
if (!bEnabled)
{
return;
}
#if defined(WINDOWS_THREADS)
EnterCriticalSection(&csLog);
#endif // WINDOWS_THREADS
while (nString > 0)
{
size_t nAvailable = SIZEOF_LOG_BUFFER - m_nBuffer;
if (nAvailable == 0)
{
Flush();
continue;
}
size_t nToMove = nAvailable;
if (nString < nToMove)
{
nToMove = nString;
}
// Move nToMove bytes from pString to aBuffer+nBuffer
//
memcpy(m_aBuffer + m_nBuffer, pString, nToMove);
2009-02-28 18:09:33 -08:00
pString += nToMove;
nString -= nToMove;
m_nBuffer += nToMove;
}
Flush();
#if defined(WINDOWS_THREADS)
LeaveCriticalSection(&csLog);
#endif // WINDOWS_THREADS
}
void CLogFile::WriteString(const UTF8 * pString)
2009-02-28 18:09:33 -08:00
{
size_t nString = strlen( reinterpret_cast<const char *>(pString));
2009-02-28 18:09:33 -08:00
WriteBuffer(nString, pString);
}
void DCL_CDECL CLogFile::tinyprintf(const UTF8 * fmt, ...)
2009-02-28 18:09:33 -08:00
{
va_list ap;
va_start(ap, fmt);
UTF8 aTempBuffer[SIZEOF_LOG_BUFFER];
size_t nString = mux_vsnprintf(aTempBuffer, SIZEOF_LOG_BUFFER, fmt, ap);
va_end(ap);
WriteBuffer(nString, aTempBuffer);
}
static void MakeLogName
(
const UTF8 *pBasename,
const UTF8 *szPrefix,
CLinearTimeAbsolute lta,
UTF8 *szLogName,
size_t nLogName
)
{
UTF8 szTimeStamp[18];
lta.ReturnUniqueString(szTimeStamp, sizeof(szTimeStamp));
if ( pBasename
&& pBasename[0] != '\0')
{
mux_sprintf(szLogName, nLogName, T("%s/%s-%s.log"),
pBasename, szPrefix, szTimeStamp);
2009-02-28 18:09:33 -08:00
}
else
{
mux_sprintf(szLogName, nLogName, T("%s-%s.log"), szPrefix, szTimeStamp);
2009-02-28 18:09:33 -08:00
}
}
bool CLogFile::CreateLogFile(void)
{
CloseLogFile();
m_nSize = 0;
bool bSuccess;
#if defined(WINDOWS_FILES)
2022-03-11 14:36:04 -07:00
size_t file_name_length;
UTF16 *file_name = ConvertFromUTF8ToUTF16(m_szFilename, file_name_length);
if (nullptr == file_name)
2009-02-28 18:09:33 -08:00
{
return false;
}
2022-03-11 14:36:04 -07:00
m_hFile = CreateFile(file_name, GENERIC_READ | GENERIC_WRITE,
2009-02-28 18:09:33 -08:00
FILE_SHARE_READ, 0, CREATE_ALWAYS,
2018-10-03 17:54:51 +00:00
FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
2009-02-28 18:09:33 -08:00
bSuccess = (INVALID_HANDLE_VALUE != m_hFile);
#elif defined(UNIX_FILES)
bSuccess = mux_open(&m_fdFile, m_szFilename,
O_RDWR | O_BINARY | O_CREAT | O_TRUNC);
2009-02-28 18:09:33 -08:00
#endif // UNIX_FILES
return bSuccess;
}
void CLogFile::AppendLogFile(void)
{
CloseLogFile();
bool bSuccess;
#if defined(WINDOWS_FILES)
2022-03-11 14:36:04 -07:00
size_t file_name_length;
UTF16 *file_name = ConvertFromUTF8ToUTF16(m_szFilename, file_name_length);
if (nullptr == file_name)
2009-02-28 18:09:33 -08:00
{
return;
}
2022-03-11 14:36:04 -07:00
m_hFile = CreateFile(file_name, GENERIC_READ | GENERIC_WRITE,
2009-02-28 18:09:33 -08:00
FILE_SHARE_READ, 0, OPEN_ALWAYS,
2018-10-03 17:54:51 +00:00
FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
2009-02-28 18:09:33 -08:00
bSuccess = (INVALID_HANDLE_VALUE != m_hFile);
#elif defined(UNIX_FILES)
bSuccess = mux_open(&m_fdFile, m_szFilename, O_RDWR | O_BINARY);
2009-02-28 18:09:33 -08:00
#endif // UNIX_FILES
if (bSuccess)
{
#if defined(WINDOWS_FILES)
SetFilePointer(m_hFile, 0, 0, FILE_END);
#elif defined(UNIX_FILES)
mux_lseek(m_fdFile, 0, SEEK_END);
#endif // UNIX_FILES
}
}
void CLogFile::CloseLogFile(void)
{
#if defined(WINDOWS_FILES)
if (INVALID_HANDLE_VALUE != m_hFile)
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
#elif defined(UNIX_FILES)
if (MUX_OPEN_INVALID_HANDLE_VALUE != m_fdFile)
{
mux_close(m_fdFile);
m_fdFile = MUX_OPEN_INVALID_HANDLE_VALUE;
}
#endif // UNIX_FILES
}
#define FILE_SIZE_TRIGGER (512*1024UL)
void CLogFile::Flush(void)
{
if ( m_nBuffer <= 0
|| !bEnabled)
{
return;
}
2009-02-28 18:09:33 -08:00
if (bUseStderr)
{
// There is no recourse if the following fails.
//
(void) fwrite(m_aBuffer, m_nBuffer, 1, stderr);
2009-02-28 18:09:33 -08:00
}
else
{
m_nSize += m_nBuffer;
#if defined(WINDOWS_FILES)
unsigned long nWritten;
bool fSuccess = true;
if (!WriteFile(m_hFile, m_aBuffer, static_cast<DWORD>(m_nBuffer), &nWritten, nullptr))
{
fSuccess = false;
}
2009-02-28 18:09:33 -08:00
#elif defined(UNIX_FILES)
ssize_t written = mux_write(m_fdFile, m_aBuffer, m_nBuffer);
bool fSuccess = (0 < written && m_nBuffer == static_cast<size_t>(written));
2009-02-28 18:09:33 -08:00
#endif // UNIX_FILES
if (!fSuccess)
{
raw_broadcast(WIZARD,
M_("GAME: Unable to write to the log. The disk may be full."));
}
2009-02-28 18:09:33 -08:00
if (m_nSize > FILE_SIZE_TRIGGER)
{
CloseLogFile();
m_ltaStarted.GetLocal();
MakeLogName(m_pBasename, m_szPrefix, m_ltaStarted, m_szFilename,
sizeof(m_szFilename));
CreateLogFile();
}
}
m_nBuffer = 0;
}
void CLogFile::SetPrefix(const UTF8 * szPrefix)
2009-02-28 18:09:33 -08:00
{
if ( !bUseStderr
&& strcmp( reinterpret_cast<const char *>(szPrefix), reinterpret_cast<const char *>(m_szPrefix)) != 0)
2009-02-28 18:09:33 -08:00
{
if (bEnabled)
{
CloseLogFile();
}
UTF8 szNewName[SIZEOF_PATHNAME];
MakeLogName(m_pBasename, szPrefix, m_ltaStarted, szNewName,
sizeof(szNewName));
2009-02-28 18:09:33 -08:00
if (bEnabled)
{
ReplaceFile(m_szFilename, szNewName);
}
mux_strncpy(m_szPrefix, szPrefix, sizeof(m_szPrefix)-1);
mux_strncpy(m_szFilename, szNewName, sizeof(m_szFilename)-1);
2009-02-28 18:09:33 -08:00
if (bEnabled)
{
AppendLogFile();
}
}
}
void CLogFile::SetBasename(const UTF8 * pBasename)
2009-02-28 18:09:33 -08:00
{
if (m_pBasename)
{
MEMFREE(m_pBasename);
2018-10-03 17:54:51 +00:00
m_pBasename = nullptr;
2009-02-28 18:09:33 -08:00
}
2009-02-28 18:09:33 -08:00
if ( pBasename
&& strcmp( reinterpret_cast<const char *>(pBasename), "-") == 0)
2009-02-28 18:09:33 -08:00
{
bUseStderr = true;
}
else
{
bUseStderr = false;
if (pBasename)
{
m_pBasename = StringClone(pBasename);
}
else
{
m_pBasename = StringClone(T(""));
}
}
}
CLogFile::CLogFile(void)
{
#if defined(WINDOWS_THREADS)
InitializeCriticalSection(&csLog);
#endif // WINDOWS_THREADS
m_ltaStarted.GetLocal();
#if defined(WINDOWS_FILES)
m_hFile = INVALID_HANDLE_VALUE;
#elif defined(UNIX_FILES)
m_fdFile = MUX_OPEN_INVALID_HANDLE_VALUE;
#endif // UNIX_FILES
m_nSize = 0;
m_nBuffer = 0;
bEnabled = false;
bUseStderr = true;
2018-10-03 17:54:51 +00:00
m_pBasename = nullptr;
2009-02-28 18:09:33 -08:00
m_szPrefix[0] = '\0';
m_szFilename[0] = '\0';
}
void CLogFile::StartLogging()
{
if (!bUseStderr)
{
m_ltaStarted.GetLocal();
MakeLogName(m_pBasename, m_szPrefix, m_ltaStarted, m_szFilename,
sizeof(m_szFilename));
CreateLogFile();
}
bEnabled = true;
}
void CLogFile::StopLogging(void)
{
Flush();
bEnabled = false;
if (!bUseStderr)
{
CloseLogFile();
m_szPrefix[0] = '\0';
m_szFilename[0] = '\0';
2018-10-03 17:54:51 +00:00
SetBasename(nullptr);
2009-02-28 18:09:33 -08:00
}
}
void CLogFile::Rotate(void)
{
#if defined(WINDOWS_THREADS)
EnterCriticalSection(&csLog);
#endif // WINDOWS_THREADS
Flush();
if (!bUseStderr)
{
CloseLogFile();
m_ltaStarted.GetLocal();
MakeLogName(m_pBasename, m_szPrefix, m_ltaStarted, m_szFilename,
sizeof(m_szFilename));
CreateLogFile();
m_nSize = 0;
}
#if defined(WINDOWS_THREADS)
LeaveCriticalSection(&csLog);
#endif // WINDOWS_THREADS
}
void do_logrotate(dbref executor, dbref caller, dbref enactor, int eval, int key)
{
UNUSED_PARAMETER(caller);
UNUSED_PARAMETER(enactor);
UNUSED_PARAMETER(eval);
UNUSED_PARAMETER(key);
STARTLOG(LOG_ALWAYS, "WIZ", "LOGROTATE");
log_name(executor);
log_text(T(" rotates the log file."));
ENDLOG;
Log.Rotate();
notify(executor, M_("Log file rotated."));
}
2009-02-28 18:09:33 -08:00
CLogFile::~CLogFile(void)
{
StopLogging();
#if defined(WINDOWS_THREADS)
DeleteCriticalSection(&csLog);
#endif // WINDOWS_THREADS
}
// CLog component which is not directly accessible.
//
class CLog : public mux_ILog
{
public:
// mux_IUnknown
//
virtual MUX_RESULT QueryInterface(MUX_IID iid, void **ppv);
virtual uint32_t AddRef(void);
virtual uint32_t Release(void);
// mux_ILog
//
virtual MUX_RESULT start_log(bool *pStarted, int key, const UTF8 *primary, const UTF8 *secondary);
virtual MUX_RESULT log_perror(const UTF8 *primary, const UTF8 *secondary, const UTF8 *extra, const UTF8 *failing_object);
virtual MUX_RESULT log_text(const UTF8 *text);
virtual MUX_RESULT log_number(int num);
virtual MUX_RESULT log_name(dbref target);
virtual MUX_RESULT log_name_and_loc(dbref player);
virtual MUX_RESULT log_type_and_name(dbref thing);
virtual MUX_RESULT end_log(void);
virtual MUX_RESULT WriteString(const UTF8 *text);
virtual MUX_RESULT SetBasename(const UTF8 *pBasename);
virtual MUX_RESULT StartLogging(void);
virtual MUX_RESULT Flush(void);
CLog(void);
virtual ~CLog();
private:
uint32_t m_cRef;
};
CLog::CLog(void) : m_cRef(1)
{
}
CLog::~CLog()
{
}
MUX_RESULT CLog::QueryInterface(MUX_IID iid, void **ppv)
{
if (mux_IID_IUnknown == iid)
{
*ppv = static_cast<mux_ILog *>(this);
}
else if (IID_ILog == iid)
{
*ppv = static_cast<mux_ILog *>(this);
}
else
{
2018-10-03 17:54:51 +00:00
*ppv = nullptr;
return MUX_E_NOINTERFACE;
}
reinterpret_cast<mux_IUnknown *>(*ppv)->AddRef();
return MUX_S_OK;
}
uint32_t CLog::AddRef(void)
{
m_cRef++;
return m_cRef;
}
uint32_t CLog::Release(void)
{
m_cRef--;
if (0 == m_cRef)
{
delete this;
return 0;
}
return m_cRef;
}
MUX_RESULT CLog::start_log(bool *fStarted, int key, const UTF8 *primary, const UTF8 *secondary)
{
if ( ((key) & mudconf.log_options) != 0
&& ::start_log(primary, secondary))
{
*fStarted = true;
}
else
{
*fStarted = false;
}
return MUX_S_OK;
}
MUX_RESULT CLog::log_perror(const UTF8 *primary, const UTF8 *secondary, const UTF8 *extra, const UTF8 *failing_object)
{
::log_perror(primary, secondary, extra, failing_object);
return MUX_S_OK;
}
MUX_RESULT CLog::log_text(const UTF8 *text)
{
::log_text(text);
return MUX_S_OK;
}
MUX_RESULT CLog::log_number(int num)
{
::log_number(num);
return MUX_S_OK;
}
MUX_RESULT CLog::log_name(dbref target)
{
::log_name(target);
return MUX_S_OK;
}
MUX_RESULT CLog::log_name_and_loc(dbref player)
{
::log_name_and_loc(player);
return MUX_S_OK;
}
MUX_RESULT CLog::log_type_and_name(dbref thing)
{
::log_type_and_name(thing);
return MUX_S_OK;
}
MUX_RESULT CLog::end_log(void)
{
::end_log();
return MUX_S_OK;
}
MUX_RESULT CLog::WriteString(const UTF8 *text)
{
Log.WriteString(text);
return MUX_S_OK;
}
MUX_RESULT CLog::SetBasename(const UTF8 *pBasename)
{
Log.SetBasename(pBasename);
return MUX_S_OK;
}
MUX_RESULT CLog::StartLogging(void)
{
Log.StartLogging();
return MUX_S_OK;
}
MUX_RESULT CLog::Flush(void)
{
Log.Flush();
return MUX_S_OK;
}
// Factory for CLog component which is not directly accessible.
//
CLogFactory::CLogFactory(void) : m_cRef(1)
{
}
CLogFactory::~CLogFactory()
{
}
MUX_RESULT CLogFactory::QueryInterface(MUX_IID iid, void **ppv)
{
if (mux_IID_IUnknown == iid)
{
*ppv = static_cast<mux_IClassFactory *>(this);
}
else if (mux_IID_IClassFactory == iid)
{
*ppv = static_cast<mux_IClassFactory *>(this);
}
else
{
2018-10-03 17:54:51 +00:00
*ppv = nullptr;
return MUX_E_NOINTERFACE;
}
reinterpret_cast<mux_IUnknown *>(*ppv)->AddRef();
return MUX_S_OK;
}
uint32_t CLogFactory::AddRef(void)
{
m_cRef++;
return m_cRef;
}
uint32_t CLogFactory::Release(void)
{
m_cRef--;
if (0 == m_cRef)
{
delete this;
return 0;
}
return m_cRef;
}
MUX_RESULT CLogFactory::CreateInstance(mux_IUnknown *pUnknownOuter, MUX_IID iid, void **ppv)
{
// Disallow attempts to aggregate this component.
//
2018-10-03 17:54:51 +00:00
if (nullptr != pUnknownOuter)
{
return MUX_E_NOAGGREGATION;
}
2018-10-03 17:54:51 +00:00
CLog *pLog = nullptr;
try
{
pLog = new CLog;
}
catch (...)
{
; // Nothing.
}
2018-10-03 17:54:51 +00:00
if (nullptr == pLog)
{
return MUX_E_OUTOFMEMORY;
}
MUX_RESULT mr = pLog->QueryInterface(iid, ppv);
pLog->Release();
return mr;
}
MUX_RESULT CLogFactory::LockServer(bool bLock)
{
UNUSED_PARAMETER(bLock);
return MUX_S_OK;
}
// Standard Marshaling support for mux_ILog.
//
// Method numbers (0-2 are IUnknown, not marshalled):
//
// 3: start_log
// 4: log_perror
// 5: log_text
// 6: log_number
// 7: log_name
// 8: log_name_and_loc
// 9: log_type_and_name
// 10: end_log
//
// CLogProxy: client-side proxy for mux_ILog over a pipe channel.
//
class CLogProxy : public mux_ILog, public mux_IRpcProxyBuffer
{
public:
// mux_IUnknown
//
virtual MUX_RESULT QueryInterface(MUX_IID iid, void **ppv);
virtual uint32_t AddRef(void);
virtual uint32_t Release(void);
// mux_IRpcProxyBuffer
//
virtual MUX_RESULT Connect(uint32_t nChannel);
virtual void Disconnect(void);
// mux_ILog
//
virtual MUX_RESULT start_log(bool *pStarted, int key, const UTF8 *primary, const UTF8 *secondary);
virtual MUX_RESULT log_perror(const UTF8 *primary, const UTF8 *secondary, const UTF8 *extra, const UTF8 *failing_object);
virtual MUX_RESULT log_text(const UTF8 *text);
virtual MUX_RESULT log_number(int num);
virtual MUX_RESULT log_name(dbref target);
virtual MUX_RESULT log_name_and_loc(dbref player);
virtual MUX_RESULT log_type_and_name(dbref thing);
virtual MUX_RESULT end_log(void);
virtual MUX_RESULT WriteString(const UTF8 *text);
virtual MUX_RESULT SetBasename(const UTF8 *pBasename);
virtual MUX_RESULT StartLogging(void);
virtual MUX_RESULT Flush(void);
CLogProxy(void);
virtual ~CLogProxy();
private:
uint32_t m_cRef;
uint32_t m_nChannel;
};
CLogProxy::CLogProxy(void) : m_cRef(1), m_nChannel(CHANNEL_INVALID)
{
}
CLogProxy::~CLogProxy()
{
}
MUX_RESULT CLogProxy::QueryInterface(MUX_IID iid, void **ppv)
{
if (mux_IID_IUnknown == iid)
{
*ppv = static_cast<mux_ILog *>(this);
}
else if (IID_ILog == iid)
{
*ppv = static_cast<mux_ILog *>(this);
}
else if (mux_IID_IRpcProxyBuffer == iid)
{
*ppv = static_cast<mux_IRpcProxyBuffer *>(this);
}
else
{
*ppv = nullptr;
return MUX_E_NOINTERFACE;
}
reinterpret_cast<mux_IUnknown *>(*ppv)->AddRef();
return MUX_S_OK;
}
uint32_t CLogProxy::AddRef(void)
{
m_cRef++;
return m_cRef;
}
uint32_t CLogProxy::Release(void)
{
m_cRef--;
if (0 == m_cRef)
{
if (CHANNEL_INVALID != m_nChannel)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
(void)Pipe_SendDiscPacket(m_nChannel, &qiFrame);
Pipe_EmptyQueue(&qiFrame);
m_nChannel = CHANNEL_INVALID;
}
delete this;
return 0;
}
return m_cRef;
}
MUX_RESULT CLogProxy::Connect(uint32_t nChannel)
{
m_nChannel = nChannel;
return MUX_S_OK;
}
void CLogProxy::Disconnect(void)
{
m_nChannel = CHANNEL_INVALID;
}
MUX_RESULT CLogProxy::start_log(bool *pStarted, int key, const UTF8 *primary, const UTF8 *secondary)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 3);
Marshal_PutInt(&qiFrame, key);
Marshal_PutString(&qiFrame, primary);
Marshal_PutString(&qiFrame, secondary);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
struct RETURN
{
MUX_RESULT mr;
bool bStarted;
} ReturnFrame;
size_t nWanted = sizeof(ReturnFrame);
if ( Pipe_GetBytes(&qiFrame, &nWanted, &ReturnFrame)
&& nWanted == sizeof(ReturnFrame))
{
*pStarted = ReturnFrame.bStarted;
mr = ReturnFrame.mr;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::log_perror(const UTF8 *primary, const UTF8 *secondary, const UTF8 *extra, const UTF8 *failing_object)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 4);
Marshal_PutString(&qiFrame, primary);
Marshal_PutString(&qiFrame, secondary);
Marshal_PutString(&qiFrame, extra);
Marshal_PutString(&qiFrame, failing_object);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::log_text(const UTF8 *text)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 5);
Marshal_PutString(&qiFrame, text);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::log_number(int num)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 6);
Marshal_PutInt(&qiFrame, num);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::log_name(dbref target)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 7);
Marshal_PutInt(&qiFrame, target);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::log_name_and_loc(dbref player)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 8);
Marshal_PutInt(&qiFrame, player);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::log_type_and_name(dbref thing)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 9);
Marshal_PutInt(&qiFrame, thing);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::end_log(void)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 10);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::WriteString(const UTF8 *text)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 11);
Marshal_PutString(&qiFrame, text);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::SetBasename(const UTF8 *pBasename)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 12);
Marshal_PutString(&qiFrame, pBasename);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::StartLogging(void)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 13);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
MUX_RESULT CLogProxy::Flush(void)
{
QUEUE_INFO qiFrame;
Pipe_InitializeQueueInfo(&qiFrame);
Marshal_PutUInt32(&qiFrame, 14);
MUX_RESULT mr = Pipe_SendCallPacketAndWait(m_nChannel, &qiFrame);
if (MUX_SUCCEEDED(mr))
{
MUX_RESULT mrReturn;
if (Marshal_GetInt(&qiFrame, &mrReturn))
{
mr = mrReturn;
}
else
{
mr = MUX_E_FAIL;
}
}
Pipe_EmptyQueue(&qiFrame);
return mr;
}
// CLogStub: server-side stub for mux_ILog over a pipe channel.
//
class CLogStub : public mux_IRpcStubBuffer
{
public:
// mux_IUnknown
//
virtual MUX_RESULT QueryInterface(MUX_IID iid, void **ppv);
virtual uint32_t AddRef(void);
virtual uint32_t Release(void);
// mux_IRpcStubBuffer
//
virtual MUX_RESULT Connect(mux_IUnknown *pUnknownServer);
virtual void Disconnect(void);
virtual MUX_RESULT Invoke(QUEUE_INFO *pqi);
virtual MUX_RESULT IsSupported(MUX_IID riid);
virtual uint32_t CountRefs(void);
CLogStub(void);
virtual ~CLogStub();
private:
uint32_t m_cRef;
mux_ILog *m_pILog;
};
CLogStub::CLogStub(void) : m_cRef(1), m_pILog(nullptr)
{
}
CLogStub::~CLogStub()
{
if (nullptr != m_pILog)
{
m_pILog->Release();
m_pILog = nullptr;
}
}
MUX_RESULT CLogStub::QueryInterface(MUX_IID iid, void **ppv)
{
if (mux_IID_IUnknown == iid)
{
*ppv = static_cast<mux_IRpcStubBuffer *>(this);
}
else if (mux_IID_IRpcStubBuffer == iid)
{
*ppv = static_cast<mux_IRpcStubBuffer *>(this);
}
else
{
*ppv = nullptr;
return MUX_E_NOINTERFACE;
}
reinterpret_cast<mux_IUnknown *>(*ppv)->AddRef();
return MUX_S_OK;
}
uint32_t CLogStub::AddRef(void)
{
m_cRef++;
return m_cRef;
}
uint32_t CLogStub::Release(void)
{
m_cRef--;
if (0 == m_cRef)
{
delete this;
return 0;
}
return m_cRef;
}
MUX_RESULT CLogStub::Connect(mux_IUnknown *pUnknownServer)
{
if (nullptr != m_pILog)
{
m_pILog->Release();
m_pILog = nullptr;
}
if (nullptr == pUnknownServer)
{
return MUX_S_OK;
}
return pUnknownServer->QueryInterface(IID_ILog, (void **)&m_pILog);
}
void CLogStub::Disconnect(void)
{
if (nullptr != m_pILog)
{
m_pILog->Release();
m_pILog = nullptr;
}
}
MUX_RESULT CLogStub::Invoke(QUEUE_INFO *pqi)
{
if (nullptr == m_pILog)
{
return MUX_E_UNEXPECTED;
}
uint32_t iMethod;
if (!Marshal_GetUInt32(pqi, &iMethod))
{
return MUX_E_INVALIDARG;
}
MUX_RESULT mr = MUX_S_OK;
switch (iMethod)
{
case 3: // start_log
{
int key;
if (!Marshal_GetInt(pqi, &key))
{
return MUX_E_INVALIDARG;
}
LBuf bufPrimary = LBuf_Src("start_log.primary");
LBuf bufSecondary = LBuf_Src("start_log.secondary");
const UTF8 *pPrimary;
const UTF8 *pSecondary;
if ( !Marshal_GetString(pqi, bufPrimary, LBUF_SIZE, &pPrimary)
|| !Marshal_GetString(pqi, bufSecondary, LBUF_SIZE, &pSecondary))
{
return MUX_E_INVALIDARG;
}
bool bStarted = false;
mr = m_pILog->start_log(&bStarted, key, pPrimary, pSecondary);
struct RETURN
{
MUX_RESULT mr;
bool bStarted;
} ReturnFrame;
ReturnFrame.mr = mr;
ReturnFrame.bStarted = bStarted;
Pipe_EmptyQueue(pqi);
Pipe_AppendBytes(pqi, sizeof(ReturnFrame), &ReturnFrame);
}
break;
case 4: // log_perror
{
LBuf bufPrimary = LBuf_Src("log_perror.primary");
LBuf bufSecondary = LBuf_Src("log_perror.secondary");
LBuf bufExtra = LBuf_Src("log_perror.extra");
LBuf bufFailing = LBuf_Src("log_perror.failing");
const UTF8 *pPrimary;
const UTF8 *pSecondary;
const UTF8 *pExtra;
const UTF8 *pFailing;
if ( !Marshal_GetString(pqi, bufPrimary, LBUF_SIZE, &pPrimary)
|| !Marshal_GetString(pqi, bufSecondary, LBUF_SIZE, &pSecondary)
|| !Marshal_GetString(pqi, bufExtra, LBUF_SIZE, &pExtra)
|| !Marshal_GetString(pqi, bufFailing, LBUF_SIZE, &pFailing))
{
return MUX_E_INVALIDARG;
}
mr = m_pILog->log_perror(pPrimary, pSecondary, pExtra, pFailing);
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 5: // log_text
{
LBuf bufText = LBuf_Src("log_text");
const UTF8 *pText;
if (!Marshal_GetString(pqi, bufText, LBUF_SIZE, &pText))
{
return MUX_E_INVALIDARG;
}
mr = m_pILog->log_text(pText);
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 6: // log_number
{
int num;
if (!Marshal_GetInt(pqi, &num))
{
return MUX_E_INVALIDARG;
}
mr = m_pILog->log_number(num);
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 7: // log_name
{
dbref target;
if (!Marshal_GetInt(pqi, &target))
{
return MUX_E_INVALIDARG;
}
mr = m_pILog->log_name(target);
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 8: // log_name_and_loc
{
dbref player;
if (!Marshal_GetInt(pqi, &player))
{
return MUX_E_INVALIDARG;
}
mr = m_pILog->log_name_and_loc(player);
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 9: // log_type_and_name
{
dbref thing;
if (!Marshal_GetInt(pqi, &thing))
{
return MUX_E_INVALIDARG;
}
mr = m_pILog->log_type_and_name(thing);
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 10: // end_log
{
mr = m_pILog->end_log();
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 11: // WriteString
{
LBuf bufText = LBuf_Src("WriteString");
const UTF8 *pText;
if (Marshal_GetString(pqi, bufText, LBUF_SIZE, &pText))
{
mr = m_pILog->WriteString(pText);
}
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 12: // SetBasename
{
LBuf bufBasename = LBuf_Src("SetBasename");
const UTF8 *pBasename;
if (Marshal_GetString(pqi, bufBasename, LBUF_SIZE, &pBasename))
{
mr = m_pILog->SetBasename(pBasename);
}
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 13: // StartLogging
{
mr = m_pILog->StartLogging();
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
case 14: // Flush
{
mr = m_pILog->Flush();
Pipe_EmptyQueue(pqi);
Marshal_PutInt(pqi, mr);
}
break;
default:
mr = MUX_E_NOTIMPLEMENTED;
break;
}
return mr;
}
MUX_RESULT CLogStub::IsSupported(MUX_IID riid)
{
if (IID_ILog == riid)
{
return MUX_S_OK;
}
return MUX_S_FALSE;
}
uint32_t CLogStub::CountRefs(void)
{
return (nullptr != m_pILog) ? 1 : 0;
}
// CLogPSFactory: proxy-stub factory for mux_ILog.
//
CLogPSFactory::CLogPSFactory(void) : m_cRef(1)
{
}
CLogPSFactory::~CLogPSFactory()
{
}
MUX_RESULT CLogPSFactory::QueryInterface(MUX_IID iid, void **ppv)
{
if (mux_IID_IUnknown == iid)
{
*ppv = static_cast<mux_IPSFactoryBuffer *>(this);
}
else if (mux_IID_IPSFactoryBuffer == iid)
{
*ppv = static_cast<mux_IPSFactoryBuffer *>(this);
}
else if (mux_IID_IClassFactory == iid)
{
*ppv = static_cast<mux_IClassFactory *>(this);
}
else
{
*ppv = nullptr;
return MUX_E_NOINTERFACE;
}
reinterpret_cast<mux_IUnknown *>(*ppv)->AddRef();
return MUX_S_OK;
}
uint32_t CLogPSFactory::AddRef(void)
{
m_cRef++;
return m_cRef;
}
uint32_t CLogPSFactory::Release(void)
{
m_cRef--;
if (0 == m_cRef)
{
delete this;
return 0;
}
return m_cRef;
}
MUX_RESULT CLogPSFactory::CreateProxy(mux_IUnknown *pUnknownOuter, MUX_IID riid, mux_IRpcProxyBuffer **ppProxy, void **ppv)
{
UNUSED_PARAMETER(pUnknownOuter);
if (IID_ILog != riid)
{
*ppProxy = nullptr;
*ppv = nullptr;
return MUX_E_NOINTERFACE;
}
CLogProxy *pProxy = nullptr;
try
{
pProxy = new CLogProxy;
}
catch (...)
{
; // Nothing.
}
if (nullptr == pProxy)
{
*ppProxy = nullptr;
*ppv = nullptr;
return MUX_E_OUTOFMEMORY;
}
// Both ppProxy and ppv point into the same object.
//
*ppProxy = static_cast<mux_IRpcProxyBuffer *>(pProxy);
pProxy->AddRef();
*ppv = static_cast<mux_ILog *>(pProxy);
return MUX_S_OK;
}
MUX_RESULT CLogPSFactory::CreateStub(MUX_IID riid, mux_IUnknown *pUnknownOuter, mux_IRpcStubBuffer **ppStub)
{
if (IID_ILog != riid)
{
*ppStub = nullptr;
return MUX_E_NOINTERFACE;
}
CLogStub *pStub = nullptr;
try
{
pStub = new CLogStub;
}
catch (...)
{
; // Nothing.
}
if (nullptr == pStub)
{
*ppStub = nullptr;
return MUX_E_OUTOFMEMORY;
}
if (nullptr != pUnknownOuter)
{
MUX_RESULT mr = pStub->Connect(pUnknownOuter);
if (MUX_FAILED(mr))
{
pStub->Release();
*ppStub = nullptr;
return mr;
}
}
*ppStub = static_cast<mux_IRpcStubBuffer *>(pStub);
return MUX_S_OK;
}
MUX_RESULT CLogPSFactory::CreateInstance(mux_IUnknown *pUnknownOuter, MUX_IID iid, void **ppv)
{
// This factory is used via IPSFactoryBuffer, but also via IClassFactory
// for the standard marshaler to obtain it through mux_CreateInstance.
//
if (nullptr != pUnknownOuter)
{
return MUX_E_NOAGGREGATION;
}
return QueryInterface(iid, ppv);
}
MUX_RESULT CLogPSFactory::LockServer(bool bLock)
{
UNUSED_PARAMETER(bLock);
return MUX_S_OK;
}