#include "debuglogger.h" // debuglogger, not depending on coredll - for use in kernel libraries struct bufferinfo { DWORD wrptr; DWORD rdptr; DWORD logsize; bool full; DWORD droppedbytes; DWORD encodingerror; DWORD totalsize; BYTE *vdata; // virtual (ptr into loadklib process space) BYTE *pdata; // physical BYTE *vpdata; // physical (ptr into kernel process space) CRITICAL_SECTION readlock; }; static bufferinfo g_log; void initlogging(DWORD bufsize) { g_log.vdata= (BYTE*)ORIGAPI(AllocPhysMem)(bufsize, PAGE_READWRITE, 0, 0, (PULONG)&g_log.pdata); g_log.vpdata= (BYTE*)PhysToVirt((DWORD)g_log.pdata); g_log.wrptr= 0; g_log.rdptr= 0; g_log.logsize= 0; g_log.full= false; g_log.droppedbytes=0; g_log.encodingerror=0; g_log.totalsize= g_log.vdata ? bufsize : 0; ORIGAPI(InitializeCriticalSection)(&g_log.readlock); if (g_log.vdata==0) { NKDbgPrintf(L"debug logger: ERROR allocating log buffer: %08lx\n", ORIGAPI(GetLastError)()); } else { NKDbgPrintf(L"debug logger: buffer = v:%08lx, p:%08lx\n", g_log.vdata, g_log.pdata); } } void log_byte(DWORD b) { g_log.vpdata[g_log.wrptr]= (BYTE)b; g_log.wrptr++; if (g_log.wrptr>=g_log.totalsize) g_log.wrptr= 0; } DWORD readlogsize() { return g_log.logsize; } void updatelogsize(int change) { InterlockedExchangeAdd((long*)&g_log.logsize, change); } bool check_room(int req) { if (readlogsize()+8+req req) want= req; if (want > g_log.totalsize-g_log.rdptr) want= g_log.totalsize-g_log.rdptr; mymemcpy(buf, g_log.vpdata+g_log.rdptr, want); req -= want; *nread += want; g_log.rdptr += want; if (g_log.rdptr==g_log.totalsize) g_log.rdptr= 0; logsize -= want; } updatelogsize(-(int)*nread); unlockreader(); return true; } DWORD calcmsgsize(const WCHAR*msg) { DWORD n=0; while (*msg) { WCHAR c= *msg++; if (c<0x80) { n++; } else if (c<0x800) { n+=2; } else if (c<0x10000) { n+=3; } else if (c<0x110000) { n+=4; } else { n++; } } return n; } bool logmsg(const WCHAR*msg) { if (g_log.vdata==0) return false; DWORD msgsize= calcmsgsize(msg); if (!check_room(msgsize)) return false; while (*msg) { DWORD c= *msg++; // convert to utf-8 if (c<0x80) { log_byte(c); } else if (c<0x800) { log_byte(0xc0|(c>>6)); log_byte(0x80|(c&0x3f)); } else if (c<0x10000) { log_byte(0xe0|(c>>12)); log_byte(0x80|((c>>6)&0x3f)); log_byte(0x80|(c&0x3f)); } else if (c<0x110000) { log_byte(0xf0|(c>>18)); log_byte(0x80|((c>>12)&0x3f)); log_byte(0x80|((c>>6)&0x3f)); log_byte(0x80|(c&0x3f)); } else { g_log.encodingerror++; // mark as error log_byte(0xFF); } } g_log.vpdata[g_log.wrptr]= 0; updatelogsize(msgsize); return true; } bool vlogmsg(const WCHAR*msg, const void *lpParms) { WCHAR buf[10240]; NKwvsprintfW(buf, msg, (va_list)lpParms, 10240); return logmsg(buf); }