运用的技术跟应用层大体一致,倒是互斥的问题干扰我很久。已开始使用的是 FastMutex,但是它会提升 IRQL 到 APC_LEVEL,显然写文件的服务函数都只能跑在 PASSIVE_LEVEL 下,最后只好使用了 Event 。
示例代码说明:
GetCurrentTimeString() 详见前文:Windows 驱动中获取系统当前时间,生成格式字符串
GetCurrentProcessName() 详见前文:Windows 驱动:获取当前进程名
示例代码:
#include
//
// Enable log event: for synchronization
//
static KEVENT gs_eventEnableKeLog;
//----------------------------------------------------------------------
//
// initialization interface
//
//----------------------------------------------------------------------
//
// initialize the global data structures, when the driver is loading.
// (Call in DriverEntry())
//
NTSTATUS
Dbg_LoadInit()
{
// Initialize the event
KeInitializeEvent(&gs_eventEnableKeLog, SynchronizationEvent, TRUE);
return STATUS_SUCCESS;
}
static void WaitForWriteMutex()
{
// Wait for enable log event
KeWaitForSingleObject(&gs_eventEnableKeLog, Executive, KernelMode, TRUE, 0);
KeClearEvent(&gs_eventEnableKeLog);
}
static void ReleaseWriteMutex()
{
// Set enable log event
KeSetEvent(&gs_eventEnableKeLog, 0, FALSE);
}
//----------------------------------------------------------------------
//
// DbgKeLog
//
// Trace to file.
//
//----------------------------------------------------------------------
BOOLEAN
DbgKeLog(LPCSTR lpszLog, ...)
{
if (KeGetCurrentIrql() > PASSIVE_LEVEL)
{
TOKdPrint(("TKeHook: KeLog: IRQL too hight.../n"));
return FALSE;
}
WaitForWriteMutex();
__try
{
IO_STATUS_BLOCK IoStatus;
OBJECT_ATTRIBUTES objectAttributes;
NTSTATUS status;
HANDLE FileHandle;
UNICODE_STRING fileName;
static WCHAR s_szLogFile[] = L"//??//C://KeLog.log";
LPCWSTR lpszLogFile = s_szLogFile;
PAGED_CODE();
if (lpszLogFile == NULL)
lpszLogFile = s_szLogFile;
//get a handle to the log file object
fileName.Buffer = NULL;
fileName.Length = 0;
fileName.MaximumLength = (wcslen(lpszLogFile) + 1) * sizeof(WCHAR);
fileName.Buffer = ExAllocatePool(PagedPool, fileName.MaximumLength);
if (!fileName.Buffer)
{
ReleaseWriteMutex();
TOKdPrint(("TKeHook: KeLog: ExAllocatePool Failed.../n"));
return FALSE;
}
RtlZeroMemory(fileName.Buffer, fileName.MaximumLength);
status = RtlAppendUnicodeToString(&fileName, (PWSTR)lpszLogFile);
InitializeObjectAttributes (&objectAttributes,
(PUNICODE_STRING)&fileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = ZwCreateFile(&FileHandle,
FILE_APPEND_DATA,
&objectAttributes,
&IoStatus,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if(NT_SUCCESS(status))
{
static CHAR szBuffer[1024];
PCHAR pszBuffer = szBuffer;
ULONG ulBufSize;
int nSize;
va_list pArglist;
// add process name and time string
sprintf(szBuffer, "[%s][%16s:%d] "
, GetCurrentTimeString()
, GetCurrentProcessName()
, (ULONG)PsGetCurrentProcessId()
);
pszBuffer = szBuffer + strlen(szBuffer);
va_start(pArglist, lpszLog);
// The last argument to wvsprintf points to the arguments
nSize = _vsnprintf( pszBuffer, 1024 - 32, lpszLog, pArglist);
// The va_end macro just zeroes out pArgList for no good reason
va_end(pArglist);
if (nSize > 0)
{
//
pszBuffer[nSize] = 0;
}
else
{
pszBuffer[0] = 0;
}
ulBufSize = strlen(szBuffer);
ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatus,
szBuffer,
ulBufSize,
NULL,
NULL
);
ZwClose(FileHandle);
}
if (fileName.Buffer)
ExFreePool (fileName.Buffer);
ReleaseWriteMutex();
return TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
ReleaseWriteMutex();
TOKdPrint(("TKeHook: DbgKeLog() except: %0xd !!/n", GetExceptionCode()));
return FALSE;
}
}