mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-04-24 09:34:44 +00:00
556 lines
17 KiB
C++
Vendored
556 lines
17 KiB
C++
Vendored
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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;
|
|
}
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|