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.

550 lines
16 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <assert.h>
  6. #include <pdh.h>
  7. #include <pdhp.h>
  8. #include <pdhmsg.h>
  9. #include <winperf.h>
  10. #include <tchar.h>
  11. #include <varg.h>
  12. #include "rpdh.h"
  13. const DWORD dwFileHeaderLength = 13;
  14. const DWORD dwTypeLoc = 2;
  15. const DWORD dwFieldLength = 7;
  16. const DWORD dwPerfmonTypeLength = 5;
  17. LPCSTR szTsvType = "PDH-TSV";
  18. LPCSTR szCsvType = "PDH-CSV";
  19. LPCSTR szBinaryType = "PDH-BIN";
  20. LPCWSTR cszPerfmonLogSig = (LPCWSTR)L"Loges";
  21. #define MemoryAllocate(x) \
  22. ((LPVOID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, x))
  23. #define MemoryFree(x) \
  24. if( x ){ ((VOID) HeapFree(GetProcessHeap(), 0, x)); x = NULL; }
  25. #define MemoryResize(x,y) \
  26. ((LPVOID) HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, x, y));
  27. #define MAKEULONGLONG(low, high) \
  28. ((ULONGLONG) (((DWORD) (low)) | ((ULONGLONG) ((DWORD) (high))) << 32))
  29. #define PDH_BLG_HEADER_SIZE 24
  30. #define PDH_MAX_BUFFER 0x01000000
  31. #define PDH_HEADER_BUFFER 65536
  32. typedef struct _PDHI_BINARY_LOG_RECORD_HEADER {
  33. DWORD dwType;
  34. DWORD dwLength;
  35. } PDHI_BINARY_LOG_RECORD_HEADER, *PPDHI_BINARY_LOG_RECORD_HEADER;
  36. PDH_STATUS
  37. R_PdhRelog( LPTSTR szSource, HQUERY hQuery, PPDH_RELOG_INFO_W pRelogInfo )
  38. {
  39. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  40. HLOG hLogOut;
  41. ULONG nSampleCount = 0;
  42. ULONG nSamplesWritten = 0;
  43. ULONG nRecordSkip;
  44. pdhStatus = PdhOpenLogW(
  45. pRelogInfo->strLog,
  46. pRelogInfo->dwFlags,
  47. &pRelogInfo->dwFileFormat,
  48. hQuery,
  49. 0,
  50. NULL,
  51. &hLogOut
  52. );
  53. if( pdhStatus == ERROR_SUCCESS ){
  54. DWORD dwNumEntries = 1;
  55. DWORD dwBufferSize = sizeof(PDH_TIME_INFO);
  56. PDH_TIME_INFO TimeInfo;
  57. ZeroMemory( &TimeInfo, sizeof( PDH_TIME_INFO ) );
  58. pdhStatus = PdhGetDataSourceTimeRange(
  59. szSource,
  60. &dwNumEntries,
  61. &TimeInfo,
  62. &dwBufferSize
  63. );
  64. if( pRelogInfo->TimeInfo.StartTime > TimeInfo.StartTime &&
  65. pRelogInfo->TimeInfo.StartTime < TimeInfo.EndTime ){
  66. TimeInfo.StartTime = pRelogInfo->TimeInfo.StartTime;
  67. }
  68. if( pRelogInfo->TimeInfo.EndTime < TimeInfo.EndTime &&
  69. pRelogInfo->TimeInfo.EndTime > TimeInfo.StartTime ){
  70. TimeInfo.EndTime = pRelogInfo->TimeInfo.EndTime;
  71. }
  72. if( TimeInfo.EndTime > TimeInfo.StartTime ){
  73. pdhStatus = PdhSetQueryTimeRange( hQuery, &TimeInfo );
  74. }
  75. nRecordSkip = pRelogInfo->TimeInfo.SampleCount >= 1 ? pRelogInfo->TimeInfo.SampleCount : 1;
  76. while( ERROR_SUCCESS == pdhStatus ){
  77. if( nSampleCount++ % nRecordSkip ){
  78. pdhStatus = PdhCollectQueryData( hQuery );
  79. continue;
  80. }
  81. if( ERROR_SUCCESS == pdhStatus ){
  82. pdhStatus = PdhUpdateLog( hLogOut, NULL );
  83. nSamplesWritten++;
  84. }
  85. }
  86. if( PDH_NO_MORE_DATA == pdhStatus ||
  87. (PDH_ENTRY_NOT_IN_LOG_FILE == pdhStatus && pRelogInfo->dwFileFormat == PDH_LOG_TYPE_BINARY) ){
  88. pdhStatus = PdhCloseLog( hLogOut, 0 );
  89. if( ERROR_SUCCESS == pdhStatus ){
  90. PdhGetDataSourceTimeRange( pRelogInfo->strLog, &dwNumEntries, &pRelogInfo->TimeInfo, &dwBufferSize );
  91. }
  92. }
  93. }
  94. pRelogInfo->TimeInfo.SampleCount = nSamplesWritten;
  95. return pdhStatus;
  96. }
  97. DWORD
  98. GetLogFileType (
  99. IN HANDLE hLogFile
  100. )
  101. {
  102. CHAR cBuffer[MAX_PATH];
  103. CHAR cType[MAX_PATH];
  104. WCHAR wcType[MAX_PATH];
  105. BOOL bStatus;
  106. DWORD dwResult;
  107. DWORD dwBytesRead;
  108. memset (&cBuffer[0], 0, sizeof(cBuffer));
  109. memset (&cType[0], 0, sizeof(cType));
  110. memset (&wcType[0], 0, sizeof(wcType));
  111. // read first log file record
  112. SetFilePointer (hLogFile, 0, NULL, FILE_BEGIN);
  113. bStatus = ReadFile (hLogFile,
  114. (LPVOID)cBuffer,
  115. dwFileHeaderLength,
  116. &dwBytesRead,
  117. NULL);
  118. if (bStatus) {
  119. // read header record to get type
  120. lstrcpynA (cType, (LPSTR)(cBuffer+dwTypeLoc), dwFieldLength+1);
  121. if (lstrcmpA(cType, szTsvType) == 0) {
  122. dwResult = PDH_LOG_TYPE_TSV;
  123. } else if (lstrcmpA(cType, szCsvType) == 0) {
  124. dwResult = PDH_LOG_TYPE_CSV;
  125. } else if (lstrcmpA(cType, szBinaryType) == 0) {
  126. dwResult = PDH_LOG_TYPE_RETIRED_BIN_;
  127. } else {
  128. // perfmon log file type string is in a different
  129. // location than sysmon logs and used wide chars.
  130. lstrcpynW (wcType, (LPWSTR)cBuffer, dwPerfmonTypeLength+1);
  131. if (lstrcmpW(wcType, cszPerfmonLogSig) == 0) {
  132. dwResult = PDH_LOG_TYPE_PERFMON;
  133. } else {
  134. dwResult = PDH_LOG_TYPE_UNDEFINED;
  135. }
  136. }
  137. } else {
  138. // unable to read file
  139. dwResult = PDH_LOG_TYPE_UNDEFINED;
  140. }
  141. return dwResult;
  142. }
  143. PDH_STATUS
  144. R_PdhBlgLogFileHeader(LPCWSTR szFile1, LPCWSTR szFile2)
  145. {
  146. BOOL bReturn = FALSE;
  147. PDH_STATUS Status = ERROR_SUCCESS;
  148. LPWSTR szHeaderList1 = NULL;
  149. LPWSTR szHeaderList2 = NULL;
  150. DWORD dwHeader1 = 0;
  151. DWORD dwHeader2 = 0;
  152. LPWSTR szName1;
  153. LPWSTR szName2;
  154. Status = PdhListLogFileHeaderW(szFile1, szHeaderList1, &dwHeader1);
  155. if (Status != ERROR_SUCCESS && Status != PDH_MORE_DATA && Status != PDH_INSUFFICIENT_BUFFER){
  156. goto Cleanup;
  157. }
  158. szHeaderList1 = (LPWSTR)MemoryAllocate( (dwHeader1+1)*sizeof(WCHAR) );
  159. Status = PdhListLogFileHeaderW(szFile1, szHeaderList1, &dwHeader1);
  160. if (Status != ERROR_SUCCESS ){
  161. goto Cleanup;
  162. }
  163. Status = PdhListLogFileHeaderW(szFile2, szHeaderList2, &dwHeader2);
  164. if (Status != ERROR_SUCCESS && Status != PDH_MORE_DATA && Status != PDH_INSUFFICIENT_BUFFER){
  165. goto Cleanup;
  166. }
  167. szHeaderList2 = (LPWSTR)MemoryAllocate( (dwHeader2+1)*sizeof(WCHAR) );
  168. Status = PdhListLogFileHeaderW(szFile2, szHeaderList2, &dwHeader2);
  169. if (Status != ERROR_SUCCESS ){
  170. goto Cleanup;
  171. }
  172. for (szName1 = szHeaderList1, szName2 = szHeaderList2;
  173. szName1[0] != L'\0' && szName2[0] != L'\0';
  174. szName1 += (lstrlenW(szName1) + 1),
  175. szName2 += (lstrlenW(szName2) + 1)) {
  176. if (lstrcmpiW(szName1, szName2) != 0) {
  177. varg_printf( g_debug, _T("(%s) != (%s)\n"), szName1, szName2);
  178. break;
  179. }
  180. }
  181. if (szName1[0] != L'\0' || szName2[0] != L'\0'){
  182. Status = PDH_HEADER_MISMATCH;
  183. }
  184. Cleanup:
  185. MemoryFree( szHeaderList1 );
  186. MemoryFree( szHeaderList2 );
  187. return Status;
  188. }
  189. PDH_STATUS
  190. R_PdhGetLogFileType(
  191. IN LPCWSTR LogFileName,
  192. IN LPDWORD LogFileType)
  193. {
  194. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  195. HANDLE hFile;
  196. DWORD dwLogFormat;
  197. if (LogFileName == NULL) {
  198. pdhStatus = PDH_INVALID_ARGUMENT;
  199. }
  200. else {
  201. __try {
  202. dwLogFormat = * LogFileType;
  203. * LogFileType = dwLogFormat;
  204. if (* LogFileName == L'\0') {
  205. pdhStatus = PDH_INVALID_ARGUMENT;
  206. }
  207. } __except (EXCEPTION_EXECUTE_HANDLER) {
  208. pdhStatus = PDH_INVALID_ARGUMENT;
  209. }
  210. }
  211. if (pdhStatus == ERROR_SUCCESS) {
  212. hFile = CreateFileW(LogFileName,
  213. GENERIC_READ,
  214. FILE_SHARE_READ | FILE_SHARE_WRITE,
  215. NULL,
  216. OPEN_EXISTING,
  217. FILE_ATTRIBUTE_NORMAL,
  218. NULL);
  219. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
  220. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  221. }
  222. }
  223. if (pdhStatus == ERROR_SUCCESS) {
  224. dwLogFormat = GetLogFileType(hFile);
  225. CloseHandle(hFile);
  226. }
  227. if (pdhStatus == ERROR_SUCCESS) {
  228. * LogFileType = dwLogFormat;
  229. }
  230. return pdhStatus;
  231. }
  232. PDH_STATUS
  233. R_PdhRelogCopyFile(
  234. HANDLE hOutFile,
  235. HANDLE hInFile,
  236. BOOL bCopyHeader
  237. )
  238. {
  239. BOOL bResult = TRUE;
  240. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  241. DWORD dwSizeLow = 0;
  242. DWORD dwSizeHigh = 0;
  243. DWORD dwBuffer = PDH_MAX_BUFFER;
  244. ULONGLONG lFileSize = 0;
  245. ULONGLONG lCurrent = 0;
  246. LPBYTE pBuffer = NULL;
  247. LPBYTE pCurrent = NULL;
  248. PPDHI_BINARY_LOG_RECORD_HEADER pPdhBlgHeader = NULL;
  249. dwSizeLow = GetFileSize(hInFile, & dwSizeHigh);
  250. lFileSize = MAKEULONGLONG(dwSizeLow, dwSizeHigh);
  251. lCurrent = PDH_BLG_HEADER_SIZE + sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  252. if (lCurrent > lFileSize) {
  253. pdhStatus = PDH_INVALID_HANDLE;
  254. goto Cleanup;
  255. }
  256. pBuffer = (LPBYTE)MemoryAllocate(dwBuffer);
  257. if (pBuffer == NULL) {
  258. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  259. goto Cleanup;
  260. }
  261. dwSizeLow = (DWORD) lCurrent;
  262. dwSizeHigh = 0;
  263. bResult = ReadFile(hInFile, pBuffer, dwSizeLow, & dwSizeHigh, NULL);
  264. if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
  265. pdhStatus = PDH_INVALID_DATA;
  266. goto Cleanup;
  267. }
  268. pPdhBlgHeader = (PPDHI_BINARY_LOG_RECORD_HEADER)
  269. (pBuffer + PDH_BLG_HEADER_SIZE);
  270. if (pPdhBlgHeader->dwType != 0x01024C42) {
  271. pdhStatus = PDH_INVALID_ARGUMENT;
  272. goto Cleanup;
  273. }
  274. if (pPdhBlgHeader->dwLength + PDH_BLG_HEADER_SIZE > dwBuffer) {
  275. LPBYTE pTemp = pBuffer;
  276. pBuffer = (LPBYTE)MemoryResize(pBuffer, pPdhBlgHeader->dwLength);
  277. if (pBuffer == NULL) {
  278. MemoryFree(pTemp);
  279. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  280. goto Cleanup;
  281. }
  282. }
  283. if ((lCurrent + dwSizeLow) > lFileSize) {
  284. pdhStatus = PDH_INVALID_HANDLE;
  285. goto Cleanup;
  286. }
  287. pCurrent = (LPBYTE) (pBuffer + dwSizeLow);
  288. dwSizeLow = pPdhBlgHeader->dwLength
  289. - sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  290. dwSizeHigh = 0;
  291. bResult = ReadFile(hInFile, pCurrent, dwSizeLow, & dwSizeHigh, NULL);
  292. if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
  293. pdhStatus = PDH_INVALID_DATA;
  294. goto Cleanup;
  295. }
  296. lCurrent += dwSizeLow;
  297. if (bCopyHeader) {
  298. dwSizeLow = dwSizeHigh = (DWORD) lCurrent;
  299. bResult = WriteFile(hOutFile, pBuffer, dwSizeLow, & dwSizeHigh, NULL);
  300. if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
  301. pdhStatus = PDH_INVALID_DATA;
  302. goto Cleanup;
  303. }
  304. }
  305. while (lCurrent + sizeof(PDHI_BINARY_LOG_RECORD_HEADER) < lFileSize) {
  306. ZeroMemory(pBuffer, dwBuffer);
  307. dwSizeLow = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  308. dwSizeHigh = 0;
  309. bResult = ReadFile(hInFile, pBuffer, dwSizeLow, & dwSizeHigh, NULL);
  310. if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
  311. pdhStatus = PDH_INVALID_DATA;
  312. goto Cleanup;
  313. }
  314. pPdhBlgHeader = (PPDHI_BINARY_LOG_RECORD_HEADER) pBuffer;
  315. if ((pPdhBlgHeader->dwType & 0x0000FFFF) != 0x00004C42) {
  316. pdhStatus = PDH_INVALID_ARGUMENT;
  317. goto Cleanup;
  318. }
  319. if (pPdhBlgHeader->dwLength > dwBuffer) {
  320. LPBYTE pTemp = pBuffer;
  321. pBuffer = (LPBYTE)MemoryResize(pBuffer, pPdhBlgHeader->dwLength);
  322. if (pBuffer == NULL) {
  323. MemoryFree(pTemp);
  324. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  325. goto Cleanup;
  326. }
  327. }
  328. if ((lCurrent + pPdhBlgHeader->dwLength) > lFileSize) {
  329. pdhStatus = PDH_INVALID_HANDLE;
  330. bResult = FALSE;
  331. goto Cleanup;
  332. }
  333. pCurrent = (LPBYTE) (pBuffer + dwSizeLow);
  334. dwSizeLow = pPdhBlgHeader->dwLength
  335. - sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  336. dwSizeHigh = 0;
  337. bResult = ReadFile(hInFile, pCurrent, dwSizeLow, & dwSizeHigh, NULL);
  338. if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
  339. pdhStatus = PDH_INVALID_DATA;
  340. goto Cleanup;
  341. }
  342. if ((pPdhBlgHeader->dwType & 0x00FF0000) == 0x00030000) {
  343. dwSizeLow = dwSizeHigh = pPdhBlgHeader->dwLength;
  344. bResult = WriteFile(
  345. hOutFile, pBuffer, dwSizeLow, & dwSizeHigh, NULL);
  346. if ((bResult == FALSE) || (dwSizeLow != dwSizeHigh)) {
  347. pdhStatus = PDH_INVALID_DATA;
  348. goto Cleanup;
  349. }
  350. }
  351. lCurrent += pPdhBlgHeader->dwLength;
  352. }
  353. Cleanup:
  354. if (pBuffer != NULL){
  355. MemoryFree(pBuffer);
  356. }
  357. return pdhStatus;
  358. }
  359. PDH_STATUS
  360. R_PdhAppendLog( LPTSTR szSource, LPTSTR szAppend )
  361. {
  362. HANDLE hSource = INVALID_HANDLE_VALUE;
  363. HANDLE hAppend = INVALID_HANDLE_VALUE;
  364. BOOL bResult = TRUE;
  365. PDH_STATUS pdhStatus;
  366. DWORD dwFormat;
  367. PDH_TIME_INFO TimeSource;
  368. PDH_TIME_INFO TimeAppend;
  369. LPTSTR mszSourceHeader = NULL;
  370. LPTSTR mszAppendHeader = NULL;
  371. DWORD dwSourceSize = 0;
  372. DWORD dwAppendSize = 0;
  373. DWORD dwNumEntries = 1;
  374. DWORD dwBufferSize = sizeof(PDH_TIME_INFO);
  375. //
  376. // Compare the log types, both must be Windows 2000 binary
  377. //
  378. pdhStatus = R_PdhGetLogFileType( szSource, &dwFormat );
  379. if( ERROR_SUCCESS != pdhStatus || PDH_LOG_TYPE_RETIRED_BIN_ != dwFormat ){
  380. if( ERROR_SUCCESS == pdhStatus ){
  381. pdhStatus = PDH_TYPE_MISMATCH;
  382. }
  383. goto cleanup;
  384. }
  385. pdhStatus = R_PdhGetLogFileType( szAppend, &dwFormat );
  386. if( ERROR_SUCCESS != pdhStatus || PDH_LOG_TYPE_RETIRED_BIN_ != dwFormat ){
  387. if( ERROR_SUCCESS == pdhStatus ){
  388. pdhStatus = PDH_TYPE_MISMATCH;
  389. }
  390. goto cleanup;
  391. }
  392. //
  393. // Compare the time ranges, source file must start after append end
  394. //
  395. ZeroMemory( &TimeSource, sizeof( PDH_TIME_INFO ) );
  396. ZeroMemory( &TimeAppend, sizeof( PDH_TIME_INFO ) );
  397. pdhStatus = PdhGetDataSourceTimeRange(
  398. szSource,
  399. &dwNumEntries,
  400. &TimeSource,
  401. &dwBufferSize
  402. );
  403. if( ERROR_SUCCESS != pdhStatus ){
  404. goto cleanup;
  405. }
  406. pdhStatus = PdhGetDataSourceTimeRange(
  407. szAppend,
  408. &dwNumEntries,
  409. &TimeAppend,
  410. &dwBufferSize
  411. );
  412. if( ERROR_SUCCESS != pdhStatus ){
  413. goto cleanup;
  414. }
  415. if( TimeSource.EndTime > TimeAppend.StartTime ){
  416. pdhStatus = PDH_TIME_MISMATCH;
  417. goto cleanup;
  418. }
  419. //
  420. // Compare the headers, must be exact match
  421. //
  422. pdhStatus = R_PdhBlgLogFileHeader( szSource, szAppend );
  423. if( ERROR_SUCCESS != pdhStatus ){
  424. goto cleanup;
  425. }
  426. //
  427. // All good, now do the actual append
  428. //
  429. hSource = CreateFileW(
  430. szSource,
  431. GENERIC_READ|GENERIC_WRITE,
  432. FILE_SHARE_READ,
  433. NULL,
  434. OPEN_EXISTING,
  435. FILE_ATTRIBUTE_NORMAL,
  436. NULL
  437. );
  438. hAppend = CreateFileW(
  439. szAppend,
  440. GENERIC_READ,
  441. FILE_SHARE_READ,
  442. NULL,
  443. OPEN_EXISTING,
  444. FILE_ATTRIBUTE_NORMAL,
  445. NULL
  446. );
  447. if ( INVALID_HANDLE_VALUE == hSource || INVALID_HANDLE_VALUE == hAppend ){
  448. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  449. goto cleanup;
  450. }
  451. SetFilePointer( hSource, NULL, NULL, FILE_END );
  452. pdhStatus = R_PdhRelogCopyFile( hSource, hAppend, FALSE);
  453. cleanup:
  454. MemoryFree( mszSourceHeader );
  455. MemoryFree( mszAppendHeader );
  456. if ( INVALID_HANDLE_VALUE != hAppend ) {
  457. CloseHandle(hAppend);
  458. }
  459. if ( INVALID_HANDLE_VALUE != hSource ) {
  460. CloseHandle(hSource);
  461. }
  462. return pdhStatus;
  463. }