📄 logger.c
字号:
static _inline void
BroadcastCeLogSetZones(
DWORD dwZoneUser,
DWORD dwZoneCE,
DWORD dwZoneProcess
)
{
CeLogDLLInfo *pDLL;
// Global zone settings will be recalculated
g_dwZoneUser = 0;
g_dwZoneCE = 0;
g_dwZoneProcess = 0;
for (pDLL = g_pCeLogList; pDLL; pDLL = pDLL->pNext) {
if (pDLL->pfnCeLogSetZones) {
pDLL->pfnCeLogSetZones(dwZoneUser, dwZoneCE, dwZoneProcess);
}
// Query the new DLL zone settings
if (pDLL->pfnCeLogQueryZones) {
pDLL->pfnCeLogQueryZones(&(pDLL->dwZoneUser), &(pDLL->dwZoneCE), &(pDLL->dwZoneProcess));
}
// Add the DLL's zones to the global zone settings
g_dwZoneUser |= pDLL->dwZoneUser;
g_dwZoneCE |= pDLL->dwZoneCE;
g_dwZoneProcess |= pDLL->dwZoneProcess;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Wrappers because these calls are functions on some processors and macros on
// others.
DWORD
Phys2VirtWrapper(
DWORD pfn
)
{
return (DWORD) Phys2Virt(pfn);
}
BOOL
InSysCallWrapper(
)
{
return InSysCall();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL KernelLibIoControl_CeLog(
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned
)
{
switch (dwIoControlCode) {
case IOCTL_CELOG_IMPORT: {
//
// A CeLog DLL is requesting information about the kernel
//
CeLogImportTable *pImports = (CeLogImportTable*)lpInBuf;
extern const PFNVOID Win32Methods[];
extern const PFNVOID EvntMthds[];
extern const PFNVOID MapMthds[];
extern DWORD dwDefaultThreadQuantum;
// PUBLIC IMPORT TABLE VERSIONS:
// 4 = Current
// 3 = Intermediate builds, post-4.2
// 2 = CE 4.1 / 4.2
// 1 = CE 4.0
DEBUGMSG(0, (TEXT("CeLog DLL import version: %u\r\n"), pImports->dwVersion));
if (pImports->dwVersion == 4) {
if (nInBufSize != sizeof(CeLogImportTable)) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
pImports->pCreateEventW = (FARPROC) SC_CreateEvent;
pImports->pEventModify = (FARPROC) SC_EventModify;
pImports->pCreateFileMappingW = (FARPROC) SC_CreateFileMapping;
pImports->pMapViewOfFile = (FARPROC) MapMthds[ID_FSMAP_MAPVIEWOFFILE]; // 0 if nomapfile
pImports->pUnmapViewOfFile = (FARPROC) SC_UnmapViewOfFile;
pImports->pCloseHandle = (FARPROC) SC_CloseHandle;
pImports->pLockPages = (FARPROC) SC_LockPages;
pImports->pUnlockPages = (FARPROC) SC_UnlockPages;
pImports->pVirtualAlloc = (FARPROC) Win32Methods[W32_VirtualAlloc];
pImports->pVirtualFree = (FARPROC) Win32Methods[W32_VirtualFree];
pImports->pMapPtrToProcess = (FARPROC) SC_MapPtrToProcess;
pImports->pQueryPerformanceCounter = (FARPROC) SC_QueryPerformanceCounter;
pImports->pQueryPerformanceFrequency = (FARPROC) SC_QueryPerformanceFrequency;
pImports->pNKDbgPrintfW = (FARPROC) NKDbgPrintfW;
pImports->pCeLogReSync = (FARPROC) SC_CeLogReSync;
pImports->pGetLastError = (FARPROC) SC_GetLastError;
pImports->pSetLastError = (FARPROC) SC_SetLastError;
pImports->pGetThreadCallStack = (FARPROC) NKGetThreadCallStack;
pImports->pInSysCall = (FARPROC) InSysCallWrapper;
pImports->pdwCeLogTLBMiss = &dwCeLogTLBMiss;
pImports->dwCeLogLargeBuf = dwCeLogLargeBuf;
pImports->dwCeLogSmallBuf = dwCeLogSmallBuf;
pImports->dwDefaultThreadQuantum = dwDefaultThreadQuantum;
} else {
// Versions 2 & 3 used a totally different import structure from
// current DLL versions.
DWORD* prgdwImports;
// Check import version and struct size
if (pImports->dwVersion == 2) {
if (nInBufSize != 14*sizeof(DWORD)) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
} else if (pImports->dwVersion == 3) {
if (nInBufSize != 16*sizeof(DWORD)) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
} else {
ERRORMSG(1, (TEXT("CeLog DLL version is not supported\r\n")));
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
prgdwImports = (DWORD*)lpInBuf;
// prgdwImports[0] is the version
prgdwImports[ 1] = (DWORD) Win32Methods;
prgdwImports[ 2] = (DWORD) EvntMthds;
prgdwImports[ 3] = (DWORD) MapMthds;
prgdwImports[ 4] = (DWORD) INTERRUPTS_ENABLE;
prgdwImports[ 5] = (DWORD) Phys2VirtWrapper;
prgdwImports[ 6] = (DWORD) InSysCallWrapper;
prgdwImports[ 7] = (DWORD) KCall;
prgdwImports[ 8] = (DWORD) NKDbgPrintfW;
prgdwImports[ 9] = (DWORD) &KData;
prgdwImports[10] = (DWORD) &dwCeLogTLBMiss;
prgdwImports[11] = (DWORD) dwCeLogLargeBuf;
prgdwImports[12] = (DWORD) dwCeLogSmallBuf;
prgdwImports[13] = (DWORD) dwDefaultThreadQuantum;
if (pImports->dwVersion == 3) {
prgdwImports[14] = (DWORD) SC_CloseHandle;
prgdwImports[15] = (DWORD) KmodeEntries();
}
}
break;
}
case IOCTL_CELOG_IMPORT_PRIVATE: {
//
// A CeLog DLL is requesting private information about the kernel
//
CeLogPrivateImports *pImports = (CeLogPrivateImports*)lpInBuf;
// PRIVATE IMPORT TABLE VERSIONS:
// 1 = Current
// (Did not exist in 4.2 and earlier)
if ((pImports->dwVersion != CELOG_PRIVATE_IMPORT_VERSION)
|| (nInBufSize != sizeof(CeLogPrivateImports))) {
ERRORMSG(1, (TEXT("CeLog DLL version does not match kernel\r\n")));
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
pImports->pRegQueryValueExW = (FARPROC) NKRegQueryValueExW;
pImports->pINTERRUPTS_ENABLE = (FARPROC) INTERRUPTS_ENABLE;
pImports->pPhys2Virt = (FARPROC) Phys2VirtWrapper;
pImports->pKCall = (FARPROC) KCall;
pImports->pCeLogData = (FARPROC) SC_CeLogData;
pImports->pKData = &KData;
break;
}
case IOCTL_CELOG_REGISTER: {
//
// A CeLog DLL is registering to receive data
//
CeLogExportTable *pExports = (CeLogExportTable*)lpInBuf;
// EXPORT TABLE VERSIONS:
// 2 = CE 4.1 to Current
// 1 = CE 4.0
if ((nInBufSize != sizeof(CeLogExportTable))
|| (pExports->dwVersion != CELOG_EXPORT_VERSION)) {
ERRORMSG(1, (TEXT("CeLog DLL version does not match kernel\r\n")));
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!EnterCeLogRegisterCS()) {
return FALSE;
}
// Add the new DLL to the list
if (!AddCeLogDLL(pExports)) {
LeaveCeLogRegisterCS();
return FALSE;
}
// For each entry point, if it is the first instance, set the pointer
// directly to the DLL. If it is any subsequent instance, set the
// pointer to be the broadcast function.
if (g_pfnCeLogData == NULL) {
g_pfnCeLogData = pExports->pfnCeLogData;
} else if (g_pfnCeLogData != BroadcastCeLogData) {
g_pfnCeLogData = BroadcastCeLogData;
}
#ifdef NKPROF
if (g_pfnCeLogInterrupt == NULL) {
g_pfnCeLogInterrupt = pExports->pfnCeLogInterrupt;
} else if ((g_pfnCeLogInterrupt != BroadcastCeLogInterrupt)
&& (pExports->pfnCeLogInterrupt != NULL)) {
g_pfnCeLogInterrupt = BroadcastCeLogInterrupt;
}
#endif // NKPROF
if (g_dwCeLogDLLCount == 1) {
// First CeLog DLL to be loaded. Enable logging.
CeLogEnable(CELOGSTATUS_ENABLED_GENERAL, g_dwZoneCE);
} else {
// Set the new zones in UserKData
CeLogEnableZones(g_dwZoneCE);
}
DEBUGMSG(1, (TEXT("New CeLog DLL is now live! (%u total)\r\n"), g_dwCeLogDLLCount));
LeaveCeLogRegisterCS();
break;
}
case IOCTL_CELOG_DEREGISTER: {
//
// A CeLog DLL is deregistering so that it no longer receives data
//
CeLogExportTable *pExports = (CeLogExportTable*)lpInBuf;
if ((nInBufSize != sizeof(CeLogExportTable))
|| (pExports->dwVersion != CELOG_EXPORT_VERSION)) {
ERRORMSG(1, (TEXT("CeLog DLL version does not match kernel\r\n")));
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!EnterCeLogRegisterCS()) {
return FALSE;
}
// Remove the DLL from the list
if (!RemoveCeLogDLL(pExports)) {
LeaveCeLogRegisterCS();
return FALSE;
}
if (g_dwCeLogDLLCount == 0) {
// Last CeLog DLL to be unloaded.
// Clear the logging function pointers
g_pfnCeLogData = NULL;
g_pfnCeLogInterrupt = NULL;
// Disable logging
CeLogDisable();
// Safety to make sure zones are all turned off
g_dwZoneCE = 0;
} else if (g_dwCeLogDLLCount == 1) {
// One CeLog DLL remains loaded.
// Switch the function pointers from the broadcast functions
// to direct calls into the remaining DLL
g_pfnCeLogData = g_pCeLogList->pfnCeLogData;
#ifdef NKPROF
g_pfnCeLogInterrupt = g_pCeLogList->pfnCeLogInterrupt;
#endif
}
// Set the new zones in UserKData
CeLogEnableZones(g_dwZoneCE);
DEBUGMSG(1, (TEXT("CeLog DLL unloaded. (%u remaining)\r\n"), g_dwCeLogDLLCount));
LeaveCeLogRegisterCS();
break;
}
case IOCTL_CELOG_GETDESKTOPZONE: {
//
// A CeLog DLL is requesting desktop zone settings
//
if (lpInBuf && lpOutBuf && (nOutBufSize == sizeof(DWORD))) {
DWORD i;
extern DWORD g_dwKeys[HOST_TRANSCFG_NUM_REGKEYS];
extern WCHAR* g_keyNames[];
for (i = 0; i < HOST_TRANSCFG_NUM_REGKEYS; i++) {
if (strcmpW (lpInBuf, g_keyNames[i]) == 0) {
*(DWORD *)lpOutBuf = g_dwKeys[i];
break;
}
}
} else {
return FALSE;
}
break;
}
case IOCTL_CELOG_REPORTZONECHANGE: {
//
// A CeLog DLL is reporting that its zones have changed internally
// without a call to CeLogSetZones
//
CeLogDLLInfo *pDLL;
// Recalculate global zone settings -- we will have to walk the
// whole list to recalculate the zones
g_dwZoneUser = 0;
g_dwZoneCE = 0;
g_dwZoneProcess = 0;
for (pDLL = g_pCeLogList; pDLL; pDLL = pDLL->pNext) {
// We don't know which DLL changed so we have to query the zone
// settings for every DLL
if (pDLL->pfnCeLogQueryZones) {
pDLL->pfnCeLogQueryZones(&(pDLL->dwZoneUser), &(pDLL->dwZoneCE), &(pDLL->dwZoneProcess));
}
// Add the DLL's zones to the global zone settings
g_dwZoneUser |= pDLL->dwZoneUser;
g_dwZoneCE |= pDLL->dwZoneCE;
g_dwZoneProcess |= pDLL->dwZoneProcess;
}
// Set the new zones in UserKData
CeLogEnableZones(g_dwZoneCE);
break;
}
default:
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
//
// KERNEL EXPORT APIS
//
//
//------------------------------------------------------------------------------
#ifdef NKPROF
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
CeLogInterrupt(
DWORD dwLogValue
)
{
// Make use of the CeLog tracking call to count interrupts for the kernel
// profiler. This counter is not really related to CeLog.
extern BOOL bProfileTimerRunning;
extern DWORD g_ProfilerState_dwInterrupts;
if (bProfileTimerRunning
&& !(dwLogValue & 0x80000000)) { g_ProfilerState_dwInterrupts++;
}
// Do the IsCeLogZoneEnabled() test here rather than in assembly because it
// does not affect non-profiling builds. The function call(s) to get to
// this point are wasted work only on profiling builds in which CeLog is not
// currently active.
if (IsCeLogZoneEnabled(CELZONE_INTERRUPT) && g_pfnCeLogInterrupt) {
g_pfnCeLogInterrupt(dwLogValue);
}
}
#endif // NKPROF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -