⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trace.c

📁 这个是一个开源项目, 有能力的人可以一起来写
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * $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 + -