Leaked source code of windows server 2003
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.

325 lines
10 KiB

  1. //-----------------------------------------------------------------------------
  2. // Util.cpp
  3. //-----------------------------------------------------------------------------
  4. #include <logutil.h>
  5. #include <tchar.h>
  6. #include <winerror.h>
  7. #include <shlwapi.h>
  8. #include <assert.h>
  9. #include <stdio.h>
  10. CLogging::CLogging( LPCTSTR ps ) :
  11. m_psLogFile(NULL), m_psDefaultPath(NULL), m_bInitialized(false), m_hInstance(NULL), m_bSkipDefaultPath(false)
  12. {
  13. assert( ps );
  14. if ( NULL != ps )
  15. {
  16. m_psLogFile = new TCHAR[ _tcslen( ps ) + 1 ];
  17. if( NULL != m_psLogFile )
  18. {
  19. _tcscpy( m_psLogFile, ps );
  20. }
  21. }
  22. }
  23. CLogging::CLogging( LPCTSTR ps, LPCTSTR psPath ) :
  24. m_psLogFile(NULL), m_psDefaultPath(NULL), m_bInitialized(false), m_hInstance(NULL), m_bSkipDefaultPath(false)
  25. {
  26. assert( ps );
  27. if ( NULL != ps )
  28. {
  29. m_psLogFile = new TCHAR[ _tcslen( ps ) + 1 ];
  30. if(NULL != m_psLogFile)
  31. {
  32. _tcscpy( m_psLogFile, ps );
  33. }
  34. }
  35. assert( psPath );
  36. if ( NULL != psPath )
  37. {
  38. //try to substitute any embedded environment variables
  39. DWORD dwRC = 0;
  40. DWORD dwSize = ExpandEnvironmentStrings( psPath, m_psDefaultPath, 0 );
  41. if ( 0 != dwSize )
  42. {
  43. m_psDefaultPath = new TCHAR[dwSize + 1];
  44. dwRC = ExpandEnvironmentStrings( psPath, m_psDefaultPath, dwSize );
  45. }
  46. if ( 0 == dwRC )
  47. {
  48. dwSize = _tcslen( psPath ) + 1;
  49. m_psDefaultPath = new TCHAR[ dwSize ];
  50. if(NULL != m_psDefaultPath)
  51. {
  52. _tcsncpy( m_psDefaultPath, psPath, dwSize );
  53. }
  54. }
  55. }
  56. }
  57. CLogging::~CLogging ()
  58. {
  59. if ( NULL != m_psLogFile )
  60. delete m_psLogFile;
  61. if ( NULL != m_psDefaultPath )
  62. delete m_psDefaultPath;
  63. }
  64. void CLogging::Init( HINSTANCE hinst )
  65. {
  66. m_hInstance = hinst;
  67. }
  68. void CLogging::LogPrivate( LPCTSTR szBuffer )
  69. {
  70. if (!m_bInitialized)
  71. Initialize();
  72. if (!m_bInitialized)
  73. return;
  74. // always create/open the log file and close it after each write
  75. HANDLE hf = CreateFile( m_psLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  76. if (hf != INVALID_HANDLE_VALUE)
  77. {
  78. // io
  79. DWORD dwWritten = 0;
  80. if (!SetFilePointer( hf, 0, NULL, FILE_END ))
  81. {
  82. #ifdef UNICODE
  83. // write UNICODE signature (only first time)
  84. unsigned char sig[2] = { 0xFF, 0xFE };
  85. WriteFile (hf, (LPVOID)sig, 2, &dwWritten, NULL);
  86. #endif
  87. }
  88. // write data
  89. dwWritten = 0;
  90. WriteFile( hf, (LPVOID)szBuffer, sizeof(TCHAR)*_tcslen( szBuffer ), &dwWritten, NULL );
  91. assert( dwWritten != 0 );
  92. // write crlf (if nec)
  93. // add a new line if not present
  94. int nLen = _tcslen( szBuffer );
  95. if ( nLen >=2 )
  96. {
  97. if (szBuffer[nLen - 2] != _T('\r') || szBuffer[nLen - 1] != _T('\n'))
  98. WriteFile( hf, (LPVOID)_T("\r\n"), 2 * sizeof(TCHAR), &dwWritten, NULL );
  99. }
  100. // close up (every time)
  101. CloseHandle( hf );
  102. }
  103. }
  104. void CLogging::Initialize()
  105. {
  106. HRESULT hr = S_OK;
  107. // use default log file name if necessary
  108. if ( NULL == m_psLogFile )
  109. {
  110. m_psLogFile = new TCHAR[32];
  111. if ( NULL == m_psLogFile )
  112. hr = E_OUTOFMEMORY;
  113. else
  114. _tcscpy( m_psLogFile, _T("LOGFILE.log"));
  115. }
  116. // skip default path for non-server running apps
  117. if( !m_bSkipDefaultPath )
  118. {
  119. // create dir if not there already
  120. if ( NULL == m_psDefaultPath )
  121. {
  122. DWORD dwSize = MAX_PATH;
  123. m_psDefaultPath = new TCHAR[MAX_PATH];
  124. if ( NULL == m_psDefaultPath )
  125. hr = E_OUTOFMEMORY;
  126. else
  127. {
  128. if ( 0 == GetModuleFileName( NULL, m_psDefaultPath, dwSize ) )
  129. hr = HRESULT_FROM_WIN32( GetLastError() );
  130. else
  131. {
  132. LPTSTR ps = _tcsrchr( m_psDefaultPath, _T( '\\' ));
  133. if ( NULL != ps )
  134. *ps = NULL;
  135. }
  136. }
  137. }
  138. else
  139. {
  140. if ( 0 == CreateDirectory( m_psDefaultPath, NULL ))
  141. {
  142. DWORD dwRC = GetLastError();
  143. if ( ERROR_ALREADY_EXISTS == dwRC )
  144. hr = S_OK;
  145. else
  146. hr = HRESULT_FROM_WIN32(hr);
  147. }
  148. if ( !PathAppend( m_psDefaultPath, m_psLogFile ))
  149. hr = E_FAIL;
  150. delete [] m_psLogFile;
  151. //m_psLogFile = m_psDefaultPath; This causes double free in the destructor...
  152. m_psLogFile = new TCHAR[ _tcslen( m_psDefaultPath ) + 1 ];
  153. if( NULL != m_psLogFile )
  154. {
  155. _tcscpy( m_psLogFile, m_psDefaultPath );
  156. }
  157. }
  158. }
  159. if SUCCEEDED( hr )
  160. {
  161. m_bInitialized = TRUE;
  162. // write initial messages to file
  163. TCHAR szTime[50];
  164. TCHAR szDate[50];
  165. GetTimeFormat( LOCALE_USER_DEFAULT, TIME_NOSECONDS, NULL, NULL, szTime, 50 );
  166. GetDateFormat( LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, szDate, 50 );
  167. Log( _T("\r\n%s %s"), szDate, szTime );
  168. }
  169. }
  170. void __cdecl CLogging::Log( int iMessageId, ... )
  171. {
  172. va_list ArgList; // to turn ellipses into va_list
  173. va_start( ArgList, iMessageId );
  174. LPTSTR lpBuffer = NULL;
  175. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, m_hInstance, iMessageId, 0, (LPTSTR)&lpBuffer, 0, &ArgList );
  176. assert( lpBuffer );
  177. if( lpBuffer )
  178. {
  179. LogPrivate (lpBuffer);
  180. LocalFree (lpBuffer);
  181. }
  182. va_end(ArgList);
  183. }
  184. void __cdecl CLogging::Log( LPCTSTR lpszFormat, ... )
  185. {
  186. // form the log string
  187. va_list args;
  188. va_start( args, lpszFormat );
  189. TCHAR szBuffer[2048];
  190. // 2KB max log string with room for new line and null termination
  191. _vsntprintf( szBuffer, 2047, lpszFormat, args );
  192. szBuffer[2047]=0;
  193. va_end( args );
  194. LogPrivate( szBuffer );
  195. }
  196. void CLogging::Size( DWORD _FileSizeLow )
  197. {
  198. if ( 0 != _FileSizeLow % 2 )
  199. {
  200. assert( false ); // Even numbers required in case this is a UNICODE file
  201. return;
  202. }
  203. if ( 1 > static_cast<long>( _FileSizeLow ))
  204. {
  205. assert( false ); // Need a positive number
  206. return;
  207. }
  208. if (m_bInitialized == FALSE)
  209. Initialize();
  210. if (!m_bInitialized)
  211. return;
  212. WIN32_FIND_DATA stWfd;
  213. HANDLE hSearch;
  214. DWORD dwRC;
  215. PBYTE pbBuffer, pbBlankLine;
  216. DWORD dwRead = 0, dwWrite, dwWritten;
  217. BOOL bRC;
  218. pbBuffer = new BYTE[_FileSizeLow];
  219. if ( pbBuffer == NULL )
  220. {
  221. return;
  222. }
  223. ZeroMemory( pbBuffer, _FileSizeLow );
  224. hSearch = FindFirstFile( m_psLogFile, &stWfd );
  225. if ( hSearch != INVALID_HANDLE_VALUE )
  226. {
  227. FindClose( hSearch );
  228. if ( 0 < stWfd.nFileSizeHigh || _FileSizeLow < stWfd.nFileSizeLow )
  229. { // Need to resize the file
  230. HANDLE hf = CreateFile( m_psLogFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  231. if (hf != INVALID_HANDLE_VALUE)
  232. { // Move the pointer to the end of the file - the size we want to truncate to
  233. dwRC = SetFilePointer( hf, _FileSizeLow * -1, NULL, FILE_END );
  234. if ( INVALID_SET_FILE_POINTER != dwRC )
  235. {
  236. bRC = ReadFile( hf, reinterpret_cast<LPVOID>( pbBuffer ), _FileSizeLow, &dwRead, NULL );
  237. CloseHandle( hf );
  238. if ( bRC && 0 < dwRead )
  239. { // Find the first blank line
  240. pbBlankLine = reinterpret_cast<PBYTE>( _tcsstr( reinterpret_cast<LPTSTR>( pbBuffer ), _T( "\r\n\r\n" )));
  241. if ( NULL != pbBlankLine )
  242. pbBlankLine += 4 * sizeof( TCHAR );
  243. else
  244. { // Let's just find the next crlf and write out the rest of the file
  245. pbBlankLine = reinterpret_cast<PBYTE>( _tcsstr( reinterpret_cast<LPTSTR>( pbBuffer ), _T( "\r\n" )));
  246. if ( NULL != pbBlankLine )
  247. pbBlankLine += 2 * sizeof( TCHAR );
  248. }
  249. if ( NULL == pbBlankLine )
  250. { // I guess we should just write out the rest of the file
  251. pbBlankLine = pbBuffer;
  252. }
  253. HANDLE hf1 = CreateFile( m_psLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  254. if (hf1 != INVALID_HANDLE_VALUE)
  255. {
  256. #ifdef UNICODE
  257. // write UNICODE signature (only first time)
  258. unsigned char sig[2] = { 0xFF, 0xFE };
  259. WriteFile (hf1, (LPVOID)sig, 2, &dwWritten, NULL);
  260. #endif
  261. // write data
  262. dwWritten = 0;
  263. dwWrite = dwRead - static_cast<DWORD>(pbBlankLine - pbBuffer);
  264. WriteFile (hf1, pbBlankLine, dwWrite, &dwWritten, NULL);
  265. assert (dwWritten != 0);
  266. // close up (every time)
  267. CloseHandle (hf1);
  268. }
  269. }
  270. }
  271. CloseHandle(hf);
  272. }
  273. }
  274. }
  275. delete [] pbBuffer;
  276. }
  277. void CLogging::SetFile( LPCTSTR psLogFile )
  278. {
  279. assert( !(NULL == psLogFile ));
  280. if ( NULL == psLogFile )
  281. return;
  282. if ( NULL != m_psLogFile )
  283. delete m_psLogFile;
  284. m_psLogFile = new TCHAR[ _tcslen( psLogFile ) + 1 ];
  285. if ( NULL == m_psLogFile )
  286. return;
  287. _tcscpy( m_psLogFile, psLogFile );
  288. }
  289. void CLogging::SkipDefaultPath( void )
  290. {
  291. m_bSkipDefaultPath = true;
  292. }