Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
11 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. log.cpp
  5. Abstract:
  6. This file implements the BITS server extensions logging
  7. --*/
  8. #include "precomp.h"
  9. #include "sddl.h"
  10. const DWORD g_LogLineSize = 160;
  11. typedef char LOG_LINE_TYPE[g_LogLineSize];
  12. CRITICAL_SECTION g_LogCs;
  13. bool g_LogFileEnabled = false;
  14. bool g_LogDebuggerEnabled = false;
  15. UINT32 g_LogFlags = DEFAULT_LOG_FLAGS;
  16. HANDLE g_LogFile = INVALID_HANDLE_VALUE;
  17. HANDLE g_LogFileMapping = NULL;
  18. char g_LogDefaultFileName[ MAX_PATH*2 ];
  19. char g_LogRegistryFileName[ MAX_PATH*2 ];
  20. char *g_LogFileName = NULL;
  21. char g_LogBuffer[512];
  22. UINT64 g_LogSlots = ( DEFAULT_LOG_SIZE * 1000000 ) / g_LogLineSize;
  23. DWORD g_LogSequence = 0;
  24. UINT64 g_LogCurrentSlot = 1;
  25. LOG_LINE_TYPE *g_LogFileBase = NULL;
  26. // Allow access to system, administrators, and the creator/owner
  27. const char g_LogSecurityString[] = "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;CO)";
  28. void OpenLogFile()
  29. {
  30. bool NewFile = false;
  31. {
  32. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  33. if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
  34. g_LogSecurityString,
  35. SDDL_REVISION_1,
  36. &SecurityDescriptor,
  37. NULL ) )
  38. return;
  39. SECURITY_ATTRIBUTES SecurityAttributes =
  40. {
  41. sizeof( SECURITY_ATTRIBUTES ),
  42. SecurityDescriptor,
  43. FALSE
  44. };
  45. g_LogFile =
  46. CreateFile(
  47. g_LogFileName,
  48. GENERIC_READ | GENERIC_WRITE,
  49. FILE_SHARE_READ | FILE_SHARE_WRITE,
  50. &SecurityAttributes,
  51. OPEN_ALWAYS,
  52. FILE_ATTRIBUTE_NORMAL,
  53. NULL );
  54. LocalFree( (HLOCAL)SecurityDescriptor );
  55. if ( INVALID_HANDLE_VALUE == g_LogFile )
  56. return;
  57. }
  58. SetFilePointer( g_LogFile, 0, NULL, FILE_BEGIN );
  59. LOG_LINE_TYPE FirstLine;
  60. DWORD dwBytesRead = 0;
  61. ReadFile( g_LogFile,
  62. FirstLine,
  63. g_LogLineSize,
  64. &dwBytesRead,
  65. NULL );
  66. DWORD LineSize;
  67. UINT64 LogSlots;
  68. if ( dwBytesRead != g_LogLineSize ||
  69. 4 != sscanf( FirstLine, "# %u %I64u %u %I64u", &LineSize, &LogSlots, &g_LogSequence, &g_LogCurrentSlot ) ||
  70. LineSize != g_LogLineSize ||
  71. LogSlots != g_LogSlots )
  72. {
  73. NewFile = true;
  74. g_LogSequence = 0;
  75. g_LogCurrentSlot = 1;
  76. if ( INVALID_SET_FILE_POINTER == SetFilePointer( g_LogFile, (DWORD)g_LogSlots * g_LogLineSize, NULL, FILE_BEGIN ) )
  77. goto fatalerror;
  78. if ( !SetEndOfFile( g_LogFile ) )
  79. goto fatalerror;
  80. SetFilePointer( g_LogFile, 0, NULL, FILE_BEGIN );
  81. }
  82. g_LogFileMapping =
  83. CreateFileMapping(
  84. g_LogFile,
  85. NULL,
  86. PAGE_READWRITE,
  87. 0,
  88. 0,
  89. NULL );
  90. if ( !g_LogFileMapping )
  91. goto fatalerror;
  92. g_LogFileBase = (LOG_LINE_TYPE *)
  93. MapViewOfFile(
  94. g_LogFileMapping, // handle to file-mapping object
  95. FILE_MAP_WRITE | FILE_MAP_READ,// access mode
  96. 0, // high-order DWORD of offset
  97. 0, // low-order DWORD of offset
  98. 0 // number of bytes to map
  99. );
  100. if ( !g_LogFileBase )
  101. goto fatalerror;
  102. if ( NewFile )
  103. {
  104. LOG_LINE_TYPE FillTemplate;
  105. memset( FillTemplate, ' ', sizeof( FillTemplate ) );
  106. StringCchPrintfA(
  107. FillTemplate,
  108. g_LogLineSize,
  109. "# %u %I64u %u %I64u",
  110. g_LogLineSize,
  111. g_LogSlots,
  112. g_LogSequence,
  113. g_LogCurrentSlot );
  114. FillTemplate[ g_LogLineSize - 2 ] = '\r';
  115. FillTemplate[ g_LogLineSize - 1 ] = '\n';
  116. memcpy( g_LogFileBase, FillTemplate, sizeof( FillTemplate ) );
  117. memset( FillTemplate, '9', sizeof( FillTemplate ) );
  118. FillTemplate[ g_LogLineSize - 2 ] = '\r';
  119. FillTemplate[ g_LogLineSize - 1 ] = '\n';
  120. for( SIZE_T i=1; i < g_LogSlots; i++ )
  121. memcpy( g_LogFileBase + i, FillTemplate, sizeof( FillTemplate ) );
  122. }
  123. g_LogFileEnabled = true;
  124. return;
  125. fatalerror:
  126. if ( g_LogFileBase )
  127. {
  128. UnmapViewOfFile( (LPCVOID)g_LogFileBase );
  129. g_LogFileBase = NULL;
  130. }
  131. if ( g_LogFileMapping )
  132. {
  133. CloseHandle( g_LogFileMapping );
  134. g_LogFileMapping = NULL;
  135. }
  136. if ( INVALID_HANDLE_VALUE != g_LogFile )
  137. {
  138. CloseHandle( g_LogFile );
  139. g_LogFile = INVALID_HANDLE_VALUE;
  140. }
  141. }
  142. HRESULT LogInit()
  143. {
  144. if ( !InitializeCriticalSectionAndSpinCount( &g_LogCs, 0x80000000 ) )
  145. return HRESULT_FROM_WIN32( GetLastError() );
  146. if (!GetSystemDirectory( g_LogDefaultFileName, MAX_PATH ) )
  147. {
  148. HRESULT Hr = HRESULT_FROM_WIN32( GetLastError() );
  149. DeleteCriticalSection( &g_LogCs );
  150. return Hr;
  151. }
  152. StringCchCatA(
  153. g_LogDefaultFileName,
  154. MAX_PATH,
  155. "\\bitsserver.log" );
  156. g_LogFileName = g_LogDefaultFileName;
  157. HKEY Key = NULL;
  158. if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, LOG_SETTINGS_PATH, &Key ) )
  159. {
  160. DWORD Type;
  161. DWORD DataSize = sizeof( g_LogRegistryFileName );
  162. if ( ERROR_SUCCESS == RegQueryValueEx( Key,
  163. LOG_FILENAME_VALUE,
  164. NULL,
  165. &Type,
  166. (LPBYTE)g_LogRegistryFileName,
  167. &DataSize ) &&
  168. ( ( REG_EXPAND_SZ == Type ) || ( REG_SZ == Type ) ) )
  169. {
  170. g_LogFileName = g_LogRegistryFileName;
  171. }
  172. DWORD LogRegistryFlags;
  173. DataSize = sizeof( LogRegistryFlags );
  174. if ( ERROR_SUCCESS == RegQueryValueEx( Key,
  175. LOG_FLAGS_VALUE,
  176. NULL,
  177. &Type,
  178. (LPBYTE)&LogRegistryFlags,
  179. &DataSize ) &&
  180. ( REG_DWORD == Type ) )
  181. {
  182. g_LogFlags = LogRegistryFlags;
  183. }
  184. DWORD LogSize;
  185. DataSize = sizeof( LogSize );
  186. if ( ERROR_SUCCESS == RegQueryValueEx( Key,
  187. LOG_SIZE_VALUE,
  188. NULL,
  189. &Type,
  190. (LPBYTE)&LogSize,
  191. &DataSize ) &&
  192. ( REG_DWORD == Type ) )
  193. {
  194. g_LogSlots = ( LogSize * 1000000 ) / g_LogLineSize;
  195. }
  196. RegCloseKey( Key );
  197. Key = NULL;
  198. }
  199. if ( g_LogFlags && g_LogFileName && g_LogSlots )
  200. {
  201. OpenLogFile();
  202. }
  203. return S_OK;
  204. }
  205. void LogClose()
  206. {
  207. EnterCriticalSection( &g_LogCs );
  208. if ( g_LogFileBase )
  209. {
  210. memset( g_LogFileBase[0], ' ', sizeof( g_LogLineSize ) );
  211. StringCchPrintfA(
  212. g_LogFileBase[0],
  213. g_LogLineSize,
  214. "# %u %I64u %u %I64u",
  215. g_LogLineSize,
  216. g_LogSlots,
  217. g_LogSequence,
  218. g_LogCurrentSlot );
  219. g_LogFileBase[0][ g_LogLineSize - 2 ] = '\r';
  220. g_LogFileBase[0][ g_LogLineSize - 1 ] = '\n';
  221. UnmapViewOfFile( (LPCVOID)g_LogFileBase );
  222. g_LogFileBase = NULL;
  223. }
  224. if ( g_LogFileMapping )
  225. {
  226. CloseHandle( g_LogFileMapping );
  227. g_LogFileMapping = NULL;
  228. }
  229. if ( INVALID_HANDLE_VALUE != g_LogFile )
  230. {
  231. CloseHandle( g_LogFile );
  232. g_LogFile = INVALID_HANDLE_VALUE;
  233. }
  234. DeleteCriticalSection( &g_LogCs );
  235. }
  236. void LogInternal( UINT32 LogFlags, char *Format, va_list arglist )
  237. {
  238. if ( !g_LogFileEnabled && !g_LogDebuggerEnabled )
  239. return;
  240. DWORD LastError = GetLastError();
  241. EnterCriticalSection( &g_LogCs );
  242. DWORD ThreadId = GetCurrentThreadId();
  243. DWORD ProcessId = GetCurrentProcessId();
  244. SYSTEMTIME Time;
  245. GetLocalTime( &Time );
  246. StringCchVPrintfA(
  247. g_LogBuffer,
  248. sizeof(g_LogBuffer) - 1,
  249. Format, arglist );
  250. int CharsWritten = strlen( g_LogBuffer );
  251. char *BeginPointer = g_LogBuffer;
  252. char *EndPointer = g_LogBuffer + CharsWritten;
  253. DWORD MinorSequence = 0;
  254. while ( BeginPointer < EndPointer )
  255. {
  256. static char StaticLineBuffer[ g_LogLineSize ];
  257. char *LineBuffer = StaticLineBuffer;
  258. if ( g_LogFileBase )
  259. {
  260. LineBuffer = g_LogFileBase[ g_LogCurrentSlot ];
  261. g_LogCurrentSlot = ( g_LogCurrentSlot + 1 ) % g_LogSlots;
  262. // leave the first line alone
  263. if ( !g_LogCurrentSlot )
  264. g_LogCurrentSlot = ( g_LogCurrentSlot + 1 ) % g_LogSlots;
  265. }
  266. char *CurrentOutput = LineBuffer;
  267. StringCchPrintfA(
  268. LineBuffer,
  269. g_LogLineSize,
  270. "%.8X.%.2X %.2u/%.2u/%.4u-%.2u:%.2u:%.2u.%.3u %.4X.%.4X %s|%s|%s|%s|%s ",
  271. g_LogSequence,
  272. MinorSequence++,
  273. Time.wMonth,
  274. Time.wDay,
  275. Time.wYear,
  276. Time.wHour,
  277. Time.wMinute,
  278. Time.wSecond,
  279. Time.wMilliseconds,
  280. ProcessId,
  281. ThreadId,
  282. ( LogFlags & LOG_INFO ) ? "I" : "-",
  283. ( LogFlags & LOG_WARNING ) ? "W" : "-",
  284. ( LogFlags & LOG_ERROR ) ? "E" : "-",
  285. ( LogFlags & LOG_CALLBEGIN ) ? "CB" : "--",
  286. ( LogFlags & LOG_CALLEND ) ? "CE" : "--" );
  287. int HeaderSize = strlen( LineBuffer );
  288. int SpaceAvailable = g_LogLineSize - HeaderSize - 2; // 2 bytes for /r/n
  289. int OutputChars = min( (int)( EndPointer - BeginPointer ), SpaceAvailable );
  290. int PadChars = SpaceAvailable - OutputChars;
  291. CurrentOutput += HeaderSize;
  292. memcpy( CurrentOutput, BeginPointer, OutputChars );
  293. CurrentOutput += OutputChars;
  294. BeginPointer += OutputChars;
  295. memset( CurrentOutput, ' ', PadChars );
  296. CurrentOutput += PadChars;
  297. *CurrentOutput++ = '\r';
  298. *CurrentOutput++ = '\n';
  299. ASSERT( CurrentOutput - LineBuffer == g_LogLineSize );
  300. if ( g_LogDebuggerEnabled )
  301. {
  302. static char DebugLineBuffer[ g_LogLineSize + 1];
  303. memcpy( DebugLineBuffer, LineBuffer, g_LogLineSize );
  304. DebugLineBuffer[ g_LogLineSize ] = '\0';
  305. OutputDebugString( DebugLineBuffer );
  306. }
  307. }
  308. g_LogSequence++;
  309. LeaveCriticalSection( &g_LogCs );
  310. SetLastError( LastError );
  311. }