The technology used is basically the same as that used in the application layer, but the problem of mutual exclusion has interfered with me for a long time. Fastmutex is used, but it will upgrade IRQL to apc_level. Obviously, all the file-writing service functions can only run under passive_level, so the event is used.
Sample Code Description:
For details about getcurrenttimestring (), refer to the previous section:Get the current system time in the Windows Driver and generate a format string
For details about getcurrentprocessname (), see the previous article: Windows Driver: Get the current process name.
Sample Code:
# Include <stdarg. h>
//
// 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_pai_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] [% 16 S: % 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;
}
_ Handler T (exception_execute_handler)
{
Releasewritemutex ();
Tokdprint ("tkehook: dbgkelog () handle T: % 0xd !! /N ", getexceptioncode ()));
Return false;
}
}