1211
This commit is contained in:
101
test/Detours/samples/syelog/Makefile
Normal file
101
test/Detours/samples/syelog/Makefile
Normal file
@@ -0,0 +1,101 @@
|
||||
##############################################################################
|
||||
##
|
||||
## Makefile for Detours.
|
||||
##
|
||||
## Microsoft Research Detours Package
|
||||
##
|
||||
## Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
TARGETOS=WINNT
|
||||
!include ..\common.mak
|
||||
|
||||
LIBS=$(LIBS) kernel32.lib
|
||||
|
||||
##############################################################################
|
||||
|
||||
all: dirs \
|
||||
$(INCD)\syelog.h \
|
||||
$(LIBD)\syelog.lib \
|
||||
$(BIND)\syelogd.exe \
|
||||
\
|
||||
$(BIND)\sltest.exe \
|
||||
$(BIND)\sltestp.exe \
|
||||
\
|
||||
!IF $(DETOURS_SOURCE_BROWSING)==1
|
||||
$(OBJD)\syelogd.bsc \
|
||||
$(OBJD)\sltest.bsc \
|
||||
$(OBJD)\sltestp.bsc \
|
||||
!ENDIF
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
clean:
|
||||
-del *~ test.txt 2> nul
|
||||
-del $(INCD)\syelog.* 2>nul
|
||||
-del $(LIBD)\syelog.* 2>nul
|
||||
-del $(BIND)\syelogd.* 2>nul
|
||||
-del $(BIND)\sltest.* 2>nul
|
||||
-del $(BIND)\sltestp.* 2>nul
|
||||
-rmdir /q /s $(OBJD) 2>nul
|
||||
|
||||
realclean: clean
|
||||
-rmdir /q /s $(OBJDS) 2>nul
|
||||
|
||||
##############################################################################
|
||||
|
||||
dirs:
|
||||
@if not exist $(INCD) mkdir $(INCD) && echo. Created $(INCD)
|
||||
@if not exist $(LIBD) mkdir $(LIBD) && echo. Created $(LIBD)
|
||||
@if not exist $(BIND) mkdir $(BIND) && echo. Created $(BIND)
|
||||
@if not exist $(OBJD) mkdir $(OBJD) && echo. Created $(OBJD)
|
||||
|
||||
$(OBJD)\syelog.obj : syelog.cpp syelog.h
|
||||
$(OBJD)\syelogd.obj: syelogd.cpp syelog.h
|
||||
$(OBJD)\sltest.obj: sltest.cpp syelog.h
|
||||
$(OBJD)\sltestp.obj: sltestp.cpp syelog.h
|
||||
|
||||
$(INCD)\syelog.h : syelog.h
|
||||
copy syelog.h $@
|
||||
|
||||
$(LIBD)\syelog.lib : $(OBJD)\syelog.obj
|
||||
link /lib $(LIBFLAGS) /out:$@ $(OBJD)\syelog.obj
|
||||
|
||||
$(BIND)\sltest.exe: $(OBJD)\sltest.obj $(OBJD)\syelog.obj $(DEPS)
|
||||
$(CC) $(CFLAGS) /Fe$@ /Fd$(@R).pdb $(OBJD)\sltest.obj \
|
||||
/link $(LINKFLAGS) $(LIBS)
|
||||
|
||||
$(OBJD)\sltest.bsc : $(OBJD)\sltest.obj
|
||||
bscmake /v /n /o $@ $(OBJD)\sltest.sbr
|
||||
|
||||
$(BIND)\sltestp.exe: $(OBJD)\sltestp.obj $(DEPS)
|
||||
$(CC) $(CFLAGS) /Fe$@ /Fd$(@R).pdb $(OBJD)\sltestp.obj \
|
||||
/link $(LINKFLAGS) $(LIBS)
|
||||
|
||||
$(OBJD)\sltestp.bsc : $(OBJD)\sltestp.obj
|
||||
bscmake /v /n /o $@ $(OBJD)\sltestp.sbr
|
||||
|
||||
$(LIBD)\detours.lib:
|
||||
cd $(ROOT)\src
|
||||
nmake /nologo
|
||||
cd $(MAKEDIR)
|
||||
|
||||
$(BIND)\syelogd.exe: $(OBJD)\syelogd.obj $(DEPS)
|
||||
$(CC) $(CFLAGS) /Fe$@ /Fd$(@R).pdb $(OBJD)\syelogd.obj \
|
||||
/link $(LINKFLAGS) ws2_32.lib mswsock.lib advapi32.lib
|
||||
|
||||
$(OBJD)\syelogd.bsc : $(OBJD)\syelogd.obj
|
||||
bscmake /v /n /o $@ $(OBJD)\syelogd.sbr
|
||||
|
||||
##############################################################################
|
||||
|
||||
test: $(BIND)\syelogd.exe $(BIND)\sltest.exe $(BIND)\sltestp.exe
|
||||
@echo -------- Logging output to test.txt ------------
|
||||
start $(BIND)\syelogd.exe test.txt
|
||||
$(BIND)\sleep5.exe 1
|
||||
$(BIND)\sltestp.exe
|
||||
$(BIND)\sltest.exe /x
|
||||
type test.txt
|
||||
|
||||
################################################################# End of File.
|
||||
145
test/Detours/samples/syelog/sltest.cpp
Normal file
145
test/Detours/samples/syelog/sltest.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Detours Test Program (sltest.cpp of sltest.exe)
|
||||
//
|
||||
// Microsoft Research Detours Package
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Test the named-pipe-based connection with syelog.lib to the syelog
|
||||
// system-event logger.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#pragma warning(push)
|
||||
#if _MSC_VER > 1400
|
||||
#pragma warning(disable:6102 6103) // /analyze warnings
|
||||
#endif
|
||||
#include <strsafe.h>
|
||||
#pragma warning(pop)
|
||||
#include "syelog.h"
|
||||
#include "detours.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
HANDLE ( WINAPI *
|
||||
Real_CreateFileW)(LPCWSTR a0,
|
||||
DWORD a1,
|
||||
DWORD a2,
|
||||
LPSECURITY_ATTRIBUTES a3,
|
||||
DWORD a4,
|
||||
DWORD a5,
|
||||
HANDLE a6)
|
||||
= CreateFileW;
|
||||
|
||||
BOOL ( WINAPI *
|
||||
Real_WriteFile)(HANDLE hFile,
|
||||
LPCVOID lpBuffer,
|
||||
DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped)
|
||||
= WriteFile;
|
||||
BOOL ( WINAPI *
|
||||
Real_FlushFileBuffers)(HANDLE hFile)
|
||||
= FlushFileBuffers;
|
||||
BOOL ( WINAPI *
|
||||
Real_CloseHandle)(HANDLE hObject)
|
||||
= CloseHandle;
|
||||
|
||||
BOOL ( WINAPI *
|
||||
Real_WaitNamedPipeW)(LPCWSTR lpNamedPipeName, DWORD nTimeOut)
|
||||
= WaitNamedPipeW;
|
||||
BOOL ( WINAPI *
|
||||
Real_SetNamedPipeHandleState)(HANDLE hNamedPipe,
|
||||
LPDWORD lpMode,
|
||||
LPDWORD lpMaxCollectionCount,
|
||||
LPDWORD lpCollectDataTimeout)
|
||||
= SetNamedPipeHandleState;
|
||||
|
||||
DWORD ( WINAPI *
|
||||
Real_GetCurrentProcessId)(VOID)
|
||||
= GetCurrentProcessId;
|
||||
VOID ( WINAPI *
|
||||
Real_GetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime)
|
||||
= GetSystemTimeAsFileTime;
|
||||
|
||||
VOID ( WINAPI *
|
||||
Real_InitializeCriticalSection)(LPCRITICAL_SECTION lpSection)
|
||||
= InitializeCriticalSection;
|
||||
VOID ( WINAPI *
|
||||
Real_EnterCriticalSection)(LPCRITICAL_SECTION lpSection)
|
||||
= EnterCriticalSection;
|
||||
VOID ( WINAPI *
|
||||
Real_LeaveCriticalSection)(LPCRITICAL_SECTION lpSection)
|
||||
= LeaveCriticalSection;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BOOL fNeedHelp = FALSE;
|
||||
BOOL fRequestExitOnClose = FALSE;
|
||||
|
||||
int arg = 1;
|
||||
for (; arg < argc && (argv[arg][0] == '-' || argv[arg][0] == '/'); arg++) {
|
||||
CHAR *argn = argv[arg] + 1;
|
||||
CHAR *argp = argn;
|
||||
while (*argp && *argp != ':') {
|
||||
argp++;
|
||||
}
|
||||
if (*argp == ':') {
|
||||
*argp++ = '\0';
|
||||
}
|
||||
|
||||
switch (argn[0]) {
|
||||
|
||||
case 'x': // Request exit on close.
|
||||
case 'X':
|
||||
fRequestExitOnClose = TRUE;
|
||||
break;
|
||||
|
||||
case '?': // Help.
|
||||
fNeedHelp = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
fNeedHelp = TRUE;
|
||||
printf("SLTEST: Bad argument: %s:%s\n", argn, argp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fNeedHelp) {
|
||||
printf("Usage:\n"
|
||||
" sltest.exe [options] message\n"
|
||||
"Options:\n"
|
||||
" /x Ask syelogd.exe to terminate when this connect closes.\n"
|
||||
" /? Display this help message.\n"
|
||||
"\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SyelogOpen("sltest", SYELOG_FACILITY_APPLICATION);
|
||||
if (arg >= argc) {
|
||||
Syelog(SYELOG_SEVERITY_INFORMATION, "Hello World! [1 of 4]");
|
||||
Syelog(SYELOG_SEVERITY_INFORMATION, "Hello World! [2 of 4]");
|
||||
Syelog(SYELOG_SEVERITY_INFORMATION, "Hello World! [3 of 4]");
|
||||
Syelog(SYELOG_SEVERITY_INFORMATION, "Hello World! [4 of 4]");
|
||||
}
|
||||
else {
|
||||
CHAR Buffer[1024] = "";
|
||||
|
||||
for (; arg < argc; arg++) {
|
||||
StringCchCatA(Buffer, ARRAYSIZE(Buffer), argv[arg]);
|
||||
if (arg + 1 < argc) {
|
||||
StringCchCatA(Buffer, ARRAYSIZE(Buffer), " ");
|
||||
}
|
||||
}
|
||||
Syelog(SYELOG_SEVERITY_INFORMATION, Buffer);
|
||||
}
|
||||
|
||||
SyelogClose(fRequestExitOnClose);
|
||||
|
||||
return 0;
|
||||
}
|
||||
104
test/Detours/samples/syelog/sltestp.cpp
Normal file
104
test/Detours/samples/syelog/sltestp.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Detours Test Program (sltestp.cpp of sltestp.exe)
|
||||
//
|
||||
// Microsoft Research Detours Package
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Test the named-pipe-based connection to the syelog system-event logger.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#pragma warning(push)
|
||||
#if _MSC_VER > 1400
|
||||
#pragma warning(disable:6102 6103) // /analyze warnings
|
||||
#endif
|
||||
#include <strsafe.h>
|
||||
#pragma warning(pop)
|
||||
#include "syelog.h"
|
||||
|
||||
VOID MyErrExit(PCSTR pszMsg)
|
||||
{
|
||||
fprintf(stderr, "Error %s: %ld\n", pszMsg, GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DWORD main(int argc, char *argv[])
|
||||
{
|
||||
HANDLE hPipe;
|
||||
SYELOG_MESSAGE Message;
|
||||
BOOL fSuccess;
|
||||
DWORD cbWritten, dwMode;
|
||||
|
||||
// Try to open a named pipe; wait for it, if necessary.
|
||||
|
||||
TIME_ZONE_INFORMATION tzi;
|
||||
GetTimeZoneInformation(&tzi);
|
||||
|
||||
for (;;) {
|
||||
hPipe = CreateFileW(SYELOG_PIPE_NAMEW, // pipe name
|
||||
GENERIC_WRITE, // write access only
|
||||
0, // no sharing
|
||||
NULL, // no security attributes
|
||||
OPEN_EXISTING, // opens existing pipe
|
||||
0, // default attributes
|
||||
NULL); // no template file
|
||||
|
||||
// Break if the pipe handle is valid.
|
||||
if (hPipe != INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
// Exit if an error other than ERROR_PIPE_BUSY occurs.
|
||||
|
||||
if (GetLastError() != ERROR_PIPE_BUSY)
|
||||
MyErrExit("Could not open pipe");
|
||||
|
||||
// All pipe instances are busy, so wait for 1 seconds.
|
||||
|
||||
if (!WaitNamedPipeW(SYELOG_PIPE_NAMEW, 1000))
|
||||
MyErrExit("Could not open pipe");
|
||||
}
|
||||
|
||||
// The pipe connected; change to message-read mode.
|
||||
dwMode = PIPE_READMODE_MESSAGE;
|
||||
fSuccess = SetNamedPipeHandleState(hPipe, // pipe handle
|
||||
&dwMode, // new pipe mode
|
||||
NULL, // don't set maximum bytes
|
||||
NULL); // don't set maximum time
|
||||
if (!fSuccess)
|
||||
MyErrExit("SetNamedPipeHandleState");
|
||||
|
||||
// Send a message to the pipe server.
|
||||
|
||||
memset(&Message, 0, sizeof(Message));
|
||||
|
||||
StringCchCopyA(Message.szMessage, ARRAYSIZE(Message.szMessage),
|
||||
(argc > 1) ? argv[1] : "sltestp: hello world!");
|
||||
|
||||
Message.nFacility = SYELOG_FACILITY_APPLICATION;
|
||||
Message.nSeverity = SYELOG_SEVERITY_INFORMATION;
|
||||
Message.nProcessId = GetCurrentProcessId();
|
||||
GetSystemTimeAsFileTime(&Message.ftOccurance);
|
||||
PCSTR pszEnd = Message.szMessage;
|
||||
for (; *pszEnd; pszEnd++) {
|
||||
// no internal contents.
|
||||
}
|
||||
Message.nBytes = (USHORT)(pszEnd - ((PCSTR)&Message) + 1);
|
||||
|
||||
fSuccess = WriteFile(hPipe, // pipe handle
|
||||
&Message, // message
|
||||
Message.nBytes, // message length
|
||||
&cbWritten, // bytes written
|
||||
NULL); // not overlapped
|
||||
if (! fSuccess)
|
||||
MyErrExit("WriteFile");
|
||||
|
||||
CloseHandle(hPipe);
|
||||
|
||||
GetTimeZoneInformation(&tzi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
847
test/Detours/samples/syelog/syelog.cpp
Normal file
847
test/Detours/samples/syelog/syelog.cpp
Normal file
@@ -0,0 +1,847 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Detours Test Program (syelog.cpp of syelog.lib)
|
||||
//
|
||||
// Microsoft Research Detours Package
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "detours.h"
|
||||
#include "syelog.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
extern "C" {
|
||||
extern HANDLE ( WINAPI * Real_CreateFileW)(LPCWSTR a0,
|
||||
DWORD a1,
|
||||
DWORD a2,
|
||||
LPSECURITY_ATTRIBUTES a3,
|
||||
DWORD a4,
|
||||
DWORD a5,
|
||||
HANDLE a6);
|
||||
extern BOOL ( WINAPI * Real_WriteFile)(HANDLE hFile,
|
||||
LPCVOID lpBuffer,
|
||||
DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
extern BOOL ( WINAPI * Real_FlushFileBuffers)(HANDLE hFile);
|
||||
extern BOOL ( WINAPI * Real_CloseHandle)(HANDLE hObject);
|
||||
|
||||
extern BOOL ( WINAPI * Real_WaitNamedPipeW)(LPCWSTR lpNamedPipeName, DWORD nTimeOut);
|
||||
extern BOOL ( WINAPI * Real_SetNamedPipeHandleState)(HANDLE hNamedPipe,
|
||||
LPDWORD lpMode,
|
||||
LPDWORD lpMaxCollectionCount,
|
||||
LPDWORD lpCollectDataTimeout);
|
||||
|
||||
extern DWORD ( WINAPI * Real_GetCurrentProcessId)(VOID);
|
||||
extern VOID ( WINAPI * Real_GetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime);
|
||||
|
||||
extern VOID ( WINAPI * Real_InitializeCriticalSection)(LPCRITICAL_SECTION lpSection);
|
||||
extern VOID ( WINAPI * Real_EnterCriticalSection)(LPCRITICAL_SECTION lpSection);
|
||||
extern VOID ( WINAPI * Real_LeaveCriticalSection)(LPCRITICAL_SECTION lpSection);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////// VPrintf.
|
||||
//
|
||||
// Completely side-effect free printf replacement (but no FP numbers).
|
||||
//
|
||||
static PCHAR do_base(PCHAR pszOut, UINT64 nValue, UINT nBase, PCSTR pszDigits)
|
||||
{
|
||||
CHAR szTmp[96];
|
||||
int nDigit = sizeof(szTmp)-2;
|
||||
for (; nDigit >= 0; nDigit--) {
|
||||
szTmp[nDigit] = pszDigits[nValue % nBase];
|
||||
nValue /= nBase;
|
||||
}
|
||||
for (nDigit = 0; nDigit < sizeof(szTmp) - 2 && szTmp[nDigit] == '0'; nDigit++) {
|
||||
// skip leading zeros.
|
||||
}
|
||||
for (; nDigit < sizeof(szTmp) - 1; nDigit++) {
|
||||
*pszOut++ = szTmp[nDigit];
|
||||
}
|
||||
*pszOut = '\0';
|
||||
return pszOut;
|
||||
}
|
||||
|
||||
static PCHAR do_str(PCHAR pszOut, PCHAR pszEnd, PCSTR pszIn)
|
||||
{
|
||||
while (*pszIn && pszOut < pszEnd) {
|
||||
*pszOut++ = *pszIn++;
|
||||
}
|
||||
*pszOut = '\0';
|
||||
return pszOut;
|
||||
}
|
||||
|
||||
static PCHAR do_wstr(PCHAR pszOut, PCHAR pszEnd, PCWSTR pszIn)
|
||||
{
|
||||
while (*pszIn && pszOut < pszEnd) {
|
||||
*pszOut++ = (CHAR)*pszIn++;
|
||||
}
|
||||
*pszOut = '\0';
|
||||
return pszOut;
|
||||
}
|
||||
|
||||
static PCHAR do_estr(PCHAR pszOut, PCHAR pszEnd, PCSTR pszIn)
|
||||
{
|
||||
while (*pszIn && pszOut < pszEnd) {
|
||||
if (*pszIn == '<') {
|
||||
if (pszOut + 4 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'l';
|
||||
*pszOut++ = 't';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn == '>') {
|
||||
if (pszOut + 4 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'g';
|
||||
*pszOut++ = 't';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn == '&') {
|
||||
if (pszOut + 5 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'a';
|
||||
*pszOut++ = 'm';
|
||||
*pszOut++ = 'p';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn == '\"') {
|
||||
if (pszOut + 6 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'q';
|
||||
*pszOut++ = 'u';
|
||||
*pszOut++ = 'o';
|
||||
*pszOut++ = 't';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn == '\'') {
|
||||
if (pszOut + 6 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'a';
|
||||
*pszOut++ = 'p';
|
||||
*pszOut++ = 'o';
|
||||
*pszOut++ = 's';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn < ' ') {
|
||||
BYTE c = (BYTE)(*pszIn++);
|
||||
if (c < 10 && pszOut + 4 <= pszEnd) {
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = '#';
|
||||
*pszOut++ = '0' + (c % 10);
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (c < 100 && pszOut + 5 <= pszEnd) {
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = '#';
|
||||
*pszOut++ = '0' + ((c / 10) % 10);
|
||||
*pszOut++ = '0' + (c % 10);
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (c < 1000 && pszOut + 6 <= pszEnd) {
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = '#';
|
||||
*pszOut++ = '0' + ((c / 100) % 10);
|
||||
*pszOut++ = '0' + ((c / 10) % 10);
|
||||
*pszOut++ = '0' + (c % 10);
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*pszOut++ = *pszIn++;
|
||||
}
|
||||
}
|
||||
*pszOut = '\0';
|
||||
return pszOut;
|
||||
}
|
||||
|
||||
static PCHAR do_ewstr(PCHAR pszOut, PCHAR pszEnd, PCWSTR pszIn)
|
||||
{
|
||||
while (*pszIn && pszOut < pszEnd) {
|
||||
if (*pszIn == '<') {
|
||||
if (pszOut + 4 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'l';
|
||||
*pszOut++ = 't';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn == '>') {
|
||||
if (pszOut + 4 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'g';
|
||||
*pszOut++ = 't';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn == '&') {
|
||||
if (pszOut + 5 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'a';
|
||||
*pszOut++ = 'm';
|
||||
*pszOut++ = 'p';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn == '\"') {
|
||||
if (pszOut + 6 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'q';
|
||||
*pszOut++ = 'u';
|
||||
*pszOut++ = 'o';
|
||||
*pszOut++ = 't';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn == '\'') {
|
||||
if (pszOut + 6 > pszEnd) {
|
||||
break;
|
||||
}
|
||||
pszIn++;
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = 'a';
|
||||
*pszOut++ = 'p';
|
||||
*pszOut++ = 'o';
|
||||
*pszOut++ = 's';
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (*pszIn < ' ' || *pszIn > 127) {
|
||||
WCHAR c = *pszIn++;
|
||||
if (c < 10 && pszOut + 4 <= pszEnd) {
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = '#';
|
||||
*pszOut++ = '0' + (CHAR)(c % 10);
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (c < 100 && pszOut + 5 <= pszEnd) {
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = '#';
|
||||
*pszOut++ = '0' + (CHAR)((c / 10) % 10);
|
||||
*pszOut++ = '0' + (CHAR)(c % 10);
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else if (c < 1000 && pszOut + 6 <= pszEnd) {
|
||||
*pszOut++ = '&';
|
||||
*pszOut++ = '#';
|
||||
*pszOut++ = '0' + (CHAR)((c / 100) % 10);
|
||||
*pszOut++ = '0' + (CHAR)((c / 10) % 10);
|
||||
*pszOut++ = '0' + (CHAR)(c % 10);
|
||||
*pszOut++ = ';';
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*pszOut++ = (CHAR)*pszIn++;
|
||||
}
|
||||
}
|
||||
*pszOut = '\0';
|
||||
return pszOut;
|
||||
}
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4456) // declaration hides previous local declaration
|
||||
#endif
|
||||
|
||||
VOID VSafePrintf(PCSTR pszMsg, va_list args, PCHAR pszBuffer, LONG cbBuffer)
|
||||
{
|
||||
PCHAR pszOut = pszBuffer;
|
||||
PCHAR pszEnd = pszBuffer + cbBuffer - 1;
|
||||
pszBuffer[0] = '\0';
|
||||
|
||||
__try {
|
||||
while (*pszMsg && pszOut < pszEnd) {
|
||||
if (*pszMsg == '%') {
|
||||
CHAR szHead[4] = "";
|
||||
INT nLen;
|
||||
INT nWidth = 0;
|
||||
INT nPrecision = 0;
|
||||
BOOL fLeft = FALSE;
|
||||
BOOL fPositive = FALSE;
|
||||
BOOL fPound = FALSE;
|
||||
BOOL fBlank = FALSE;
|
||||
BOOL fZero = FALSE;
|
||||
BOOL fDigit = FALSE;
|
||||
BOOL fSmall = FALSE;
|
||||
BOOL fLarge = FALSE;
|
||||
BOOL f64Bit = FALSE;
|
||||
PCSTR pszArg = pszMsg;
|
||||
|
||||
pszMsg++;
|
||||
|
||||
for (; (*pszMsg == '-' ||
|
||||
*pszMsg == '+' ||
|
||||
*pszMsg == '#' ||
|
||||
*pszMsg == ' ' ||
|
||||
*pszMsg == '0'); pszMsg++) {
|
||||
switch (*pszMsg) {
|
||||
case '-': fLeft = TRUE; break;
|
||||
case '+': fPositive = TRUE; break;
|
||||
case '#': fPound = TRUE; break;
|
||||
case ' ': fBlank = TRUE; break;
|
||||
case '0': fZero = TRUE; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*pszMsg == '*') {
|
||||
nWidth = va_arg(args, INT);
|
||||
pszMsg++;
|
||||
}
|
||||
else {
|
||||
while (*pszMsg >= '0' && *pszMsg <= '9') {
|
||||
nWidth = nWidth * 10 + (*pszMsg++ - '0');
|
||||
}
|
||||
}
|
||||
if (*pszMsg == '.') {
|
||||
pszMsg++;
|
||||
fDigit = TRUE;
|
||||
if (*pszMsg == '*') {
|
||||
nPrecision = va_arg(args, INT);
|
||||
pszMsg++;
|
||||
}
|
||||
else {
|
||||
while (*pszMsg >= '0' && *pszMsg <= '9') {
|
||||
nPrecision = nPrecision * 10 + (*pszMsg++ - '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*pszMsg == 'h') {
|
||||
fSmall = TRUE;
|
||||
pszMsg++;
|
||||
}
|
||||
else if (*pszMsg == 'l') {
|
||||
fLarge = TRUE;
|
||||
pszMsg++;
|
||||
}
|
||||
else if (*pszMsg == 'I' && pszMsg[1] == '6' && pszMsg[2] == '4') {
|
||||
f64Bit = TRUE;
|
||||
pszMsg += 3;
|
||||
}
|
||||
|
||||
if (*pszMsg == 's' || *pszMsg == 'e' || *pszMsg == 'c') {
|
||||
// We ignore the length, precision, and alignment
|
||||
// to avoid using a temporary buffer.
|
||||
|
||||
if (*pszMsg == 's') { // [GalenH] need to not use temp.
|
||||
PVOID pvData = va_arg(args, PVOID);
|
||||
|
||||
pszMsg++;
|
||||
|
||||
if (fSmall) {
|
||||
fLarge = FALSE;
|
||||
}
|
||||
|
||||
__try {
|
||||
if (pvData == NULL) {
|
||||
pszOut = do_str(pszOut, pszEnd, "<NULL>");
|
||||
}
|
||||
else if (pvData < (PVOID)0x10000) {
|
||||
pszOut = do_str(pszOut, pszEnd, "#");
|
||||
pszOut = do_base(pszOut, (UINT64)pvData, 16,
|
||||
"0123456789ABCDEF");
|
||||
pszOut = do_str(pszOut, pszEnd, "#");
|
||||
}
|
||||
else if (fLarge) {
|
||||
pszOut = do_wstr(pszOut, pszEnd, (PWCHAR)pvData);
|
||||
}
|
||||
else {
|
||||
pszOut = do_str(pszOut, pszEnd, (PCHAR)pvData);
|
||||
}
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
pszOut = do_str(pszOut, pszEnd, "-");
|
||||
pszOut = do_base(pszOut, (UINT64)pvData, 16,
|
||||
"0123456789ABCDEF");
|
||||
pszOut = do_str(pszOut, pszEnd, "-");
|
||||
}
|
||||
}
|
||||
else if (*pszMsg == 'e') { // Escape the string.
|
||||
PVOID pvData = va_arg(args, PVOID);
|
||||
|
||||
pszMsg++;
|
||||
|
||||
if (fSmall) {
|
||||
fLarge = FALSE;
|
||||
}
|
||||
|
||||
__try {
|
||||
if (pvData == NULL) {
|
||||
pszOut = do_str(pszOut, pszEnd, "<NULL>");
|
||||
}
|
||||
else if (pvData < (PVOID)0x10000) {
|
||||
pszOut = do_str(pszOut, pszEnd, ">");
|
||||
pszOut = do_base(pszOut, (UINT64)pvData, 16,
|
||||
"0123456789ABCDEF");
|
||||
pszOut = do_str(pszOut, pszEnd, ">");
|
||||
}
|
||||
else if (fLarge) {
|
||||
pszOut = do_ewstr(pszOut, pszEnd, (PWCHAR)pvData);
|
||||
}
|
||||
else {
|
||||
pszOut = do_estr(pszOut, pszEnd, (PCHAR)pvData);
|
||||
}
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
pszOut = do_str(pszOut, pszEnd, "-");
|
||||
pszOut = do_base(pszOut, (UINT64)pvData, 16,
|
||||
"0123456789ABCDEF");
|
||||
pszOut = do_str(pszOut, pszEnd, "-");
|
||||
}
|
||||
}
|
||||
else {
|
||||
CHAR szTemp[2];
|
||||
pszMsg++;
|
||||
|
||||
szTemp[0] = (CHAR)va_arg(args, INT);
|
||||
szTemp[1] = '\0';
|
||||
pszOut = do_str(pszOut, pszEnd, szTemp);
|
||||
}
|
||||
}
|
||||
else if (*pszMsg == 'd' || *pszMsg == 'i' || *pszMsg == 'o' ||
|
||||
*pszMsg == 'x' || *pszMsg == 'X' || *pszMsg == 'b' ||
|
||||
*pszMsg == 'u') {
|
||||
CHAR szTemp[128];
|
||||
UINT64 value;
|
||||
if (f64Bit) {
|
||||
value = va_arg(args, UINT64);
|
||||
}
|
||||
else {
|
||||
value = va_arg(args, UINT);
|
||||
}
|
||||
|
||||
if (*pszMsg == 'x') {
|
||||
pszMsg++;
|
||||
nLen = (int)(do_base(szTemp, value, 16, "0123456789abcdef") - szTemp);
|
||||
if (fPound && value) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "0x");
|
||||
}
|
||||
}
|
||||
else if (*pszMsg == 'X') {
|
||||
pszMsg++;
|
||||
nLen = (int)(do_base(szTemp, value, 16, "0123456789ABCDEF") - szTemp);
|
||||
if (fPound && value) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "0X");
|
||||
}
|
||||
}
|
||||
else if (*pszMsg == 'd') {
|
||||
pszMsg++;
|
||||
if ((INT64)value < 0) {
|
||||
value = -(INT64)value;
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "-");
|
||||
}
|
||||
else if (fPositive) {
|
||||
if (value > 0) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "+");
|
||||
}
|
||||
}
|
||||
else if (fBlank) {
|
||||
if (value > 0) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, " ");
|
||||
}
|
||||
}
|
||||
nLen = (int)(do_base(szTemp, value, 10, "0123456789") - szTemp);
|
||||
nPrecision = 0;
|
||||
}
|
||||
else if (*pszMsg == 'u') {
|
||||
pszMsg++;
|
||||
nLen = (int)(do_base(szTemp, value, 10, "0123456789") - szTemp);
|
||||
nPrecision = 0;
|
||||
}
|
||||
else if (*pszMsg == 'o') {
|
||||
pszMsg++;
|
||||
nLen = (int)(do_base(szTemp, value, 8, "01234567") - szTemp);
|
||||
nPrecision = 0;
|
||||
|
||||
if (fPound && value) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "0");
|
||||
}
|
||||
}
|
||||
else if (*pszMsg == 'b') {
|
||||
pszMsg++;
|
||||
nLen = (int)(do_base(szTemp, value, 2, "01") - szTemp);
|
||||
nPrecision = 0;
|
||||
|
||||
if (fPound && value) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "0b");
|
||||
}
|
||||
}
|
||||
else {
|
||||
pszMsg++;
|
||||
if ((INT64)value < 0) {
|
||||
value = -(INT64)value;
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "-");
|
||||
}
|
||||
else if (fPositive) {
|
||||
if (value > 0) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "+");
|
||||
}
|
||||
}
|
||||
else if (fBlank) {
|
||||
if (value > 0) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, " ");
|
||||
}
|
||||
}
|
||||
nLen = (int)(do_base(szTemp, value, 10, "0123456789") - szTemp);
|
||||
nPrecision = 0;
|
||||
}
|
||||
|
||||
INT nHead = 0;
|
||||
for (; szHead[nHead]; nHead++) {
|
||||
// Count characters in head string.
|
||||
}
|
||||
|
||||
if (fLeft) {
|
||||
if (nHead) {
|
||||
pszOut = do_str(pszOut, pszEnd, szHead);
|
||||
nLen += nHead;
|
||||
}
|
||||
pszOut = do_str(pszOut, pszEnd, szTemp);
|
||||
for (; nLen < nWidth && pszOut < pszEnd; nLen++) {
|
||||
*pszOut++ = ' ';
|
||||
}
|
||||
}
|
||||
else if (fZero) {
|
||||
if (nHead) {
|
||||
pszOut = do_str(pszOut, pszEnd, szHead);
|
||||
nLen += nHead;
|
||||
}
|
||||
for (; nLen < nWidth && pszOut < pszEnd; nLen++) {
|
||||
*pszOut++ = '0';
|
||||
}
|
||||
pszOut = do_str(pszOut, pszEnd, szTemp);
|
||||
}
|
||||
else {
|
||||
if (nHead) {
|
||||
nLen += nHead;
|
||||
}
|
||||
for (; nLen < nWidth && pszOut < pszEnd; nLen++) {
|
||||
*pszOut++ = ' ';
|
||||
}
|
||||
if (nHead) {
|
||||
pszOut = do_str(pszOut, pszEnd, szHead);
|
||||
}
|
||||
pszOut = do_str(pszOut, pszEnd, szTemp);
|
||||
}
|
||||
}
|
||||
else if (*pszMsg == 'p') {
|
||||
CHAR szTemp[64];
|
||||
ULONG_PTR value;
|
||||
value = va_arg(args, ULONG_PTR);
|
||||
|
||||
if ((INT64)value == (INT64)-1 ||
|
||||
(INT64)value == (INT64)-2) {
|
||||
if (*pszMsg == 'p') {
|
||||
pszMsg++;
|
||||
}
|
||||
szTemp[0] = '-';
|
||||
szTemp[1] = ((INT64)value == (INT64)-1) ? '1' : '2';
|
||||
szTemp[2] = '\0';
|
||||
nLen = 2;
|
||||
}
|
||||
else {
|
||||
if (*pszMsg == 'p') {
|
||||
pszMsg++;
|
||||
nLen = (int)(do_base(szTemp, (UINT64)value, 16, "0123456789abcdef") - szTemp);
|
||||
if (fPound && value) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "0x");
|
||||
}
|
||||
}
|
||||
else {
|
||||
pszMsg++;
|
||||
nLen = (int)(do_base(szTemp, (UINT64)value, 16, "0123456789ABCDEF") - szTemp);
|
||||
if (fPound && value) {
|
||||
do_str(szHead, szHead + sizeof(szHead) - 1, "0x");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT nHead = 0;
|
||||
for (; szHead[nHead]; nHead++) {
|
||||
// Count characters in head string.
|
||||
}
|
||||
|
||||
if (nHead) {
|
||||
pszOut = do_str(pszOut, pszEnd, szHead);
|
||||
nLen += nHead;
|
||||
}
|
||||
for (; nLen < nWidth && pszOut < pszEnd; nLen++) {
|
||||
*pszOut++ = '0';
|
||||
}
|
||||
pszOut = do_str(pszOut, pszEnd, szTemp);
|
||||
}
|
||||
else {
|
||||
pszMsg++;
|
||||
while (pszArg < pszMsg && pszOut < pszEnd) {
|
||||
*pszOut++ = *pszArg++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pszOut < pszEnd) {
|
||||
*pszOut++ = *pszMsg++;
|
||||
}
|
||||
}
|
||||
}
|
||||
*pszOut = '\0';
|
||||
pszBuffer[cbBuffer - 1] = '\0';
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
PCHAR pszOut = pszBuffer;
|
||||
*pszOut = '\0';
|
||||
pszOut = do_str(pszOut, pszEnd, "-exception:");
|
||||
pszOut = do_base(pszOut, (UINT64)GetExceptionCode(), 10, "0123456789");
|
||||
pszOut = do_str(pszOut, pszEnd, "-");
|
||||
}
|
||||
}
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
PCHAR SafePrintf(PCHAR pszBuffer, LONG cbBuffer, PCSTR pszMsg, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, pszMsg);
|
||||
VSafePrintf(pszMsg, args, pszBuffer, cbBuffer);
|
||||
va_end(args);
|
||||
|
||||
while (*pszBuffer) {
|
||||
pszBuffer++;
|
||||
}
|
||||
return pszBuffer;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
static CRITICAL_SECTION s_csPipe; // Guards access to hPipe.
|
||||
static HANDLE s_hPipe = INVALID_HANDLE_VALUE;
|
||||
static DWORD s_nPipeError = 0;
|
||||
static FILETIME s_ftRetry = {0,0};
|
||||
static BYTE s_nFacility = SYELOG_FACILITY_APPLICATION;
|
||||
static CHAR s_szIdent[256] = "";
|
||||
static DWORD s_nProcessId = 0;
|
||||
|
||||
static inline INT syelogCompareTimes(CONST PFILETIME pft1, CONST PFILETIME pft2)
|
||||
{
|
||||
INT64 ut1 = *(PINT64)pft1;
|
||||
INT64 ut2 = *(PINT64)pft2;
|
||||
|
||||
if (ut1 < ut2) {
|
||||
return -1;
|
||||
}
|
||||
else if (ut1 > ut2) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline VOID syelogAddMilliseconds(PFILETIME pft, DWORD nMilliseconds)
|
||||
{
|
||||
*(PINT64&)pft += ((INT64)nMilliseconds * 10000);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Tries to insure that a named-pipe connection to the system log is open
|
||||
// If the pipe closes, the next call will immediately try to re-open the pipe.
|
||||
// If the pipe doesn't open again, we wait 5 minutes before trying again.
|
||||
// We wait 5 minutes, because each attempt may take up to a full second to
|
||||
// time out.
|
||||
//
|
||||
static BOOL syelogIsOpen(PFILETIME pftLog)
|
||||
{
|
||||
if (s_hPipe != INVALID_HANDLE_VALUE) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (syelogCompareTimes(pftLog, &s_ftRetry) < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s_hPipe = Real_CreateFileW(SYELOG_PIPE_NAMEW,
|
||||
GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
||||
SECURITY_ANONYMOUS, NULL);
|
||||
if (s_hPipe != INVALID_HANDLE_VALUE) {
|
||||
DWORD dwMode = PIPE_READMODE_MESSAGE;
|
||||
if (Real_SetNamedPipeHandleState(s_hPipe, &dwMode, NULL, NULL)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (Real_WaitNamedPipeW(SYELOG_PIPE_NAMEW, 2000)) { // Wait 2 seconds.
|
||||
// Pipe connected, change to message-read mode.
|
||||
//
|
||||
s_hPipe = Real_CreateFileW(SYELOG_PIPE_NAMEW,
|
||||
GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
||||
SECURITY_ANONYMOUS, NULL);
|
||||
if (s_hPipe != INVALID_HANDLE_VALUE) {
|
||||
DWORD dwMode = PIPE_READMODE_MESSAGE;
|
||||
if (Real_SetNamedPipeHandleState(s_hPipe, &dwMode, NULL, NULL)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't open pipe.
|
||||
s_ftRetry = *pftLog;
|
||||
syelogAddMilliseconds(&s_ftRetry, 300000); // Wait 5 minute before retry.
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID SyelogOpen(PCSTR pszIdentifier, BYTE nFacility)
|
||||
{
|
||||
Real_InitializeCriticalSection(&s_csPipe);
|
||||
|
||||
if (pszIdentifier) {
|
||||
PCHAR pszOut = s_szIdent;
|
||||
PCHAR pszEnd = s_szIdent + ARRAYSIZE(s_szIdent) - 1;
|
||||
pszOut = do_str(pszOut, pszEnd, pszIdentifier);
|
||||
pszOut = do_str(pszOut, pszEnd, ": ");
|
||||
*pszEnd = '\0';
|
||||
}
|
||||
else {
|
||||
s_szIdent[0] = '\0';
|
||||
}
|
||||
|
||||
s_nFacility = nFacility;
|
||||
s_nProcessId = Real_GetCurrentProcessId();
|
||||
}
|
||||
|
||||
VOID SyelogExV(BOOL fTerminate, BYTE nSeverity, PCSTR pszMsgf, va_list args)
|
||||
{
|
||||
SYELOG_MESSAGE Message;
|
||||
DWORD cbWritten = 0;
|
||||
|
||||
Real_GetSystemTimeAsFileTime(&Message.ftOccurance);
|
||||
Message.fTerminate = fTerminate;
|
||||
Message.nFacility = s_nFacility;
|
||||
Message.nSeverity = nSeverity;
|
||||
Message.nProcessId = s_nProcessId;
|
||||
PCHAR pszBuf = Message.szMessage;
|
||||
PCHAR pszEnd = Message.szMessage + ARRAYSIZE(Message.szMessage) - 1;
|
||||
if (s_szIdent[0]) {
|
||||
pszBuf = do_str(pszBuf, pszEnd, s_szIdent);
|
||||
}
|
||||
*pszEnd = '\0';
|
||||
VSafePrintf(pszMsgf, args,
|
||||
pszBuf, (int)(Message.szMessage + sizeof(Message.szMessage) - 1 - pszBuf));
|
||||
|
||||
pszEnd = Message.szMessage;
|
||||
for (; *pszEnd; pszEnd++) {
|
||||
// no internal contents.
|
||||
}
|
||||
|
||||
// Insure that the message always ends with a '\n'
|
||||
//
|
||||
if (pszEnd > Message.szMessage) {
|
||||
if (pszEnd[-1] != '\n') {
|
||||
*pszEnd++ = '\n';
|
||||
*pszEnd++ = '\0';
|
||||
}
|
||||
else {
|
||||
*pszEnd++ = '\0';
|
||||
}
|
||||
}
|
||||
else {
|
||||
*pszEnd++ = '\n';
|
||||
*pszEnd++ = '\0';
|
||||
}
|
||||
Message.nBytes = (USHORT)(pszEnd - ((PCSTR)&Message));
|
||||
|
||||
Real_EnterCriticalSection(&s_csPipe);
|
||||
|
||||
if (syelogIsOpen(&Message.ftOccurance)) {
|
||||
if (!Real_WriteFile(s_hPipe, &Message, Message.nBytes, &cbWritten, NULL)) {
|
||||
s_nPipeError = GetLastError();
|
||||
if (s_nPipeError == ERROR_BAD_IMPERSONATION_LEVEL) {
|
||||
// Don't close the file just for a temporary impersonation level.
|
||||
}
|
||||
else {
|
||||
if (s_hPipe != INVALID_HANDLE_VALUE) {
|
||||
Real_CloseHandle(s_hPipe);
|
||||
s_hPipe = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (syelogIsOpen(&Message.ftOccurance)) {
|
||||
Real_WriteFile(s_hPipe, &Message, Message.nBytes, &cbWritten, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Real_LeaveCriticalSection(&s_csPipe);
|
||||
}
|
||||
|
||||
VOID SyelogV(BYTE nSeverity, PCSTR pszMsgf, va_list args)
|
||||
{
|
||||
SyelogExV(FALSE, nSeverity, pszMsgf, args);
|
||||
}
|
||||
|
||||
VOID Syelog(BYTE nSeverity, PCSTR pszMsgf, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, pszMsgf);
|
||||
SyelogExV(FALSE, nSeverity, pszMsgf, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
VOID SyelogEx(BOOL fTerminate, BYTE nSeverity, PCSTR pszMsgf, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, pszMsgf);
|
||||
SyelogExV(fTerminate, nSeverity, pszMsgf, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
VOID SyelogClose(BOOL fTerminate)
|
||||
{
|
||||
if (fTerminate) {
|
||||
SyelogEx(TRUE, SYELOG_SEVERITY_NOTICE, "Requesting exit on close.\n");
|
||||
}
|
||||
|
||||
Real_EnterCriticalSection(&s_csPipe);
|
||||
|
||||
if (s_hPipe != INVALID_HANDLE_VALUE) {
|
||||
Real_FlushFileBuffers(s_hPipe);
|
||||
Real_CloseHandle(s_hPipe);
|
||||
s_hPipe = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
Real_LeaveCriticalSection(&s_csPipe);
|
||||
}
|
||||
//
|
||||
///////////////////////////////////////////////////////////////// End of File.
|
||||
89
test/Detours/samples/syelog/syelog.h
Normal file
89
test/Detours/samples/syelog/syelog.h
Normal file
@@ -0,0 +1,89 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Detours Test Program (syelog.h of syelog.lib)
|
||||
//
|
||||
// Microsoft Research Detours Package
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
#pragma once
|
||||
#ifndef _SYELOGD_H_
|
||||
#define _SYELOGD_H_
|
||||
#include <stdarg.h>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4200)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
#define SYELOG_PIPE_NAMEA "\\\\.\\pipe\\syelog"
|
||||
#define SYELOG_PIPE_NAMEW L"\\\\.\\pipe\\syelog"
|
||||
#ifdef UNICODE
|
||||
#define SYELOG_PIPE_NAME SYELOG_PIPE_NAMEW
|
||||
#else
|
||||
#define SYELOG_PIPE_NAME SYELOG_PIPE_NAMEA
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
#define SYELOG_MAXIMUM_MESSAGE 4086 // 4096 - sizeof(header stuff)
|
||||
|
||||
typedef struct _SYELOG_MESSAGE
|
||||
{
|
||||
USHORT nBytes;
|
||||
BYTE nFacility;
|
||||
BYTE nSeverity;
|
||||
DWORD nProcessId;
|
||||
FILETIME ftOccurance;
|
||||
BOOL fTerminate;
|
||||
CHAR szMessage[SYELOG_MAXIMUM_MESSAGE];
|
||||
} SYELOG_MESSAGE, *PSYELOG_MESSAGE;
|
||||
|
||||
|
||||
// Facility Codes.
|
||||
//
|
||||
#define SYELOG_FACILITY_KERNEL 0x10 // OS Kernel
|
||||
#define SYELOG_FACILITY_SECURITY 0x20 // OS Security
|
||||
#define SYELOG_FACILITY_LOGGING 0x30 // OS Logging-internal
|
||||
#define SYELOG_FACILITY_SERVICE 0x40 // User-mode system daemon
|
||||
#define SYELOG_FACILITY_APPLICATION 0x50 // User-mode application
|
||||
#define SYELOG_FACILITY_USER 0x60 // User self-generated.
|
||||
#define SYELOG_FACILITY_LOCAL0 0x70 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL1 0x71 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL2 0x72 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL3 0x73 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL4 0x74 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL5 0x75 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL6 0x76 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL7 0x77 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL8 0x78 // Locally defined.
|
||||
#define SYELOG_FACILITY_LOCAL9 0x79 // Locally defined.
|
||||
|
||||
// Severity Codes.
|
||||
//
|
||||
#define SYELOG_SEVERITY_FATAL 0x00 // System is dead.
|
||||
#define SYELOG_SEVERITY_ALERT 0x10 // Take action immediately.
|
||||
#define SYELOG_SEVERITY_CRITICAL 0x20 // Critical condition.
|
||||
#define SYELOG_SEVERITY_ERROR 0x30 // Error
|
||||
#define SYELOG_SEVERITY_WARNING 0x40 // Warning
|
||||
#define SYELOG_SEVERITY_NOTICE 0x50 // Significant condition.
|
||||
#define SYELOG_SEVERITY_INFORMATION 0x60 // Informational
|
||||
#define SYELOG_SEVERITY_AUDIT_FAIL 0x66 // Audit Failed
|
||||
#define SYELOG_SEVERITY_AUDIT_PASS 0x67 // Audit Succeeeded
|
||||
#define SYELOG_SEVERITY_DEBUG 0x70 // Debugging
|
||||
|
||||
// Logging Functions.
|
||||
//
|
||||
VOID SyelogOpen(PCSTR pszIdentifier, BYTE nFacility);
|
||||
VOID Syelog(BYTE nSeverity, PCSTR pszMsgf, ...);
|
||||
VOID SyelogV(BYTE nSeverity, PCSTR pszMsgf, va_list args);
|
||||
VOID SyelogClose(BOOL fTerminate);
|
||||
|
||||
#pragma warning(pop)
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // _SYELOGD_H_
|
||||
//
|
||||
///////////////////////////////////////////////////////////////// End of File.
|
||||
556
test/Detours/samples/syelog/syelogd.cpp
Normal file
556
test/Detours/samples/syelog/syelogd.cpp
Normal file
@@ -0,0 +1,556 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Detours Test Program (syelogd.cpp of syelogd.exe)
|
||||
//
|
||||
// Microsoft Research Detours Package
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#pragma warning(push)
|
||||
#if _MSC_VER > 1400
|
||||
#pragma warning(disable:6102 6103) // /analyze warnings
|
||||
#endif
|
||||
#include <strsafe.h>
|
||||
#pragma warning(pop)
|
||||
#include "syelog.h"
|
||||
|
||||
#if (_MSC_VER < 1299)
|
||||
typedef ULONG * PULONG_PTR;
|
||||
typedef ULONG ULONG_PTR;
|
||||
typedef LONG * PLONG_PTR;
|
||||
typedef LONG LONG_PTR;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
CLIENT_AWAITING_PIPE_ACCEPT = 0x21,
|
||||
CLIENT_AWAITING_PIPE_DATA = 0x22,
|
||||
};
|
||||
|
||||
typedef struct _CLIENT : OVERLAPPED
|
||||
{
|
||||
HANDLE hPipe;
|
||||
BOOL fAwaitingAccept;
|
||||
PVOID Zero;
|
||||
SYELOG_MESSAGE Message;
|
||||
} CLIENT, *PCLIENT;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
BOOL s_fLogToScreen = TRUE; // Log output to screen.
|
||||
BOOL s_fExitAfterOne = FALSE;
|
||||
BOOL s_fDeltaTime = FALSE;
|
||||
HANDLE s_hOutFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
LONG s_nActiveClients = 0;
|
||||
LONGLONG s_llStartTime = 0;
|
||||
LONGLONG s_llLastTime = 0;
|
||||
|
||||
BOOL LogMessageV(BYTE nSeverity, PCHAR pszMsg, ...);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
VOID MyErrExit(PCSTR pszMsg)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
|
||||
LogMessageV(SYELOG_SEVERITY_FATAL, "Error %d in %s.", error, pszMsg);
|
||||
fprintf(stderr, "SYELOGD: Error %ld in %s.\n", error, pszMsg);
|
||||
fflush(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
static PCSTR FileTimeToString(PCHAR pszBuffer, DWORD cbBuffer, FILETIME ftTime)
|
||||
{
|
||||
(void)cbBuffer;
|
||||
|
||||
static BOOL bGotTzi = FALSE;
|
||||
static DWORD dwTzi = TIME_ZONE_ID_UNKNOWN;
|
||||
static TIME_ZONE_INFORMATION tzi;
|
||||
if (!bGotTzi) {
|
||||
dwTzi = GetTimeZoneInformation(&tzi);
|
||||
if (dwTzi == TIME_ZONE_ID_UNKNOWN) {
|
||||
ZeroMemory(&tzi, sizeof(tzi));
|
||||
}
|
||||
bGotTzi = TRUE;
|
||||
}
|
||||
SYSTEMTIME stUtc;
|
||||
SYSTEMTIME stLocal;
|
||||
|
||||
pszBuffer[0] = '\0';
|
||||
|
||||
if (s_fDeltaTime) {
|
||||
if (s_llLastTime == 0) {
|
||||
s_llLastTime = s_llStartTime;
|
||||
}
|
||||
|
||||
ULARGE_INTEGER ul;
|
||||
ul.LowPart = ftTime.dwLowDateTime;
|
||||
ul.HighPart = ftTime.dwHighDateTime;
|
||||
|
||||
LONG64 delta = ul.QuadPart - s_llLastTime;
|
||||
s_llLastTime = ul.QuadPart;
|
||||
delta /= 10000;
|
||||
|
||||
StringCchPrintfA(pszBuffer, cbBuffer, "%7I64d", delta);
|
||||
}
|
||||
else {
|
||||
if (!FileTimeToSystemTime(&ftTime, &stUtc)) {
|
||||
StringCchPrintfA(pszBuffer, cbBuffer, "ft:%16I64d", *(LONGLONG *)&ftTime);
|
||||
return pszBuffer;
|
||||
}
|
||||
else if (!SystemTimeToTzSpecificLocalTime(&tzi, &stUtc, &stLocal)) {
|
||||
CopyMemory(&stLocal, &stUtc, sizeof(stLocal));
|
||||
}
|
||||
|
||||
StringCchPrintfA(pszBuffer, cbBuffer, "%4d%02d%02d%02d%02d%02d%03d",
|
||||
stLocal.wYear,
|
||||
stLocal.wMonth,
|
||||
stLocal.wDay,
|
||||
stLocal.wHour,
|
||||
stLocal.wMinute,
|
||||
stLocal.wSecond,
|
||||
stLocal.wMilliseconds);
|
||||
}
|
||||
return pszBuffer;
|
||||
}
|
||||
|
||||
BOOL CloseConnection(PCLIENT pClient)
|
||||
{
|
||||
LogMessageV(SYELOG_SEVERITY_INFORMATION, "Client closed pipe.");
|
||||
|
||||
InterlockedDecrement(&s_nActiveClients);
|
||||
if (pClient != NULL) {
|
||||
if (pClient->hPipe != INVALID_HANDLE_VALUE) {
|
||||
FlushFileBuffers(pClient->hPipe);
|
||||
if (!DisconnectNamedPipe(pClient->hPipe)) {
|
||||
MyErrExit("DisconnectNamedPipe");
|
||||
}
|
||||
CloseHandle(pClient->hPipe);
|
||||
pClient->hPipe = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
GlobalFree(pClient);
|
||||
pClient = NULL;
|
||||
}
|
||||
|
||||
if (s_fExitAfterOne) {
|
||||
ExitProcess(0);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Creates a pipe instance and initiate an accept request.
|
||||
//
|
||||
PCLIENT CreatePipeConnection(HANDLE hCompletionPort)
|
||||
{
|
||||
HANDLE hPipe = CreateNamedPipe(SYELOG_PIPE_NAME, // pipe name
|
||||
PIPE_ACCESS_INBOUND | // read-only access
|
||||
FILE_FLAG_OVERLAPPED, // overlapped mode
|
||||
PIPE_TYPE_MESSAGE | // message-type pipe
|
||||
PIPE_READMODE_MESSAGE | // message read mode
|
||||
PIPE_WAIT, // blocking mode
|
||||
PIPE_UNLIMITED_INSTANCES, // unlimited instances
|
||||
0, // output buffer size
|
||||
0, // input buffer size
|
||||
20000, // client time-out
|
||||
NULL); // no security attributes
|
||||
if (hPipe == INVALID_HANDLE_VALUE) {
|
||||
MyErrExit("CreatePipe");
|
||||
}
|
||||
|
||||
// Allocate the client data structure.
|
||||
//
|
||||
PCLIENT pClient = (PCLIENT) GlobalAlloc(GPTR, sizeof(CLIENT));
|
||||
if (pClient == NULL) {
|
||||
MyErrExit("GlobalAlloc pClient");
|
||||
}
|
||||
|
||||
ZeroMemory(pClient, sizeof(*pClient));
|
||||
pClient->hPipe = hPipe;
|
||||
pClient->fAwaitingAccept = TRUE;
|
||||
|
||||
// Associate file with our complietion port.
|
||||
//
|
||||
if (!CreateIoCompletionPort(pClient->hPipe, hCompletionPort, (ULONG_PTR)pClient, 0)) {
|
||||
MyErrExit("CreateIoComplietionPort pClient");
|
||||
}
|
||||
|
||||
if (!ConnectNamedPipe(hPipe, pClient)) {
|
||||
if (GetLastError() != ERROR_IO_PENDING &&
|
||||
GetLastError() != ERROR_PIPE_LISTENING) {
|
||||
MyErrExit("ConnectNamedPipe");
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogMessageV(SYELOG_SEVERITY_INFORMATION,
|
||||
"ConnectNamedPipe accepted immediately.");
|
||||
}
|
||||
return pClient;
|
||||
}
|
||||
|
||||
BOOL LogMessageV(BYTE nSeverity, PCHAR pszMsg, ...)
|
||||
{
|
||||
FILETIME ftOccurance;
|
||||
CHAR szTime[64];
|
||||
GetSystemTimeAsFileTime(&ftOccurance);
|
||||
FileTimeToString(szTime, sizeof(szTime), ftOccurance);
|
||||
|
||||
if (s_fLogToScreen) {
|
||||
printf(s_fDeltaTime
|
||||
? "%-7.7s ---- --.%02x: "
|
||||
: "%-17.17s ---- --.%02x: "
|
||||
, szTime, nSeverity);
|
||||
va_list args;
|
||||
va_start(args, pszMsg);
|
||||
vprintf(pszMsg, args);
|
||||
va_end(args);
|
||||
printf("\n");
|
||||
}
|
||||
if (s_hOutFile != INVALID_HANDLE_VALUE) {
|
||||
DWORD cbWritten = 0;
|
||||
CHAR szBuf[4096] = "";
|
||||
PCHAR pcchEnd = szBuf + ARRAYSIZE(szBuf) - 2;
|
||||
PCHAR pcchCur = szBuf;
|
||||
HRESULT hr;
|
||||
|
||||
hr = StringCchPrintfExA(pcchCur, pcchEnd - pcchCur,
|
||||
&pcchCur, NULL, STRSAFE_NULL_ON_FAILURE,
|
||||
s_fDeltaTime
|
||||
? "%-7.7s ---- --.%02x: "
|
||||
: "%-17.17s ---- --.%02x: "
|
||||
, szTime, nSeverity);
|
||||
if (FAILED(hr)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, pszMsg);
|
||||
hr = StringCchPrintfExA(pcchCur, pcchEnd - pcchCur,
|
||||
&pcchCur, NULL, STRSAFE_NULL_ON_FAILURE,
|
||||
pszMsg, args);
|
||||
va_end(args);
|
||||
if (FAILED(hr)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
hr = StringCchPrintfExA(pcchCur, (szBuf + ARRAYSIZE(szBuf)) - pcchCur,
|
||||
&pcchCur, NULL, STRSAFE_NULL_ON_FAILURE,
|
||||
"\n");
|
||||
if (FAILED(hr)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
Cleanup:
|
||||
WriteFile(s_hOutFile, szBuf, (DWORD)(pcchCur - szBuf), &cbWritten, NULL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LogMessage(PSYELOG_MESSAGE pMessage, DWORD nBytes)
|
||||
{
|
||||
// Sanity check the size of the message.
|
||||
//
|
||||
if (nBytes > pMessage->nBytes) {
|
||||
nBytes = pMessage->nBytes;
|
||||
}
|
||||
if (nBytes >= sizeof(*pMessage)) {
|
||||
nBytes = sizeof(*pMessage) - 1;
|
||||
}
|
||||
|
||||
// Don't log message if there isn't and message text.
|
||||
//
|
||||
if (nBytes <= offsetof(SYELOG_MESSAGE, szMessage)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CHAR szTime[64];
|
||||
FileTimeToString(szTime, sizeof(szTime), pMessage->ftOccurance);
|
||||
|
||||
PCHAR pszMsg = pMessage->szMessage;
|
||||
while (*pszMsg) {
|
||||
pszMsg++;
|
||||
}
|
||||
while (pszMsg > pMessage->szMessage && isspace(pszMsg[-1])) {
|
||||
*--pszMsg = '\0';
|
||||
}
|
||||
|
||||
if (s_fLogToScreen) {
|
||||
printf(s_fDeltaTime
|
||||
? "%-7.7s %4d %02x.%02x: %s\n"
|
||||
: "%-17.17s %4d %02x.%02x: %s\n",
|
||||
szTime,
|
||||
pMessage->nProcessId,
|
||||
pMessage->nFacility,
|
||||
pMessage->nSeverity,
|
||||
pMessage->szMessage);
|
||||
}
|
||||
if (s_hOutFile != INVALID_HANDLE_VALUE) {
|
||||
DWORD cbWritten = 0;
|
||||
CHAR szBuf[4096];
|
||||
PCHAR pcchEnd = szBuf + ARRAYSIZE(szBuf);
|
||||
PCHAR pcchCur = szBuf;
|
||||
HRESULT hr;
|
||||
|
||||
hr = StringCchPrintfExA(pcchCur, pcchEnd - pcchCur,
|
||||
&pcchCur, NULL, STRSAFE_NULL_ON_FAILURE,
|
||||
s_fDeltaTime
|
||||
? "%-7.7s %4d %02x.%02x: %s\n"
|
||||
: "%-17.17s %4d %02x.%02x: %s\n",
|
||||
szTime,
|
||||
pMessage->nProcessId,
|
||||
pMessage->nFacility,
|
||||
pMessage->nSeverity,
|
||||
pMessage->szMessage);
|
||||
if (FAILED(hr)) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
Cleanup:
|
||||
WriteFile(s_hOutFile, szBuf, (DWORD)(pcchCur - szBuf), &cbWritten, NULL);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD WINAPI WorkerThread(LPVOID pvVoid)
|
||||
{
|
||||
PCLIENT pClient;
|
||||
BOOL b;
|
||||
LPOVERLAPPED lpo;
|
||||
DWORD nBytes;
|
||||
HANDLE hCompletionPort = (HANDLE)pvVoid;
|
||||
|
||||
for (BOOL fKeepLooping = TRUE; fKeepLooping;) {
|
||||
pClient = NULL;
|
||||
lpo = NULL;
|
||||
nBytes = 0;
|
||||
b = GetQueuedCompletionStatus(hCompletionPort,
|
||||
&nBytes, (PULONG_PTR)&pClient, &lpo, INFINITE);
|
||||
|
||||
if (!b || lpo == NULL) {
|
||||
fKeepLooping = FALSE;
|
||||
MyErrExit("GetQueuedCompletionState");
|
||||
break;
|
||||
}
|
||||
else if (!b) {
|
||||
if (pClient) {
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE) {
|
||||
LogMessageV(SYELOG_SEVERITY_INFORMATION, "Client closed pipe.");
|
||||
}
|
||||
else {
|
||||
LogMessageV(SYELOG_SEVERITY_ERROR,
|
||||
"GetQueuedCompletionStatus failed %d [%p]",
|
||||
GetLastError(), pClient);
|
||||
}
|
||||
CloseConnection(pClient);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pClient->fAwaitingAccept) {
|
||||
InterlockedIncrement(&s_nActiveClients);
|
||||
pClient->fAwaitingAccept = FALSE;
|
||||
b = ReadFile(pClient->hPipe,
|
||||
&pClient->Message,
|
||||
sizeof(pClient->Message),
|
||||
&nBytes,
|
||||
pClient);
|
||||
if (!b) {
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
LogMessageV(SYELOG_SEVERITY_ERROR,
|
||||
"ReadFile failed %d.", GetLastError());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
CreatePipeConnection(hCompletionPort);
|
||||
}
|
||||
else {
|
||||
if (nBytes < offsetof(SYELOG_MESSAGE, szMessage)) {
|
||||
CloseConnection(pClient);
|
||||
}
|
||||
|
||||
if (pClient->Message.fTerminate) {
|
||||
LogMessageV(SYELOG_SEVERITY_NOTICE,
|
||||
"Client requested terminate on next connection close.");
|
||||
s_fExitAfterOne = TRUE;
|
||||
}
|
||||
|
||||
LogMessage(&pClient->Message, nBytes);
|
||||
|
||||
b = ReadFile(pClient->hPipe,
|
||||
&pClient->Message,
|
||||
sizeof(pClient->Message),
|
||||
&nBytes,
|
||||
pClient);
|
||||
if (!b && GetLastError() == ERROR_BROKEN_PIPE) {
|
||||
CloseConnection(pClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL CreateWorkers(HANDLE hCompletionPort)
|
||||
{
|
||||
DWORD dwThread;
|
||||
HANDLE hThread;
|
||||
DWORD i;
|
||||
SYSTEM_INFO SystemInfo;
|
||||
|
||||
GetSystemInfo(&SystemInfo);
|
||||
|
||||
for (i = 0; i < 2 * SystemInfo.dwNumberOfProcessors; i++) {
|
||||
hThread = CreateThread(NULL, 0, WorkerThread, hCompletionPort, 0, &dwThread);
|
||||
if (!hThread) {
|
||||
MyErrExit("CreateThread WorkerThread");
|
||||
// Unreachable: return FALSE;
|
||||
}
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
switch (dwCtrlType) {
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
LogMessageV(SYELOG_SEVERITY_INFORMATION, "User requested stop.");
|
||||
printf("\nSYELOGD: Closing connections.\n");
|
||||
if (s_hOutFile != INVALID_HANDLE_VALUE) {
|
||||
printf("Closing file.\n");
|
||||
FlushFileBuffers(s_hOutFile);
|
||||
CloseHandle(s_hOutFile);
|
||||
s_hOutFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
ExitProcess(0);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD main(int argc, char **argv)
|
||||
{
|
||||
HANDLE hCompletionPort;
|
||||
BOOL fNeedHelp = FALSE;
|
||||
|
||||
GetSystemTimeAsFileTime((FILETIME *)&s_llStartTime);
|
||||
SetConsoleCtrlHandler(ControlHandler, TRUE);
|
||||
|
||||
int arg = 1;
|
||||
for (; arg < argc; arg++) {
|
||||
if (argv[arg][0] == '-' || argv[arg][0] == '/') {
|
||||
CHAR *argn = argv[arg] + 1;
|
||||
CHAR *argp = argn;
|
||||
while (*argp && *argp != ':') {
|
||||
argp++;
|
||||
}
|
||||
if (*argp == ':') {
|
||||
*argp++ = '\0';
|
||||
}
|
||||
|
||||
switch (argn[0]) {
|
||||
|
||||
case 'd': // Delta time.
|
||||
case 'D':
|
||||
s_fDeltaTime = TRUE;
|
||||
break;
|
||||
|
||||
case 'o': // Only one.
|
||||
case 'O':
|
||||
s_fExitAfterOne = TRUE;
|
||||
break;
|
||||
|
||||
case 'q': // Quiet.
|
||||
case 'Q':
|
||||
s_fLogToScreen = FALSE;
|
||||
break;
|
||||
|
||||
case '?': // Help.
|
||||
fNeedHelp = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
fNeedHelp = TRUE;
|
||||
printf("SYELOGD: Bad argument: %s:%s\n", argn, argp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (s_hOutFile != INVALID_HANDLE_VALUE) {
|
||||
printf("SYELOGD: Error, more than one output file specified.\n\n");
|
||||
fNeedHelp = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
s_hOutFile = CreateFileA(argv[arg],
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL |
|
||||
FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
NULL);
|
||||
if (s_hOutFile == INVALID_HANDLE_VALUE) {
|
||||
printf("SYELOGD: Error opening output file: %s: %ld\n\n",
|
||||
argv[arg], GetLastError());
|
||||
fNeedHelp = TRUE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
printf("SYELOGD: Logging to %s.\n", argv[arg]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fNeedHelp) {
|
||||
printf("Usage:\n"
|
||||
" syelogd [options] {output_file}\n"
|
||||
"Options:\n"
|
||||
" /d List delta time in ms from previous event (not absolute time).\n"
|
||||
" /o Exit after one client disconnects.\n"
|
||||
" /q Disable event logging to screen (quiet mode).\n"
|
||||
" /? Display this help message.\n"
|
||||
"Summary:\n"
|
||||
" If given, all events will be logged to the output file.\n"
|
||||
"\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// Create the completion port.
|
||||
hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
|
||||
if (hCompletionPort == NULL) {
|
||||
MyErrExit("CreateIoCompletionPort");
|
||||
}
|
||||
|
||||
// Create completion port worker threads.
|
||||
//
|
||||
CreateWorkers(hCompletionPort);
|
||||
CreatePipeConnection(hCompletionPort);
|
||||
|
||||
printf("SYELOGD: Ready for clients. Press Ctrl-C to stop.\n");
|
||||
while (argc) {
|
||||
Sleep(10000);
|
||||
}
|
||||
|
||||
SetConsoleCtrlHandler(ControlHandler, FALSE);
|
||||
|
||||
if (s_hOutFile != INVALID_HANDLE_VALUE) {
|
||||
FlushFileBuffers(s_hOutFile);
|
||||
CloseHandle(s_hOutFile);
|
||||
s_hOutFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
Reference in New Issue
Block a user