📄 htrace.cpp
字号:
bool p_bDontComplainIfDeviceAbsent);
#endif
#if defined(__linux__)
bool CreateAndMapFile(const char * p_pszMemMapFilePath,
int p_iFileSize);
#endif
bool TraceFreeBuffer();
bool TraceDumpBufferToFile(LPCTSTR p_pszFileName);
LocalTraceBufferPointers m_BufferPointers;
bool m_bBufferAllocated;
#if defined(WINAPP)
HANDLE m_hFileMapping;
bool m_bBufferMapped;
HANDLE m_hDeviceWithBuffer;
bool m_bMappedDriverBuffer;
int m_iIOCTLToUnmapDriverBuffer;
#endif
#if defined(__linux__)
int m_iMemMapFile;
int m_iMappingSize;
int m_iSemKey;
int m_iSemID;
bool m_bBufferMapped;
#endif
#ifdef TRACER_NTDRIVER
PDRIVER_OBJECT m_pDriverObject;
FAST_MUTEX m_FastMutexToProtectMemMap;
#else
#endif
ULONG m_dwFlushFileMask;
ULONG m_dwTotalMask;
ULONG*m_pdwTotalMask;
ULONG m_dwConsoleMask;
ULONG m_dwDebugMask;
#ifdef HAVE_FILE_OUTPUT
HTraceFileImpl m_File;
TCHAR m_szFileName[_MAX_PATH];
#endif
bool m_bAddTime;
bool m_bAddThread;
};//struct TraceImpl
static TraceImpl s_Impl;
static long s_lChangeLock = -1;
/*
Current implementation does not allow simultaneous modification
of trace parameters by multiple threads. Ideally, a process
should initialize trace from the beginning and, may be,
update trace parameters from a single thread.
Functions, which generate trace, such as HTraceImpl and
OutputTraceString can be called by any thread at any time(after
the trace is initialized by TraceInitialize.
*/
//We will use s_lChangeLock and class ChangeLock
//to protect all functions, which can modify trace settings,
//from simultaneous calls from several threads.
class ChangeLock
{
public:
ChangeLock()
{
m_lChangeLock = InterlockedIncrement(&s_lChangeLock);
}
~ChangeLock()
{
InterlockedDecrement(&s_lChangeLock);
}
bool isFirst()
{
return (m_lChangeLock == 0)? true : false;
}
long m_lChangeLock;
};//class ChangeLock
/*-------------------------------------------------------------
FUNCTION: TraceInitialize
PURPOSE: Initialize the trace. Must be called before any
other trace routine. We cannot use constructor in class
TraceImpl, because constructors in static classes require
presence of a C++ library, which is not always available.
-------------------------------------------------------------*/
bool TraceInitialize()
{
ChangeLock l_ChangeLock;
if(!l_ChangeLock.isFirst())
return false;
if(s_bInitialized)
return true;
s_Impl.Clean();
s_bInitialized = true;
#ifdef TRACER_NTDRIVER
ExInitializeFastMutex(&s_Impl.m_FastMutexToProtectMemMap);
#endif
return true;
}
/*-------------------------------------------------------------
FUNCTION: TraceUnInitialize
PURPOSE: Uninitialize the trace. Must be called before
application or driver terminates. We cannot use destructor
in class TraceImpl, because constructors in static classes
require presence of C++ library, which may not be available
-------------------------------------------------------------*/
bool TraceUnInitialize()
{
ChangeLock l_ChangeLock;
if(!l_ChangeLock.isFirst())
return false;
s_Impl.Free();
return true;
}
#ifndef TRACER_NTDRIVER
#ifdef TRACE_ADD_DLLMAIN
/*-------------------------------------------------------------
FUNCTION: DllMain
PURPOSE: If the HTrace.cpp is built into a stand-alone DLL,
such as HTrcJni.DLL, we will use standard Win32 DllMain to
initialize and uninitialize the trace.
-------------------------------------------------------------*/
BOOL WINAPI DllMain
(
HINSTANCE p_hInstDLL,
DWORD p_dwReason,
LPVOID p_lpvReserved
)
{
switch (p_dwReason)
{
case DLL_PROCESS_ATTACH:
{
TraceInitialize();
//By default, show errors and warnings on the
//debugger's log window and in message boxes.
TraceAssignGroupsToStream(
TO_DebugMonitor | TO_MessageBox,
TG_MessageBox | TG_Error, (DWORD)-1);
//Print bank account and thread swaps(if the
//driver is loaded) to the memory buffer
TraceAssignGroupsToStream(TO_MemoryBuffer,
TG_BankAccount | TG_ThreadSwaps, (DWORD)-1);
char l_szFullINIPath[_MAX_PATH];
GetFullPathName("HTrace.ini",
sizeof(l_szFullINIPath), l_szFullINIPath,NULL);
//Read state of all streams. This can override the
//assignments made in the preceding calls.
TraceReadWriteSettings(NULL, l_szFullINIPath,
false, (DWORD)-1);
}
break;
case DLL_PROCESS_DETACH:
TraceUnInitialize();
break;
}
return TRUE;
}
#endif// TRACE_ADD_DLLMAIN
#endif
void SetOneTraceMask
(
PULONG p_pdwMask,
ULONG p_dwNewGroupFlags,
ULONG p_dwGroupFlagsToModify
)
{
*p_pdwMask = (*p_pdwMask & ~p_dwGroupFlagsToModify) |
(p_dwNewGroupFlags & p_dwGroupFlagsToModify);
}
/*-------------------------------------------------------------
FUNCTION: TraceImpl::TraceAssignGroupsToStream
PURPOSE: This function allows to enable/disable output
of the specified groups of HTRACE operators to
the specified output stream.
Each HTRACE operator has a bit mask as a first parameter.
This mask will be matched against a mask for a particular
device to decide whether to allow output or not.
PARAMETERS: .
ULONG p_dwTraceOutputs flags from TraceOutputs.
ULONG p_dwNewGroupFlags new bits to set or reset
ULONG p_dwGroupFlagsToModify which bits can be modified
char * p_pszGroupKeyWord new keyword mask
-------------------------------------------------------------*/
bool TraceImpl::TraceAssignGroupsToStream
(
ULONG p_dwTraceOutputs,
ULONG p_dwNewGroupFlags,
ULONG p_dwGroupFlagsToModify,
char * p_pszGroupKeyWord
)
{
m_dwTotalMask = 0;
m_dwConsoleMask = 0;
m_dwDebugMask = 0;
//Loop for all available output streams
for(int i = 0; i < NUM_STREAMS; i++)
{
TraceOutput & l_rOutput = s_Outputs[i];
//Check whether we are asked to modify this stream
if(l_rOutput.m_dwOutputID & p_dwTraceOutputs)
{
//Update bits in the group mask of this stream
SetOneTraceMask(&l_rOutput.m_dwEnabledGroups,
p_dwNewGroupFlags, p_dwGroupFlagsToModify);
if(p_pszGroupKeyWord)
{
//We are asked to update the stream keyword
int l_iLen = strlen(p_pszGroupKeyWord);
if(l_iLen >=
sizeof(l_rOutput.m_szEnabledGroupsKeywords))
{
HTRACE(TG_Error,
_T("ERROR: not enough space for keyword %s"),
p_pszGroupKeyWord);
}
else if(memcmp(
l_rOutput.m_szEnabledGroupsKeywords,
p_pszGroupKeyWord, l_iLen+1))
{//need to change the keyword
memcpy(l_rOutput.m_szEnabledGroupsKeywords,
p_pszGroupKeyWord, l_iLen+1);
//Increment modification counter,
//store its value to force all HTRACEK
//macros to check whether they match the
//new keyword on the next call.
l_rOutput.m_dwKeyWordModificationCounter =
++s_dwKeyWordModifCounter;
}
}
if(l_rOutput.m_dwOutputID == TO_MemoryBuffer)
{
//Some additional processing for memory buffer
if(l_rOutput.m_dwEnabledGroups ||
*l_rOutput.m_szEnabledGroupsKeywords)
{
#if defined(WINAPP)
//If we have no buffer,try first to connect
//to our driver and if not successful, try
//to map to a mem-map file
if(!m_BufferPointers.m_pGlobalHeader)
{
TraceAttachToNTDriverBuffer(
NULL, -1, -1, true);
}
#endif
#if defined(WINAPP) || defined(__linux__)
if(!m_BufferPointers.m_pGlobalHeader)
{
CreateAndMapFile(NULL, -1);
}
#endif
}
if(m_BufferPointers.m_pGlobalFooter != NULL)
{
//If the buffer is present,
//copy the mask to it, so it will
//immediately affect other applications,
//which share the buffer with us.
GlobalTraceBufferFooter * l_Footer =
m_BufferPointers.m_pGlobalFooter;
l_Footer->m_dwEnabledGroups =
l_rOutput.m_dwEnabledGroups;
strcpy(l_Footer->m_szKeyWordMask,
l_rOutput.m_szEnabledGroupsKeywords);
l_Footer->m_dwKeyWordModificationCounter =
l_rOutput.m_dwKeyWordModificationCounter;
//Start using shared mask:
m_pdwTotalMask =
&l_Footer->m_dwEnabledGroupsTotal;
}
}//if(l_rOutput.m_dwOutputID == TO_MemoryBuffer)
#ifndef CE_KERNEL_DRV
if(l_rOutput.m_dwOutputID == TO_File &&
(l_rOutput.m_dwEnabledGroups ||
*l_rOutput.m_szEnabledGroupsKeywords) &&
!m_File.IsOpened())
{//We need to open the file
if(m_File.OpenFile
(m_szFileName, true, true, NULL))
{
//Cannot open the file. Need to
//disable the trace
l_rOutput.m_dwEnabledGroups = 0;
*l_rOutput.m_szEnabledGroupsKeywords = 0;
}
}
#endif
#if defined(WINAPP) && !defined(_WIN32_WCE)
if(l_rOutput.m_dwOutputID == TO_Console &&
(l_rOutput.m_dwEnabledGroups ||
*l_rOutput.m_szEnabledGroupsKeywords))
{
AllocConsole();
}
#endif
}//if(l_rOutput.m_dwOutputID & p_dwTraceOutputs)
m_dwTotalMask |= l_rOutput.m_dwEnabledGroups;
if(l_rOutput.m_dwOutputID == TO_Console)
{ //Keep the console mask separately for Java sake.
m_dwConsoleMask = l_rOutput.m_dwEnabledGroups;
}
if(l_rOutput.m_dwOutputID == TO_DebugMonitor)
{
m_dwDebugMask = l_rOutput.m_dwEnabledGroups;
}
}//for(int i = 0; i < NUM_STREAMS;
//Treat TO_FlushFile separately, because it is not a
//separate output stream, but modification of TO_File
if(p_dwTraceOutputs & TO_FlushFile)
{
SetOneTraceMask(&m_dwFlushFileMask,
p_dwNewGroupFlags, p_dwGroupFlagsToModify);
}
*m_pdwTotalMask = m_dwTotalMask;
#ifdef TRACE_JNI
//Inform Java class about new masks
JNISetTotalMask(*m_pdwTotalMask, m_dwConsoleMask);
#endif
return true;
}//bool TraceImpl::TraceAssignGroupsToStream
/*-------------------------------------------------------------
FUNCTION: TraceAssignGroupsToStream
PURPOSE: The same as TraceImpl::TraceAssignGroupsToStream.
It accepts only integer group bitmap.
Use TraceAssignGroupKeyWordToStream to change keyword masks
Increment lock counter to prevent multiple threads from
simultaneous access.
-------------------------------------------------------------*/
bool TraceAssignGroupsToStream
(
ULONG p_dwTraceOutputs,
ULONG p_dwNewGroupFlags,
ULONG p_dwGroupFlagsToModify
)
{
ChangeLock l_ChangeLock;
if(!l_ChangeLock.isFirst())
return false;
return s_Impl.TraceAssignGroupsToStream(p_dwTraceOutputs,
p_dwNewGroupFlags, p_dwGroupFlagsToModify, NULL);
}//bool TraceAssignGroupsToStream
/*-------------------------------------------------------------
FUNCTION: TraceAssignGroupKeyWordToStream
PURPOSE: The same as TraceImpl::TraceAssignGroupsToStream.
It accepts only string keyword masks.
Use TraceAssignGroupsToStream to change integer group mask.
Increment lock counter to prevent multiple threads from
simultaneous access.
-------------------------------------------------------------*/
bool TraceAssignGroupKeyWordToStream
(
ULONG p_dwTraceOutputs,
char * p_pszGroupKeyWord
)
{
ChangeLock l_ChangeLock;
if(!l_ChangeLock.isFirst())
return false;
return s_Impl.TraceAssignGroupsToStream(p_dwTraceOutputs,
0, 0, p_pszGroupKeyWord);
}//bool TraceAssignGroupsToStream
/*-------------------------------------------------------------
FUNCTION: TraceGetAssignedGroupsToStream
PURPOSE: Return all group flags, which are enabled for the
specified output stream(s)
-------------------------------------------------------------*/
ULONG TraceGetAssignedGroupsToStream
(
ULONG p_dwTraceOutputs
)
{
ULONG l_ulResult = 0;
for(int i = 0; i < NUM_STREAMS;i++)
{
TraceOutput & l_rOutput = s_Outputs[i];
if(l_rOutput.m_dwOutputID & p_dwTraceOutputs)
{
l_ulResult |= l_rOutput.m_dwEnabledGroups;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -