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.

3113 lines
112 KiB

  1. /*++
  2. Copyright (C) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. log.c
  5. Abstract:
  6. Log file interface functions exposed in pdh.dll
  7. --*/
  8. #include <windows.h>
  9. #ifndef _PRSHT_H_ // to eliminate W4 errors in commdlg.h
  10. #define _PRSHT_H_
  11. #endif
  12. #include <commdlg.h>
  13. #include <mbctype.h>
  14. #include <strsafe.h>
  15. #include <pdh.h>
  16. #include "pdhidef.h"
  17. #include "strings.h"
  18. #include "log_text.h"
  19. #include "log_bin.h"
  20. #include "log_sql.h"
  21. #include "log_pm.h"
  22. #include "log_wmi.h"
  23. #include "resource.h"
  24. #include "pdhmsg.h"
  25. #pragma warning (disable : 4213)
  26. // note that when the log file headers are written
  27. // they will be prefixed with a double quote character
  28. LPCSTR szTsvLogFileHeader = "(PDH-TSV 4.0)";
  29. LPCSTR szCsvLogFileHeader = "(PDH-CSV 4.0)";
  30. LPCSTR szBinLogFileHeader = "(PDH-BIN 4.0)";
  31. LPCSTR szTsvType = "PDH-TSV";
  32. LPCSTR szCsvType = "PDH-CSV";
  33. LPCSTR szBinaryType = "PDH-BIN";
  34. const DWORD dwFileHeaderLength = 13;
  35. const DWORD dwTypeLoc = 2;
  36. const DWORD dwVersionLoc = 10;
  37. const DWORD dwFieldLength = 7;
  38. const DWORD dwPerfmonTypeLength = 5; //size in chars
  39. // max mapping size of headers for binary log files
  40. #define PDH_LOG_HEADER_MAP_SIZE 8192
  41. #define VALUE_BUFFER_SIZE 32
  42. typedef struct _FILE_FILTER_INFO {
  43. UINT nDisplayTextResourceId;
  44. LPWSTR szFilterText;
  45. DWORD dwFilterTextSize;
  46. } FILE_FILTER_INFO;
  47. //
  48. // global variables
  49. //
  50. PPDHI_LOG PdhiFirstLogEntry = NULL;
  51. PPDHI_MAPPED_LOG_FILE PdhipFirstLogFile = NULL;
  52. FILE_FILTER_INFO ffiLogFilterInfo[] = {
  53. {IDS_LOGTYPE_PDH_LOGS, (LPWSTR) L"*.blg;*.csv;*.tsv", 17},
  54. {IDS_LOGTYPE_BIN_LOGS, (LPWSTR) L"*.blg", 5},
  55. {IDS_LOGTYPE_CSV_LOGS, (LPWSTR) L"*.csv", 5},
  56. {IDS_LOGTYPE_TSV_LOGS, (LPWSTR) L"*.tsv", 5},
  57. {IDS_LOGTYPE_PM_LOGS, (LPWSTR) L"*.log", 5},
  58. {IDS_LOGTYPE_ALL_LOGS, (LPWSTR) L"*.blg;*.csv;*.tsv;*.log", 23},
  59. {IDS_LOGTYPE_ALL_FILES, (LPWSTR) L"*.*", 4},
  60. {0, NULL, 0}
  61. };
  62. STATIC_DWORD
  63. MakeLogFilterInfoString(
  64. LPWSTR szLogFilter,
  65. DWORD cchLogFilterSize
  66. )
  67. {
  68. FILE_FILTER_INFO * pFFI = & ffiLogFilterInfo[0];
  69. WCHAR szThisEntry[MAX_PATH];
  70. DWORD dwStatus = ERROR_SUCCESS;
  71. LPWSTR szDestPtr = szLogFilter;
  72. LPWSTR szEndPtr = szDestPtr + cchLogFilterSize;
  73. DWORD dwUsed = 0;
  74. DWORD dwThisStringLen;
  75. ZeroMemory(szLogFilter, cchLogFilterSize * sizeof(WCHAR));
  76. while (szEndPtr > szDestPtr && pFFI->szFilterText != NULL) {
  77. dwThisStringLen = LoadStringW(ThisDLLHandle, pFFI->nDisplayTextResourceId, szThisEntry, MAX_PATH);
  78. if (dwThisStringLen > 0) {
  79. if (dwUsed + dwThisStringLen + 1 <= cchLogFilterSize) {
  80. // add in this string
  81. StringCchCopyW(szDestPtr, cchLogFilterSize - dwUsed, szThisEntry);
  82. dwUsed += dwThisStringLen + 1;
  83. szDestPtr += dwThisStringLen + 1;
  84. }
  85. }
  86. dwThisStringLen = pFFI->dwFilterTextSize;
  87. if (dwUsed + dwThisStringLen + 1 <= cchLogFilterSize) {
  88. // add in this string
  89. StringCchCopyW(szDestPtr, cchLogFilterSize - dwUsed, pFFI->szFilterText);
  90. dwUsed += dwThisStringLen + 1;
  91. szDestPtr += dwThisStringLen + 1;
  92. }
  93. pFFI ++;
  94. }
  95. if (dwUsed > 0 && dwUsed < cchLogFilterSize) {
  96. // add MSZ NULL
  97. * szDestPtr = L'\0';
  98. }
  99. else {
  100. dwStatus = ERROR_INSUFFICIENT_BUFFER;
  101. }
  102. return dwStatus;
  103. }
  104. //
  105. // Internal Logging utility functions
  106. //
  107. STATIC_DWORD
  108. OpenReadonlyMappedFile(
  109. PPDHI_LOG pLog,
  110. LPCWSTR szFileName,
  111. PPDHI_MAPPED_LOG_FILE * pFileEntry,
  112. DWORD dwLogType
  113. )
  114. {
  115. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  116. DWORD dwSize;
  117. PPDHI_MAPPED_LOG_FILE pOpenedFile = NULL;
  118. LPWSTR szSectionName = NULL;
  119. LPWSTR szThisChar;
  120. DWORD dwLoSize, dwHiSize;
  121. pdhStatus = WaitForSingleObject(hPdhContextMutex, 10000);
  122. if (pdhStatus == WAIT_TIMEOUT) {
  123. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  124. }
  125. else {
  126. if (PdhipFirstLogFile == NULL) {
  127. // then there are no mapped files so create a new entry and
  128. // fill it with this file
  129. pOpenedFile = NULL;
  130. }
  131. else {
  132. for (pOpenedFile = PdhipFirstLogFile; pOpenedFile != NULL; pOpenedFile = pOpenedFile->pNext) {
  133. if (lstrcmpiW(szFileName, pOpenedFile->szLogFileName) == 0) break;
  134. }
  135. // here pOpenedFile will either be NULL or a ponter
  136. }
  137. if (pOpenedFile == NULL) {
  138. DWORD dwPID = GetCurrentProcessId();
  139. DWORD dwSection = lstrlenW(cszLogSectionName) + lstrlenW(szFileName) + 16;
  140. szSectionName = (LPWSTR) G_ALLOC(dwSection * sizeof(WCHAR));
  141. // create a new entry
  142. dwSize = sizeof(PDHI_MAPPED_LOG_FILE) + QWORD_MULTIPLE((lstrlenW(szFileName) + 1) * sizeof(WCHAR));
  143. pOpenedFile = (PPDHI_MAPPED_LOG_FILE) G_ALLOC(dwSize);
  144. if (pOpenedFile != NULL && szSectionName != NULL) {
  145. // initialize the pointers
  146. pOpenedFile->szLogFileName = (LPWSTR) & pOpenedFile[1];
  147. StringCchCopyW(pOpenedFile->szLogFileName, lstrlenW(szFileName) + 1, szFileName);
  148. pOpenedFile->hFileHandle = CreateFileW(pOpenedFile->szLogFileName,
  149. GENERIC_READ, // Read Access for input
  150. FILE_SHARE_READ | FILE_SHARE_WRITE, // allow read sharing
  151. NULL, // default security
  152. OPEN_EXISTING,
  153. FILE_ATTRIBUTE_NORMAL, // ignored
  154. NULL); // no template file
  155. if (pOpenedFile->hFileHandle != INVALID_HANDLE_VALUE) {
  156. StringCchPrintfW(szSectionName, dwSection, L"%s_%8.8x_%s",
  157. cszLogSectionName, dwPID, pOpenedFile->szLogFileName);
  158. // remove filename type characters
  159. for (szThisChar = szSectionName; * szThisChar != L'\0'; szThisChar ++) {
  160. switch (*szThisChar) {
  161. case L'\\':
  162. case L':':
  163. case L'.':
  164. * szThisChar = L'_';
  165. break;
  166. default:
  167. break;
  168. }
  169. }
  170. dwLoSize = GetFileSize(pOpenedFile->hFileHandle, & dwHiSize);
  171. pOpenedFile->llFileSize = dwHiSize;
  172. pOpenedFile->llFileSize <<= 32;
  173. pOpenedFile->llFileSize &= 0xFFFFFFFF00000000;
  174. pOpenedFile->llFileSize += dwLoSize;
  175. // just map the header for starters
  176. if (pOpenedFile->llFileSize > 0) {
  177. pLog->iRunidSQL = 0;
  178. if (dwLogType == PDH_LOG_TYPE_RETIRED_BIN) {
  179. pOpenedFile->hMappedFile = CreateFileMappingW(pOpenedFile->hFileHandle,
  180. NULL,
  181. PAGE_READONLY,
  182. dwHiSize,
  183. dwLoSize,
  184. szSectionName);
  185. if (pOpenedFile->hMappedFile == NULL) {
  186. dwHiSize = 0;
  187. dwLoSize = PDH_LOG_HEADER_MAP_SIZE;
  188. }
  189. else {
  190. pOpenedFile->pData = MapViewOfFile(pOpenedFile->hMappedFile,
  191. FILE_MAP_READ,
  192. 0,
  193. 0,
  194. dwLoSize);
  195. if (pOpenedFile->pData == NULL) {
  196. dwHiSize = 0;
  197. dwLoSize = PDH_LOG_HEADER_MAP_SIZE;
  198. }
  199. else {
  200. pLog->iRunidSQL = 1;
  201. }
  202. }
  203. }
  204. if (pLog->iRunidSQL == 0) {
  205. pOpenedFile->hMappedFile = CreateFileMappingW(pOpenedFile->hFileHandle,
  206. NULL,
  207. PAGE_READONLY,
  208. dwHiSize, dwLoSize, szSectionName);
  209. if (pOpenedFile->hMappedFile != NULL) {
  210. pOpenedFile->pData = MapViewOfFile(pOpenedFile->hMappedFile,
  211. FILE_MAP_READ,
  212. 0,
  213. 0,
  214. dwLoSize);
  215. if (pOpenedFile->pData == NULL) {
  216. pdhStatus = GetLastError();
  217. }
  218. }
  219. else {
  220. pdhStatus = GetLastError();
  221. }
  222. }
  223. } else {
  224. // 0-length file
  225. pdhStatus = ERROR_FILE_INVALID;
  226. }
  227. }
  228. else {
  229. pdhStatus = GetLastError();
  230. }
  231. if (pdhStatus == ERROR_SUCCESS) {
  232. // then add this to the list and return the answer
  233. pOpenedFile->pNext = PdhipFirstLogFile;
  234. PdhipFirstLogFile = pOpenedFile;
  235. // init ref count
  236. pOpenedFile->dwRefCount = 1;
  237. * pFileEntry = pOpenedFile;
  238. }
  239. else {
  240. // delete it from the list and return NULL
  241. if (pOpenedFile->pData != NULL) UnmapViewOfFile(pOpenedFile->pData);
  242. if (pOpenedFile->hMappedFile != NULL) CloseHandle(pOpenedFile->hMappedFile);
  243. if (pOpenedFile->hFileHandle != NULL) CloseHandle(pOpenedFile->hFileHandle);
  244. * pFileEntry = NULL;
  245. }
  246. }
  247. else {
  248. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  249. }
  250. }
  251. else {
  252. * pFileEntry = pOpenedFile;
  253. pOpenedFile->dwRefCount ++;
  254. }
  255. RELEASE_MUTEX(hPdhContextMutex);
  256. }
  257. if (pdhStatus != ERROR_SUCCESS) G_FREE(pOpenedFile);
  258. G_FREE(szSectionName);
  259. return pdhStatus;
  260. }
  261. DWORD
  262. UnmapReadonlyMappedFile(
  263. LPVOID pMemoryBase,
  264. BOOL * bNeedToCloseHandles
  265. )
  266. {
  267. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  268. PPDHI_MAPPED_LOG_FILE pOpenedFile;
  269. PPDHI_MAPPED_LOG_FILE pPrevFile = NULL;
  270. pdhStatus = WaitForSingleObject(hPdhContextMutex, 10000);
  271. if (pdhStatus == WAIT_TIMEOUT) {
  272. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  273. }
  274. else {
  275. // find file to close
  276. for (pOpenedFile = PdhipFirstLogFile; pOpenedFile != NULL; pOpenedFile = pOpenedFile->pNext) {
  277. if (pOpenedFile->pData == pMemoryBase) {
  278. break;
  279. }
  280. else {
  281. pPrevFile = pOpenedFile;
  282. }
  283. }
  284. // here pOpenedFile will either be NULL or a ponter
  285. if (pOpenedFile != NULL) {
  286. -- pOpenedFile->dwRefCount;
  287. if (pOpenedFile->dwRefCount == 0) {
  288. // found so remove from list and close
  289. if (pOpenedFile == PdhipFirstLogFile) {
  290. PdhipFirstLogFile = pOpenedFile->pNext;
  291. }
  292. else {
  293. #pragma warning( disable: 4701 ) // pPrevFile will only be used if the opened log is not the first log
  294. pPrevFile->pNext = pOpenedFile->pNext;
  295. #pragma warning (default : 4701 )
  296. }
  297. // close open resources
  298. if (pOpenedFile->pData != NULL) UnmapViewOfFile(pOpenedFile->pData);
  299. if (pOpenedFile->hMappedFile != NULL) CloseHandle(pOpenedFile->hMappedFile);
  300. if (pOpenedFile->hFileHandle != NULL) CloseHandle(pOpenedFile->hFileHandle);
  301. G_FREE(pOpenedFile);
  302. }
  303. * bNeedToCloseHandles = FALSE;
  304. }
  305. else {
  306. // then this must be a normal mapped file
  307. if (! UnmapViewOfFile(pMemoryBase)) {
  308. pdhStatus = GetLastError();
  309. }
  310. * bNeedToCloseHandles = TRUE;
  311. }
  312. RELEASE_MUTEX (hPdhContextMutex);
  313. }
  314. return pdhStatus;
  315. }
  316. STATIC_BOOL
  317. IsValidLogHandle(
  318. PDH_HLOG hLog
  319. )
  320. /*++
  321. Routine Description:
  322. examines the log handle to verify it is a valid log entry. For now
  323. the test amounts to:
  324. the Handle is NOT NULL
  325. the memory is accessible (i.e. it doesn't AV)
  326. the signature array is valid
  327. the size field is correct
  328. if any tests fail, the handle is presumed to be invalid
  329. Arguments:
  330. IN HLOG hLog
  331. the handle of the log entry to test
  332. Return Value:
  333. TRUE the handle passes all the tests
  334. FALSE one of the test's failed and the handle is not a valid counter
  335. --*/
  336. {
  337. BOOL bReturn = FALSE; // assume it's not a valid query
  338. PPDHI_LOG pLog;
  339. __try {
  340. if (hLog != NULL) {
  341. // see if a valid signature
  342. pLog = (PPDHI_LOG) hLog;
  343. if ((* (DWORD *) & pLog->signature[0] == SigLog) && (pLog->dwLength == sizeof(PDHI_LOG))) {
  344. bReturn = TRUE;
  345. }
  346. else {
  347. // this is not a valid log entry because the sig is bad
  348. // or the structure is the wrong size
  349. }
  350. }
  351. else {
  352. // this is not a valid counter because the handle is NULL
  353. }
  354. }
  355. __except (EXCEPTION_EXECUTE_HANDLER) {
  356. // something failed miserably so we can assume this is invalid
  357. }
  358. return bReturn;
  359. }
  360. STATIC_DWORD
  361. GetLogFileType(
  362. HANDLE hLogFile
  363. )
  364. {
  365. CHAR cBuffer[MAX_PATH];
  366. LPSTR aszString;
  367. LPWSTR wszString;
  368. CHAR aszChar;
  369. WCHAR wszChar;
  370. BOOL bStatus;
  371. DWORD dwResult = PDH_LOG_TYPE_UNDEFINED;
  372. DWORD dwBytesRead;
  373. ZeroMemory(cBuffer, MAX_PATH * sizeof(CHAR));
  374. // read first log file record
  375. SetFilePointer(hLogFile, 0, NULL, FILE_BEGIN);
  376. bStatus = ReadFile(hLogFile, (LPVOID) cBuffer, dwFileHeaderLength, & dwBytesRead, NULL);
  377. if (bStatus) {
  378. // read header record to get type
  379. aszString = (cBuffer + dwTypeLoc);
  380. aszChar = * (aszString + dwFieldLength);
  381. * (aszString + dwFieldLength) = '\0';
  382. if (lstrcmpiA(aszString, szTsvType) == 0) {
  383. dwResult = PDH_LOG_TYPE_TSV;
  384. }
  385. else if (lstrcmpiA(aszString, szCsvType) == 0) {
  386. dwResult = PDH_LOG_TYPE_CSV;
  387. }
  388. else if (lstrcmpiA(aszString, szBinaryType) == 0) {
  389. dwResult = PDH_LOG_TYPE_RETIRED_BIN;
  390. }
  391. else {
  392. * (aszString + dwFieldLength) = aszChar;
  393. wszString = (LPWSTR) cBuffer;
  394. wszChar = * (wszString + dwPerfmonTypeLength);
  395. * (wszString + dwPerfmonTypeLength) = L'\0';
  396. // perfmon log file type string is in a different
  397. // location than sysmon logs and used wide chars.
  398. if (lstrcmpiW(wszString, cszPerfmonLogSig) == 0) {
  399. dwResult = PDH_LOG_TYPE_PERFMON;
  400. }
  401. }
  402. }
  403. return dwResult;
  404. }
  405. STATIC_PDH_FUNCTION
  406. CreateNewLogEntry(
  407. LPCWSTR szLogFileName,
  408. PDH_HQUERY hQuery,
  409. DWORD dwMaxSize,
  410. PPDHI_LOG * pLog
  411. )
  412. /*++
  413. creates a new log entry and inserts it in the list of open log files
  414. --*/
  415. {
  416. PPDHI_LOG pNewLog;
  417. PPDHI_LOG pFirstLog;
  418. PPDHI_LOG pLastLog;
  419. DWORD dwSize;
  420. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  421. DWORD dwLogFileNameSize = lstrlenW(szLogFileName) + 1;
  422. dwSize = sizeof(PDHI_LOG) + DWORD_MULTIPLE(2 * dwLogFileNameSize * sizeof(WCHAR));
  423. pNewLog = G_ALLOC(dwSize); // allocate new structure
  424. if (pNewLog == NULL) {
  425. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  426. * pLog = NULL;
  427. }
  428. else {
  429. // initialize the elements in the structure
  430. * ((LPDWORD) (& pNewLog->signature[0])) = SigLog;
  431. // create and acquire a data mutex for this
  432. pNewLog->hLogMutex = CreateMutexW(NULL, TRUE, NULL);
  433. // insert this item at the end of the list
  434. if (PdhiFirstLogEntry == NULL) {
  435. // then this is the first entry
  436. PdhiFirstLogEntry = pNewLog;
  437. pNewLog->next.flink =
  438. pNewLog->next.blink = pNewLog;
  439. }
  440. else {
  441. // go to the first entry and insert this one just before it
  442. pFirstLog = PdhiFirstLogEntry;
  443. pLastLog = pFirstLog->next.blink;
  444. pNewLog->next.flink = pLastLog->next.flink;
  445. pLastLog->next.flink = pNewLog;
  446. pNewLog->next.blink = pFirstLog->next.blink;
  447. pFirstLog->next.blink = pNewLog;
  448. }
  449. // set length field (this is used more for validation
  450. // than anything else
  451. pNewLog->dwLength = sizeof(PDHI_LOG);
  452. // append filename strings immediately after this block
  453. pNewLog->szLogFileName = (LPWSTR) (& pNewLog[1]);
  454. StringCchCopyW(pNewLog->szLogFileName, dwLogFileNameSize, szLogFileName);
  455. // locate catalog name immediately after log file name
  456. pNewLog->szCatFileName = pNewLog->szLogFileName + dwLogFileNameSize;
  457. //
  458. // NOTE: Catalog should be in the logfile itself, so no need for
  459. // yet another file extension
  460. StringCchCopyW(pNewLog->szCatFileName, dwLogFileNameSize, szLogFileName);
  461. // initialize the file handles
  462. pNewLog->hLogFileHandle = INVALID_HANDLE_VALUE;
  463. pNewLog->hCatFileHandle = INVALID_HANDLE_VALUE;
  464. // initialize the Record Length size
  465. pNewLog->llMaxSize = (LONGLONG) ((ULONGLONG) dwMaxSize);
  466. pNewLog->dwRecord1Size = 0;
  467. // assign the query
  468. pNewLog->pQuery = (PPDHI_QUERY) hQuery;
  469. pNewLog->dwLogFormat = 0; // for now
  470. pNewLog->pPerfmonInfo = NULL;
  471. * pLog = pNewLog;
  472. }
  473. return pdhStatus;
  474. }
  475. OpenSQLLog(
  476. PPDHI_LOG pLog,
  477. DWORD dwAccessFlags,
  478. LPDWORD lpdwLogType
  479. )
  480. {
  481. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  482. pLog->dwLogFormat = PDH_LOG_TYPE_SQL;
  483. pLog->dwLogFormat |= dwAccessFlags & (PDH_LOG_ACCESS_MASK | PDH_LOG_OPT_MASK);
  484. if ((dwAccessFlags & PDH_LOG_WRITE_ACCESS) == PDH_LOG_WRITE_ACCESS) {
  485. pdhStatus = PdhiOpenOutputSQLLog(pLog);
  486. }
  487. else {
  488. pdhStatus = PdhiOpenInputSQLLog(pLog);
  489. }
  490. if (pdhStatus == ERROR_SUCCESS) {
  491. *lpdwLogType = (DWORD) (LOWORD(pLog->dwLogFormat));
  492. }
  493. return pdhStatus;
  494. }
  495. STATIC_PDH_FUNCTION
  496. OpenInputLogFile(
  497. PPDHI_LOG pLog,
  498. DWORD dwAccessFlags,
  499. LPDWORD lpdwLogType
  500. )
  501. {
  502. LONG Win32Error;
  503. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  504. DWORD dwFileCreate = 0;
  505. PPDHI_MAPPED_LOG_FILE pMappedFileInfo = NULL;
  506. // for input, the query handle is NULL
  507. pLog->pQuery = NULL;
  508. ////////////////
  509. // SQL goes here
  510. ///////////////
  511. // First test whether logfile is WMI Event Trace format.
  512. // If all logfiles are WMI Event Trace format, return immediately;
  513. // otherwise try other formats.
  514. //
  515. pdhStatus = PdhiOpenInputWmiLog(pLog);
  516. if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_BINARY_LOG_CORRUPT || pdhStatus == PDH_LOG_SAMPLE_TOO_SMALL) {
  517. pLog->dwLogFormat = PDH_LOG_TYPE_BINARY;
  518. pLog->dwLogFormat |= dwAccessFlags & (PDH_LOG_ACCESS_MASK | PDH_LOG_OPT_MASK);
  519. * lpdwLogType = PDH_LOG_TYPE_BINARY;
  520. return pdhStatus;
  521. }
  522. pdhStatus = ERROR_SUCCESS;
  523. // open file for input based on the specified access flags
  524. switch (dwAccessFlags & PDH_LOG_CREATE_MASK) {
  525. case PDH_LOG_OPEN_EXISTING:
  526. dwFileCreate = OPEN_EXISTING;
  527. break;
  528. case PDH_LOG_CREATE_NEW:
  529. case PDH_LOG_CREATE_ALWAYS:
  530. case PDH_LOG_OPEN_ALWAYS:
  531. // a log file to be read from must not be empty or non-existent
  532. default:
  533. // unrecognized value
  534. pdhStatus = PDH_INVALID_ARGUMENT;
  535. break;
  536. }
  537. if (pdhStatus == ERROR_SUCCESS) {
  538. pLog->hLogFileHandle = CreateFileW(pLog->szLogFileName,
  539. GENERIC_READ, // Read Access for input
  540. FILE_SHARE_READ | FILE_SHARE_WRITE, // allow read sharing
  541. NULL, // default security
  542. dwFileCreate,
  543. FILE_ATTRIBUTE_NORMAL, // ignored
  544. NULL); // no template file
  545. if (pLog->hLogFileHandle == INVALID_HANDLE_VALUE) {
  546. Win32Error = GetLastError();
  547. // translate to PDH_ERROR
  548. switch (Win32Error) {
  549. case ERROR_FILE_NOT_FOUND:
  550. pdhStatus = PDH_FILE_NOT_FOUND;
  551. break;
  552. case ERROR_ALREADY_EXISTS:
  553. pdhStatus = PDH_FILE_ALREADY_EXISTS;
  554. break;
  555. default:
  556. switch (dwAccessFlags & PDH_LOG_CREATE_MASK) {
  557. case PDH_LOG_CREATE_NEW:
  558. case PDH_LOG_CREATE_ALWAYS:
  559. pdhStatus = PDH_LOG_FILE_CREATE_ERROR;
  560. break;
  561. case PDH_LOG_OPEN_EXISTING:
  562. case PDH_LOG_OPEN_ALWAYS:
  563. default:
  564. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  565. break;
  566. }
  567. break;
  568. }
  569. }
  570. }
  571. if (pdhStatus == ERROR_SUCCESS) {
  572. // read the log header and determine the log file type
  573. pLog->dwLogFormat = GetLogFileType(pLog->hLogFileHandle);
  574. if (pLog->dwLogFormat != 0) {
  575. pLog->dwLogFormat |= dwAccessFlags & (PDH_LOG_ACCESS_MASK | PDH_LOG_OPT_MASK);
  576. }
  577. else {
  578. pdhStatus = PDH_LOG_TYPE_NOT_FOUND;
  579. }
  580. switch (LOWORD(pLog->dwLogFormat)) {
  581. case PDH_LOG_TYPE_RETIRED_BIN:
  582. case PDH_LOG_TYPE_PERFMON:
  583. // close file opened above
  584. CloseHandle(pLog->hLogFileHandle);
  585. pLog->iRunidSQL = 0;
  586. pdhStatus = OpenReadonlyMappedFile(pLog,
  587. pLog->szLogFileName,
  588. & pMappedFileInfo,
  589. (DWORD) LOWORD(pLog->dwLogFormat));
  590. if (pdhStatus == ERROR_SUCCESS) {
  591. // then update log fields
  592. pLog->hLogFileHandle = pMappedFileInfo->hFileHandle;
  593. pLog->hMappedLogFile = pMappedFileInfo->hMappedFile;
  594. pLog->lpMappedFileBase = pMappedFileInfo->pData;
  595. pLog->llFileSize = pMappedFileInfo->llFileSize;
  596. }
  597. break;
  598. case PDH_LOG_TYPE_CSV:
  599. case PDH_LOG_TYPE_TSV:
  600. default:
  601. break;
  602. }
  603. }
  604. if (pdhStatus == ERROR_SUCCESS) {
  605. // call any type-specific open functions
  606. switch (LOWORD(pLog->dwLogFormat)) {
  607. case PDH_LOG_TYPE_CSV:
  608. case PDH_LOG_TYPE_TSV:
  609. pdhStatus = PdhiOpenInputTextLog(pLog);
  610. break;
  611. case PDH_LOG_TYPE_RETIRED_BIN:
  612. pdhStatus = PdhiOpenInputBinaryLog(pLog);
  613. break;
  614. case PDH_LOG_TYPE_PERFMON:
  615. pdhStatus = PdhiOpenInputPerfmonLog(pLog);
  616. break;
  617. default:
  618. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  619. break;
  620. }
  621. * lpdwLogType = (DWORD) (LOWORD(pLog->dwLogFormat));
  622. }
  623. return pdhStatus;
  624. }
  625. STATIC_PDH_FUNCTION
  626. OpenUpdateLogFile(
  627. PPDHI_LOG pLog,
  628. DWORD dwAccessFlags,
  629. LPDWORD lpdwLogType
  630. )
  631. {
  632. LONG Win32Error;
  633. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  634. DWORD dwFileCreate = 0;
  635. // for input, the query handle is NULL
  636. pLog->pQuery = NULL;
  637. // open file for input based on the specified access flags
  638. switch (dwAccessFlags & PDH_LOG_CREATE_MASK) {
  639. case PDH_LOG_OPEN_EXISTING:
  640. dwFileCreate = OPEN_EXISTING;
  641. break;
  642. case PDH_LOG_CREATE_NEW:
  643. case PDH_LOG_CREATE_ALWAYS:
  644. case PDH_LOG_OPEN_ALWAYS:
  645. // a log file to be updated must not be empty or non-existent
  646. default:
  647. // unrecognized value
  648. pdhStatus = PDH_INVALID_ARGUMENT;
  649. break;
  650. }
  651. if (pdhStatus == ERROR_SUCCESS) {
  652. pLog->hLogFileHandle = CreateFileW(pLog->szLogFileName,
  653. GENERIC_READ | GENERIC_WRITE, // Read & Write Access for input
  654. FILE_SHARE_READ, // allow read sharing
  655. NULL, // default security
  656. dwFileCreate,
  657. FILE_ATTRIBUTE_NORMAL, // ignored
  658. NULL); // no template file
  659. if (pLog->hLogFileHandle == INVALID_HANDLE_VALUE) {
  660. Win32Error = GetLastError();
  661. // translate to PDH_ERROR
  662. switch (Win32Error) {
  663. case ERROR_FILE_NOT_FOUND:
  664. pdhStatus = PDH_FILE_NOT_FOUND;
  665. break;
  666. case ERROR_ALREADY_EXISTS:
  667. pdhStatus = PDH_FILE_ALREADY_EXISTS;
  668. break;
  669. default:
  670. switch (dwAccessFlags & PDH_LOG_CREATE_MASK) {
  671. case PDH_LOG_CREATE_NEW:
  672. case PDH_LOG_CREATE_ALWAYS:
  673. pdhStatus = PDH_LOG_FILE_CREATE_ERROR;
  674. break;
  675. case PDH_LOG_OPEN_EXISTING:
  676. case PDH_LOG_OPEN_ALWAYS:
  677. default:
  678. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  679. break;
  680. }
  681. break;
  682. }
  683. }
  684. }
  685. if (pdhStatus == ERROR_SUCCESS) {
  686. // read the log header and determine the log file type
  687. pLog->dwLogFormat = GetLogFileType(pLog->hLogFileHandle);
  688. if (pLog->dwLogFormat != 0) {
  689. pLog->dwLogFormat |= dwAccessFlags & (PDH_LOG_ACCESS_MASK | PDH_LOG_OPT_MASK);
  690. }
  691. else {
  692. pdhStatus = PDH_LOG_TYPE_NOT_FOUND;
  693. }
  694. // call any type-specific open functions
  695. switch (LOWORD(pLog->dwLogFormat)) {
  696. case PDH_LOG_TYPE_CSV:
  697. case PDH_LOG_TYPE_TSV:
  698. case PDH_LOG_TYPE_BINARY:
  699. // this will be added later
  700. // updating a text file will be limited to appending, but that
  701. // has it's own problems (e.g. insuring the counter list
  702. // is the same in the new query as the one stored in the log file
  703. pdhStatus = PDH_NOT_IMPLEMENTED;
  704. break;
  705. case PDH_LOG_TYPE_RETIRED_BIN:
  706. case PDH_LOG_TYPE_PERFMON:
  707. pdhStatus = PDH_NOT_IMPLEMENTED;
  708. break;
  709. default:
  710. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  711. break;
  712. }
  713. * lpdwLogType = (DWORD) (LOWORD(pLog->dwLogFormat));
  714. }
  715. return pdhStatus;
  716. }
  717. STATIC_PDH_FUNCTION
  718. OpenOutputLogFile(
  719. PPDHI_LOG pLog,
  720. DWORD dwAccessFlags,
  721. LPDWORD lpdwLogType
  722. )
  723. {
  724. LONG Win32Error;
  725. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  726. DWORD dwFileCreate = 0;
  727. // for output, the query handle must be valid
  728. if (!IsValidQuery((PDH_HQUERY) pLog->pQuery)) {
  729. pdhStatus = PDH_INVALID_HANDLE;
  730. }
  731. if (pdhStatus == ERROR_SUCCESS) {
  732. // special handling PDH_LOG_TYPE_BINARY
  733. //
  734. if (* lpdwLogType == PDH_LOG_TYPE_BINARY) {
  735. * lpdwLogType = PDH_LOG_TYPE_BINARY;
  736. pLog->dwLogFormat = dwAccessFlags & (PDH_LOG_ACCESS_MASK | PDH_LOG_OPT_MASK);
  737. pLog->dwLogFormat |= *lpdwLogType & ~(PDH_LOG_ACCESS_MASK | PDH_LOG_OPT_MASK);
  738. return (PdhiOpenOutputWmiLog(pLog));
  739. }
  740. }
  741. // open file for output based on the specified access flags
  742. if (pdhStatus == ERROR_SUCCESS) {
  743. switch (dwAccessFlags & PDH_LOG_CREATE_MASK) {
  744. case PDH_LOG_CREATE_NEW:
  745. dwFileCreate = CREATE_NEW;
  746. break;
  747. case PDH_LOG_CREATE_ALWAYS:
  748. dwFileCreate = CREATE_ALWAYS;
  749. break;
  750. case PDH_LOG_OPEN_EXISTING:
  751. dwFileCreate = OPEN_EXISTING;
  752. break;
  753. case PDH_LOG_OPEN_ALWAYS:
  754. dwFileCreate = OPEN_ALWAYS;
  755. break;
  756. default:
  757. // unrecognized value
  758. pdhStatus = PDH_INVALID_ARGUMENT;
  759. break;
  760. }
  761. }
  762. if (pdhStatus == ERROR_SUCCESS) {
  763. pLog->hLogFileHandle = CreateFileW(pLog->szLogFileName,
  764. GENERIC_WRITE | GENERIC_READ, // write access for output
  765. FILE_SHARE_READ, // allow read sharing
  766. NULL, // default security
  767. dwFileCreate,
  768. FILE_ATTRIBUTE_NORMAL,
  769. NULL); // no template file
  770. if (pLog->hLogFileHandle == INVALID_HANDLE_VALUE) {
  771. Win32Error = GetLastError();
  772. // translate to PDH_ERROR
  773. switch (Win32Error) {
  774. case ERROR_FILE_NOT_FOUND:
  775. pdhStatus = PDH_FILE_NOT_FOUND;
  776. break;
  777. case ERROR_ALREADY_EXISTS:
  778. pdhStatus = PDH_FILE_ALREADY_EXISTS;
  779. break;
  780. default:
  781. switch (dwAccessFlags & PDH_LOG_CREATE_MASK) {
  782. case PDH_LOG_CREATE_NEW:
  783. case PDH_LOG_CREATE_ALWAYS:
  784. pdhStatus = PDH_LOG_FILE_CREATE_ERROR;
  785. break;
  786. case PDH_LOG_OPEN_EXISTING:
  787. case PDH_LOG_OPEN_ALWAYS:
  788. default:
  789. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  790. break;
  791. }
  792. break;
  793. }
  794. }
  795. }
  796. if (pdhStatus == ERROR_SUCCESS) {
  797. // the file opened successfully so update the data structure
  798. // this assumes the access flags are in the HIWORD and the...
  799. pLog->dwLogFormat = dwAccessFlags & (PDH_LOG_ACCESS_MASK | PDH_LOG_OPT_MASK);
  800. // the type id is in the LOWORD
  801. pLog->dwLogFormat |= *lpdwLogType & ~(PDH_LOG_ACCESS_MASK | PDH_LOG_OPT_MASK);
  802. // call any type-specific open functions
  803. switch (LOWORD(pLog->dwLogFormat)) {
  804. case PDH_LOG_TYPE_CSV:
  805. case PDH_LOG_TYPE_TSV:
  806. pdhStatus = PdhiOpenOutputTextLog(pLog);
  807. break;
  808. case PDH_LOG_TYPE_RETIRED_BIN:
  809. case PDH_LOG_TYPE_PERFMON:
  810. // cannot create counter logfile with PERFMON4 LOG format or WIN2K BLG format.
  811. pdhStatus = PDH_NOT_IMPLEMENTED;
  812. break;
  813. case PDH_LOG_TYPE_SQL:
  814. // SQL data soruce should be handled in PdhOpenLogW() before
  815. // it calls OpenOutputLogFile(). If it goes here, this is
  816. // an incorrect SQL datasoruce format.
  817. //
  818. pdhStatus = PDH_INVALID_SQL_LOG_FORMAT;
  819. break;
  820. default:
  821. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  822. break;
  823. }
  824. }
  825. return pdhStatus;
  826. }
  827. STATIC_PDH_FUNCTION
  828. WriteLogHeader(
  829. PPDHI_LOG pLog,
  830. LPCWSTR szUserCaption
  831. )
  832. {
  833. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  834. switch (LOWORD(pLog->dwLogFormat)) {
  835. case PDH_LOG_TYPE_CSV:
  836. case PDH_LOG_TYPE_TSV:
  837. pdhStatus = PdhiWriteTextLogHeader(pLog, szUserCaption);
  838. break;
  839. case PDH_LOG_TYPE_RETIRED_BIN:
  840. case PDH_LOG_TYPE_PERFMON:
  841. pdhStatus = PDH_NOT_IMPLEMENTED;
  842. break;
  843. case PDH_LOG_TYPE_BINARY:
  844. break;
  845. case PDH_LOG_TYPE_SQL:
  846. pdhStatus = PdhiWriteSQLLogHeader(pLog, szUserCaption);
  847. break;
  848. default:
  849. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  850. break;
  851. }
  852. return pdhStatus;
  853. }
  854. STATIC_PDH_FUNCTION
  855. DeleteLogEntry(
  856. PPDHI_LOG pLog
  857. )
  858. {
  859. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  860. PPDHI_LOG pLogNext;
  861. // assumes structure is locked
  862. if (IsValidLogHandle ((PDH_HLOG) pLog)) {
  863. if (PdhiFirstLogEntry == pLog) {
  864. // then this is the first entry in the list so the
  865. // the "first" entry will be the next forward entry
  866. if (pLog->next.flink == pLog->next.blink && pLog->next.flink == pLog) {
  867. // then this is the only entry in the list so clear the first
  868. // log entry
  869. PdhiFirstLogEntry = NULL;
  870. }
  871. else {
  872. // remove this entry from the list
  873. (pLog->next.flink)->next.blink = pLog->next.blink;
  874. (pLog->next.blink)->next.flink = pLog->next.flink;
  875. PdhiFirstLogEntry = pLog->next.flink;
  876. }
  877. }
  878. else {
  879. // it's not the first one, so
  880. // just remove it from the list
  881. (pLog->next.flink)->next.blink = pLog->next.blink;
  882. (pLog->next.blink)->next.flink = pLog->next.flink;
  883. }
  884. // and release the memory block;
  885. if (pLog->hLogMutex != NULL) {
  886. while (WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex) == WAIT_TIMEOUT);
  887. RELEASE_MUTEX(pLog->hLogMutex);
  888. CloseHandle(pLog->hLogMutex);
  889. }
  890. while (pLog) {
  891. pLogNext = pLog->NextLog;
  892. G_FREE(pLog);
  893. pLog = pLogNext;
  894. }
  895. pdhStatus = ERROR_SUCCESS;
  896. }
  897. else {
  898. pdhStatus = PDH_INVALID_HANDLE;
  899. }
  900. return pdhStatus;
  901. }
  902. STATIC_PDH_FUNCTION
  903. CloseAndDeleteLogEntry(
  904. PPDHI_LOG pLog,
  905. DWORD dwFlags,
  906. BOOLEAN bForceDelete
  907. )
  908. {
  909. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  910. BOOL bStatus;
  911. BOOL bNeedToCloseHandles = TRUE;
  912. // call any type-specific open functions
  913. switch (LOWORD(pLog->dwLogFormat)) {
  914. case PDH_LOG_TYPE_CSV:
  915. case PDH_LOG_TYPE_TSV:
  916. pdhStatus = PdhiCloseTextLog(pLog, dwFlags);
  917. break;
  918. case PDH_LOG_TYPE_RETIRED_BIN:
  919. pdhStatus = PdhiCloseBinaryLog(pLog, dwFlags);
  920. break;
  921. case PDH_LOG_TYPE_PERFMON:
  922. pdhStatus = PdhiClosePerfmonLog(pLog, dwFlags);
  923. break;
  924. case PDH_LOG_TYPE_BINARY:
  925. pdhStatus = PdhiCloseWmiLog(pLog, dwFlags);
  926. break;
  927. case PDH_LOG_TYPE_SQL:
  928. pdhStatus = PdhiCloseSQLLog(pLog, dwFlags);
  929. break;
  930. default:
  931. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  932. break;
  933. }
  934. if (bForceDelete || pdhStatus == ERROR_SUCCESS) {
  935. if (pLog->lpMappedFileBase != NULL) {
  936. UnmapReadonlyMappedFile(pLog->lpMappedFileBase, & bNeedToCloseHandles);
  937. }
  938. else {
  939. // if this wasn't a mapped file, then delete
  940. // the "current record" buffer
  941. if (pLog->pLastRecordRead != NULL) {
  942. G_FREE(pLog->pLastRecordRead);
  943. pLog->pLastRecordRead = NULL;
  944. }
  945. }
  946. if (bNeedToCloseHandles) {
  947. if (pLog->hMappedLogFile != NULL) {
  948. bStatus = CloseHandle(pLog->hMappedLogFile);
  949. pLog->hMappedLogFile = NULL;
  950. }
  951. if (pLog->hLogFileHandle != INVALID_HANDLE_VALUE) {
  952. bStatus = CloseHandle(pLog->hLogFileHandle);
  953. pLog->hLogFileHandle = INVALID_HANDLE_VALUE;
  954. }
  955. }
  956. else {
  957. // the handles have already been closed so just
  958. // clear their values
  959. pLog->lpMappedFileBase = NULL;
  960. pLog->hMappedLogFile = NULL;
  961. pLog->hLogFileHandle = INVALID_HANDLE_VALUE;
  962. }
  963. if (pLog->pPerfmonInfo != NULL) {
  964. G_FREE (pLog->pPerfmonInfo);
  965. pLog->pPerfmonInfo = NULL;
  966. }
  967. pLog->dwLastRecordRead = 0;
  968. if (pLog->hCatFileHandle != INVALID_HANDLE_VALUE) {
  969. bStatus = CloseHandle(pLog->hCatFileHandle);
  970. pLog->hCatFileHandle = INVALID_HANDLE_VALUE;
  971. }
  972. if ((dwFlags & PDH_FLAGS_CLOSE_QUERY) == PDH_FLAGS_CLOSE_QUERY) {
  973. pdhStatus = PdhCloseQuery((HQUERY)pLog->pQuery);
  974. }
  975. pdhStatus = DeleteLogEntry(pLog);
  976. }
  977. return pdhStatus;
  978. }
  979. //
  980. // Local utility functions
  981. //
  982. PDH_FUNCTION
  983. PdhiGetLogCounterInfo(
  984. PDH_HLOG hLog,
  985. PPDHI_COUNTER pCounter
  986. )
  987. // validates the counter is in the log file and initializes the data fields
  988. {
  989. PPDHI_LOG pLog;
  990. PDH_STATUS pdhStatus;
  991. if (IsValidLogHandle(hLog)) {
  992. pLog = (PPDHI_LOG)hLog;
  993. switch (LOWORD(pLog->dwLogFormat)) {
  994. case PDH_LOG_TYPE_CSV:
  995. case PDH_LOG_TYPE_TSV:
  996. pdhStatus = PdhiGetTextLogCounterInfo(pLog, pCounter);
  997. break;
  998. case PDH_LOG_TYPE_BINARY:
  999. case PDH_LOG_TYPE_RETIRED_BIN:
  1000. pdhStatus = PdhiGetBinaryLogCounterInfo(pLog, pCounter);
  1001. break;
  1002. case PDH_LOG_TYPE_PERFMON:
  1003. pdhStatus = PdhiGetPerfmonLogCounterInfo(pLog, pCounter);
  1004. break;
  1005. case PDH_LOG_TYPE_SQL:
  1006. pdhStatus = PdhiGetSQLLogCounterInfo(pLog, pCounter);
  1007. break;
  1008. default:
  1009. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  1010. break;
  1011. }
  1012. }
  1013. else {
  1014. pdhStatus = PDH_INVALID_HANDLE;
  1015. }
  1016. return pdhStatus;
  1017. }
  1018. PDH_FUNCTION
  1019. AddUniqueWideStringToMultiSz(
  1020. LPVOID mszDest,
  1021. LPWSTR szSource,
  1022. DWORD dwSizeLeft,
  1023. LPDWORD pdwSize,
  1024. BOOL bUnicodeDest
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. searches the Multi-SZ list, mszDest for szSource and appends it
  1029. to mszDest if it wasn't found
  1030. Arguments:
  1031. OUT LPVOID mszDest Multi-SZ list to get new string
  1032. IN LPWSTR szSource string to add if it's not already in list
  1033. ReturnValue:
  1034. The new length of the destination string including both
  1035. trailing NULL characters if the string was added, or 0 if the
  1036. string is already in the list.
  1037. --*/
  1038. {
  1039. PDH_STATUS Status = ERROR_SUCCESS;
  1040. LPVOID szDestElem;
  1041. DWORD dwReturnLength = 0;
  1042. LPSTR aszSource = NULL;
  1043. DWORD dwLength;
  1044. // check arguments
  1045. if (mszDest == NULL || szSource == NULL || pdwSize == NULL) {
  1046. Status = PDH_INVALID_ARGUMENT; // invalid buffers
  1047. goto AddString_Bailout;
  1048. }
  1049. else if (* szSource == L'\0') {
  1050. goto AddString_Bailout; // no source string to add
  1051. }
  1052. // if not a unicode list, make an ansi copy of the source string to
  1053. // compare
  1054. // and ultimately copy if it's not already in the list
  1055. if (! bUnicodeDest) {
  1056. aszSource = PdhiWideCharToMultiByte(_getmbcp(), szSource);
  1057. if (aszSource != NULL) {
  1058. dwReturnLength = lstrlenA(aszSource);
  1059. }
  1060. else {
  1061. // unable to allocate memory for the temp string
  1062. dwReturnLength = 0;
  1063. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1064. }
  1065. }
  1066. else {
  1067. // just use the ANSI version of the source file name
  1068. dwReturnLength = 1;
  1069. }
  1070. if (dwReturnLength > 0) {
  1071. // go to end of dest string
  1072. //
  1073. for (szDestElem = mszDest;
  1074. (bUnicodeDest ? (* (LPWSTR) szDestElem != L'\0') : (* (LPSTR) szDestElem != '\0'));) {
  1075. if (bUnicodeDest) {
  1076. // bail out if string already in list
  1077. if (lstrcmpiW((LPCWSTR) szDestElem, szSource) == 0) {
  1078. dwReturnLength = 0;
  1079. goto AddString_Bailout;
  1080. }
  1081. else {
  1082. // goto the next item
  1083. szDestElem = (LPVOID) ((LPWSTR) szDestElem + (lstrlenW((LPCWSTR) szDestElem) + 1));
  1084. }
  1085. }
  1086. else {
  1087. // bail out if string already in list
  1088. if (lstrcmpiA((LPSTR) szDestElem, aszSource) == 0) {
  1089. dwReturnLength = 0;
  1090. goto AddString_Bailout;
  1091. }
  1092. else {
  1093. // goto the next item
  1094. szDestElem = (LPVOID) ((LPSTR) szDestElem + (lstrlenA((LPCSTR) szDestElem) + 1));
  1095. }
  1096. }
  1097. }
  1098. // if here, then add string
  1099. // szDestElem is at end of list
  1100. if (bUnicodeDest) {
  1101. if ((DWORD) (lstrlenW(szSource) + 2) <= dwSizeLeft) {
  1102. StringCchCopyW((LPWSTR) szDestElem, dwSizeLeft, szSource);
  1103. szDestElem = (LPVOID)((LPWSTR)szDestElem + lstrlenW((LPWSTR) szDestElem) + 1);
  1104. * ((LPWSTR) szDestElem) = L'\0';
  1105. dwReturnLength = (DWORD) ((LPWSTR) szDestElem - (LPWSTR) mszDest);
  1106. }
  1107. else {
  1108. dwReturnLength = lstrlenW(szSource) + 2;
  1109. Status = PDH_MORE_DATA;
  1110. }
  1111. }
  1112. else {
  1113. if ((DWORD) (lstrlenA(aszSource) + 2) <= dwSizeLeft) {
  1114. StringCchCopyA((LPSTR)szDestElem, dwSizeLeft, aszSource);
  1115. szDestElem = (LPVOID)((LPSTR)szDestElem + lstrlenA((LPSTR) szDestElem) + 1);
  1116. * ((LPSTR) szDestElem) = '\0'; // add second NULL
  1117. dwReturnLength = (DWORD) ((LPSTR) szDestElem - (LPSTR) mszDest);
  1118. }
  1119. else {
  1120. dwReturnLength = lstrlenA(aszSource) + 2;
  1121. Status = PDH_MORE_DATA;
  1122. }
  1123. }
  1124. }
  1125. AddString_Bailout:
  1126. G_FREE(aszSource);
  1127. if (pdwSize != NULL) * pdwSize = dwReturnLength;
  1128. return Status;
  1129. }
  1130. //
  1131. // Exported Logging Functions
  1132. //
  1133. PDH_FUNCTION
  1134. PdhOpenLogW(
  1135. IN LPCWSTR szLogFileName,
  1136. IN DWORD dwAccessFlags,
  1137. IN LPDWORD lpdwLogType,
  1138. IN PDH_HQUERY hQuery,
  1139. IN DWORD dwMaxSize,
  1140. IN LPCWSTR szUserCaption,
  1141. IN PDH_HLOG * phLog
  1142. )
  1143. {
  1144. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1145. DWORD dwLocalLogType = 0;
  1146. PPDHI_LOG pLog;
  1147. if (szLogFileName == NULL || lpdwLogType == NULL || phLog == NULL) {
  1148. pdhStatus = PDH_INVALID_ARGUMENT;
  1149. }
  1150. else {
  1151. __try {
  1152. dwLocalLogType = *lpdwLogType;
  1153. * lpdwLogType = dwLocalLogType;
  1154. if (* szLogFileName == L'\0' || lstrlenW(szLogFileName) > PDH_MAX_DATASOURCE_PATH) {
  1155. pdhStatus = PDH_INVALID_ARGUMENT;
  1156. }
  1157. if (szUserCaption != NULL) {
  1158. // if not NULL, it must be valid
  1159. if (* szUserCaption == L'\0' || lstrlenW(szUserCaption) > PDH_MAX_COUNTER_PATH) {
  1160. pdhStatus = PDH_INVALID_ARGUMENT;
  1161. }
  1162. }
  1163. }
  1164. __except (EXCEPTION_EXECUTE_HANDLER) {
  1165. // something failed so give up here
  1166. pdhStatus = PDH_INVALID_ARGUMENT;
  1167. }
  1168. }
  1169. if (pdhStatus == ERROR_SUCCESS) {
  1170. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
  1171. if (pdhStatus == ERROR_SUCCESS) {
  1172. // create a log entry
  1173. // if successful, this also acquires the lock for this structure
  1174. pdhStatus = CreateNewLogEntry((LPCWSTR) szLogFileName, hQuery, dwMaxSize, & pLog);
  1175. // Here we must check for SQL: in the file name, and branch off to do SQL
  1176. // Processing /end SJM/
  1177. // open the file
  1178. if (pdhStatus == ERROR_SUCCESS) {
  1179. // find out if SQL file type
  1180. if (lstrlenW(szLogFileName) > 4 && (szLogFileName[0] == L'S' || szLogFileName[0] == L's') &&
  1181. (szLogFileName[1] == L'Q' || szLogFileName[1] == L'q') &&
  1182. (szLogFileName[2] == L'L' || szLogFileName[2] == L'l') &&
  1183. szLogFileName[3] == L':') {
  1184. dwLocalLogType = PDH_LOG_TYPE_SQL;
  1185. pLog->llMaxSize = (LONGLONG) ((ULONGLONG) dwMaxSize);
  1186. pdhStatus = OpenSQLLog(pLog, dwAccessFlags, & dwLocalLogType);
  1187. if ((dwAccessFlags & PDH_LOG_WRITE_ACCESS) == PDH_LOG_WRITE_ACCESS) {
  1188. if (pLog->pQuery != NULL) {
  1189. pLog->pQuery->hOutLog = (HLOG) pLog;
  1190. }
  1191. if (pdhStatus == ERROR_SUCCESS) {
  1192. pdhStatus = WriteLogHeader(pLog, (LPCWSTR)szUserCaption);
  1193. }
  1194. }
  1195. // dispatch based on read/write attribute
  1196. }
  1197. else if ((dwAccessFlags & PDH_LOG_READ_ACCESS) == PDH_LOG_READ_ACCESS) {
  1198. pdhStatus = OpenInputLogFile(pLog, dwAccessFlags, & dwLocalLogType);
  1199. }
  1200. else if ((dwAccessFlags & PDH_LOG_WRITE_ACCESS) == PDH_LOG_WRITE_ACCESS) {
  1201. pdhStatus = OpenOutputLogFile(pLog, dwAccessFlags, & dwLocalLogType);
  1202. if (pdhStatus == ERROR_SUCCESS) {
  1203. pLog->pQuery->hOutLog = (HLOG) pLog;
  1204. pdhStatus = WriteLogHeader(pLog, (LPCWSTR) szUserCaption);
  1205. }
  1206. }
  1207. else if ((dwAccessFlags & PDH_LOG_UPDATE_ACCESS) == PDH_LOG_UPDATE_ACCESS) {
  1208. pdhStatus = OpenUpdateLogFile(pLog, dwAccessFlags, & dwLocalLogType);
  1209. }
  1210. else {
  1211. pdhStatus = PDH_INVALID_ARGUMENT;
  1212. }
  1213. if (pdhStatus == ERROR_SUCCESS) {
  1214. __try {
  1215. // return handle to caller
  1216. * phLog = (HLOG) pLog;
  1217. * lpdwLogType = dwLocalLogType;
  1218. }
  1219. __except (EXCEPTION_EXECUTE_HANDLER) {
  1220. // something failed so give up here
  1221. pdhStatus = PDH_INVALID_ARGUMENT;
  1222. }
  1223. }
  1224. // release the lock for the next thread
  1225. if (pdhStatus != ERROR_SUCCESS) {
  1226. // unable to complete this operation so toss this entry
  1227. // since it isn't really a valid log entry.
  1228. // NOTE: DeleteLogEntry will release the mutex
  1229. DeleteLogEntry(pLog);
  1230. }
  1231. else {
  1232. RELEASE_MUTEX (pLog->hLogMutex);
  1233. }
  1234. }
  1235. RELEASE_MUTEX(hPdhDataMutex);
  1236. }
  1237. }
  1238. return pdhStatus;
  1239. }
  1240. PDH_FUNCTION
  1241. PdhOpenLogA(
  1242. IN LPCSTR szLogFileName,
  1243. IN DWORD dwAccessFlags,
  1244. IN LPDWORD lpdwLogType,
  1245. IN PDH_HQUERY hQuery,
  1246. IN DWORD dwMaxRecords,
  1247. IN LPCSTR szUserCaption,
  1248. IN PDH_HLOG * phLog
  1249. )
  1250. {
  1251. LPWSTR wszLogName = NULL;
  1252. LPWSTR wszUserCaption = NULL;
  1253. DWORD dwLocalLogType;
  1254. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1255. if (szLogFileName == NULL || lpdwLogType == NULL || phLog == NULL) {
  1256. pdhStatus = PDH_INVALID_ARGUMENT;
  1257. }
  1258. else {
  1259. __try {
  1260. if (* szLogFileName == L'\0' || lstrlenA(szLogFileName) > PDH_MAX_DATASOURCE_PATH) {
  1261. pdhStatus = PDH_INVALID_ARGUMENT;
  1262. }
  1263. else {
  1264. dwLocalLogType = *lpdwLogType; // test read
  1265. wszLogName = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szLogFileName);
  1266. if (wszLogName == NULL) {
  1267. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1268. }
  1269. else if (szUserCaption != NULL) {
  1270. // if not NULL, it must be valid
  1271. if (* szUserCaption == L'\0' || lstrlenA(szUserCaption) > PDH_MAX_COUNTER_PATH) {
  1272. pdhStatus = PDH_INVALID_ARGUMENT;
  1273. }
  1274. else {
  1275. wszUserCaption = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szUserCaption);
  1276. if (wszUserCaption == NULL) {
  1277. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1278. }
  1279. }
  1280. }
  1281. }
  1282. }
  1283. __except (EXCEPTION_EXECUTE_HANDLER) {
  1284. // assume a bad parameter caused the exception
  1285. pdhStatus = PDH_INVALID_ARGUMENT;
  1286. }
  1287. }
  1288. if (pdhStatus == ERROR_SUCCESS) {
  1289. pdhStatus = PdhOpenLogW(
  1290. wszLogName, dwAccessFlags, & dwLocalLogType, hQuery, dwMaxRecords, wszUserCaption, phLog);
  1291. }
  1292. if (pdhStatus == ERROR_SUCCESS) {
  1293. __try {
  1294. // return handle to caller
  1295. * lpdwLogType = dwLocalLogType;
  1296. }
  1297. __except (EXCEPTION_EXECUTE_HANDLER) {
  1298. // something failed so give up here
  1299. pdhStatus = PDH_INVALID_ARGUMENT;
  1300. }
  1301. }
  1302. G_FREE(wszLogName);
  1303. G_FREE(wszUserCaption);
  1304. return pdhStatus;
  1305. }
  1306. PDH_FUNCTION
  1307. PdhUpdateLogW(
  1308. IN PDH_HLOG hLog,
  1309. IN LPCWSTR szUserString
  1310. )
  1311. {
  1312. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1313. SYSTEMTIME st;
  1314. FILETIME ft;
  1315. PPDHI_LOG pLog;
  1316. if (szUserString != NULL) {
  1317. __try {
  1318. if (* szUserString == L'\0' || lstrlenW(szUserString) > PDH_MAX_COUNTER_PATH) {
  1319. pdhStatus = PDH_INVALID_ARGUMENT;
  1320. }
  1321. }
  1322. __except (EXCEPTION_EXECUTE_HANDLER) {
  1323. pdhStatus = PDH_INVALID_ARGUMENT;
  1324. }
  1325. }
  1326. if (pdhStatus == ERROR_SUCCESS) {
  1327. if (IsValidLogHandle(hLog)) {
  1328. pLog = (PPDHI_LOG) hLog;
  1329. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  1330. if (pdhStatus == ERROR_SUCCESS) {
  1331. // make sure it's still valid as it could have
  1332. // been deleted while we were waiting
  1333. if (IsValidLogHandle(hLog)) {
  1334. if (pLog->pQuery == NULL) {
  1335. pdhStatus = PDH_INVALID_ARGUMENT;
  1336. }
  1337. else {
  1338. // get the timestamp and update the log's query,
  1339. // then write the data to the log file in the
  1340. // appropriate format
  1341. // update data samples
  1342. pdhStatus = PdhiCollectQueryData((HQUERY) pLog->pQuery, (LONGLONG *) & ft);
  1343. if (pdhStatus == ERROR_SUCCESS) {
  1344. FileTimeToSystemTime(& ft, & st);
  1345. }
  1346. else {
  1347. GetLocalTime(& st);
  1348. }
  1349. // test for end of log file in case the caller is
  1350. // reading from a log file. If this value is returned,
  1351. // then don't update the output log file any more.
  1352. if (pdhStatus != PDH_NO_MORE_DATA) {
  1353. switch (LOWORD(pLog->dwLogFormat)) {
  1354. case PDH_LOG_TYPE_CSV:
  1355. case PDH_LOG_TYPE_TSV:
  1356. pdhStatus =PdhiWriteTextLogRecord(pLog, & st, (LPCWSTR) szUserString);
  1357. break;
  1358. case PDH_LOG_TYPE_RETIRED_BIN:
  1359. case PDH_LOG_TYPE_PERFMON:
  1360. pdhStatus = PDH_NOT_IMPLEMENTED;
  1361. break;
  1362. case PDH_LOG_TYPE_BINARY:
  1363. pdhStatus = PdhiWriteWmiLogRecord(pLog, & st, (LPCWSTR) szUserString);
  1364. break;
  1365. // add case for SQL
  1366. case PDH_LOG_TYPE_SQL:
  1367. pdhStatus =PdhiWriteSQLLogRecord(pLog, & st, (LPCWSTR) szUserString);
  1368. break;
  1369. default:
  1370. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  1371. break;
  1372. }
  1373. }
  1374. else {
  1375. // return the NO_MORE_DATA error to the caller
  1376. // so they know not to call this function any more
  1377. }
  1378. }
  1379. }
  1380. else {
  1381. pdhStatus = PDH_INVALID_HANDLE;
  1382. }
  1383. RELEASE_MUTEX(pLog->hLogMutex);
  1384. } // else couldn't lock the log
  1385. }
  1386. else {
  1387. pdhStatus = PDH_INVALID_HANDLE;
  1388. }
  1389. }
  1390. return pdhStatus;
  1391. }
  1392. PDH_FUNCTION
  1393. PdhUpdateLogA(
  1394. IN PDH_HLOG hLog,
  1395. IN LPCSTR szUserString
  1396. )
  1397. {
  1398. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1399. LPWSTR wszLocalUserString = NULL;
  1400. DWORD dwUserStringLen;
  1401. __try {
  1402. if (szUserString != NULL) {
  1403. if (* szUserString == L'\0' || lstrlenA(szUserString) > PDH_MAX_COUNTER_PATH) {
  1404. pdhStatus = PDH_INVALID_ARGUMENT;
  1405. }
  1406. else {
  1407. wszLocalUserString = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szUserString);
  1408. if (wszLocalUserString == NULL) {
  1409. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1410. }
  1411. }
  1412. }
  1413. }
  1414. __except (EXCEPTION_EXECUTE_HANDLER) {
  1415. pdhStatus = PDH_INVALID_ARGUMENT;
  1416. }
  1417. if (pdhStatus == ERROR_SUCCESS) {
  1418. pdhStatus = PdhUpdateLogW(hLog, wszLocalUserString);
  1419. }
  1420. G_FREE(wszLocalUserString);
  1421. return pdhStatus;
  1422. }
  1423. PDH_FUNCTION
  1424. PdhUpdateLogFileCatalog(
  1425. IN PDH_HLOG hLog
  1426. )
  1427. {
  1428. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1429. PPDHI_LOG pLog;
  1430. if (IsValidLogHandle(hLog)) {
  1431. pLog = (PPDHI_LOG) hLog;
  1432. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  1433. // make sure it's still valid as it could have
  1434. // been deleted while we were waiting
  1435. if (pdhStatus == ERROR_SUCCESS) {
  1436. if (IsValidLogHandle(hLog)) {
  1437. pLog = (PPDHI_LOG) hLog;
  1438. switch (LOWORD(pLog->dwLogFormat)) {
  1439. case PDH_LOG_TYPE_CSV:
  1440. case PDH_LOG_TYPE_TSV:
  1441. case PDH_LOG_TYPE_BINARY:
  1442. case PDH_LOG_TYPE_SQL:
  1443. case PDH_LOG_TYPE_RETIRED_BIN:
  1444. case PDH_LOG_TYPE_PERFMON:
  1445. pdhStatus = PDH_NOT_IMPLEMENTED;
  1446. break;
  1447. default:
  1448. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  1449. break;
  1450. }
  1451. }
  1452. else {
  1453. pdhStatus = PDH_INVALID_HANDLE;
  1454. }
  1455. RELEASE_MUTEX (pLog->hLogMutex);
  1456. }
  1457. }
  1458. else {
  1459. pdhStatus = PDH_INVALID_HANDLE;
  1460. }
  1461. return pdhStatus;
  1462. }
  1463. PDH_FUNCTION
  1464. PdhCloseLog(
  1465. IN PDH_HLOG hLog,
  1466. IN DWORD dwFlags
  1467. )
  1468. {
  1469. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1470. PPDHI_LOG pLog;
  1471. if (hLog != H_REALTIME_DATASOURCE && hLog != H_WBEM_DATASOURCE) {
  1472. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
  1473. if (pdhStatus == ERROR_SUCCESS) {
  1474. if (IsValidLogHandle(hLog)) {
  1475. pLog = (PPDHI_LOG) hLog;
  1476. // make sure it's still valid as it could have
  1477. // been deleted while we were waiting
  1478. if (IsValidLogHandle(hLog)) {
  1479. // this will release and delete the mutex
  1480. pdhStatus = CloseAndDeleteLogEntry(pLog, dwFlags, FALSE);
  1481. }
  1482. else {
  1483. pdhStatus = PDH_INVALID_HANDLE;
  1484. }
  1485. }
  1486. else {
  1487. pdhStatus = PDH_INVALID_HANDLE;
  1488. }
  1489. RELEASE_MUTEX(hPdhDataMutex);
  1490. }
  1491. }
  1492. return pdhStatus;
  1493. }
  1494. BOOL
  1495. PdhiBrowseDataSource(
  1496. HWND hWndParent,
  1497. LPVOID szFileName,
  1498. LPDWORD pcchFileNameSize,
  1499. BOOL bUnicodeString
  1500. )
  1501. {
  1502. OPENFILENAMEW ofn;
  1503. LPWSTR szTempString = NULL;
  1504. LPWSTR szDirString = NULL;
  1505. LPWSTR szTempFileName = NULL;
  1506. BOOL bReturn;
  1507. DWORD dwSize;
  1508. LPWSTR szMsg = NULL;
  1509. LPWSTR szLogFilterString = NULL;
  1510. LPWSTR szLogFilter;
  1511. if (szFileName == NULL) {
  1512. SetLastError(PDH_INVALID_ARGUMENT);
  1513. bReturn = FALSE;
  1514. }
  1515. else {
  1516. // clear last error
  1517. SetLastError (ERROR_SUCCESS);
  1518. dwSize = * pcchFileNameSize * 2;
  1519. if (dwSize < (DWORD) (lstrlenW(szFileName) + 1)) dwSize = (DWORD) (lstrlenW(szFileName) + 1);
  1520. if (dwSize < SMALL_BUFFER_SIZE) dwSize = SMALL_BUFFER_SIZE;
  1521. szLogFilterString = G_ALLOC(3 * dwSize * sizeof(WCHAR));
  1522. if (szLogFilterString == NULL) {
  1523. SetLastError(PDH_MEMORY_ALLOCATION_FAILURE);
  1524. bReturn = FALSE;
  1525. }
  1526. else {
  1527. szTempString = szLogFilterString + dwSize;
  1528. szDirString = szTempString + dwSize;
  1529. // continue
  1530. // get the current filename
  1531. if (bUnicodeString) {
  1532. StringCchCopyW(szTempString, dwSize, (LPWSTR) szFileName);
  1533. }
  1534. else {
  1535. MultiByteToWideChar(_getmbcp(), 0, (LPSTR) szFileName, -1, (LPWSTR) szTempString, dwSize);
  1536. }
  1537. // set the path up for the initial dir display
  1538. if (szTempString[0] != L'\0') {
  1539. if (SearchPathW(NULL, szTempString, NULL, dwSize, szDirString, & szTempFileName) > 0) {
  1540. // then update the buffers to show file and dir path
  1541. if (szTempFileName > szDirString) {
  1542. // then we have a path with a file name so
  1543. // truncate the path at the last backslash and
  1544. // then copy the filename to the original buffer
  1545. * (szTempFileName - 1) = L'\0'; // should be L'\\' originally.
  1546. StringCchCopyW(szTempString, dwSize, szTempFileName);
  1547. }
  1548. }
  1549. }
  1550. // get the log filter string
  1551. if (MakeLogFilterInfoString(szLogFilterString, dwSize) == ERROR_SUCCESS) {
  1552. szLogFilter = szLogFilterString;
  1553. }
  1554. else {
  1555. // then use default filter string
  1556. szLogFilter = NULL;
  1557. }
  1558. // display file open dialog to browse for log files.
  1559. szMsg = GetStringResource(IDS_DSRC_SELECT);
  1560. ofn.lStructSize = sizeof(ofn);
  1561. ofn.hwndOwner = hWndParent;
  1562. ofn.hInstance = ThisDLLHandle;
  1563. ofn.lpstrFilter = szLogFilter;
  1564. ofn.lpstrCustomFilter = NULL;
  1565. ofn.nMaxCustFilter = 0;
  1566. ofn.nFilterIndex = 1;
  1567. ofn.lpstrFile = szTempString;
  1568. ofn.nMaxFile = SMALL_BUFFER_SIZE - 1;
  1569. ofn.lpstrFileTitle = NULL;
  1570. ofn.nMaxFileTitle = 0;
  1571. ofn.lpstrInitialDir = szDirString;
  1572. ofn.lpstrTitle = szMsg;
  1573. ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
  1574. ofn.nFileOffset = 0;
  1575. ofn.nFileExtension = 0;
  1576. ofn.lpstrDefExt = cszBlg;
  1577. ofn.lCustData = 0;
  1578. ofn.lpfnHook = NULL;
  1579. ofn.lpTemplateName = NULL;
  1580. if (GetOpenFileNameW(& ofn)) {
  1581. // then update the return string
  1582. if (bUnicodeString) {
  1583. StringCchCopyW((LPWSTR) szFileName, *pcchFileNameSize, szTempString);
  1584. * pcchFileNameSize = lstrlenW(szTempString) + 1;
  1585. }
  1586. else {
  1587. PdhiConvertUnicodeToAnsi(_getmbcp(), szTempString, (LPSTR) szFileName, pcchFileNameSize);
  1588. }
  1589. bReturn = TRUE;
  1590. }
  1591. else {
  1592. bReturn = FALSE;
  1593. }
  1594. G_FREE(szMsg);
  1595. G_FREE(szLogFilterString);
  1596. }
  1597. }
  1598. return bReturn;
  1599. }
  1600. PDH_FUNCTION
  1601. PdhGetDataSourceTimeRangeH(
  1602. IN PDH_HLOG hDataSource,
  1603. IN LPDWORD pdwNumEntries,
  1604. IN PPDH_TIME_INFO pInfo,
  1605. IN LPDWORD pdwBufferSize
  1606. )
  1607. {
  1608. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1609. DWORD dwLocalBufferSize = 0;
  1610. DWORD dwLocalNumEntries = 0;
  1611. PDH_TIME_INFO LocalInfo;
  1612. PPDHI_LOG pLog;
  1613. if (hDataSource == H_REALTIME_DATASOURCE || hDataSource == H_WBEM_DATASOURCE) {
  1614. pdhStatus = PDH_DATA_SOURCE_IS_REAL_TIME;
  1615. }
  1616. else if (pdwNumEntries == NULL || pInfo == NULL || pdwBufferSize == NULL) {
  1617. pdhStatus = PDH_INVALID_ARGUMENT;
  1618. }
  1619. else {
  1620. // test caller's buffers before trying to use them
  1621. __try {
  1622. dwLocalNumEntries = * pdwNumEntries;
  1623. dwLocalBufferSize = * pdwBufferSize;
  1624. LocalInfo.StartTime = pInfo->StartTime;
  1625. }
  1626. __except (EXCEPTION_EXECUTE_HANDLER) {
  1627. pdhStatus = PDH_INVALID_ARGUMENT;
  1628. }
  1629. }
  1630. if (pdhStatus == ERROR_SUCCESS) {
  1631. if (IsValidLogHandle(hDataSource)) {
  1632. pLog = (PPDHI_LOG) hDataSource;
  1633. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  1634. if (pdhStatus == ERROR_SUCCESS) {
  1635. if (IsValidLogHandle(hDataSource)) {
  1636. // enum machines based on log type
  1637. //
  1638. ZeroMemory(& LocalInfo, sizeof(PDH_TIME_INFO));
  1639. switch (LOWORD(pLog->dwLogFormat)) {
  1640. case PDH_LOG_TYPE_CSV:
  1641. case PDH_LOG_TYPE_TSV:
  1642. pdhStatus = PdhiGetTimeRangeFromTextLog(
  1643. pLog, & dwLocalNumEntries, & LocalInfo, & dwLocalBufferSize);
  1644. break;
  1645. case PDH_LOG_TYPE_BINARY:
  1646. pdhStatus = PdhiGetTimeRangeFromWmiLog(
  1647. pLog, & dwLocalNumEntries, & LocalInfo, & dwLocalBufferSize);
  1648. break;
  1649. case PDH_LOG_TYPE_RETIRED_BIN:
  1650. pdhStatus = PdhiGetTimeRangeFromBinaryLog(
  1651. pLog, & dwLocalNumEntries, & LocalInfo, & dwLocalBufferSize);
  1652. break;
  1653. case PDH_LOG_TYPE_SQL:
  1654. pdhStatus = PdhiGetTimeRangeFromSQLLog(
  1655. pLog, & dwLocalNumEntries, & LocalInfo, & dwLocalBufferSize);
  1656. break;
  1657. case PDH_LOG_TYPE_PERFMON:
  1658. pdhStatus = PdhiGetTimeRangeFromPerfmonLog(
  1659. pLog, & dwLocalNumEntries, & LocalInfo, & dwLocalBufferSize);
  1660. break;
  1661. default:
  1662. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  1663. break;
  1664. }
  1665. __try {
  1666. * pdwBufferSize = dwLocalBufferSize;
  1667. * pdwNumEntries = dwLocalNumEntries;
  1668. pInfo->StartTime = LocalInfo.StartTime;
  1669. pInfo->EndTime = LocalInfo.EndTime;
  1670. pInfo->SampleCount = LocalInfo.SampleCount;
  1671. }
  1672. __except (EXCEPTION_EXECUTE_HANDLER) {
  1673. pdhStatus = PDH_INVALID_ARGUMENT;
  1674. }
  1675. }
  1676. else {
  1677. pdhStatus = PDH_INVALID_HANDLE;
  1678. }
  1679. RELEASE_MUTEX (pLog->hLogMutex);
  1680. }
  1681. }
  1682. else {
  1683. pdhStatus = PDH_INVALID_HANDLE;
  1684. }
  1685. }
  1686. return pdhStatus;
  1687. }
  1688. PDH_FUNCTION
  1689. PdhGetDataSourceTimeRangeW(
  1690. IN LPCWSTR szDataSource,
  1691. IN LPDWORD pdwNumEntries,
  1692. IN PPDH_TIME_INFO pInfo,
  1693. IN LPDWORD pdwBufferSize
  1694. )
  1695. {
  1696. PDH_STATUS PdhStatus = PDH_DATA_SOURCE_IS_REAL_TIME;
  1697. PDH_HLOG hDataSource = NULL;
  1698. DWORD dwLogType = -1;
  1699. if (szDataSource != NULL) {
  1700. // open log file
  1701. //
  1702. PdhStatus = PdhOpenLogW(szDataSource,
  1703. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  1704. & dwLogType,
  1705. NULL,
  1706. 0,
  1707. NULL,
  1708. & hDataSource);
  1709. if (PdhStatus == ERROR_SUCCESS) {
  1710. PdhStatus = PdhGetDataSourceTimeRangeH(hDataSource, pdwNumEntries, pInfo, pdwBufferSize);
  1711. PdhCloseLog(hDataSource, 0);
  1712. }
  1713. }
  1714. return PdhStatus;
  1715. }
  1716. PDH_FUNCTION
  1717. PdhGetDataSourceTimeRangeA(
  1718. IN LPCSTR szDataSource,
  1719. IN LPDWORD pdwNumEntries,
  1720. IN PPDH_TIME_INFO pInfo,
  1721. IN LPDWORD pdwBufferSize
  1722. )
  1723. {
  1724. LPWSTR wszDataSource = NULL;
  1725. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1726. DWORD dwLocalBufferSize = 0;
  1727. DWORD dwLocalNumEntries = 0;
  1728. if (szDataSource == NULL) {
  1729. // null data source == the current activity so return
  1730. pdhStatus = PDH_DATA_SOURCE_IS_REAL_TIME;
  1731. }
  1732. else if (pdwNumEntries == NULL || pInfo == NULL || pdwBufferSize == NULL) {
  1733. pdhStatus = PDH_INVALID_ARGUMENT;
  1734. }
  1735. else {
  1736. __try {
  1737. dwLocalBufferSize = * pdwBufferSize;
  1738. dwLocalNumEntries = * pdwNumEntries;
  1739. if (* szDataSource == '\0' || lstrlenA(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
  1740. pdhStatus = PDH_INVALID_ARGUMENT;
  1741. }
  1742. else {
  1743. wszDataSource = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szDataSource);
  1744. if (wszDataSource == NULL) {
  1745. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1746. }
  1747. }
  1748. }
  1749. __except (EXCEPTION_EXECUTE_HANDLER) {
  1750. // assume a bad parameter caused the exception
  1751. pdhStatus = PDH_INVALID_ARGUMENT;
  1752. }
  1753. }
  1754. if (pdhStatus == ERROR_SUCCESS) {
  1755. pdhStatus = PdhGetDataSourceTimeRangeW(wszDataSource, & dwLocalNumEntries, pInfo, & dwLocalBufferSize);
  1756. }
  1757. if (pdhStatus == ERROR_SUCCESS) {
  1758. // copy returned values regardless of status
  1759. __try {
  1760. * pdwBufferSize = dwLocalBufferSize;
  1761. * pdwNumEntries = dwLocalNumEntries;
  1762. }
  1763. __except (EXCEPTION_EXECUTE_HANDLER) {
  1764. pdhStatus = PDH_INVALID_ARGUMENT;
  1765. }
  1766. }
  1767. G_FREE(wszDataSource);
  1768. return pdhStatus;
  1769. }
  1770. PDH_FUNCTION
  1771. PdhGetLogFileSize(
  1772. IN PDH_HLOG hLog,
  1773. IN LONGLONG * llSize
  1774. )
  1775. {
  1776. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1777. PPDHI_LOG pLog;
  1778. UINT nErrorMode;
  1779. DWORD dwFileSizeLow = 0;
  1780. DWORD dwFileSizeHigh = 0;
  1781. LONGLONG llFileLength;
  1782. DWORD dwError;
  1783. if (llSize == NULL) {
  1784. pdhStatus = PDH_INVALID_ARGUMENT;
  1785. }
  1786. else if (IsValidLogHandle (hLog)) {
  1787. pLog = (PPDHI_LOG) hLog;
  1788. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  1789. if (pdhStatus == ERROR_SUCCESS) {
  1790. if (IsValidLogHandle(hLog)) {
  1791. if (LOWORD(pLog->dwLogFormat) == PDH_LOG_TYPE_SQL) {
  1792. __try {
  1793. * llSize = pLog->dwNextRecordIdToWrite - 1;
  1794. }
  1795. __except (EXCEPTION_EXECUTE_HANDLER) {
  1796. pdhStatus = PDH_INVALID_ARGUMENT;
  1797. }
  1798. }
  1799. else if (LOWORD(pLog->dwLogFormat) == PDH_LOG_TYPE_BINARY) {
  1800. pdhStatus = PdhiGetWmiLogFileSize(pLog, llSize);
  1801. }
  1802. else {
  1803. // disable windows error message popup
  1804. nErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  1805. if (pLog->hLogFileHandle != INVALID_HANDLE_VALUE) {
  1806. dwFileSizeLow = GetFileSize(pLog->hLogFileHandle, &dwFileSizeHigh);
  1807. // test for error
  1808. if ((dwFileSizeLow == 0xFFFFFFFF) && ((dwError = GetLastError()) != NO_ERROR)) {
  1809. // then we couldn't get the file size
  1810. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  1811. }
  1812. else {
  1813. if (dwFileSizeHigh > 0) {
  1814. llFileLength = ((LONGLONG) dwFileSizeHigh) << (sizeof(DWORD) * 8);
  1815. }
  1816. else {
  1817. llFileLength = 0;
  1818. }
  1819. llFileLength += dwFileSizeLow;
  1820. // write to the caller' buffer
  1821. __try {
  1822. * llSize = llFileLength;
  1823. }
  1824. __except (EXCEPTION_EXECUTE_HANDLER) {
  1825. pdhStatus = PDH_INVALID_ARGUMENT;
  1826. }
  1827. }
  1828. }
  1829. else {
  1830. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  1831. }
  1832. SetErrorMode(nErrorMode); // restore old error mode
  1833. }
  1834. }
  1835. else {
  1836. pdhStatus = PDH_INVALID_HANDLE;
  1837. }
  1838. RELEASE_MUTEX (pLog->hLogMutex);
  1839. }
  1840. }
  1841. else {
  1842. pdhStatus = PDH_INVALID_HANDLE;
  1843. }
  1844. return pdhStatus;
  1845. }
  1846. PDH_FUNCTION
  1847. PdhReadRawLogRecord(
  1848. IN PDH_HLOG hLog,
  1849. IN FILETIME ftRecord,
  1850. IN PPDH_RAW_LOG_RECORD pBuffer,
  1851. IN LPDWORD pdwBufferLength
  1852. )
  1853. {
  1854. PPDHI_LOG pLog;
  1855. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1856. DWORD dwLocalBufferLength = 0;
  1857. if (pdwBufferLength == NULL) {
  1858. pdhStatus = PDH_INVALID_ARGUMENT;
  1859. }
  1860. else {
  1861. __try {
  1862. CHAR TestChar;
  1863. // test read & write access to the user's buffer.
  1864. dwLocalBufferLength = * pdwBufferLength;
  1865. if (dwLocalBufferLength > 0) {
  1866. // test beginnging and end of the buffer passed in
  1867. TestChar = ((CHAR *) pBuffer)[0];
  1868. ((CHAR *) pBuffer)[0] = '\0';
  1869. ((CHAR *) pBuffer)[0] = TestChar;
  1870. TestChar = ((CHAR *) pBuffer)[dwLocalBufferLength - 1];
  1871. ((CHAR *) pBuffer)[dwLocalBufferLength - 1] = '\0';
  1872. ((CHAR *) pBuffer)[dwLocalBufferLength - 1] = TestChar;
  1873. }
  1874. }
  1875. __except (EXCEPTION_EXECUTE_HANDLER) {
  1876. pdhStatus = PDH_INVALID_ARGUMENT;
  1877. }
  1878. }
  1879. if (pdhStatus == ERROR_SUCCESS) {
  1880. if (! IsValidLogHandle(hLog)) {
  1881. pdhStatus = PDH_INVALID_HANDLE;
  1882. }
  1883. else {
  1884. pLog = (PPDHI_LOG)hLog;
  1885. // see if the log is open, first?
  1886. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  1887. if (pdhStatus == ERROR_SUCCESS) {
  1888. // make sure it's still valid
  1889. if (IsValidLogHandle(hLog)) {
  1890. switch (LOWORD(pLog->dwLogFormat)) {
  1891. case PDH_LOG_TYPE_CSV:
  1892. case PDH_LOG_TYPE_TSV:
  1893. pdhStatus = PdhiReadRawTextLogRecord(hLog, & ftRecord, pBuffer, & dwLocalBufferLength);
  1894. break;
  1895. case PDH_LOG_TYPE_BINARY:
  1896. case PDH_LOG_TYPE_RETIRED_BIN:
  1897. pdhStatus = PdhiReadRawBinaryLogRecord(hLog, & ftRecord, pBuffer, & dwLocalBufferLength);
  1898. break;
  1899. case PDH_LOG_TYPE_SQL:
  1900. //note this is only supported with a null buffer
  1901. // as we don't actually read the record, and
  1902. // positioning the file at the record doesn't
  1903. // mean anything for SQL
  1904. pdhStatus = PdhiReadRawSQLLogRecord(hLog, & ftRecord, pBuffer, & dwLocalBufferLength);
  1905. break;
  1906. case PDH_LOG_TYPE_PERFMON:
  1907. pdhStatus = PdhiReadRawPerfmonLogRecord(hLog, & ftRecord, pBuffer, & dwLocalBufferLength);
  1908. break;
  1909. default:
  1910. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  1911. break;
  1912. }
  1913. }
  1914. __try {
  1915. * pdwBufferLength = dwLocalBufferLength;
  1916. }
  1917. __except (EXCEPTION_EXECUTE_HANDLER) {
  1918. pdhStatus = PDH_INVALID_ARGUMENT;
  1919. }
  1920. }
  1921. else {
  1922. pdhStatus = PDH_INVALID_HANDLE;
  1923. }
  1924. RELEASE_MUTEX (pLog->hLogMutex);
  1925. }
  1926. }
  1927. return pdhStatus;
  1928. }
  1929. PDH_FUNCTION
  1930. PdhiEnumLoggedMachines(
  1931. PDH_HLOG hDataSource,
  1932. LPVOID mszMachineList,
  1933. LPDWORD pcchBufferSize,
  1934. BOOL bUnicode
  1935. )
  1936. {
  1937. PDH_STATUS pdhStatus = PDH_INVALID_HANDLE;
  1938. PPDHI_LOG pDataSource;
  1939. DWORD dwLogType;
  1940. // enum machines based on log type
  1941. //
  1942. if (IsValidLogHandle(hDataSource)) {
  1943. pDataSource = (PPDHI_LOG) hDataSource;
  1944. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pDataSource->hLogMutex);
  1945. if (pdhStatus == ERROR_SUCCESS) {
  1946. if (IsValidLogHandle(hDataSource)) {
  1947. dwLogType = pDataSource->dwLogFormat;
  1948. switch (LOWORD(dwLogType)) {
  1949. case PDH_LOG_TYPE_CSV:
  1950. case PDH_LOG_TYPE_TSV:
  1951. pdhStatus = PdhiEnumMachinesFromTextLog(
  1952. (PPDHI_LOG) hDataSource, mszMachineList, pcchBufferSize, bUnicode);
  1953. break;
  1954. case PDH_LOG_TYPE_BINARY:
  1955. pdhStatus = PdhiEnumMachinesFromWmiLog(
  1956. (PPDHI_LOG) hDataSource, mszMachineList, pcchBufferSize, bUnicode);
  1957. break;
  1958. case PDH_LOG_TYPE_RETIRED_BIN:
  1959. pdhStatus = PdhiEnumMachinesFromBinaryLog(
  1960. (PPDHI_LOG) hDataSource, mszMachineList, pcchBufferSize, bUnicode);
  1961. break;
  1962. case PDH_LOG_TYPE_SQL:
  1963. pdhStatus = PdhiEnumMachinesFromSQLLog(
  1964. (PPDHI_LOG) hDataSource, mszMachineList, pcchBufferSize, bUnicode);
  1965. break;
  1966. case PDH_LOG_TYPE_PERFMON:
  1967. pdhStatus = PdhiEnumMachinesFromPerfmonLog(
  1968. (PPDHI_LOG) hDataSource, mszMachineList, pcchBufferSize, bUnicode);
  1969. break;
  1970. default:
  1971. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  1972. break;
  1973. }
  1974. }
  1975. else {
  1976. pdhStatus = PDH_INVALID_HANDLE;
  1977. }
  1978. RELEASE_MUTEX (pDataSource->hLogMutex);
  1979. }
  1980. }
  1981. return pdhStatus;
  1982. }
  1983. PDH_FUNCTION
  1984. PdhiEnumLoggedObjects(
  1985. PDH_HLOG hDataSource,
  1986. LPCWSTR szMachineName,
  1987. LPVOID mszObjectList,
  1988. LPDWORD pcchBufferSize,
  1989. DWORD dwDetailLevel,
  1990. BOOL bRefresh,
  1991. BOOL bUnicode
  1992. )
  1993. {
  1994. PDH_STATUS pdhStatus = PDH_INVALID_HANDLE;
  1995. PPDHI_LOG pDataSource;
  1996. DWORD dwLogType;
  1997. UNREFERENCED_PARAMETER(bRefresh);
  1998. if (IsValidLogHandle(hDataSource)) {
  1999. pDataSource = (PPDHI_LOG) hDataSource;
  2000. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pDataSource->hLogMutex);
  2001. if (pdhStatus == ERROR_SUCCESS) {
  2002. if (IsValidLogHandle(hDataSource)) {
  2003. dwLogType = pDataSource->dwLogFormat;
  2004. // enum objects based on log type & machine name
  2005. switch (LOWORD(dwLogType)) {
  2006. case PDH_LOG_TYPE_CSV:
  2007. case PDH_LOG_TYPE_TSV:
  2008. pdhStatus = PdhiEnumObjectsFromTextLog((PPDHI_LOG) hDataSource,
  2009. szMachineName, mszObjectList, pcchBufferSize, dwDetailLevel, bUnicode);
  2010. break;
  2011. case PDH_LOG_TYPE_BINARY:
  2012. pdhStatus = PdhiEnumObjectsFromWmiLog((PPDHI_LOG) hDataSource,
  2013. szMachineName, mszObjectList, pcchBufferSize, dwDetailLevel, bUnicode);
  2014. break;
  2015. case PDH_LOG_TYPE_RETIRED_BIN:
  2016. pdhStatus = PdhiEnumObjectsFromBinaryLog((PPDHI_LOG) hDataSource,
  2017. szMachineName, mszObjectList, pcchBufferSize, dwDetailLevel, bUnicode);
  2018. break;
  2019. case PDH_LOG_TYPE_SQL:
  2020. pdhStatus = PdhiEnumObjectsFromSQLLog((PPDHI_LOG) hDataSource,
  2021. szMachineName, mszObjectList, pcchBufferSize, dwDetailLevel, bUnicode);
  2022. break;
  2023. case PDH_LOG_TYPE_PERFMON:
  2024. pdhStatus = PdhiEnumObjectsFromPerfmonLog((PPDHI_LOG) hDataSource,
  2025. szMachineName, mszObjectList, pcchBufferSize, dwDetailLevel, bUnicode);
  2026. break;
  2027. default:
  2028. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  2029. break;
  2030. }
  2031. }
  2032. else {
  2033. pdhStatus = PDH_INVALID_HANDLE;
  2034. }
  2035. RELEASE_MUTEX(pDataSource->hLogMutex);
  2036. }
  2037. }
  2038. return pdhStatus;
  2039. }
  2040. PDH_FUNCTION
  2041. PdhiEnumLoggedObjectItems(
  2042. PDH_HLOG hDataSource,
  2043. LPCWSTR szMachineName,
  2044. LPCWSTR szObjectName,
  2045. LPVOID mszCounterList,
  2046. LPDWORD pdwCounterListLength,
  2047. LPVOID mszInstanceList,
  2048. LPDWORD pdwInstanceListLength,
  2049. DWORD dwDetailLevel,
  2050. DWORD dwFlags,
  2051. BOOL bUnicode
  2052. )
  2053. {
  2054. PDH_STATUS pdhStatus = PDH_INVALID_HANDLE;
  2055. PPDHI_LOG pDataSource;
  2056. DWORD dwLogType;
  2057. PDHI_COUNTER_TABLE CounterTable;
  2058. DWORD dwIndex;
  2059. LIST_ENTRY InstanceList;
  2060. PLIST_ENTRY pHeadInst;
  2061. PLIST_ENTRY pNextInst;
  2062. PPDHI_INSTANCE pInstance;
  2063. PPDHI_INST_LIST pInstList;
  2064. LPVOID TempBuffer = NULL;
  2065. DWORD dwNewBuffer = 0;
  2066. LPVOID LocalCounter = NULL;
  2067. DWORD LocalCounterSize = 0;
  2068. LPVOID LocalInstance = NULL;
  2069. DWORD LocalInstanceSize = 0;
  2070. DWORD dwCntrBufferUsed = 0;
  2071. DWORD dwInstBufferUsed = 0;
  2072. PdhiInitCounterHashTable(CounterTable);
  2073. InitializeListHead(& InstanceList);
  2074. LocalCounter = G_ALLOC(MEDIUM_BUFFER_SIZE);
  2075. LocalInstance = G_ALLOC(MEDIUM_BUFFER_SIZE);
  2076. if (LocalCounter == NULL || LocalInstance == NULL) {
  2077. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2078. goto Cleanup;
  2079. }
  2080. LocalCounterSize = LocalInstanceSize = MEDIUM_BUFFER_SIZE;
  2081. if (mszCounterList != NULL) {
  2082. ZeroMemory(mszCounterList, (* pdwCounterListLength) * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)));
  2083. }
  2084. if (mszInstanceList != NULL) {
  2085. ZeroMemory(mszInstanceList, (* pdwInstanceListLength) * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)));
  2086. }
  2087. if (IsValidLogHandle(hDataSource)) {
  2088. pDataSource = (PPDHI_LOG) hDataSource;
  2089. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pDataSource->hLogMutex);
  2090. if (pdhStatus == ERROR_SUCCESS) {
  2091. if (IsValidLogHandle(hDataSource)) {
  2092. dwLogType = pDataSource->dwLogFormat;
  2093. // enum objects based on log type & machine name
  2094. switch (LOWORD(dwLogType)) {
  2095. case PDH_LOG_TYPE_CSV:
  2096. case PDH_LOG_TYPE_TSV:
  2097. pdhStatus = PdhiEnumObjectItemsFromTextLog((PPDHI_LOG) hDataSource,
  2098. szMachineName, szObjectName, CounterTable, dwDetailLevel, dwFlags);
  2099. break;
  2100. case PDH_LOG_TYPE_BINARY:
  2101. pdhStatus = PdhiEnumObjectItemsFromWmiLog((PPDHI_LOG) hDataSource,
  2102. szMachineName, szObjectName, CounterTable, dwDetailLevel, dwFlags);
  2103. break;
  2104. case PDH_LOG_TYPE_RETIRED_BIN:
  2105. pdhStatus = PdhiEnumObjectItemsFromBinaryLog((PPDHI_LOG) hDataSource,
  2106. szMachineName, szObjectName, CounterTable, dwDetailLevel, dwFlags);
  2107. break;
  2108. case PDH_LOG_TYPE_SQL:
  2109. pdhStatus = PdhiEnumObjectItemsFromSQLLog((PPDHI_LOG) hDataSource,
  2110. szMachineName, szObjectName, CounterTable, dwDetailLevel, dwFlags);
  2111. break;
  2112. case PDH_LOG_TYPE_PERFMON:
  2113. pdhStatus = PdhiEnumObjectItemsFromPerfmonLog((PPDHI_LOG) hDataSource,
  2114. szMachineName, szObjectName, CounterTable, dwDetailLevel, dwFlags);
  2115. break;
  2116. default:
  2117. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  2118. break;
  2119. }
  2120. }
  2121. else {
  2122. pdhStatus = PDH_INVALID_HANDLE;
  2123. }
  2124. RELEASE_MUTEX (pDataSource->hLogMutex);
  2125. }
  2126. }
  2127. if (pdhStatus == ERROR_SUCCESS) {
  2128. dwCntrBufferUsed = 0;
  2129. for (dwIndex = 0; dwIndex < HASH_TABLE_SIZE; dwIndex ++) {
  2130. PPDHI_INSTANCE pNewInst;
  2131. pInstList = CounterTable[dwIndex];
  2132. while (pInstList != NULL) {
  2133. if (! IsListEmpty(& pInstList->InstList)) {
  2134. pHeadInst = & pInstList->InstList;
  2135. pNextInst = pHeadInst->Flink;
  2136. while (pNextInst != pHeadInst) {
  2137. pInstance = CONTAINING_RECORD(pNextInst, PDHI_INSTANCE, Entry);
  2138. pdhStatus = PdhiFindInstance(& InstanceList, pInstance->szInstance, FALSE, & pNewInst);
  2139. if (pNewInst->dwTotal < pInstance->dwTotal) {
  2140. pNewInst->dwTotal = pInstance->dwTotal;
  2141. }
  2142. pNextInst = pNextInst->Flink;
  2143. }
  2144. }
  2145. dwNewBuffer = (lstrlenW(pInstList->szCounter) + 1) * sizeof(WCHAR);
  2146. while (LocalCounterSize < (dwCntrBufferUsed + dwNewBuffer)) {
  2147. TempBuffer = LocalCounter;
  2148. LocalCounter = G_REALLOC(TempBuffer, LocalCounterSize + MEDIUM_BUFFER_SIZE);
  2149. if (LocalCounter == NULL) {
  2150. G_FREE(TempBuffer);
  2151. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2152. goto Cleanup;
  2153. }
  2154. LocalCounterSize += MEDIUM_BUFFER_SIZE;
  2155. }
  2156. dwNewBuffer = AddStringToMultiSz((LPVOID) LocalCounter, pInstList->szCounter, bUnicode);
  2157. if (dwNewBuffer > 0) {
  2158. dwCntrBufferUsed = dwNewBuffer * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
  2159. }
  2160. pInstList = pInstList->pNext;
  2161. }
  2162. }
  2163. dwInstBufferUsed = 0;
  2164. if (! IsListEmpty(& InstanceList)) {
  2165. pHeadInst = & InstanceList;
  2166. pNextInst = pHeadInst->Flink;
  2167. while (pNextInst != pHeadInst) {
  2168. pInstance = CONTAINING_RECORD(pNextInst, PDHI_INSTANCE, Entry);
  2169. dwNewBuffer = (lstrlenW(pInstance->szInstance) + 1) * sizeof(WCHAR) * pInstance->dwTotal;
  2170. while (LocalInstanceSize < (dwInstBufferUsed + dwNewBuffer)) {
  2171. TempBuffer = LocalInstance;
  2172. LocalInstance = G_REALLOC(TempBuffer, LocalInstanceSize + MEDIUM_BUFFER_SIZE);
  2173. if (LocalInstance == NULL) {
  2174. G_FREE(TempBuffer);
  2175. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2176. goto Cleanup;
  2177. }
  2178. LocalInstanceSize += MEDIUM_BUFFER_SIZE;
  2179. }
  2180. for (dwIndex = 0; dwIndex < pInstance->dwTotal; dwIndex ++) {
  2181. dwNewBuffer = AddStringToMultiSz((LPVOID) LocalInstance, pInstance->szInstance, bUnicode);
  2182. }
  2183. if (dwNewBuffer > 0) {
  2184. dwInstBufferUsed = dwNewBuffer * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
  2185. }
  2186. pNextInst = pNextInst->Flink;
  2187. }
  2188. }
  2189. if (mszCounterList != NULL && dwCntrBufferUsed <= * pdwCounterListLength) {
  2190. RtlCopyMemory(mszCounterList, LocalCounter, dwCntrBufferUsed);
  2191. }
  2192. else {
  2193. if (mszCounterList != NULL)
  2194. RtlCopyMemory(mszCounterList, LocalCounter, * pdwCounterListLength);
  2195. dwCntrBufferUsed += (bUnicode) ? sizeof(WCHAR) : sizeof(CHAR);
  2196. pdhStatus = PDH_MORE_DATA;
  2197. }
  2198. * pdwCounterListLength = dwCntrBufferUsed;
  2199. if (dwInstBufferUsed > 0) {
  2200. if (mszInstanceList != NULL && dwInstBufferUsed <= * pdwInstanceListLength) {
  2201. RtlCopyMemory(mszInstanceList, LocalInstance, dwInstBufferUsed);
  2202. }
  2203. else {
  2204. if (mszInstanceList != NULL)
  2205. RtlCopyMemory(mszInstanceList, LocalInstance, * pdwInstanceListLength);
  2206. dwInstBufferUsed += (bUnicode) ? sizeof(WCHAR) : sizeof(CHAR);
  2207. pdhStatus = PDH_MORE_DATA;
  2208. }
  2209. }
  2210. * pdwInstanceListLength = dwInstBufferUsed;
  2211. }
  2212. Cleanup:
  2213. if (! IsListEmpty(& InstanceList)) {
  2214. pHeadInst = & InstanceList;
  2215. pNextInst = pHeadInst->Flink;
  2216. while (pNextInst != pHeadInst) {
  2217. pInstance = CONTAINING_RECORD(pNextInst, PDHI_INSTANCE, Entry);
  2218. pNextInst = pNextInst->Flink;
  2219. RemoveEntryList(& pInstance->Entry);
  2220. G_FREE(pInstance);
  2221. }
  2222. }
  2223. for (dwIndex = 0; dwIndex < HASH_TABLE_SIZE; dwIndex ++) {
  2224. PPDHI_INST_LIST pCurrent;
  2225. pInstList = CounterTable[dwIndex];
  2226. while (pInstList != NULL) {
  2227. if (! IsListEmpty(& pInstList->InstList)) {
  2228. pHeadInst = & pInstList->InstList;
  2229. pNextInst = pHeadInst->Flink;
  2230. while (pNextInst != pHeadInst) {
  2231. pInstance = CONTAINING_RECORD(pNextInst, PDHI_INSTANCE, Entry);
  2232. pNextInst = pNextInst->Flink;
  2233. RemoveEntryList(& pInstance->Entry);
  2234. G_FREE(pInstance);
  2235. }
  2236. }
  2237. pCurrent = pInstList;
  2238. pInstList = pInstList->pNext;
  2239. G_FREE(pCurrent);
  2240. }
  2241. }
  2242. G_FREE(LocalCounter);
  2243. G_FREE(LocalInstance);
  2244. return pdhStatus;
  2245. }
  2246. BOOL
  2247. PdhiDataSourceHasDetailLevelsH(
  2248. PDH_HLOG hDataSource
  2249. )
  2250. {
  2251. return (hDataSource == H_REALTIME_DATASOURCE);
  2252. }
  2253. PDH_FUNCTION
  2254. PdhiGetMatchingLogRecord(
  2255. PDH_HLOG hLog,
  2256. LONGLONG * pStartTime,
  2257. LPDWORD pdwIndex
  2258. )
  2259. {
  2260. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2261. PPDHI_LOG pLog;
  2262. DWORD dwTempIndex;
  2263. __try {
  2264. dwTempIndex = *pdwIndex;
  2265. * pdwIndex = 0;
  2266. * pdwIndex = dwTempIndex;
  2267. }
  2268. __except (EXCEPTION_EXECUTE_HANDLER) {
  2269. pdhStatus = PDH_INVALID_ARGUMENT;
  2270. }
  2271. if (pdhStatus == ERROR_SUCCESS) {
  2272. if (IsValidLogHandle(hLog)) {
  2273. pLog = (PPDHI_LOG) hLog;
  2274. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  2275. if (pdhStatus == ERROR_SUCCESS) {
  2276. if (IsValidLogHandle(hLog)) {
  2277. // call any type-specific open functions
  2278. switch (LOWORD(pLog->dwLogFormat)) {
  2279. case PDH_LOG_TYPE_CSV:
  2280. case PDH_LOG_TYPE_TSV:
  2281. pdhStatus = PdhiGetMatchingTextLogRecord(pLog, pStartTime, pdwIndex);
  2282. break;
  2283. case PDH_LOG_TYPE_RETIRED_BIN:
  2284. pdhStatus = PdhiGetMatchingBinaryLogRecord(pLog, pStartTime, pdwIndex);
  2285. break;
  2286. case PDH_LOG_TYPE_SQL:
  2287. pdhStatus = PdhiGetMatchingSQLLogRecord(pLog, pStartTime, pdwIndex);
  2288. break;
  2289. case PDH_LOG_TYPE_PERFMON:
  2290. pdhStatus = PdhiGetMatchingPerfmonLogRecord(pLog, pStartTime, pdwIndex);
  2291. break;
  2292. case PDH_LOG_TYPE_BINARY:
  2293. default:
  2294. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  2295. break;
  2296. }
  2297. }
  2298. else {
  2299. pdhStatus = PDH_INVALID_HANDLE;
  2300. }
  2301. RELEASE_MUTEX (pLog->hLogMutex);
  2302. }
  2303. }
  2304. else {
  2305. pdhStatus = PDH_INVALID_HANDLE;
  2306. }
  2307. }
  2308. return pdhStatus;
  2309. }
  2310. PDH_FUNCTION
  2311. PdhiGetCounterValueFromLogFile(
  2312. PDH_HLOG hLog,
  2313. DWORD dwIndex,
  2314. PPDHI_COUNTER pCounter
  2315. )
  2316. {
  2317. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2318. PPDHI_LOG pLog = NULL;
  2319. PDH_RAW_COUNTER pValue;
  2320. ZeroMemory(& pValue, sizeof(PDH_RAW_COUNTER));
  2321. pCounter->LastValue = pCounter->ThisValue;
  2322. if (pdhStatus == ERROR_SUCCESS) {
  2323. if (IsValidLogHandle (hLog)) {
  2324. pLog = (PPDHI_LOG) hLog;
  2325. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  2326. if (pdhStatus == ERROR_SUCCESS) {
  2327. if (IsValidLogHandle (hLog)) {
  2328. // call any type-specific open functions
  2329. switch (LOWORD(pLog->dwLogFormat)) {
  2330. case PDH_LOG_TYPE_CSV:
  2331. case PDH_LOG_TYPE_TSV:
  2332. pdhStatus = PdhiGetCounterValueFromTextLog(pLog, dwIndex, & pCounter->plCounterInfo, & pValue);
  2333. break;
  2334. case PDH_LOG_TYPE_RETIRED_BIN:
  2335. pdhStatus = PdhiGetCounterValueFromBinaryLog(pLog, dwIndex, pCounter);
  2336. break;
  2337. case PDH_LOG_TYPE_SQL:
  2338. pdhStatus = PdhiGetCounterValueFromSQLLog(pLog, dwIndex, pCounter, & pValue);
  2339. break;
  2340. case PDH_LOG_TYPE_PERFMON:
  2341. pdhStatus = PdhiGetCounterValueFromPerfmonLog(pLog, dwIndex, pCounter, & pValue);
  2342. break;
  2343. case PDH_LOG_TYPE_BINARY:
  2344. default:
  2345. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  2346. break;
  2347. }
  2348. }
  2349. else {
  2350. pdhStatus = PDH_INVALID_HANDLE;
  2351. }
  2352. RELEASE_MUTEX (pLog->hLogMutex);
  2353. }
  2354. }
  2355. else {
  2356. pdhStatus = PDH_INVALID_HANDLE;
  2357. }
  2358. }
  2359. if (pdhStatus == ERROR_SUCCESS && LOWORD(pLog->dwLogFormat) != PDH_LOG_TYPE_RETIRED_BIN
  2360. && LOWORD(pLog->dwLogFormat) != PDH_LOG_TYPE_BINARY) {
  2361. if (pdhStatus != ERROR_SUCCESS) {
  2362. // See if this is because there's no more entries.
  2363. // If not, clear the counter value & return error
  2364. //
  2365. if (pdhStatus != PDH_NO_MORE_DATA) {
  2366. ZeroMemory(& pCounter->ThisValue, sizeof(PDH_RAW_COUNTER));
  2367. pCounter->ThisValue.CStatus = pdhStatus;
  2368. }
  2369. }
  2370. else {
  2371. pCounter->ThisValue = pValue;
  2372. }
  2373. }
  2374. return pdhStatus;
  2375. }
  2376. PDH_FUNCTION
  2377. PdhiResetLogBuffers(
  2378. PDH_HLOG hLog
  2379. )
  2380. {
  2381. PDH_STATUS pdhStatus;
  2382. PPDHI_LOG pLog;
  2383. if (IsValidLogHandle(hLog)) {
  2384. pLog = (PPDHI_LOG) hLog;
  2385. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  2386. if (pdhStatus == ERROR_SUCCESS) {
  2387. if (IsValidLogHandle(hLog)) {
  2388. if (LOWORD(pLog->dwLogFormat) == PDH_LOG_TYPE_BINARY) {
  2389. pdhStatus = PdhiRewindWmiLog(pLog);
  2390. }
  2391. else {
  2392. pLog->dwLastRecordRead = 0;
  2393. if (pLog->lpMappedFileBase != NULL) {
  2394. // for mapped files we use a pointer into the buffer
  2395. // so reset it
  2396. pLog->pLastRecordRead = pLog->lpMappedFileBase;
  2397. }
  2398. else {
  2399. // for other files we have a separate buffer
  2400. if (pLog->pLastRecordRead != NULL) {
  2401. G_FREE(pLog->pLastRecordRead);
  2402. pLog->pLastRecordRead = NULL;
  2403. }
  2404. }
  2405. pdhStatus = ERROR_SUCCESS;
  2406. }
  2407. }
  2408. else {
  2409. pdhStatus = PDH_INVALID_HANDLE;
  2410. }
  2411. RELEASE_MUTEX (pLog->hLogMutex);
  2412. }
  2413. }
  2414. else {
  2415. pdhStatus = PDH_INVALID_HANDLE;
  2416. }
  2417. return pdhStatus;
  2418. }
  2419. PDH_FUNCTION
  2420. PdhListLogFileHeaderW(
  2421. IN LPCWSTR szFileName,
  2422. IN LPWSTR mszHeaderList,
  2423. IN LPDWORD pcchHeaderListSize
  2424. )
  2425. {
  2426. HLOG hDataSource = NULL;
  2427. PDH_STATUS pdhStatus;
  2428. DWORD dwLogType = -1;
  2429. PPDHI_LOG pDataSource;
  2430. if (szFileName == NULL || pcchHeaderListSize == NULL) {
  2431. pdhStatus = PDH_INVALID_ARGUMENT;
  2432. }
  2433. else {
  2434. // open log file
  2435. pdhStatus = PdhOpenLogW(szFileName,
  2436. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  2437. & dwLogType,
  2438. NULL,
  2439. 0,
  2440. NULL,
  2441. & hDataSource);
  2442. }
  2443. if (pdhStatus == ERROR_SUCCESS) {
  2444. pDataSource = (PPDHI_LOG) hDataSource;
  2445. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pDataSource->hLogMutex);
  2446. if (pdhStatus == ERROR_SUCCESS) {
  2447. if (IsValidLogHandle(hDataSource)) {
  2448. __try {
  2449. // enum objects based on log type & machine name
  2450. switch (LOWORD(dwLogType)) {
  2451. case PDH_LOG_TYPE_CSV:
  2452. case PDH_LOG_TYPE_TSV:
  2453. pdhStatus = PdhiListHeaderFromTextLog((PPDHI_LOG) hDataSource,
  2454. (LPVOID) mszHeaderList,
  2455. pcchHeaderListSize,
  2456. TRUE);
  2457. break;
  2458. case PDH_LOG_TYPE_BINARY:
  2459. case PDH_LOG_TYPE_RETIRED_BIN:
  2460. pdhStatus = PdhiListHeaderFromBinaryLog((PPDHI_LOG) hDataSource,
  2461. (LPVOID) mszHeaderList,
  2462. pcchHeaderListSize,
  2463. TRUE);
  2464. break;
  2465. case PDH_LOG_TYPE_SQL:
  2466. pdhStatus = PdhiListHeaderFromSQLLog((PPDHI_LOG) hDataSource,
  2467. (LPVOID) mszHeaderList,
  2468. pcchHeaderListSize,
  2469. TRUE);
  2470. break;
  2471. case PDH_LOG_TYPE_PERFMON:
  2472. pdhStatus = PDH_NOT_IMPLEMENTED;
  2473. break;
  2474. default:
  2475. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  2476. break;
  2477. }
  2478. }
  2479. __except(EXCEPTION_EXECUTE_HANDLER) {
  2480. pdhStatus = PDH_INVALID_ARGUMENT;
  2481. }
  2482. }
  2483. else {
  2484. pdhStatus = PDH_INVALID_HANDLE;
  2485. }
  2486. RELEASE_MUTEX(pDataSource->hLogMutex);
  2487. }
  2488. PdhCloseLog(hDataSource, 0);
  2489. }
  2490. return pdhStatus;
  2491. }
  2492. PDH_FUNCTION
  2493. PdhListLogFileHeaderA(
  2494. IN LPCSTR szFileName,
  2495. IN LPSTR mszHeaderList,
  2496. IN LPDWORD pcchHeaderListSize
  2497. )
  2498. {
  2499. HLOG hDataSource = NULL;
  2500. PDH_STATUS pdhStatus;
  2501. DWORD dwLogType = -1;
  2502. PPDHI_LOG pDataSource;
  2503. if (szFileName == NULL || pcchHeaderListSize == NULL) {
  2504. pdhStatus = PDH_INVALID_ARGUMENT;
  2505. }
  2506. else {
  2507. // open log file
  2508. pdhStatus = PdhOpenLogA(szFileName,
  2509. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  2510. & dwLogType,
  2511. NULL,
  2512. 0,
  2513. NULL,
  2514. & hDataSource);
  2515. }
  2516. if (pdhStatus == ERROR_SUCCESS) {
  2517. pDataSource = (PPDHI_LOG) hDataSource;
  2518. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pDataSource->hLogMutex);
  2519. if (pdhStatus == ERROR_SUCCESS) {
  2520. if (IsValidLogHandle(hDataSource)) {
  2521. __try {
  2522. // enum objects based on log type & machine name
  2523. switch (LOWORD(dwLogType)) {
  2524. case PDH_LOG_TYPE_CSV:
  2525. case PDH_LOG_TYPE_TSV:
  2526. pdhStatus = PdhiListHeaderFromTextLog((PPDHI_LOG) hDataSource,
  2527. (LPVOID)mszHeaderList,
  2528. pcchHeaderListSize,
  2529. FALSE);
  2530. break;
  2531. case PDH_LOG_TYPE_BINARY:
  2532. case PDH_LOG_TYPE_RETIRED_BIN:
  2533. pdhStatus = PdhiListHeaderFromBinaryLog((PPDHI_LOG) hDataSource,
  2534. (LPVOID) mszHeaderList,
  2535. pcchHeaderListSize,
  2536. FALSE);
  2537. break;
  2538. case PDH_LOG_TYPE_SQL:
  2539. pdhStatus = PdhiListHeaderFromSQLLog((PPDHI_LOG) hDataSource,
  2540. (LPVOID) mszHeaderList,
  2541. pcchHeaderListSize,
  2542. FALSE);
  2543. break;
  2544. case PDH_LOG_TYPE_PERFMON:
  2545. pdhStatus = PDH_NOT_IMPLEMENTED;
  2546. break;
  2547. default:
  2548. pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
  2549. break;
  2550. }
  2551. }
  2552. __except(EXCEPTION_EXECUTE_HANDLER) {
  2553. pdhStatus = PDH_INVALID_ARGUMENT;
  2554. }
  2555. }
  2556. else {
  2557. pdhStatus = PDH_INVALID_HANDLE;
  2558. }
  2559. RELEASE_MUTEX (pDataSource->hLogMutex);
  2560. }
  2561. PdhCloseLog(hDataSource, 0);
  2562. }
  2563. return pdhStatus;
  2564. }
  2565. extern DWORD DataSourceTypeW(IN LPCWSTR szDataSource);
  2566. PDH_FUNCTION
  2567. PdhBindInputDataSourceW(
  2568. IN PDH_HLOG * phDataSource,
  2569. IN LPCWSTR LogFileNameList
  2570. )
  2571. {
  2572. PDH_STATUS PdhStatus = ERROR_SUCCESS;
  2573. DWORD dwDataSource = DataSourceTypeW(LogFileNameList);
  2574. LPWSTR NextLogFile = (LPWSTR) LogFileNameList;
  2575. ULONG LogFileCount = 0;
  2576. ULONG LogFileSize;
  2577. PPDHI_LOG pLogHead = NULL;
  2578. PPDHI_LOG pLogNew = NULL;
  2579. DWORD dwLogType;
  2580. PDH_HLOG hLogLocal = H_REALTIME_DATASOURCE;
  2581. __try {
  2582. dwDataSource = DataSourceTypeW(LogFileNameList);
  2583. }
  2584. __except(EXCEPTION_EXECUTE_HANDLER) {
  2585. PdhStatus = PDH_INVALID_ARGUMENT;
  2586. }
  2587. if (PdhStatus == ERROR_SUCCESS) {
  2588. switch (dwDataSource) {
  2589. case DATA_SOURCE_WBEM:
  2590. hLogLocal = H_WBEM_DATASOURCE;
  2591. break;
  2592. case DATA_SOURCE_REGISTRY:
  2593. hLogLocal = H_REALTIME_DATASOURCE;
  2594. break;
  2595. case DATA_SOURCE_LOGFILE:
  2596. if (LogFileNameList == NULL) {
  2597. PdhStatus = PDH_INVALID_ARGUMENT;
  2598. }
  2599. else {
  2600. if (lstrlenW(LogFileNameList) > 4 && (LogFileNameList[0] == L'S' || LogFileNameList[0] == L's') &&
  2601. (LogFileNameList[1] == L'Q' || LogFileNameList[1] == L'q') &&
  2602. (LogFileNameList[2] == L'L' || LogFileNameList[2] == L'l') &&
  2603. LogFileNameList[3] == L':') {
  2604. // special handling for SQL datasource
  2605. //
  2606. dwLogType = PDH_LOG_TYPE_SQL;
  2607. PdhStatus = PdhOpenLogW(LogFileNameList,
  2608. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  2609. & dwLogType,
  2610. NULL,
  2611. 0,
  2612. NULL,
  2613. & hLogLocal);
  2614. break;
  2615. }
  2616. __try {
  2617. while (* NextLogFile != L'\0') {
  2618. if (lstrlenW(NextLogFile) <= PDH_MAX_DATASOURCE_PATH) {
  2619. LogFileSize = sizeof(WCHAR) * (lstrlenW(NextLogFile) + 1);
  2620. LogFileSize = DWORD_MULTIPLE(LogFileSize);
  2621. //LogFileSize += sizeof(PDHI_LOG);
  2622. pLogNew = G_ALLOC(LogFileSize + sizeof(PDHI_LOG));
  2623. if (pLogNew == NULL) {
  2624. PdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2625. break;
  2626. }
  2627. * ((LPDWORD)(& pLogNew->signature[0])) = SigLog;
  2628. pLogNew->dwLength = sizeof(PDHI_LOG);
  2629. pLogNew->szLogFileName = (LPWSTR) (((PUCHAR) pLogNew) + sizeof(PDHI_LOG));
  2630. StringCbCopyW(pLogNew->szLogFileName, LogFileSize, NextLogFile);
  2631. pLogNew->NextLog = pLogHead;
  2632. pLogHead = pLogNew;
  2633. LogFileCount ++;
  2634. }
  2635. // skip counter log with datasource name longer than PDH_MAX_DATASOURCE_PATH
  2636. NextLogFile += (lstrlenW(NextLogFile) + 1);
  2637. }
  2638. if (pLogHead == NULL) {
  2639. PdhStatus = PDH_INVALID_ARGUMENT;
  2640. }
  2641. }
  2642. __except (EXCEPTION_EXECUTE_HANDLER) {
  2643. PdhStatus = PDH_INVALID_ARGUMENT;
  2644. }
  2645. }
  2646. if (PdhStatus == ERROR_SUCCESS) {
  2647. pLogHead->hLogMutex = CreateMutexW(NULL, TRUE, NULL);
  2648. pLogHead->hLogFileHandle = INVALID_HANDLE_VALUE;
  2649. pLogHead->hCatFileHandle = INVALID_HANDLE_VALUE;
  2650. if (PdhiFirstLogEntry == NULL) {
  2651. PdhiFirstLogEntry = pLogHead;
  2652. pLogHead->next.flink =
  2653. pLogHead->next.blink = pLogHead;
  2654. }
  2655. else {
  2656. PPDHI_LOG pFirstLog = PdhiFirstLogEntry;
  2657. PPDHI_LOG pLastLog = pFirstLog->next.blink;
  2658. pLogHead->next.flink = pLastLog->next.flink;
  2659. pLastLog->next.flink = pLogHead;
  2660. pLogHead->next.blink = pFirstLog->next.blink;
  2661. pFirstLog->next.blink = pLogHead;
  2662. }
  2663. PdhStatus = OpenInputLogFile(pLogHead, PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING, & dwDataSource);
  2664. if (PdhStatus == ERROR_SUCCESS && (dwDataSource == PDH_LOG_TYPE_BINARY || LogFileCount == 1)) {
  2665. hLogLocal = (PDH_HLOG) pLogHead;
  2666. }
  2667. else {
  2668. if (PdhStatus == ERROR_SUCCESS) {
  2669. PdhStatus = PDH_INVALID_ARGUMENT;
  2670. PdhCloseLog(pLogHead, 0);
  2671. }
  2672. DeleteLogEntry(pLogHead);
  2673. }
  2674. }
  2675. else {
  2676. while (pLogHead != NULL) {
  2677. pLogNew = pLogHead;
  2678. pLogHead = pLogNew->NextLog;
  2679. G_FREE(pLogNew);
  2680. }
  2681. }
  2682. break;
  2683. default:
  2684. PdhStatus = PDH_INVALID_ARGUMENT;
  2685. break;
  2686. }
  2687. }
  2688. if (PdhStatus == ERROR_SUCCESS) {
  2689. __try {
  2690. * phDataSource = hLogLocal;
  2691. }
  2692. __except(EXCEPTION_EXECUTE_HANDLER) {
  2693. PdhStatus = PDH_INVALID_ARGUMENT;
  2694. PdhCloseLog(hLogLocal, 0);
  2695. }
  2696. }
  2697. return PdhStatus;
  2698. }
  2699. PDH_FUNCTION
  2700. PdhBindInputDataSourceA(
  2701. IN PDH_HLOG * phDataSource,
  2702. IN LPCSTR LogFileNameList
  2703. )
  2704. {
  2705. LPWSTR wLogFileNameList = NULL;
  2706. LPWSTR wNextFileName;
  2707. LPSTR aNextFileName;
  2708. ULONG LogFileListSize = 1;
  2709. PDH_STATUS PdhStatus = ERROR_SUCCESS;
  2710. if (LogFileNameList == NULL) {
  2711. wLogFileNameList = NULL;
  2712. }
  2713. else {
  2714. __try {
  2715. while (LogFileNameList[LogFileListSize - 1] != '\0' || LogFileNameList[LogFileListSize] != '\0') {
  2716. LogFileListSize ++;
  2717. }
  2718. LogFileListSize = (LogFileListSize + 1) * sizeof(WCHAR);
  2719. wLogFileNameList = (LPWSTR) G_ALLOC(LogFileListSize);
  2720. if (wLogFileNameList == NULL) {
  2721. PdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2722. }
  2723. else {
  2724. aNextFileName = (LPSTR) LogFileNameList;
  2725. wNextFileName = wLogFileNameList;
  2726. while (* aNextFileName != '\0') {
  2727. LogFileListSize = lstrlenA(aNextFileName) + 1;
  2728. if (LogFileListSize <= PDH_MAX_DATASOURCE_PATH) {
  2729. MultiByteToWideChar(_getmbcp(), 0, aNextFileName, -1, (LPWSTR) wNextFileName, LogFileListSize);
  2730. wNextFileName += LogFileListSize;
  2731. }
  2732. // skip counter log with datasource name longer than PDH_MAX_DATASOURCE_PATH
  2733. aNextFileName += LogFileListSize;
  2734. }
  2735. * wNextFileName = L'\0';
  2736. }
  2737. }
  2738. __except (EXCEPTION_EXECUTE_HANDLER) {
  2739. PdhStatus = PDH_INVALID_ARGUMENT;
  2740. }
  2741. }
  2742. if (PdhStatus == ERROR_SUCCESS) {
  2743. PdhStatus = PdhBindInputDataSourceW(phDataSource, wLogFileNameList);
  2744. }
  2745. G_FREE(wLogFileNameList);
  2746. return PdhStatus;
  2747. }
  2748. BOOL
  2749. PdhiCloseAllLoggers(
  2750. )
  2751. {
  2752. BOOL bReturn = FALSE;
  2753. if (WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex) == ERROR_SUCCESS) {
  2754. while (PdhiFirstLogEntry != NULL) {
  2755. PPDHI_LOG pLog = PdhiFirstLogEntry;
  2756. CloseAndDeleteLogEntry(pLog, 0, TRUE);
  2757. }
  2758. RELEASE_MUTEX(hPdhDataMutex);
  2759. bReturn = TRUE;
  2760. }
  2761. return bReturn;
  2762. }
  2763. PDH_FUNCTION PdhiCheckWmiLogFileType(IN LPCWSTR LogFileName, IN LPDWORD LogFileType);
  2764. PDH_FUNCTION
  2765. PdhGetLogFileTypeW(
  2766. IN LPCWSTR LogFileName,
  2767. IN LPDWORD LogFileType
  2768. )
  2769. {
  2770. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2771. HANDLE hFile;
  2772. DWORD dwLogFormat;
  2773. if (LogFileName == NULL) {
  2774. pdhStatus = PDH_INVALID_ARGUMENT;
  2775. }
  2776. else {
  2777. __try {
  2778. dwLogFormat = * LogFileType;
  2779. * LogFileType = dwLogFormat;
  2780. if (* LogFileName == L'\0' || lstrlenW(LogFileName) > PDH_MAX_DATASOURCE_PATH) {
  2781. pdhStatus = PDH_INVALID_ARGUMENT;
  2782. }
  2783. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2784. pdhStatus = PDH_INVALID_ARGUMENT;
  2785. }
  2786. }
  2787. if (pdhStatus == ERROR_SUCCESS) {
  2788. hFile = CreateFileW(LogFileName,
  2789. GENERIC_READ,
  2790. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2791. NULL,
  2792. OPEN_EXISTING,
  2793. FILE_ATTRIBUTE_NORMAL,
  2794. NULL);
  2795. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
  2796. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  2797. }
  2798. }
  2799. if (pdhStatus == ERROR_SUCCESS) {
  2800. dwLogFormat = GetLogFileType(hFile);
  2801. CloseHandle(hFile);
  2802. if (dwLogFormat == PDH_LOG_TYPE_UNDEFINED) {
  2803. pdhStatus = PdhiCheckWmiLogFileType(LogFileName, & dwLogFormat);
  2804. }
  2805. }
  2806. if (pdhStatus == ERROR_SUCCESS) {
  2807. * LogFileType = dwLogFormat;
  2808. }
  2809. return pdhStatus;
  2810. }
  2811. PDH_FUNCTION
  2812. PdhGetLogFileTypeA(
  2813. IN LPCSTR LogFileName,
  2814. IN LPDWORD LogFileType
  2815. )
  2816. {
  2817. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2818. LPWSTR wszLogFileName = NULL;
  2819. DWORD dwLogFileName = 0;
  2820. if (LogFileName == NULL) {
  2821. pdhStatus = PDH_INVALID_ARGUMENT;
  2822. }
  2823. else {
  2824. __try {
  2825. if (* LogFileName == '\0' || lstrlenA(LogFileName) > PDH_MAX_DATASOURCE_PATH) {
  2826. pdhStatus = PDH_INVALID_ARGUMENT;
  2827. }
  2828. else {
  2829. wszLogFileName = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) LogFileName);
  2830. if (wszLogFileName == NULL) {
  2831. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2832. }
  2833. }
  2834. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2835. pdhStatus = PDH_INVALID_ARGUMENT;
  2836. }
  2837. }
  2838. if (pdhStatus == ERROR_SUCCESS) {
  2839. pdhStatus = PdhGetLogFileTypeW(wszLogFileName, LogFileType);
  2840. }
  2841. G_FREE(wszLogFileName);
  2842. return pdhStatus;
  2843. }