📄 trace.c
字号:
/*
* $Id: trace.c,v 1.22 2006/10/27 12:36:58 vfrolov Exp $
*
* Copyright (c) 2004-2006 Vyacheslav Frolov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* $Log: trace.c,v $
* Revision 1.22 2006/10/27 12:36:58 vfrolov
* Removed unnecessary InterlockedExchange*()
*
* Revision 1.21 2006/08/23 13:05:43 vfrolov
* Added ability to trace w/o table
* Added tracing IRP_MN_QUERY_ID result
* Added tracing GUID for IRP_MN_QUERY_INTERFACE
* Added tracing WMI
*
* Revision 1.20 2006/06/08 11:30:52 vfrolov
* Added params check to Trace0() and Trace00()
*
* Revision 1.19 2006/05/19 15:02:03 vfrolov
* Implemented IOCTL_SERIAL_GET_MODEM_CONTROL
*
* Revision 1.18 2006/01/10 09:44:04 vfrolov
* Added ability to enable/disable dump
* Added tracing of HoldReasons, WaitForImmediate, AmountInOutQueue for SERIAL_STATUS
*
* Revision 1.17 2005/12/06 13:01:54 vfrolov
* Implemented IOCTL_SERIAL_GET_DTRRTS
*
* Revision 1.16 2005/12/05 10:54:55 vfrolov
* Implemented IOCTL_SERIAL_IMMEDIATE_CHAR
*
* Revision 1.15 2005/11/30 16:04:12 vfrolov
* Implemented IOCTL_SERIAL_GET_STATS and IOCTL_SERIAL_CLEAR_STATS
*
* Revision 1.14 2005/09/28 10:06:42 vfrolov
* Implemented IRP_MJ_QUERY_INFORMATION and IRP_MJ_SET_INFORMATION
*
* Revision 1.13 2005/09/13 08:55:41 vfrolov
* Disabled modem status tracing by default
*
* Revision 1.12 2005/09/09 15:21:32 vfrolov
* Added additional flushing for saved strings
*
* Revision 1.11 2005/09/06 06:58:20 vfrolov
* Added SERIAL_STATUS.Errors tracing
* Added version tracing
*
* Revision 1.10 2005/08/30 13:12:04 vfrolov
* Disabled IOCTL_SERIAL_GET_MODEMSTATUS tracing by default
*
* Revision 1.9 2005/08/25 07:48:39 vfrolov
* Changed type of code names from wchar to char
* Fixed HandFlow tracing
*
* Revision 1.8 2005/08/23 15:28:26 vfrolov
* Added build timestamp
*
* Revision 1.7 2005/07/14 13:51:09 vfrolov
* Replaced ASSERT by HALT_UNLESS
*
* Revision 1.6 2005/07/01 11:03:50 vfrolov
* Included <stdarg.h>
*
* Revision 1.5 2005/05/19 08:23:41 vfrolov
* Fixed data types
*
* Revision 1.4 2005/05/13 16:58:03 vfrolov
* Implemented IOCTL_SERIAL_LSRMST_INSERT
*
* Revision 1.3 2005/02/28 12:10:08 vfrolov
* Log skipped lines to trace file (was to syslog)
* Fixed missing trace file close
*
* Revision 1.2 2005/02/01 16:39:35 vfrolov
* Added AnsiStrCopyCommStatus()
*
* Revision 1.1 2005/01/26 12:18:54 vfrolov
* Initial revision
*
*/
#include "precomp.h"
#if DBG
#include "version.h"
/*
* FILE_ID used by HALT_UNLESS to put it on BSOD
*/
#define FILE_ID 4
/********************************************************************/
#include <stdarg.h>
#include "trace.h"
#include "strutils.h"
/********************************************************************/
#define TRACE_BUF_SIZE 256
#define TRACE_BUFS_NUM 4
/********************************************************************/
typedef struct _TRACE_BUFFER {
BOOLEAN busy;
CHAR buf[TRACE_BUF_SIZE];
} TRACE_BUFFER, *PTRACE_BUFFER;
/********************************************************************/
#define TRACE_ENABLE_IRP 0x00000001
#define TRACE_ENABLE_DUMP 0x00000002
#define TRACE_ENABLE_ALL 0xFFFFFFFF
static struct {
ULONG read;
ULONG write;
ULONG getTimeouts;
ULONG setTimeouts;
ULONG getCommStatus;
ULONG getModemStatus;
ULONG modemStatus;
} traceEnable;
/********************************************************************/
static WCHAR traceFileNameBuf[256];
static UNICODE_STRING traceFileName;
static PDRIVER_OBJECT pDrvObj;
static KSPIN_LOCK strOldLock;
static KSPIN_LOCK bufsLock;
static TRACE_BUFFER traceBufs[TRACE_BUFS_NUM];
static LONG skippedTraces;
/********************************************************************/
#define TRACE_FILE_OK (traceFileName.Buffer != NULL)
/********************************************************************/
VOID QueryRegistryTrace(IN PUNICODE_STRING pRegistryPath)
{
NTSTATUS status;
UNICODE_STRING traceRegistryPath;
RTL_QUERY_REGISTRY_TABLE queryTable[2];
status = STATUS_SUCCESS;
RtlInitUnicodeString(&traceRegistryPath, NULL);
StrAppendStr(&status, &traceRegistryPath, pRegistryPath->Buffer, pRegistryPath->Length);
StrAppendStr0(&status, &traceRegistryPath, L"\\Trace");
if (!NT_SUCCESS(status)) {
SysLog(pDrvObj, status, L"QueryRegistryTrace FAIL");
return;
}
RtlZeroMemory(queryTable, sizeof(queryTable));
traceFileName.Length = 0;
traceFileName.MaximumLength = sizeof(traceFileNameBuf);
traceFileName.Buffer = traceFileNameBuf;
queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
queryTable[0].Name = L"TraceFile";
queryTable[0].EntryContext = &traceFileName;
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
traceRegistryPath.Buffer,
queryTable,
NULL,
NULL);
StrFree(&traceRegistryPath);
if (!NT_SUCCESS(status))
RtlInitUnicodeString(&traceFileName, NULL);
}
VOID QueryRegistryTraceEnable(IN PUNICODE_STRING pRegistryPath)
{
NTSTATUS status;
UNICODE_STRING traceRegistryPath;
RTL_QUERY_REGISTRY_TABLE queryTable[8];
ULONG zero = 0;
RtlZeroMemory(&traceEnable, sizeof(traceEnable));
status = STATUS_SUCCESS;
RtlInitUnicodeString(&traceRegistryPath, NULL);
StrAppendStr(&status, &traceRegistryPath, pRegistryPath->Buffer, pRegistryPath->Length);
StrAppendStr0(&status, &traceRegistryPath, L"\\Trace\\Enable");
if (!NT_SUCCESS(status)) {
SysLog(pDrvObj, status, L"QueryRegistryTraceEnable FAIL");
return;
}
RtlZeroMemory(queryTable, sizeof(queryTable));
queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
queryTable[0].Name = L"Read";
queryTable[0].EntryContext = &traceEnable.read;
queryTable[0].DefaultType = REG_DWORD;
queryTable[0].DefaultData = &zero;
queryTable[0].DefaultLength = sizeof(ULONG);
queryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
queryTable[1].Name = L"Write";
queryTable[1].EntryContext = &traceEnable.write;
queryTable[1].DefaultType = REG_DWORD;
queryTable[1].DefaultData = &zero;
queryTable[1].DefaultLength = sizeof(ULONG);
queryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
queryTable[2].Name = L"GetTimeouts";
queryTable[2].EntryContext = &traceEnable.getTimeouts;
queryTable[2].DefaultType = REG_DWORD;
queryTable[2].DefaultData = &zero;
queryTable[2].DefaultLength = sizeof(ULONG);
queryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
queryTable[3].Name = L"SetTimeouts";
queryTable[3].EntryContext = &traceEnable.setTimeouts;
queryTable[3].DefaultType = REG_DWORD;
queryTable[3].DefaultData = &zero;
queryTable[3].DefaultLength = sizeof(ULONG);
queryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
queryTable[4].Name = L"GetCommStatus";
queryTable[4].EntryContext = &traceEnable.getCommStatus;
queryTable[4].DefaultType = REG_DWORD;
queryTable[4].DefaultData = &zero;
queryTable[4].DefaultLength = sizeof(ULONG);
queryTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
queryTable[5].Name = L"GetModemStatus";
queryTable[5].EntryContext = &traceEnable.getModemStatus;
queryTable[5].DefaultType = REG_DWORD;
queryTable[5].DefaultData = &zero;
queryTable[5].DefaultLength = sizeof(ULONG);
queryTable[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
queryTable[6].Name = L"ModemStatus";
queryTable[6].EntryContext = &traceEnable.modemStatus;
queryTable[6].DefaultType = REG_DWORD;
queryTable[6].DefaultData = &zero;
queryTable[6].DefaultLength = sizeof(ULONG);
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
traceRegistryPath.Buffer,
queryTable,
NULL,
NULL);
StrFree(&traceRegistryPath);
}
/********************************************************************/
PTRACE_BUFFER AllocTraceBuf()
{
PTRACE_BUFFER pBuf;
KIRQL oldIrql;
int i;
pBuf = NULL;
KeAcquireSpinLock(&bufsLock, &oldIrql);
for (i = 0 ; i < TRACE_BUFS_NUM ; i++) {
if (!traceBufs[i].busy) {
traceBufs[i].busy = TRUE;
pBuf = &traceBufs[i];
break;
}
}
KeReleaseSpinLock(&bufsLock, oldIrql);
if (!pBuf)
InterlockedIncrement(&skippedTraces);
return pBuf;
}
VOID FreeTraceBuf(PTRACE_BUFFER pBuf)
{
HALT_UNLESS(pBuf);
pBuf->busy = FALSE;
}
/********************************************************************/
PCHAR AnsiStrCopyStr(
PCHAR pDestStr,
PSIZE_T pSize,
IN PCHAR pStr)
{
SIZE_T len, size;
PCHAR pStrTmp;
pStrTmp = pStr;
while (*(pStrTmp++))
;
len = pStrTmp - pStr;
size = *pSize;
if (len > size)
len = size;
if (len) {
RtlCopyMemory(pDestStr, pStr, len - 1);
size -= len - 1;
pDestStr += len - 1;
*pDestStr = 0;
*pSize = size;
}
return pDestStr;
}
PCHAR AnsiStrCopyStrW(
PCHAR pDestStr,
PSIZE_T pSize,
PWCHAR pStr)
{
SIZE_T len, size;
PWCHAR pStrTmp;
pStrTmp = pStr;
while (*(pStrTmp++))
;
len = pStrTmp - pStr;
size = *pSize;
if (len > size)
len = size;
if (len) {
SIZE_T i;
for (i = 0 ; i < len - 1 ; i++) {
if ((pStr[i] & 0xFF00) == 0)
pDestStr[i] = (CHAR)(pStr[i]);
else
pDestStr[i] = '?';
}
size -= len - 1;
pDestStr += len - 1;
*pDestStr = 0;
*pSize = size;
}
return pDestStr;
}
PCHAR AnsiStrCopyNum(
PCHAR pDestStr,
PSIZE_T pSize,
IN ULONG num,
IN ULONG base,
int width)
{
CHAR buf[sizeof(num) * 8 + 1];
PCHAR pBuf;
if (!(base > 0 && base <= 36))
base = 10;
pBuf = buf + sizeof(buf);
*(--pBuf) = 0;
do {
ULONG d = num % base;
*(--pBuf) = (CHAR)(d + ((d < 10) ? '0' : ('A' - 10)));
num /= base;
width--;
} while (num);
while (width-- > 0)
pDestStr = AnsiStrCopyStr(pDestStr, pSize, "0");
return AnsiStrCopyStr(pDestStr, pSize, pBuf);
}
PCHAR _AnsiStrVaFormat(
PCHAR pDestStr,
PSIZE_T pSize,
IN PCHAR pFmt,
va_list va)
{
SIZE_T size;
size = *pSize;
while (*pFmt) {
BOOLEAN format;
BOOLEAN l;
BOOLEAN fail;
int width;
CHAR ch;
ch = *(pFmt++);
if (ch != '%') {
CHAR buf[2];
buf[0] = ch;
buf[1] = 0;
pDestStr = AnsiStrCopyStr(pDestStr, &size, buf);
continue;
}
fail = FALSE;
format = TRUE;
l = FALSE;
width = 0;
while (*pFmt && format) {
ch = *(pFmt++);
switch (ch) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
width = width*10 + ch - '0';
break;
case 'l':
l = TRUE;
break;
case 's': {
PCHAR pStr = va_arg(va, PCHAR);
pDestStr = AnsiStrCopyStr(pDestStr, &size, pStr);
format = FALSE;
break;
}
case 'S': {
PWCHAR pStr = va_arg(va, PWCHAR);
pDestStr = AnsiStrCopyStrW(pDestStr, &size, pStr);
format = FALSE;
break;
}
case 'u': {
ULONG n;
if (l)
n = va_arg(va, unsigned long);
else
n = va_arg(va, unsigned int);
pDestStr = AnsiStrCopyNum(pDestStr, &size, n, 10, width);
format = FALSE;
break;
}
case 'x':
case 'X': {
ULONG n;
if (l)
n = va_arg(va, unsigned long);
else
n = va_arg(va, unsigned int);
pDestStr = AnsiStrCopyNum(pDestStr, &size, n, 16, width);
format = FALSE;
break;
}
case '%':
pDestStr = AnsiStrCopyStr(pDestStr, &size, "%");
format = FALSE;
break;
default:
fail = TRUE;
}
if (fail)
break;
}
if (fail)
break;
}
*pSize = size;
return pDestStr;
}
PCHAR AnsiStrVaFormat(
PCHAR pDestStr,
PSIZE_T pSize,
IN PCHAR pFmt,
va_list va)
{
SIZE_T oldSize = *pSize;
try {
return _AnsiStrVaFormat(pDestStr, pSize, pFmt, va);
} except (EXCEPTION_EXECUTE_HANDLER) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -