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.

4216 lines
169 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. log_SQL.c
  5. Abstract:
  6. <abstract>
  7. --*/
  8. #include <windows.h>
  9. //#include <stdio.h>
  10. //#include <stdlib.h>
  11. #include <mbctype.h>
  12. #include <strsafe.h>
  13. #include <pdh.h>
  14. #include "strings.h"
  15. #include <pdhmsg.h>
  16. #include "pdhidef.h"
  17. #include <sql.h>
  18. #include <odbcss.h>
  19. // pragma to supress /W4 errors
  20. #pragma warning ( disable : 4201 )
  21. #include <sqlext.h>
  22. #pragma warning ( default : 4201 )
  23. #include "log_SQL.h"
  24. #include "log_bin.h" // to get the binary log file record formatting
  25. #pragma warning ( disable : 4213)
  26. #define TIME_FIELD_BUFF_SIZE 24
  27. #define TIMEZONE_BUFF_SIZE 32
  28. #define PDH_SQL_BULK_COPY_REC 2048
  29. #define SQL_COUNTER_ID_SIZE 12
  30. #define SQLSTMTSIZE 4096
  31. #define INITIAL_MSZ_SIZE 1024
  32. #define MSZ_SIZE_ADDON 1024
  33. #define MULTI_COUNT_DOUBLE_RAW 0xFFFFFFFF
  34. #define ALLOC_CHECK(pB) if (NULL == pB) { return PDH_MEMORY_ALLOCATION_FAILURE; }
  35. #define ALLOC_CHECK_HSTMT(pB) if (NULL == pB) { SQLFreeStmt(hstmt, SQL_DROP); return PDH_MEMORY_ALLOCATION_FAILURE; }
  36. #define SQLSUCCEEDED(rc) (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA)
  37. #define ReportSQLError(pLog, SQL_ERROR, NULL, Status) PdhiReportSQLError(pLog, SQL_ERROR, NULL, Status, __LINE__)
  38. typedef struct _PDH_SQL_BULK_COPY {
  39. GUID dbGuid;
  40. INT dbCounterId;
  41. INT dbRecordIndex;
  42. CHAR dbDateTime[TIME_FIELD_BUFF_SIZE];
  43. double dbCounterValue;
  44. INT dbFirstValueA;
  45. INT dbFirstValueB;
  46. INT dbSecondValueA;
  47. INT dbSecondValueB;
  48. INT dbMultiCount;
  49. DWORD dwRecordCount;
  50. } PDH_SQL_BULK_COPY, * PPDH_SQL_BULK_COPY;
  51. typedef struct _PDHI_SQL_LOG_DATA PDHI_SQL_LOG_DATA, * PPDHI_SQL_LOG_DATA;
  52. struct _PDHI_SQL_LOG_DATA {
  53. PDH_RAW_COUNTER RawData;
  54. DOUBLE dFormattedValue;
  55. DWORD dwRunId;
  56. };
  57. typedef struct _PDHI_SQL_LOG_INFO {
  58. PPDHI_LOG_MACHINE MachineList;
  59. PPDHI_SQL_LOG_DATA * LogData;
  60. FILETIME RecordTime;
  61. DWORD dwRunId;
  62. DWORD dwMaxCounter;
  63. DWORD dwMinCounter;
  64. } PDHI_SQL_LOG_INFO, * PPDHI_SQL_LOG_INFO;
  65. /* external functions */
  66. BOOL __stdcall
  67. IsValidLogHandle(
  68. HLOG hLog
  69. );
  70. /* forward declares */
  71. PDH_FUNCTION
  72. PdhpGetSQLLogHeader(
  73. PPDHI_LOG pLog
  74. );
  75. PDH_FUNCTION
  76. PdhpWriteSQLCounters(
  77. PPDHI_LOG pLog
  78. );
  79. BOOL __stdcall
  80. PdhpConvertFileTimeToSQLString(
  81. FILETIME * pFileTime,
  82. LPWSTR szStartDate,
  83. DWORD dwStartDate
  84. )
  85. {
  86. //1998-01-02 12:00:00.000
  87. SYSTEMTIME st;
  88. BOOL bReturn = FALSE;
  89. if (FileTimeToSystemTime(pFileTime, & st)) {
  90. StringCchPrintfW(szStartDate, dwStartDate, L"%04d-%02d-%02d %02d:%02d:%02d.%03d",
  91. st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
  92. bReturn = TRUE;
  93. }
  94. return bReturn;
  95. }
  96. BOOL __stdcall
  97. PdhpConvertSQLStringToFileTime(
  98. LPWSTR szStartDate,
  99. FILETIME * pFileTime
  100. ) // 1111111111222
  101. { // 01234567890123456789012
  102. // 1998-01-02 12:00:00.000
  103. SYSTEMTIME st;
  104. WCHAR buffer[TIME_FIELD_BUFF_SIZE];
  105. WCHAR * pwchar;
  106. ZeroMemory(buffer, sizeof(WCHAR) * TIME_FIELD_BUFF_SIZE);
  107. StringCchCopyW(buffer, TIME_FIELD_BUFF_SIZE, szStartDate);
  108. buffer[4] = L'\0';
  109. st.wYear = (WORD) _wtoi(buffer);
  110. pwchar = & (buffer[5]);
  111. buffer[7] = L'\0';
  112. st.wMonth = (WORD) _wtoi(pwchar);
  113. pwchar = & (buffer[8]);
  114. buffer[10] = L'\0';
  115. st.wDay = (WORD) _wtoi(pwchar);
  116. pwchar = & (buffer[11]);
  117. buffer[13] = L'\0';
  118. st.wHour = (WORD) _wtoi(pwchar);
  119. pwchar = & (buffer[14]);
  120. buffer[16] = L'\0';
  121. st.wMinute = (WORD) _wtoi(pwchar);
  122. pwchar = & (buffer[17]);
  123. buffer[19] = L'\0';
  124. st.wSecond = (WORD) _wtoi(pwchar);
  125. pwchar = & (buffer[20]);
  126. st.wMilliseconds = (WORD) _wtoi(pwchar);
  127. st.wDayOfWeek = 0;
  128. return SystemTimeToFileTime(& st, pFileTime);
  129. }
  130. LPWSTR __stdcall
  131. PdhpGetNextMultisz(
  132. LPWSTR mszSource
  133. )
  134. {
  135. // get the next string in a multisz
  136. LPVOID szDestElem;
  137. szDestElem = mszSource;
  138. szDestElem = (LPVOID) ((LPWSTR) szDestElem + (lstrlenW((LPCWSTR) szDestElem) + 1));
  139. return ((LPWSTR) szDestElem);
  140. }
  141. PPDH_SQL_BULK_COPY
  142. PdhiBindBulkCopyStructure(
  143. PPDHI_LOG pLog
  144. )
  145. {
  146. PDH_STATUS Status = ERROR_SUCCESS;
  147. PPDH_SQL_BULK_COPY pBulk = (PPDH_SQL_BULK_COPY) pLog->lpMappedFileBase;
  148. RETCODE rc;
  149. if (pBulk != NULL) return pBulk;
  150. pBulk = G_ALLOC(sizeof(PDH_SQL_BULK_COPY));
  151. if (pBulk != NULL) {
  152. pLog->lpMappedFileBase = pBulk;
  153. pBulk->dbGuid = pLog->guidSQL;
  154. pBulk->dwRecordCount = 0;
  155. rc = bcp_initW(pLog->hdbcSQL, L"CounterData", NULL, NULL, DB_IN);
  156. if (rc == FAIL) {
  157. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  158. goto Cleanup;
  159. }
  160. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbGuid), 0, sizeof(GUID), NULL, 0, SQLUNIQUEID, 1);
  161. if (rc == FAIL) {
  162. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  163. goto Cleanup;
  164. }
  165. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbCounterId), 0, sizeof(INT), NULL, 0, SQLINT4, 2);
  166. if (rc == FAIL) {
  167. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  168. goto Cleanup;
  169. }
  170. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbRecordIndex), 0, sizeof(INT), NULL, 0, SQLINT4, 3);
  171. if (rc == FAIL) {
  172. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  173. goto Cleanup;
  174. }
  175. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) (pBulk->dbDateTime), 0, 24, NULL, 0, SQLCHARACTER, 4);
  176. if (rc == FAIL) {
  177. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  178. goto Cleanup;
  179. }
  180. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbCounterValue), 0, sizeof(double), NULL, 0, SQLFLT8, 5);
  181. if (rc == FAIL) {
  182. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  183. goto Cleanup;
  184. }
  185. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbFirstValueA), 0, sizeof(INT), NULL, 0, SQLINT4, 6);
  186. if (rc == FAIL) {
  187. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  188. goto Cleanup;
  189. }
  190. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbFirstValueB), 0, sizeof(INT), NULL, 0, SQLINT4, 7);
  191. if (rc == FAIL) {
  192. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  193. goto Cleanup;
  194. }
  195. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbSecondValueA), 0, sizeof(INT), NULL, 0, SQLINT4, 8);
  196. if (rc == FAIL) {
  197. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  198. goto Cleanup;
  199. }
  200. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbSecondValueB), 0, sizeof(INT), NULL, 0, SQLINT4, 9);
  201. if (rc == FAIL) {
  202. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  203. goto Cleanup;
  204. }
  205. rc = bcp_bind(pLog->hdbcSQL, (LPCBYTE) & (pBulk->dbMultiCount), 0, sizeof(INT), NULL, 0, SQLINT4, 10);
  206. if (rc == FAIL) {
  207. Status = PDH_SQL_EXEC_DIRECT_FAILED;
  208. goto Cleanup;
  209. }
  210. }
  211. else {
  212. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  213. }
  214. Cleanup:
  215. if (Status != ERROR_SUCCESS) {
  216. G_FREE(pBulk);
  217. pBulk = pLog->lpMappedFileBase = NULL;
  218. Status = ReportSQLError(pLog, SQL_ERROR, NULL, Status);
  219. SetLastError(Status);
  220. }
  221. return pBulk;
  222. }
  223. PDH_FUNCTION
  224. PdhiSqlUpdateCounterDetails(
  225. PPDHI_LOG pLog,
  226. BOOL bBeforeSendRow,
  227. PPDHI_LOG_MACHINE pMachine,
  228. PPDHI_LOG_OBJECT pObject,
  229. PPDHI_LOG_COUNTER pCounter,
  230. LONGLONG TimeBase,
  231. LPWSTR szMachine,
  232. LPWSTR szObject,
  233. LPWSTR szCounter,
  234. DWORD dwCounterType,
  235. DWORD dwDefaultScale,
  236. LPWSTR szInstance,
  237. DWORD dwInstance,
  238. LPWSTR szParent,
  239. DWORD dwParent
  240. )
  241. {
  242. PDH_STATUS Status = ERROR_SUCCESS;
  243. HSTMT hstmt = NULL;
  244. RETCODE rc;
  245. LPWSTR szSQLStmt = NULL;
  246. DWORD dwSQLStmt = 0;
  247. DWORD dwCounterId;
  248. SQLLEN dwCounterIdLen;
  249. SQLLEN dwRowCount;
  250. PPDH_SQL_BULK_COPY pBulk = (PPDH_SQL_BULK_COPY) pLog->lpMappedFileBase;
  251. if (! bBeforeSendRow) {
  252. if (pBulk != NULL && pBulk->dwRecordCount > 0) {
  253. DBINT rcBCP = bcp_batch(pLog->hdbcSQL);
  254. if (rcBCP < 0) {
  255. TRACE((PDH_DBG_TRACE_ERROR),
  256. (__LINE__,
  257. PDH_LOGSQL,
  258. 0,
  259. PDH_SQL_EXEC_DIRECT_FAILED,
  260. TRACE_DWORD(rcBCP),
  261. TRACE_DWORD(pBulk->dwRecordCount),
  262. NULL));
  263. ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
  264. }
  265. pBulk->dwRecordCount = 0;
  266. }
  267. }
  268. dwSQLStmt = MAX_PATH + lstrlenW(szMachine) + lstrlenW(szObject) + lstrlenW(szCounter);
  269. if (szInstance != NULL) dwSQLStmt += lstrlenW(szInstance);
  270. if (szParent != NULL) dwSQLStmt += lstrlenW(szParent);
  271. if (dwSQLStmt < SQLSTMTSIZE) dwSQLStmt = SQLSTMTSIZE;
  272. szSQLStmt = G_ALLOC(dwSQLStmt * sizeof(WCHAR));
  273. if (szSQLStmt == NULL) {
  274. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  275. goto Cleanup;
  276. }
  277. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  278. if (! SQLSUCCEEDED(rc)) {
  279. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  280. goto Cleanup;
  281. }
  282. // need to cover the following cases where 0 = NULL, 1 = present,
  283. // can't have an Instance Index without an Instance Name
  284. //
  285. // Instance Name
  286. // Instance Index
  287. // Parent Name
  288. // Parent Object ID
  289. // 0000
  290. // 1000 pos 4 & 5 are countertype,defscale
  291. // 0010
  292. // 0001
  293. // 1100
  294. // 1010
  295. // 1001
  296. // 0011
  297. // 1110
  298. // 1101
  299. // 1011
  300. // 1111
  301. //
  302. if ((szInstance == NULL || szInstance[0] == L'\0') && dwInstance == 0
  303. && (szParent == NULL || szParent[0] == L'\0') && dwParent == 0) {
  304. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 0000
  305. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,NULL,NULL,NULL,NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  306. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
  307. LODWORD(TimeBase), HIDWORD(TimeBase));
  308. }
  309. else if ((szInstance != NULL && szInstance[0] != '\0') && dwInstance == 0
  310. && (szParent == NULL || szParent[0] == '\0') && dwParent == 0) {
  311. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 1000
  312. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,'%ws',NULL,NULL,NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  313. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szInstance,
  314. LODWORD(TimeBase), HIDWORD(TimeBase));
  315. }
  316. else if ((szInstance == NULL || szInstance[0] == '\0') && dwInstance == 0
  317. && (szParent != NULL && szParent[0] != '\0') && dwParent == 0) {
  318. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 0010
  319. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,NULL,NULL,'%ws',NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  320. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szParent,
  321. LODWORD(TimeBase), HIDWORD(TimeBase));
  322. }
  323. else if ((szInstance == NULL || szInstance[0] == '\0') && dwInstance == 0
  324. && (szParent == NULL || szParent[0] == '\0') && dwParent != 0) {
  325. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 0001
  326. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,NULL,NULL,NULL,%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  327. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, dwParent,
  328. LODWORD(TimeBase), HIDWORD(TimeBase));
  329. }
  330. else if ((szInstance != NULL && szInstance[0] != '\0') && dwInstance != 0
  331. && (szParent == NULL || szParent[0] == '\0') && dwParent == 0) {
  332. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 1100
  333. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,'%ws',%d,NULL,NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  334. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szInstance, dwInstance,
  335. LODWORD(TimeBase), HIDWORD(TimeBase));
  336. }
  337. else if ((szInstance != NULL && szInstance[0] != '\0') && dwInstance == 0
  338. && (szParent != NULL && szParent[0] != '\0') && dwParent == 0) {
  339. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 1010
  340. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,'%ws',NULL,'%ws',NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  341. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szInstance, szParent,
  342. LODWORD(TimeBase), HIDWORD(TimeBase));
  343. }
  344. else if ((szInstance != NULL && szInstance[0] != '\0') && dwInstance == 0
  345. && (szParent == NULL || szParent[0] == '\0') && dwParent != 0) {
  346. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 1001
  347. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,'%ws',NULL,NULL,%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  348. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szInstance, dwParent,
  349. LODWORD(TimeBase), HIDWORD(TimeBase));
  350. }
  351. else if ((szInstance == NULL || szInstance[0] == '\0') && dwInstance == 0
  352. && (szParent != NULL && szParent[0] != '\0') && dwParent != 0) {
  353. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 0011
  354. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,NULL,NULL,'%ws',%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  355. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szParent, dwParent,
  356. LODWORD(TimeBase), HIDWORD(TimeBase));
  357. }
  358. else if ((szInstance != NULL && szInstance[0] != '\0') && dwInstance != 0
  359. && (szParent != NULL && szParent[0] != '\0') && dwParent == 0) {
  360. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 1110
  361. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,'%ws',%d,'%ws',NULL,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  362. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szInstance, dwInstance, szParent,
  363. LODWORD(TimeBase), HIDWORD(TimeBase));
  364. }
  365. else if ((szInstance != NULL && szInstance[0] != '\0') && dwInstance != 0
  366. && (szParent == NULL || szParent[0] == '\0') && dwParent != 0) {
  367. StringCchPrintfW(szSQLStmt, dwSQLStmt, //1101
  368. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,'%ws',%d,NULL,%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  369. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szInstance, dwInstance, dwParent,
  370. LODWORD(TimeBase), HIDWORD(TimeBase));
  371. }
  372. else if ((szInstance != NULL && szInstance[0] != '\0') && dwInstance == 0
  373. && (szParent != NULL && szParent[0] != '\0') && dwParent != 0) {
  374. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 1011
  375. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,'%ws',NULL,'%ws',%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  376. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale, szInstance, szParent, dwParent,
  377. LODWORD(TimeBase), HIDWORD(TimeBase));
  378. }
  379. else if ((szInstance != NULL && szInstance[0] != '\0') && dwInstance != 0
  380. && (szParent != NULL && szParent[0] != '\0') && dwParent != 0) {
  381. StringCchPrintfW(szSQLStmt, dwSQLStmt, // 1111
  382. L"begin transaction AddCounterDetails insert into CounterDetails values ('%ws','%ws','%ws',%d,%d,'%ws',%d,'%ws',%d,%d,%d) Select @@Identity commit transaction AddCounterDetails",
  383. szMachine, szObject, szCounter, dwCounterType, dwDefaultScale,
  384. szInstance, dwInstance, szParent, dwParent,
  385. LODWORD(TimeBase), HIDWORD(TimeBase));
  386. }
  387. else {
  388. Status = PDH_INVALID_ARGUMENT;
  389. goto Cleanup;
  390. }
  391. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  392. if (! SQLSUCCEEDED(rc)) {
  393. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  394. goto Cleanup;
  395. }
  396. rc = SQLRowCount(hstmt, & dwRowCount);
  397. if (! SQLSUCCEEDED(rc)) {
  398. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ROWCOUNT_FAILED);
  399. goto Cleanup;
  400. }
  401. rc = SQLMoreResults(hstmt);
  402. if (! SQLSUCCEEDED(rc)) {
  403. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_MORE_RESULTS_FAILED);
  404. goto Cleanup;
  405. }
  406. rc = SQLBindCol(hstmt, 1, SQL_C_SLONG, & dwCounterId, 0, & dwCounterIdLen);
  407. if (! SQLSUCCEEDED(rc)) {
  408. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  409. goto Cleanup;
  410. }
  411. rc = SQLFetch(hstmt);
  412. if (! SQLSUCCEEDED(rc)) {
  413. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  414. goto Cleanup;
  415. }
  416. if (SQL_NO_DATA == rc) {
  417. Status = PDH_NO_DATA;
  418. goto Cleanup;
  419. }
  420. if (pCounter != NULL) {
  421. pCounter->dwCounterID = dwCounterId;
  422. }
  423. Cleanup:
  424. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  425. G_FREE(szSQLStmt);
  426. return Status;
  427. }
  428. PPDHI_LOG_COUNTER
  429. PdhiSqlFindCounter(
  430. PPDHI_LOG pLog,
  431. PPDHI_LOG_MACHINE * MachineTable,
  432. LPWSTR szMachine,
  433. LPWSTR szObject,
  434. LPWSTR szCounter,
  435. DWORD dwCounterType,
  436. DWORD dwDefaultScale,
  437. LPWSTR szInstance,
  438. DWORD dwInstance,
  439. LPWSTR szParent,
  440. DWORD dwParent,
  441. LONGLONG TimeBase,
  442. BOOL bBeforeSendRow,
  443. BOOL bInsert
  444. )
  445. {
  446. PPDHI_LOG_MACHINE pMachine = NULL;
  447. PPDHI_LOG_OBJECT pObject = NULL;
  448. PPDHI_LOG_COUNTER pCounter = NULL;
  449. PPDHI_LOG_COUNTER pNode = NULL;
  450. PPDHI_LOG_COUNTER * pStack[MAX_BTREE_DEPTH];
  451. PPDHI_LOG_COUNTER * pLink;
  452. int dwStack = 0;
  453. PPDHI_LOG_COUNTER pParent;
  454. PPDHI_LOG_COUNTER pSibling;
  455. PPDHI_LOG_COUNTER pChild;
  456. int iCompare;
  457. BOOL bUpdateCounterDetail = FALSE;
  458. WCHAR szTmp[PDH_SQL_STRING_SIZE];
  459. ZeroMemory(szTmp, PDH_SQL_STRING_SIZE * sizeof(WCHAR));
  460. StringCchCopyW(szTmp, PDH_SQL_STRING_SIZE, szMachine);
  461. for (pMachine = (* MachineTable);
  462. (pMachine != NULL) && lstrcmpiW(pMachine->szMachine, szTmp) != 0;
  463. pMachine = pMachine->next);
  464. if (pMachine == NULL) {
  465. pMachine = G_ALLOC(sizeof(PDHI_LOG_MACHINE) + (PDH_SQL_STRING_SIZE + 1) * sizeof(WCHAR));
  466. if (pMachine == NULL) goto Cleanup;
  467. pMachine->szMachine = (LPWSTR) (((PCHAR) pMachine) + sizeof(PDHI_LOG_MACHINE));
  468. StringCchCopyW(pMachine->szMachine, PDH_SQL_STRING_SIZE, szMachine);
  469. pMachine->ObjTable = NULL;
  470. pMachine->next = (* MachineTable);
  471. * MachineTable = pMachine;
  472. }
  473. pObject = PdhiFindLogObject(pMachine, & (pMachine->ObjTable), szObject, TRUE);
  474. if (pObject == NULL) goto Cleanup;
  475. pStack[dwStack ++] = & (pObject->CtrTable);
  476. pCounter = pObject->CtrTable;
  477. while (pCounter != NULL) {
  478. iCompare = PdhiCompareLogCounterInstance(pCounter, szCounter, szInstance, dwInstance, szParent);
  479. if (iCompare == 0) {
  480. if (dwCounterType < pCounter->dwCounterType) {
  481. iCompare = -1;
  482. }
  483. else if (dwCounterType > pCounter->dwCounterType) {
  484. iCompare = 1;
  485. }
  486. else {
  487. iCompare = 0;
  488. }
  489. }
  490. if (iCompare < 0) {
  491. pStack[dwStack ++] = & (pCounter->left);
  492. pCounter = pCounter->left;
  493. }
  494. else if (iCompare > 0) {
  495. pStack[dwStack ++] = & (pCounter->right);
  496. pCounter = pCounter->right;
  497. }
  498. else {
  499. break;
  500. }
  501. }
  502. if (pCounter == NULL) {
  503. pCounter = G_ALLOC(sizeof(PDHI_LOG_COUNTER) + 3 * sizeof(WCHAR) * (PDH_SQL_STRING_SIZE + 1));
  504. if (pCounter == NULL) goto Cleanup;
  505. pCounter->next = pObject->CtrList;
  506. pObject->CtrList = pCounter;
  507. pCounter->bIsRed = TRUE;
  508. pCounter->left = NULL;
  509. pCounter->right = NULL;
  510. pCounter->dwCounterType = dwCounterType;
  511. pCounter->dwDefaultScale = dwDefaultScale;
  512. pCounter->dwInstance = dwInstance;
  513. pCounter->dwParent = dwParent;
  514. pCounter->TimeStamp = 0;
  515. pCounter->TimeBase = TimeBase;
  516. pCounter->szCounter = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER));
  517. StringCchCopyW(pCounter->szCounter, PDH_SQL_STRING_SIZE, szCounter);
  518. if (szInstance == NULL || szInstance[0] == L'\0') {
  519. pCounter->szInstance = NULL;
  520. }
  521. else {
  522. pCounter->szInstance = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER)
  523. + sizeof(WCHAR) * (PDH_SQL_STRING_SIZE + 1));
  524. StringCchCopyW(pCounter->szInstance, PDH_SQL_STRING_SIZE, szInstance);
  525. }
  526. if (szParent == NULL || szParent[0] == L'\0') {
  527. pCounter->szParent = NULL;
  528. }
  529. else {
  530. pCounter->szParent = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER)
  531. + 2 * sizeof(WCHAR) * (PDH_SQL_STRING_SIZE + 1));
  532. StringCchCopyW(pCounter->szParent, PDH_SQL_STRING_SIZE, szParent);
  533. }
  534. if (bInsert) {
  535. bUpdateCounterDetail = TRUE;
  536. }
  537. pLink = pStack[-- dwStack];
  538. * pLink = pCounter;
  539. pChild = NULL;
  540. pNode = pCounter;
  541. while (dwStack > 0) {
  542. pLink = pStack[-- dwStack];
  543. pParent = * pLink;
  544. if (! pParent->bIsRed) {
  545. pSibling = (pParent->left == pNode)
  546. ? pParent->right : pParent->left;
  547. if (pSibling && pSibling->bIsRed) {
  548. pNode->bIsRed = FALSE;
  549. pSibling->bIsRed = FALSE;
  550. pParent->bIsRed = TRUE;
  551. }
  552. else {
  553. if (pChild && pChild->bIsRed) {
  554. if (pChild == pNode->left) {
  555. if (pNode == pParent->left) {
  556. pParent->bIsRed = TRUE;
  557. pParent->left = pNode->right;
  558. pNode->right = pParent;
  559. pNode->bIsRed = FALSE;
  560. * pLink = pNode;
  561. }
  562. else {
  563. pParent->bIsRed = TRUE;
  564. pParent->right = pChild->left;
  565. pChild->left = pParent;
  566. pNode->left = pChild->right;
  567. pChild->right = pNode;
  568. pChild->bIsRed = FALSE;
  569. * pLink = pChild;
  570. }
  571. }
  572. else {
  573. if (pNode == pParent->right) {
  574. pParent->bIsRed = TRUE;
  575. pParent->right = pNode->left;
  576. pNode->left = pParent;
  577. pNode->bIsRed = FALSE;
  578. * pLink = pNode;
  579. }
  580. else {
  581. pParent->bIsRed = TRUE;
  582. pParent->left = pChild->right;
  583. pChild->right = pParent;
  584. pNode->right = pChild->left;
  585. pChild->left = pNode;
  586. pChild->bIsRed = FALSE;
  587. * pLink = pChild;
  588. }
  589. }
  590. }
  591. break;
  592. }
  593. }
  594. pChild = pNode;
  595. pNode = pParent;
  596. }
  597. pObject->CtrTable->bIsRed = FALSE;
  598. }
  599. if (bUpdateCounterDetail && pCounter) {
  600. PdhiSqlUpdateCounterDetails(pLog,
  601. bBeforeSendRow,
  602. pMachine,
  603. pObject,
  604. pCounter,
  605. pCounter->TimeBase,
  606. pMachine->szMachine,
  607. pObject->szObject,
  608. pCounter->szCounter,
  609. dwCounterType,
  610. dwDefaultScale,
  611. pCounter->szInstance,
  612. dwInstance,
  613. pCounter->szParent,
  614. dwParent);
  615. }
  616. Cleanup:
  617. return pCounter;
  618. }
  619. PDH_FUNCTION
  620. PdhiSqlBuildCounterObjectNode(
  621. PPDHI_LOG pLog,
  622. LPWSTR szMachine,
  623. LPWSTR szObject
  624. )
  625. {
  626. PDH_STATUS Status = ERROR_SUCCESS;
  627. RETCODE rc = SQL_SUCCESS;
  628. HSTMT hstmt = NULL;
  629. DWORD CounterID = 0;
  630. SQLLEN dwCounterID = 0;
  631. LPWSTR CounterName = NULL;
  632. SQLLEN dwCounterName = 0;
  633. DWORD CounterType = 0;
  634. SQLLEN dwCounterType = 0;
  635. DWORD DefaultScale = 0;
  636. SQLLEN dwDefaultScale = 0;
  637. LPWSTR InstanceName = NULL;
  638. SQLLEN dwInstanceName = 0;
  639. DWORD InstanceIndex = 0;
  640. SQLLEN dwInstanceIndex = 0;
  641. LPWSTR ParentName = NULL;
  642. SQLLEN dwParentName = 0;
  643. DWORD ParentObjectID = 0;
  644. SQLLEN dwParentObjectID = 0;
  645. LARGE_INTEGER lTimeBase;
  646. SQLLEN dwTimeBaseA = 0;
  647. SQLLEN dwTimeBaseB = 0;
  648. LPWSTR SQLStmt = NULL;
  649. DWORD dwSQLStmt = 0;
  650. BOOL bFind = FALSE;
  651. PPDHI_LOG_OBJECT pObject = NULL;
  652. PPDHI_LOG_MACHINE pMachine;
  653. PPDHI_LOG_COUNTER pCounter;
  654. CounterName = (LPWSTR) G_ALLOC(3 * PDH_SQL_STRING_SIZE * sizeof(WCHAR));
  655. if (CounterName == NULL) {
  656. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  657. goto Cleanup;
  658. }
  659. InstanceName = CounterName + PDH_SQL_STRING_SIZE;
  660. ParentName = InstanceName + PDH_SQL_STRING_SIZE;
  661. for (pMachine = ((PPDHI_LOG_MACHINE) (pLog->pPerfmonInfo));
  662. pMachine != NULL && lstrcmpiW(pMachine->szMachine, szMachine) != 0;
  663. pMachine = pMachine->next);
  664. if (pMachine != NULL) {
  665. pObject = pMachine->ObjTable;
  666. while (pObject != NULL) {
  667. int iCompare = lstrcmpiW(szObject, pObject->szObject);
  668. if (iCompare < 0) pObject = pObject->left;
  669. else if (iCompare > 0) pObject = pObject->right;
  670. else break;
  671. }
  672. }
  673. if (pObject != NULL) goto Cleanup;
  674. dwSQLStmt = MAX_PATH + lstrlenW(szMachine) + lstrlenW(szObject);
  675. if (dwSQLStmt < SQLSTMTSIZE) dwSQLStmt = SQLSTMTSIZE;
  676. SQLStmt = G_ALLOC(dwSQLStmt * sizeof(WCHAR));
  677. if (SQLStmt == NULL) {
  678. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  679. goto Cleanup;
  680. }
  681. StringCchPrintfW(SQLStmt, dwSQLStmt,
  682. L"select CounterID, CounterName, CounterType, DefaultScale, InstanceName, InstanceIndex, ParentName, ParentObjectID, TimeBaseA, TimeBaseB from CounterDetails where MachineName = '%ws' and ObjectName = '%ws'",
  683. szMachine, szObject);
  684. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  685. if (! SQLSUCCEEDED(rc)) {
  686. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  687. goto Cleanup;
  688. }
  689. rc = SQLBindCol(hstmt, 1, SQL_C_LONG, & CounterID, 0, & dwCounterID);
  690. if (! SQLSUCCEEDED(rc)) {
  691. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  692. goto Cleanup;
  693. }
  694. rc = SQLBindCol(hstmt, 2, SQL_C_WCHAR, CounterName, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwCounterName);
  695. if (! SQLSUCCEEDED(rc)) {
  696. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  697. goto Cleanup;
  698. }
  699. rc = SQLBindCol(hstmt, 3, SQL_C_LONG, & CounterType, 0, & dwCounterType);
  700. if (! SQLSUCCEEDED(rc)) {
  701. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  702. goto Cleanup;
  703. }
  704. rc = SQLBindCol(hstmt, 4, SQL_C_LONG, & DefaultScale, 0, & dwDefaultScale);
  705. if (! SQLSUCCEEDED(rc)) {
  706. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  707. goto Cleanup;
  708. }
  709. rc = SQLBindCol(hstmt, 5, SQL_C_WCHAR, InstanceName, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwInstanceName);
  710. if (! SQLSUCCEEDED(rc)) {
  711. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  712. goto Cleanup;
  713. }
  714. rc = SQLBindCol(hstmt, 6, SQL_C_LONG, & InstanceIndex, 0, & dwInstanceIndex);
  715. if (! SQLSUCCEEDED(rc)) {
  716. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  717. goto Cleanup;
  718. }
  719. rc = SQLBindCol(hstmt, 7, SQL_C_WCHAR, ParentName, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwParentName);
  720. if (! SQLSUCCEEDED(rc)) {
  721. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  722. goto Cleanup;
  723. }
  724. rc = SQLBindCol(hstmt, 8, SQL_C_LONG, & ParentObjectID, 0, & dwParentObjectID);
  725. if (! SQLSUCCEEDED(rc)) {
  726. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  727. goto Cleanup;
  728. }
  729. rc = SQLBindCol(hstmt, 9, SQL_C_LONG, & lTimeBase.LowPart, 0, & dwTimeBaseA);
  730. if (! SQLSUCCEEDED(rc)) {
  731. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  732. goto Cleanup;
  733. }
  734. rc = SQLBindCol(hstmt, 10, SQL_C_LONG, & lTimeBase.HighPart, 0, & dwTimeBaseB);
  735. if (! SQLSUCCEEDED(rc)) {
  736. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  737. goto Cleanup;
  738. }
  739. rc = SQLExecDirectW(hstmt, SQLStmt, SQL_NTS);
  740. if (! SQLSUCCEEDED(rc)) {
  741. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  742. goto Cleanup;
  743. }
  744. CounterType = DefaultScale = InstanceIndex = ParentObjectID = 0;
  745. rc = SQLFetch(hstmt);
  746. while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
  747. pCounter = PdhiSqlFindCounter(pLog,
  748. (PPDHI_LOG_MACHINE *) (& (pLog->pPerfmonInfo)),
  749. szMachine,
  750. szObject,
  751. CounterName,
  752. CounterType,
  753. DefaultScale,
  754. InstanceName,
  755. InstanceIndex,
  756. ParentName,
  757. ParentObjectID,
  758. 0,
  759. TRUE,
  760. FALSE);
  761. if (pCounter != NULL) {
  762. pCounter->dwCounterID = CounterID;
  763. if (dwTimeBaseA != SQL_NULL_DATA && dwTimeBaseB != SQL_NULL_DATA) {
  764. pCounter->TimeBase = lTimeBase.QuadPart;
  765. }
  766. else {
  767. pCounter->TimeBase = 0;
  768. pCounter->dwCounterType = PERF_DOUBLE_RAW;
  769. }
  770. }
  771. ZeroMemory(CounterName, PDH_SQL_STRING_SIZE * sizeof(WCHAR));
  772. ZeroMemory(InstanceName, PDH_SQL_STRING_SIZE * sizeof(WCHAR));
  773. ZeroMemory(ParentName, PDH_SQL_STRING_SIZE * sizeof(WCHAR));
  774. CounterType = DefaultScale = InstanceIndex = ParentObjectID = 0;
  775. rc = SQLFetch(hstmt);
  776. }
  777. if (! SQLSUCCEEDED(rc)) {
  778. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  779. goto Cleanup;
  780. }
  781. Cleanup:
  782. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  783. G_FREE(SQLStmt);
  784. G_FREE(CounterName);
  785. return Status;
  786. }
  787. PDH_FUNCTION
  788. PdhiSqlGetCounterArray(
  789. PPDHI_COUNTER pCounter,
  790. LPDWORD lpdwBufferSize,
  791. LPDWORD lpdwItemCount,
  792. LPVOID ItemBuffer
  793. )
  794. {
  795. PDH_STATUS Status = ERROR_SUCCESS;
  796. PDH_STATUS PdhFnStatus = ERROR_SUCCESS;
  797. DWORD dwRequiredSize = 0;
  798. PPDHI_RAW_COUNTER_ITEM pThisItem = NULL;
  799. PPDHI_RAW_COUNTER_ITEM pLastItem = NULL;
  800. LPWSTR szThisItem = NULL;
  801. LPWSTR szLastItem = NULL;
  802. PPDH_RAW_COUNTER pThisRawCounter = NULL;
  803. PPDH_RAW_COUNTER pLastRawCounter = NULL;
  804. PPDH_FMT_COUNTERVALUE_ITEM_W pThisFmtItem = NULL;
  805. DWORD dwThisItemIndex;
  806. LPWSTR wszNextString;
  807. DWORD dwRetItemCount = 0;
  808. LIST_ENTRY InstList;
  809. PPDHI_INSTANCE pInstance;
  810. WCHAR szPound[16];
  811. InitializeListHead(& InstList);
  812. Status = WAIT_FOR_AND_LOCK_MUTEX(pCounter->pOwner->hMutex);
  813. if (Status != ERROR_SUCCESS) {
  814. return Status;
  815. }
  816. if(pCounter->pThisRawItemList == NULL) {
  817. Status = PDH_CSTATUS_ITEM_NOT_VALIDATED;
  818. goto Cleanup;
  819. }
  820. dwRetItemCount = pCounter->pThisRawItemList->dwItemCount;
  821. dwThisItemIndex = 0;
  822. if (ItemBuffer != NULL) {
  823. pThisRawCounter = (PPDH_RAW_COUNTER) ItemBuffer;
  824. }
  825. else {
  826. pThisRawCounter = NULL;
  827. }
  828. dwRequiredSize = (DWORD) (dwRetItemCount * sizeof(PDH_RAW_COUNTER));
  829. if ((ItemBuffer != NULL) && (dwRequiredSize <= * lpdwBufferSize)) {
  830. pThisFmtItem = (PPDH_FMT_COUNTERVALUE_ITEM_W) (((LPBYTE) ItemBuffer) + dwRequiredSize);
  831. }
  832. else {
  833. pThisFmtItem = NULL;
  834. }
  835. dwRequiredSize += (DWORD) (dwRetItemCount * sizeof(PDH_FMT_COUNTERVALUE_ITEM_W));
  836. if ((ItemBuffer != NULL) && (dwRequiredSize <= * lpdwBufferSize)) {
  837. wszNextString = (LPWSTR) (((LPBYTE) ItemBuffer) + dwRequiredSize);
  838. }
  839. else {
  840. wszNextString = NULL;
  841. }
  842. for (pThisItem = & (pCounter->pThisRawItemList->pItemArray[0]);
  843. dwThisItemIndex < dwRetItemCount;
  844. dwThisItemIndex ++, pThisItem ++, pLastItem ++) {
  845. szThisItem = (LPWSTR) (((LPBYTE) pCounter->pThisRawItemList) + pThisItem->szName);
  846. pInstance = NULL;
  847. Status = PdhiFindInstance(& InstList, szThisItem, TRUE, & pInstance);
  848. if (Status == ERROR_SUCCESS && pInstance != NULL && pInstance->dwCount > 1) {
  849. ZeroMemory(szPound, 16 * sizeof(WCHAR));
  850. _itow(pInstance->dwCount - 1, szPound, 10);
  851. dwRequiredSize += (lstrlenW(szThisItem) + lstrlenW(szPound) + 2) * sizeof(WCHAR);
  852. }
  853. else {
  854. dwRequiredSize += (lstrlenW(szThisItem) + 1) * sizeof(WCHAR);
  855. }
  856. if ((dwRequiredSize <= * lpdwBufferSize) && (wszNextString != NULL)) {
  857. DWORD dwNextString;
  858. pThisFmtItem->szName = wszNextString;
  859. StringCchCopyW(wszNextString, * lpdwBufferSize, szThisItem);
  860. if (pInstance != NULL) {
  861. if (pInstance->dwCount > 1) {
  862. StringCchCatW(wszNextString, * lpdwBufferSize, cszPoundSign);
  863. StringCchCatW(wszNextString, * lpdwBufferSize, szPound);
  864. }
  865. }
  866. dwNextString = lstrlenW(wszNextString);
  867. wszNextString += (dwNextString + 1);
  868. Status = ERROR_SUCCESS;
  869. }
  870. else {
  871. Status = PDH_MORE_DATA;
  872. }
  873. if (Status == ERROR_SUCCESS) {
  874. if (pCounter->pThisRawItemList != NULL) {
  875. pThisRawCounter->CStatus = pCounter->pThisRawItemList->CStatus;
  876. pThisRawCounter->TimeStamp = pCounter->pThisRawItemList->TimeStamp;
  877. pThisRawCounter->FirstValue = pThisItem->FirstValue;
  878. pThisRawCounter->SecondValue = pThisItem->SecondValue;
  879. pThisRawCounter->MultiCount = pThisItem->MultiCount;
  880. }
  881. else {
  882. ZeroMemory(pThisRawCounter, sizeof(PDH_RAW_COUNTER));
  883. }
  884. pLastRawCounter = NULL;
  885. if (pCounter->pLastRawItemList != NULL) {
  886. PPDH_FMT_COUNTERVALUE_ITEM_W pFmtValue;
  887. DWORD dwLastItem = pCounter->LastValue.MultiCount;
  888. DWORD i;
  889. pFmtValue = (PPDH_FMT_COUNTERVALUE_ITEM_W)
  890. (((LPBYTE) pCounter->pLastObject) + sizeof(PDH_RAW_COUNTER) * dwLastItem);
  891. for (i = 0; i < dwLastItem; i ++) {
  892. if (lstrcmpiW(pThisFmtItem->szName, pFmtValue->szName) == 0) {
  893. pLastRawCounter = (PPDH_RAW_COUNTER)
  894. (((LPBYTE) pCounter->pLastObject) + sizeof(PDH_RAW_COUNTER) * i);
  895. break;
  896. }
  897. else {
  898. pFmtValue = (PPDH_FMT_COUNTERVALUE_ITEM_W)
  899. (((LPBYTE) pFmtValue) + sizeof(PDH_FMT_COUNTERVALUE_ITEM_W));
  900. }
  901. }
  902. }
  903. PdhFnStatus = PdhiComputeFormattedValue(pCounter->CalcFunc,
  904. pCounter->plCounterInfo.dwCounterType,
  905. pCounter->lScale,
  906. PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
  907. pThisRawCounter,
  908. pLastRawCounter,
  909. & pCounter->TimeBase,
  910. 0L,
  911. & pThisFmtItem->FmtValue);
  912. if (PdhFnStatus != ERROR_SUCCESS) {
  913. //Status = PdhFnStatus;
  914. pThisFmtItem->FmtValue.CStatus = PDH_CSTATUS_INVALID_DATA;
  915. pThisFmtItem->FmtValue.doubleValue = 0;
  916. }
  917. pThisRawCounter = (PPDH_RAW_COUNTER) (((LPBYTE) pThisRawCounter) + sizeof(PDH_RAW_COUNTER));
  918. pThisFmtItem = (PPDH_FMT_COUNTERVALUE_ITEM_W)
  919. (((LPBYTE) pThisFmtItem) + sizeof(PDH_FMT_COUNTERVALUE_ITEM_W));
  920. }
  921. }
  922. dwRetItemCount = dwThisItemIndex;
  923. Cleanup:
  924. RELEASE_MUTEX(pCounter->pOwner->hMutex);
  925. if (! IsListEmpty(& InstList)) {
  926. PLIST_ENTRY pHead = & InstList;
  927. PLIST_ENTRY pNext = pHead->Flink;
  928. while (pNext != pHead) {
  929. pInstance = CONTAINING_RECORD(pNext, PDHI_INSTANCE, Entry);
  930. pNext = pNext->Flink;
  931. RemoveEntryList(& pInstance->Entry);
  932. G_FREE(pInstance);
  933. }
  934. }
  935. if (Status == ERROR_SUCCESS || Status == PDH_MORE_DATA) {
  936. * lpdwBufferSize = dwRequiredSize;
  937. * lpdwItemCount = dwRetItemCount;
  938. }
  939. return Status;
  940. }
  941. LPCSTR g_szSQLStat[8] = {
  942. "42S01", "S0001", "42S02", "S0002", "42S11", "S0011", "42S12", "S0012"
  943. };
  944. RETCODE
  945. PdhiCheckSQLExist(
  946. HSTMT hstmt,
  947. RETCODE rcIn
  948. )
  949. {
  950. static SQLCHAR szSQLStat[6];
  951. static SQLCHAR szMessage[PDH_SQL_STRING_SIZE];
  952. RETCODE rc = rcIn;
  953. SQLSMALLINT iMessage = PDH_SQL_STRING_SIZE;
  954. SQLSMALLINT iSize = 0;
  955. SQLINTEGER iNativeError = 0;
  956. ZeroMemory(szSQLStat, 6 * sizeof(SQLCHAR));
  957. ZeroMemory(szMessage, PDH_SQL_STRING_SIZE * sizeof(SQLCHAR));
  958. rc = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, 1, szSQLStat, & iNativeError, szMessage, iMessage, & iSize);
  959. TRACE((PDH_DBG_TRACE_INFO),
  960. (__LINE__,
  961. PDH_LOGSQL,
  962. ARG_DEF(ARG_TYPE_STR,1) | ARG_DEF(ARG_TYPE_STR, 2),
  963. ERROR_SUCCESS,
  964. TRACE_STR(szSQLStat),
  965. TRACE_STR(szMessage),
  966. TRACE_DWORD(rcIn),
  967. TRACE_DWORD(rc),
  968. NULL));
  969. if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
  970. int i;
  971. for (i = 0; i < 8; i ++) {
  972. if (lstrcmpi(szSQLStat, g_szSQLStat[i]) == 0) {
  973. rc = SQL_SUCCESS;
  974. break;
  975. }
  976. }
  977. if (i >= 8) {
  978. rc = rcIn;
  979. }
  980. }
  981. else {
  982. rc = rcIn;
  983. }
  984. return rc;
  985. }
  986. PDH_FUNCTION
  987. PdhiSQLUpdateCounterDetailTimeBase(
  988. PPDHI_LOG pLog,
  989. DWORD dwCounterId,
  990. LONGLONG lTimeBase,
  991. BOOL bBeforeSendRow
  992. )
  993. {
  994. PDH_STATUS Status = ERROR_SUCCESS;
  995. HSTMT hstmt = NULL;
  996. RETCODE rc;
  997. LPWSTR szSQLStmt = NULL;
  998. if (! bBeforeSendRow) {
  999. PPDH_SQL_BULK_COPY pBulk = (PPDH_SQL_BULK_COPY) pLog->lpMappedFileBase;
  1000. if (pBulk != NULL && pBulk->dwRecordCount > 0) {
  1001. DBINT rcBCP = bcp_batch(pLog->hdbcSQL);
  1002. if (rcBCP < 0) {
  1003. TRACE((PDH_DBG_TRACE_ERROR),
  1004. (__LINE__,
  1005. PDH_LOGSQL,
  1006. 0,
  1007. PDH_SQL_EXEC_DIRECT_FAILED,
  1008. TRACE_DWORD(rcBCP),
  1009. TRACE_DWORD(pBulk->dwRecordCount),
  1010. NULL));
  1011. ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
  1012. }
  1013. pBulk->dwRecordCount = 0;
  1014. }
  1015. }
  1016. szSQLStmt = (LPWSTR) G_ALLOC(SQLSTMTSIZE * sizeof(WCHAR));
  1017. if (szSQLStmt == NULL) {
  1018. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1019. }
  1020. else {
  1021. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1022. L"UPDATE CounterDetails SET TimeBaseA = %d, TimeBaseB = %d WHERE CounterID = %d",
  1023. LODWORD(lTimeBase), HIDWORD(lTimeBase), dwCounterId);
  1024. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1025. if (! SQLSUCCEEDED(rc)) {
  1026. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1027. }
  1028. else {
  1029. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1030. if (! SQLSUCCEEDED(rc)) {
  1031. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALTER_DETAIL_FAILED);
  1032. }
  1033. SQLFreeStmt(hstmt, SQL_DROP);
  1034. }
  1035. G_FREE(szSQLStmt);
  1036. }
  1037. return Status;
  1038. }
  1039. PDH_FUNCTION
  1040. PdhiSQLExtendCounterDetail(
  1041. PPDHI_LOG pLog
  1042. )
  1043. {
  1044. PDH_STATUS Status = ERROR_SUCCESS;
  1045. BOOL bExtend = FALSE;
  1046. HSTMT hstmt = NULL;
  1047. RETCODE rc;
  1048. DWORD dwTimeBaseA;
  1049. SQLLEN lenTimeBaseA;
  1050. LPWSTR szSQLStmt = NULL;
  1051. LPWSTR szErrMsg = NULL;
  1052. szSQLStmt = (LPWSTR) G_ALLOC(2 * SQLSTMTSIZE * sizeof(WCHAR));
  1053. if (szSQLStmt == NULL) {
  1054. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1055. }
  1056. else {
  1057. szErrMsg = szSQLStmt + SQLSTMTSIZE;
  1058. StringCchCopyW(szSQLStmt, SQLSTMTSIZE, L"SELECT TimeBaseA FROM CounterDetails");
  1059. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1060. if (! SQLSUCCEEDED(rc)) {
  1061. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1062. }
  1063. else {
  1064. rc = SQLBindCol(hstmt, 1, SQL_C_LONG, & dwTimeBaseA, 0, & lenTimeBaseA);
  1065. if (! SQLSUCCEEDED(rc)) {
  1066. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  1067. }
  1068. else {
  1069. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1070. if (! SQLSUCCEEDED(rc)) {
  1071. long iError;
  1072. short cbErrMsg = SQLSTMTSIZE;
  1073. SQLErrorW(pLog->henvSQL, pLog->hdbcSQL, hstmt, NULL, & iError, szErrMsg, SQLSTMTSIZE, & cbErrMsg);
  1074. if (iError == 0x00CF) { // 207, Invalid Column Name.
  1075. bExtend = TRUE;
  1076. }
  1077. else {
  1078. ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1079. }
  1080. }
  1081. }
  1082. SQLFreeStmt(hstmt, SQL_DROP);
  1083. }
  1084. if (bExtend) {
  1085. StringCchCopyW(szSQLStmt, SQLSTMTSIZE, L"ALTER TABLE CounterDetails ADD TimeBaseA int NULL");
  1086. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1087. if (! SQLSUCCEEDED(rc)) {
  1088. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1089. }
  1090. else {
  1091. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1092. if (! SQLSUCCEEDED(rc)) {
  1093. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALTER_DETAIL_FAILED);
  1094. }
  1095. SQLFreeStmt(hstmt, SQL_DROP);
  1096. }
  1097. if (Status == ERROR_SUCCESS) {
  1098. StringCchCopyW(szSQLStmt, SQLSTMTSIZE, L"ALTER TABLE CounterDetails ADD TimeBaseB int NULL");
  1099. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1100. if (! SQLSUCCEEDED(rc)) {
  1101. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1102. }
  1103. else {
  1104. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1105. if (! SQLSUCCEEDED(rc)) {
  1106. Status = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALTER_DETAIL_FAILED);
  1107. }
  1108. SQLFreeStmt(hstmt, SQL_DROP);
  1109. }
  1110. }
  1111. }
  1112. G_FREE(szSQLStmt);
  1113. }
  1114. return Status;
  1115. }
  1116. PDH_FUNCTION
  1117. PdhpCreateSQLTables(
  1118. PPDHI_LOG pLog
  1119. )
  1120. {
  1121. // INTERNAL FUNCTION to
  1122. //Create the correct perfmon tables in the database
  1123. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1124. HSTMT hstmt = NULL;
  1125. RETCODE rc;
  1126. BOOL bExistData = FALSE;
  1127. LPWSTR szSQLStmt = NULL;
  1128. szSQLStmt = (LPWSTR) G_ALLOC(SQLSTMTSIZE * sizeof(WCHAR));
  1129. if (szSQLStmt == NULL) {
  1130. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1131. goto Cleanup;
  1132. }
  1133. // difficult to cleanup old tables, also dangerous so we won't...
  1134. // PdhiOpenOutputSQLLog calls this routine to ensure the tables are here without checking
  1135. // create the CounterDetails Table
  1136. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1137. L"CREATE TABLE CounterDetails(\
  1138. CounterID int IDENTITY PRIMARY KEY,\
  1139. MachineName varchar(%d) NOT NULL,\
  1140. ObjectName varchar(%d) NOT NULL,\
  1141. CounterName varchar(%d) NOT NULL,\
  1142. CounterType int NOT NULL,\
  1143. DefaultScale int NOT NULL,\
  1144. InstanceName varchar(%d),\
  1145. InstanceIndex int,\
  1146. ParentName varchar(%d),\
  1147. ParentObjectID int,\
  1148. TimeBaseA int,\
  1149. TimeBaseB int\
  1150. )",
  1151. PDH_SQL_STRING_SIZE,
  1152. PDH_SQL_STRING_SIZE,
  1153. PDH_SQL_STRING_SIZE,
  1154. PDH_SQL_STRING_SIZE,
  1155. PDH_SQL_STRING_SIZE);
  1156. // allocate an hstmt
  1157. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1158. if (! SQLSUCCEEDED(rc)) {
  1159. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1160. goto Cleanup;
  1161. }
  1162. // execute the create statement
  1163. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1164. if (!SQLSUCCEEDED(rc))
  1165. {
  1166. rc = PdhiCheckSQLExist(hstmt, rc);
  1167. if (! (SQLSUCCEEDED(rc))) {
  1168. // don't report the error, as this could be called from
  1169. // opening a database that already exists...
  1170. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1171. goto Cleanup;
  1172. }
  1173. else {
  1174. SQLFreeStmt(hstmt, SQL_DROP);
  1175. hstmt = NULL;
  1176. if ((pdhStatus = PdhiSQLExtendCounterDetail(pLog)) != ERROR_SUCCESS) goto Cleanup;
  1177. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1178. L"ALTER TABLE CounterDetails ALTER COLUMN MachineName varchar(%d) NOT NULL",
  1179. PDH_SQL_STRING_SIZE);
  1180. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1181. if (! SQLSUCCEEDED(rc)) {
  1182. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1183. goto Cleanup;
  1184. }
  1185. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1186. if (! SQLSUCCEEDED(rc)) {
  1187. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALTER_DETAIL_FAILED);
  1188. goto Cleanup;
  1189. }
  1190. SQLFreeStmt(hstmt, SQL_DROP);
  1191. hstmt = NULL;
  1192. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1193. L"ALTER TABLE CounterDetails ALTER COLUMN ObjectName varchar(%d) NOT NULL",
  1194. PDH_SQL_STRING_SIZE);
  1195. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1196. if (! SQLSUCCEEDED(rc)) {
  1197. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1198. goto Cleanup;
  1199. }
  1200. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1201. if (! SQLSUCCEEDED(rc)) {
  1202. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALTER_DETAIL_FAILED);
  1203. goto Cleanup;
  1204. }
  1205. SQLFreeStmt(hstmt, SQL_DROP);
  1206. hstmt = NULL;
  1207. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1208. L"ALTER TABLE CounterDetails ALTER COLUMN CounterName varchar(%d) NOT NULL",
  1209. PDH_SQL_STRING_SIZE);
  1210. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1211. if (! SQLSUCCEEDED(rc)) {
  1212. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1213. goto Cleanup;
  1214. }
  1215. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1216. if (! SQLSUCCEEDED(rc)) {
  1217. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALTER_DETAIL_FAILED);
  1218. goto Cleanup;
  1219. }
  1220. SQLFreeStmt(hstmt, SQL_DROP);
  1221. hstmt = NULL;
  1222. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1223. L"ALTER TABLE CounterDetails ALTER COLUMN InstanceName varchar(%d)",
  1224. PDH_SQL_STRING_SIZE);
  1225. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1226. if (! SQLSUCCEEDED(rc)) {
  1227. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1228. goto Cleanup;
  1229. }
  1230. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1231. if (! SQLSUCCEEDED(rc)) {
  1232. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALTER_DETAIL_FAILED);
  1233. goto Cleanup;
  1234. }
  1235. SQLFreeStmt(hstmt, SQL_DROP);
  1236. hstmt = NULL;
  1237. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1238. L"ALTER TABLE CounterDetails ALTER COLUMN ParentName varchar(%d)",
  1239. PDH_SQL_STRING_SIZE);
  1240. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1241. if (! SQLSUCCEEDED(rc)) {
  1242. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1243. goto Cleanup;
  1244. }
  1245. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1246. if (! SQLSUCCEEDED(rc)) {
  1247. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALTER_DETAIL_FAILED);
  1248. goto Cleanup;
  1249. }
  1250. }
  1251. }
  1252. SQLFreeStmt(hstmt, SQL_DROP);
  1253. hstmt = NULL;
  1254. // Create the CounterData table
  1255. StringCchCopyW(szSQLStmt, SQLSTMTSIZE,
  1256. L"CREATE TABLE CounterData(\
  1257. GUID uniqueidentifier NOT NULL,\
  1258. CounterID int NOT NULL,\
  1259. RecordIndex int NOT NULL,\
  1260. CounterDateTime char(24) NOT NULL,\
  1261. CounterValue float NOT NULL,\
  1262. FirstValueA int,\
  1263. FirstValueB int,\
  1264. SecondValueA int,\
  1265. SecondValueB int,\
  1266. MultiCount int,\
  1267. )");
  1268. // allocate an hstmt
  1269. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1270. if (! SQLSUCCEEDED(rc)) {
  1271. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1272. goto Cleanup;
  1273. }
  1274. // execute the create statement
  1275. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1276. if (! SQLSUCCEEDED(rc)) {
  1277. rc = PdhiCheckSQLExist(hstmt, rc);
  1278. if (! (SQLSUCCEEDED(rc))) {
  1279. // don't report the error, as this could be called from
  1280. // opening a database that already exists...
  1281. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1282. goto Cleanup;
  1283. }
  1284. else {
  1285. bExistData = TRUE;
  1286. }
  1287. }
  1288. SQLFreeStmt(hstmt, SQL_DROP);
  1289. hstmt = NULL;
  1290. if (! bExistData) {
  1291. // add the primary keys
  1292. StringCchCopyW(szSQLStmt, SQLSTMTSIZE, L"ALTER TABLE CounterData ADD PRIMARY KEY (GUID,counterID,RecordIndex)");
  1293. // allocate an hstmt
  1294. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1295. if (! SQLSUCCEEDED(rc)) {
  1296. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1297. goto Cleanup;
  1298. }
  1299. // execute the create statement
  1300. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1301. if (! SQLSUCCEEDED(rc)) {
  1302. rc = PdhiCheckSQLExist(hstmt, rc);
  1303. if (! (SQLSUCCEEDED(rc))) {
  1304. // don't report the error, as this could be called from
  1305. // opening a database that already exists...
  1306. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1307. goto Cleanup;
  1308. }
  1309. }
  1310. }
  1311. SQLFreeStmt(hstmt, SQL_DROP);
  1312. hstmt = NULL;
  1313. // create the DisplayToID table
  1314. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1315. L"CREATE TABLE DisplayToID(\
  1316. GUID uniqueidentifier NOT NULL PRIMARY KEY,\
  1317. RunID int,\
  1318. DisplayString varchar(%d) NOT NULL UNIQUE,\
  1319. LogStartTime char(24),\
  1320. LogStopTime char(24),\
  1321. NumberOfRecords int,\
  1322. MinutesToUTC int,\
  1323. TimeZoneName char(32)\
  1324. )",
  1325. PDH_SQL_STRING_SIZE);
  1326. // allocate an hstmt
  1327. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1328. if (! SQLSUCCEEDED(rc)) {
  1329. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1330. goto Cleanup;
  1331. }
  1332. // execute the create statement
  1333. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1334. if (! SQLSUCCEEDED(rc)) {
  1335. rc = PdhiCheckSQLExist(hstmt, rc);
  1336. if (! (SQLSUCCEEDED(rc))) {
  1337. // don't report the error, as this could be called from
  1338. // opening a database that already exists...
  1339. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1340. goto Cleanup;
  1341. }
  1342. }
  1343. SQLFreeStmt(hstmt, SQL_DROP);
  1344. hstmt = NULL;
  1345. Cleanup:
  1346. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  1347. G_FREE(szSQLStmt);
  1348. return pdhStatus;
  1349. }
  1350. PDH_FUNCTION
  1351. PdhiGetSQLLogCounterInfo(
  1352. PPDHI_LOG pLog,
  1353. PPDHI_COUNTER pCounter
  1354. )
  1355. {
  1356. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1357. PPDHI_SQL_LOG_INFO pLogInfo;
  1358. PPDHI_LOG_COUNTER pLogCounter = NULL;
  1359. DWORD dwCtrIndex = 0;
  1360. BOOL bNoMachine = FALSE;
  1361. LPWSTR szMachine;
  1362. pdhStatus = PdhpGetSQLLogHeader(pLog);
  1363. if (pdhStatus != ERROR_SUCCESS) goto Cleanup;
  1364. pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
  1365. if (pLogInfo == NULL) {
  1366. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  1367. goto Cleanup;
  1368. }
  1369. if (pCounter->pCounterPath->szMachineName == NULL) {
  1370. bNoMachine = TRUE;
  1371. szMachine = szStaticLocalMachineName;
  1372. }
  1373. else if (lstrcmpiW(pCounter->pCounterPath->szMachineName, L"\\\\.") == 0) {
  1374. bNoMachine = TRUE;
  1375. szMachine = szStaticLocalMachineName;
  1376. }
  1377. else {
  1378. szMachine = pCounter->pCounterPath->szMachineName;
  1379. }
  1380. pLogCounter = PdhiFindLogCounter(pLog,
  1381. & pLogInfo->MachineList,
  1382. szMachine,
  1383. pCounter->pCounterPath->szObjectName,
  1384. pCounter->pCounterPath->szCounterName,
  1385. 0,
  1386. 0,
  1387. pCounter->pCounterPath->szInstanceName,
  1388. pCounter->pCounterPath->dwIndex,
  1389. pCounter->pCounterPath->szParentName,
  1390. 0,
  1391. & dwCtrIndex,
  1392. FALSE);
  1393. if (pLogCounter != NULL) {
  1394. if (bNoMachine) {
  1395. pCounter->pCounterPath->szMachineName = NULL;
  1396. }
  1397. pCounter->TimeBase = pLogCounter->TimeBase;
  1398. pCounter->plCounterInfo.dwObjectId = 0;
  1399. pCounter->plCounterInfo.lInstanceId = pLogCounter->dwInstance;
  1400. pCounter->plCounterInfo.szInstanceName = pLogCounter->szInstance;
  1401. pCounter->plCounterInfo.dwParentObjectId = pLogCounter->dwParent;
  1402. pCounter->plCounterInfo.szParentInstanceName = pLogCounter->szParent;
  1403. pCounter->plCounterInfo.dwCounterId = pLogCounter->dwCounterID;
  1404. pCounter->plCounterInfo.dwCounterType = pLogCounter->dwCounterType;
  1405. pCounter->plCounterInfo.lDefaultScale = pLogCounter->dwDefaultScale;
  1406. pCounter->plCounterInfo.dwCounterSize = (pLogCounter->dwCounterType & PERF_SIZE_LARGE)
  1407. ? sizeof(LONGLONG) : sizeof(DWORD);
  1408. pCounter->plCounterInfo.dwSQLCounterId = dwCtrIndex;
  1409. pdhStatus = ERROR_SUCCESS;
  1410. }
  1411. else {
  1412. pdhStatus = PDH_CSTATUS_NO_COUNTER;
  1413. }
  1414. Cleanup:
  1415. return pdhStatus;
  1416. }
  1417. PDH_FUNCTION
  1418. PdhiOpenSQLLog(
  1419. PPDHI_LOG pLog,
  1420. BOOL bOpenInput
  1421. )
  1422. {
  1423. // string to compare with file name to see if SQL
  1424. LPCWSTR szSQLType = L"SQL:";
  1425. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1426. RETCODE rc = SQL_SUCCESS;
  1427. pLog->henvSQL = NULL;
  1428. pLog->hdbcSQL = NULL;
  1429. // format is SQL:DSNNAME!COMMENT
  1430. // parse out the DSN name and 'dataset' (comment) name from the LogFileName
  1431. // pLog->szDSN - pointer to Data Source Name within LogFileName
  1432. // (separators replaced with 0's)
  1433. // pLog->szCommentSQL - pointer to the Comment string that defines the
  1434. // name of the data set within the SQL database
  1435. pLog->szDSN = pLog->szLogFileName + lstrlenW(szSQLType);
  1436. pLog->szCommentSQL = wcschr((const wchar_t *) pLog->szDSN, '!');
  1437. if (NULL == pLog->szCommentSQL) {
  1438. pdhStatus = PDH_INVALID_DATASOURCE;
  1439. goto Cleanup;
  1440. }
  1441. pLog->szCommentSQL[0] = 0; // null terminate the DSN name
  1442. pLog->szCommentSQL ++; // increment past to the Comment string
  1443. if (0 == lstrlenW(pLog->szCommentSQL)) {
  1444. pdhStatus = PDH_INVALID_DATASOURCE;
  1445. goto Cleanup;
  1446. }
  1447. // initialize the rest of the SQL fields
  1448. pLog->dwNextRecordIdToWrite = 1; // start with record 1
  1449. pLog->dwRecord1Size = 0;
  1450. //////////////////////////////////////////////////////////////
  1451. // obtain the ODBC environment and connection
  1452. //
  1453. rc = SQLAllocEnv(&pLog->henvSQL);
  1454. if (! SQLSUCCEEDED(rc)) goto Cleanup;
  1455. rc = SQLAllocConnect(pLog->henvSQL, &pLog->hdbcSQL);
  1456. if (! SQLSUCCEEDED(rc)) goto Cleanup;
  1457. rc = SQLSetConnectAttr(pLog->hdbcSQL, SQL_COPT_SS_BCP, (SQLPOINTER) SQL_BCP_ON, SQL_IS_INTEGER);
  1458. if (! SQLSUCCEEDED(rc)) goto Cleanup;
  1459. rc = SQLConnectW(pLog->hdbcSQL, (SQLWCHAR *) pLog->szDSN, SQL_NTS, NULL, SQL_NULL_DATA, NULL, SQL_NULL_DATA);
  1460. Cleanup:
  1461. if (! SQLSUCCEEDED(rc)) {
  1462. pdhStatus = ReportSQLError(pLog,rc,NULL,PDH_SQL_ALLOCCON_FAILED);
  1463. if (pLog->hdbcSQL != NULL) {
  1464. SQLDisconnect(pLog->hdbcSQL);
  1465. SQLFreeHandle(SQL_HANDLE_DBC, pLog->hdbcSQL);
  1466. }
  1467. if (pLog->henvSQL) SQLFreeHandle(SQL_HANDLE_ENV, pLog->henvSQL);
  1468. pLog->henvSQL = NULL;
  1469. pLog->hdbcSQL = NULL;
  1470. }
  1471. return pdhStatus;
  1472. }
  1473. PDH_FUNCTION
  1474. PdhiOpenInputSQLLog(
  1475. PPDHI_LOG pLog
  1476. )
  1477. {
  1478. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1479. LPWSTR szSQLStmt = NULL;
  1480. DWORD dwSQLStmt = 0;
  1481. HSTMT hstmt = NULL;
  1482. RETCODE rc;
  1483. LONG lMinutesToUTC = 0;
  1484. WCHAR szTimeZoneName[TIMEZONE_BUFF_SIZE];
  1485. SQLLEN dwTimeZoneLen;
  1486. pdhStatus = PdhiOpenSQLLog(pLog, TRUE);
  1487. if (SUCCEEDED(pdhStatus)) {
  1488. if ((pdhStatus = PdhiSQLExtendCounterDetail(pLog)) != ERROR_SUCCESS) goto Cleanup;
  1489. // Check that the database exists
  1490. // Select the guid & runid from DisplayToId table
  1491. // allocate an hstmt
  1492. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1493. if (! SQLSUCCEEDED(rc)) {
  1494. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1495. goto Cleanup;
  1496. }
  1497. dwSQLStmt = MAX_PATH;
  1498. if (pLog->szCommentSQL != NULL) dwSQLStmt += lstrlenW(pLog->szCommentSQL);
  1499. if (dwSQLStmt < SQLSTMTSIZE) dwSQLStmt = SQLSTMTSIZE;
  1500. szSQLStmt = G_ALLOC(dwSQLStmt * sizeof(WCHAR));
  1501. if (szSQLStmt == NULL) {
  1502. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1503. goto Cleanup;
  1504. }
  1505. StringCchPrintfW(szSQLStmt, dwSQLStmt,
  1506. L"select GUID, RunID, NumberOfRecords, MinutesToUTC, TimeZoneName from DisplayToID where DisplayString = '%ws'",
  1507. pLog->szCommentSQL);
  1508. // bind the columns
  1509. rc = SQLBindCol(hstmt, 1, SQL_C_GUID, & pLog->guidSQL, 0, NULL);
  1510. if (! SQLSUCCEEDED(rc)) {
  1511. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  1512. goto Cleanup;
  1513. }
  1514. rc = SQLBindCol(hstmt, 2, SQL_C_LONG, & pLog->iRunidSQL, 0, NULL);
  1515. if (! SQLSUCCEEDED(rc)) {
  1516. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  1517. goto Cleanup;
  1518. }
  1519. rc = SQLBindCol(hstmt, 3, SQL_C_LONG, & pLog->dwNextRecordIdToWrite, 0, NULL);
  1520. if (! SQLSUCCEEDED(rc)) {
  1521. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  1522. goto Cleanup;
  1523. }
  1524. rc = SQLBindCol(hstmt, 4, SQL_C_LONG, & lMinutesToUTC, 0, NULL);
  1525. if (! SQLSUCCEEDED(rc)) {
  1526. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  1527. goto Cleanup;
  1528. }
  1529. rc = SQLBindCol(hstmt, 5, SQL_C_WCHAR, szTimeZoneName, TIMEZONE_BUFF_SIZE * sizeof(WCHAR), & dwTimeZoneLen);
  1530. if (! SQLSUCCEEDED(rc)) {
  1531. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  1532. goto Cleanup;
  1533. }
  1534. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1535. if (! SQLSUCCEEDED(rc)) {
  1536. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1537. goto Cleanup;
  1538. }
  1539. rc = SQLFetch(hstmt);
  1540. if (! SQLSUCCEEDED(rc)) {
  1541. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  1542. goto Cleanup;
  1543. }
  1544. pLog->dwNextRecordIdToWrite ++; // increment number of current records to get next recordid to write
  1545. }
  1546. Cleanup:
  1547. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  1548. G_FREE(szSQLStmt);
  1549. return pdhStatus;
  1550. }
  1551. PDH_FUNCTION
  1552. PdhiOpenOutputSQLLog(
  1553. PPDHI_LOG pLog
  1554. )
  1555. // open SQL database for output
  1556. // May have to create DB
  1557. {
  1558. PDH_STATUS pdhStatus = PdhiOpenSQLLog(pLog, FALSE);
  1559. LPWSTR szSQLStmt = NULL;
  1560. DWORD dwSQLStmt = MAX_PATH;
  1561. HSTMT hstmt = NULL;
  1562. RETCODE rc;
  1563. SQLLEN dwGuid = 0;
  1564. SQLLEN dwRunIdSQL = 0;
  1565. SQLLEN dwNextRecord = 0;
  1566. if (SUCCEEDED(pdhStatus)) {
  1567. // see if we need to create the database
  1568. // creating the tables is harmless, it won't drop
  1569. // them if they already exist, but ignore any errors
  1570. pdhStatus = PdhpCreateSQLTables(pLog);
  1571. if (pLog->szCommentSQL != NULL) dwSQLStmt += lstrlenW(pLog->szCommentSQL);
  1572. if (dwSQLStmt < SQLSTMTSIZE) dwSQLStmt = SQLSTMTSIZE;
  1573. szSQLStmt = G_ALLOC(dwSQLStmt * sizeof(WCHAR));
  1574. if (szSQLStmt == NULL) {
  1575. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1576. goto Cleanup;
  1577. }
  1578. // See if logset already exists. If it does, treat it as an
  1579. // logset append case.
  1580. //
  1581. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1582. if (! SQLSUCCEEDED(rc)) {
  1583. pdhStatus = PDH_SQL_ALLOC_FAILED;
  1584. goto Cleanup;
  1585. }
  1586. StringCchPrintfW(szSQLStmt, dwSQLStmt,
  1587. L"select GUID, RunID, NumberOfRecords from DisplayToID where DisplayString = '%ws'",
  1588. pLog->szCommentSQL);
  1589. rc = SQLBindCol(hstmt, 1, SQL_C_GUID, & pLog->guidSQL, 0, & dwGuid);
  1590. if (! SQLSUCCEEDED(rc)) {
  1591. pdhStatus = PDH_SQL_BIND_FAILED;
  1592. goto Cleanup;
  1593. }
  1594. rc = SQLBindCol(hstmt, 2, SQL_C_LONG, & pLog->iRunidSQL, 0, & dwRunIdSQL);
  1595. if (! SQLSUCCEEDED(rc)) {
  1596. pdhStatus = PDH_SQL_BIND_FAILED;
  1597. goto Cleanup;
  1598. }
  1599. rc = SQLBindCol(hstmt, 3, SQL_C_LONG, & pLog->dwNextRecordIdToWrite, 0, & dwNextRecord);
  1600. if (! SQLSUCCEEDED(rc)) {
  1601. pdhStatus = PDH_SQL_BIND_FAILED;
  1602. goto Cleanup;
  1603. }
  1604. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1605. if (! SQLSUCCEEDED(rc)) {
  1606. pdhStatus = PDH_SQL_EXEC_DIRECT_FAILED;
  1607. goto Cleanup;
  1608. }
  1609. rc = SQLFetch(hstmt);
  1610. if ((! SQLSUCCEEDED(rc)) || (rc == SQL_NO_DATA)) {
  1611. pdhStatus = PDH_SQL_FETCH_FAILED;
  1612. goto Cleanup;
  1613. }
  1614. pLog->dwNextRecordIdToWrite ++;
  1615. pLog->dwRecord1Size = 1;
  1616. Cleanup:
  1617. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  1618. G_FREE(szSQLStmt);
  1619. if (pdhStatus != ERROR_SUCCESS) {
  1620. // initialize the GUID
  1621. HRESULT hr = CoCreateGuid(& pLog->guidSQL);
  1622. pLog->dwNextRecordIdToWrite = 1;
  1623. pLog->iRunidSQL = 0;
  1624. pdhStatus = ERROR_SUCCESS;
  1625. }
  1626. }
  1627. if (SUCCEEDED(pdhStatus)) {
  1628. PPDH_SQL_BULK_COPY pBulk = PdhiBindBulkCopyStructure(pLog);
  1629. if (pBulk == NULL) {
  1630. pdhStatus = GetLastError();
  1631. }
  1632. }
  1633. return pdhStatus;
  1634. }
  1635. PDH_FUNCTION
  1636. PdhiReportSQLError(
  1637. PPDHI_LOG pLog,
  1638. RETCODE rc,
  1639. HSTMT hstmt,
  1640. DWORD dwEventNumber,
  1641. DWORD dwLine
  1642. )
  1643. {
  1644. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1645. if (! SQLSUCCEEDED(rc)) {
  1646. pdhStatus = dwEventNumber;
  1647. }
  1648. if (FAILED(pdhStatus)) {
  1649. // for now this will be reported only whe specifically enabled
  1650. short cbErrMsgSize = 512;
  1651. WCHAR szError[512];
  1652. LPWSTR lpszStrings[1];
  1653. DWORD dwData[2];
  1654. long iError;
  1655. lpszStrings[0] = szError;
  1656. SQLErrorW(pLog->henvSQL, pLog->hdbcSQL, hstmt, NULL, & iError, szError, 512, & cbErrMsgSize);
  1657. dwData[0] = iError;
  1658. dwData[1] = dwLine;
  1659. if (pdhStatus == PDH_SQL_EXEC_DIRECT_FAILED && iError == 1105) {
  1660. pdhStatus = ERROR_DISK_FULL;
  1661. }
  1662. ReportEventW(hEventLog,
  1663. EVENTLOG_ERROR_TYPE, // error type
  1664. 0, // category (not used)
  1665. (DWORD) dwEventNumber, // event,
  1666. NULL, // SID (not used),
  1667. 1, // number of strings
  1668. 2, // sizeof raw data
  1669. (LPCWSTR *) lpszStrings, // message text array
  1670. (LPVOID) & dwData[0]); // raw data
  1671. }
  1672. return pdhStatus;
  1673. }
  1674. PDH_FUNCTION
  1675. PdhiCloseSQLLog(
  1676. PPDHI_LOG pLog,
  1677. DWORD dwFlags
  1678. )
  1679. // close the SQL database
  1680. {
  1681. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1682. LPWSTR szSQLStmt = NULL;
  1683. HSTMT hstmt = NULL;
  1684. RETCODE rc;
  1685. SQLLEN dwDateTimeLen;
  1686. WCHAR szDateTime[TIME_FIELD_BUFF_SIZE];
  1687. DBINT rcBCP;
  1688. DWORD dwReturn;
  1689. WCHAR * pTimeZone;
  1690. TIME_ZONE_INFORMATION TimeZone;
  1691. LONG lMinutesToUTC = 0;
  1692. UNREFERENCED_PARAMETER(dwFlags);
  1693. szSQLStmt = (LPWSTR) G_ALLOC(SQLSTMTSIZE * sizeof(WCHAR));
  1694. if (szSQLStmt == NULL) {
  1695. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1696. goto Cleanup;
  1697. }
  1698. if ((pLog->dwLogFormat & PDH_LOG_ACCESS_MASK) == PDH_LOG_WRITE_ACCESS) {
  1699. // need to save the last datetime in the DisplayToID as well as the number of records written
  1700. // allocate an hstmt
  1701. rc = SQLAllocStmt(pLog->hdbcSQL, &hstmt);
  1702. if (!SQLSUCCEEDED(rc)) {
  1703. pdhStatus = ReportSQLError(pLog,rc,hstmt,PDH_SQL_ALLOC_FAILED);
  1704. goto Cleanup;
  1705. }
  1706. // first have to read the date time from the last record
  1707. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1708. L"select CounterDateTime from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x' and RecordIndex = %d",
  1709. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  1710. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  1711. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  1712. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7], (pLog->dwNextRecordIdToWrite - 1));
  1713. // bind the column
  1714. rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szDateTime, sizeof(szDateTime), & dwDateTimeLen);
  1715. if (! SQLSUCCEEDED(rc)) {
  1716. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  1717. goto Cleanup;
  1718. }
  1719. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1720. if (! SQLSUCCEEDED(rc)) {
  1721. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1722. goto Cleanup;
  1723. }
  1724. rc = SQLFetch(hstmt);
  1725. if (! SQLSUCCEEDED(rc)) {
  1726. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  1727. goto Cleanup;
  1728. }
  1729. // close the hstmt since we're done, and don't want more rows
  1730. SQLFreeStmt(hstmt, SQL_DROP);
  1731. hstmt = NULL;
  1732. if (SQL_NO_DATA != rc) { // if there is no data, we didn't write any rows
  1733. // allocate an hstmt
  1734. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1735. if (! SQLSUCCEEDED(rc)) {
  1736. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1737. goto Cleanup;
  1738. }
  1739. // szDateTime should have the correct date & time in it from above.
  1740. // get MinutesToUTC
  1741. //
  1742. dwReturn = GetTimeZoneInformation(& TimeZone);
  1743. if (dwReturn != TIME_ZONE_ID_INVALID) {
  1744. if (dwReturn == TIME_ZONE_ID_DAYLIGHT) {
  1745. pTimeZone = TimeZone.DaylightName;
  1746. lMinutesToUTC = TimeZone.Bias + TimeZone.DaylightBias;
  1747. }
  1748. else {
  1749. pTimeZone = TimeZone.StandardName;
  1750. lMinutesToUTC = TimeZone.Bias + TimeZone.StandardBias;
  1751. }
  1752. }
  1753. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  1754. L"update DisplayToID set LogStopTime = '%ws', NumberOfRecords = %d, MinutesToUTC = %d, TimeZoneName = '%s' where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
  1755. szDateTime, (pLog->dwNextRecordIdToWrite - 1),
  1756. lMinutesToUTC,pTimeZone,
  1757. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  1758. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  1759. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  1760. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
  1761. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1762. if (! SQLSUCCEEDED(rc)) {
  1763. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1764. goto Cleanup;
  1765. }
  1766. }
  1767. rcBCP = bcp_done(pLog->hdbcSQL);
  1768. if (rcBCP < 0) {
  1769. TRACE((PDH_DBG_TRACE_ERROR),
  1770. (__LINE__,
  1771. PDH_LOGSQL,
  1772. 0,
  1773. PDH_SQL_EXEC_DIRECT_FAILED,
  1774. TRACE_DWORD(rcBCP),
  1775. NULL));
  1776. pdhStatus = ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
  1777. }
  1778. G_FREE(pLog->lpMappedFileBase);
  1779. pLog->lpMappedFileBase = NULL;
  1780. if (pLog->pPerfmonInfo != NULL) {
  1781. PdhiFreeLogMachineTable((PPDHI_LOG_MACHINE *) (& (pLog->pPerfmonInfo)));
  1782. pLog->pPerfmonInfo = NULL;
  1783. }
  1784. pLog->dwRecord1Size = 0;
  1785. }
  1786. else if (pLog->pPerfmonInfo != NULL) {
  1787. PPDHI_SQL_LOG_INFO pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
  1788. PdhiFreeLogMachineTable((PPDHI_LOG_MACHINE *) (& pLogInfo->MachineList));
  1789. if (pLogInfo->LogData != NULL) {
  1790. DWORD dwStart = 0;
  1791. DWORD dwEnd = pLogInfo->dwMaxCounter - pLogInfo->dwMinCounter;
  1792. PPDHI_SQL_LOG_DATA * LogData = pLogInfo->LogData;
  1793. for (dwStart = 0; dwStart <= dwEnd; dwStart ++) {
  1794. if (LogData[dwStart] != NULL) G_FREE(LogData[dwStart]);
  1795. }
  1796. G_FREE(LogData);
  1797. }
  1798. G_FREE(pLog->pPerfmonInfo);
  1799. pLog->pPerfmonInfo = NULL;
  1800. }
  1801. Cleanup:
  1802. G_FREE(szSQLStmt);
  1803. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  1804. if (pLog->hdbcSQL != NULL) {
  1805. SQLDisconnect(pLog->hdbcSQL);
  1806. SQLFreeHandle(SQL_HANDLE_DBC, pLog->hdbcSQL);
  1807. }
  1808. if (pLog->henvSQL != NULL) SQLFreeHandle(SQL_HANDLE_ENV, pLog->henvSQL);
  1809. return pdhStatus;
  1810. }
  1811. PDH_FUNCTION
  1812. PdhpWriteSQLCounters(
  1813. PPDHI_LOG pLog
  1814. )
  1815. // write the CounterTable entries that are new.
  1816. // An entry might already exist for a counter from a previous run
  1817. // so the first step is to read a counter (server+object+instance name)
  1818. // and see if it exists - if so - just record the counterid in the
  1819. // PDHI_LOG structure under pLog->pQuery->pCounterListHead in the
  1820. // PDHI_COUNTER. If the counter doesn't exist - create it in SQL and
  1821. // record the counterid in the PDHI_LOG structure under
  1822. // pLog->pQuery->pCounterListHead in the PDHI_COUNTER.
  1823. {
  1824. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1825. PPDHI_COUNTER pCtrEntry;
  1826. if(NULL == pLog->pQuery) {
  1827. goto Cleanup; // no counters to process
  1828. }
  1829. pCtrEntry = pLog->pQuery->pCounterListHead;
  1830. if (pCtrEntry == NULL) {
  1831. goto Cleanup; // no counters to process
  1832. }
  1833. do {
  1834. PPDHI_LOG_COUNTER pSqlCounter = NULL;
  1835. pdhStatus = PdhiSqlBuildCounterObjectNode(pLog,
  1836. pCtrEntry->pCounterPath->szMachineName,
  1837. pCtrEntry->pCounterPath->szObjectName);
  1838. if (pdhStatus != ERROR_SUCCESS) break;
  1839. if ((pCtrEntry->dwFlags & PDHIC_MULTI_INSTANCE) == 0) {
  1840. pSqlCounter = PdhiSqlFindCounter(pLog,
  1841. (PPDHI_LOG_MACHINE *) (& (pLog->pPerfmonInfo)),
  1842. pCtrEntry->pCounterPath->szMachineName,
  1843. pCtrEntry->pCounterPath->szObjectName,
  1844. pCtrEntry->pCounterPath->szCounterName,
  1845. pCtrEntry->plCounterInfo.dwCounterType,
  1846. pCtrEntry->plCounterInfo.lDefaultScale,
  1847. pCtrEntry->pCounterPath->szInstanceName,
  1848. pCtrEntry->pCounterPath->dwIndex,
  1849. pCtrEntry->pCounterPath->szParentName,
  1850. pCtrEntry->plCounterInfo.dwParentObjectId,
  1851. pCtrEntry->TimeBase,
  1852. TRUE,
  1853. TRUE);
  1854. if (pSqlCounter != NULL) {
  1855. pCtrEntry->pBTreeNode = (LPVOID) pSqlCounter;
  1856. pCtrEntry->plCounterInfo.dwSQLCounterId = pSqlCounter->dwCounterID;
  1857. if (pSqlCounter->dwCounterType == PERF_DOUBLE_RAW) {
  1858. pSqlCounter->dwCounterType = pCtrEntry->plCounterInfo.dwCounterType;
  1859. pSqlCounter->TimeBase = pCtrEntry->TimeBase;
  1860. pdhStatus = PdhiSQLUpdateCounterDetailTimeBase(pLog,
  1861. pCtrEntry->plCounterInfo.dwSQLCounterId,
  1862. pCtrEntry->TimeBase,
  1863. TRUE);
  1864. if (pdhStatus != ERROR_SUCCESS) {
  1865. pSqlCounter->dwCounterType = PERF_DOUBLE_RAW;
  1866. pSqlCounter->TimeBase = 0;
  1867. }
  1868. }
  1869. }
  1870. }
  1871. pCtrEntry = pCtrEntry->next.flink;
  1872. }
  1873. while (pCtrEntry != pLog->pQuery->pCounterListHead); // loop thru pCtrEntry's
  1874. Cleanup:
  1875. return pdhStatus;
  1876. }
  1877. PDH_FUNCTION
  1878. PdhiWriteSQLLogHeader(
  1879. PPDHI_LOG pLog,
  1880. LPCWSTR szUserCaption
  1881. )
  1882. // there is no 'header record' in the SQL database,
  1883. // but we need to write the CounterTable entries that are new.
  1884. // use PdhpWriteSQLCounters to do that
  1885. // then write the DisplayToID record to identify this logset
  1886. {
  1887. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1888. LPWSTR szSQLStmt = NULL;
  1889. DWORD dwSQLStmt;
  1890. HSTMT hstmt = NULL;
  1891. RETCODE rc;
  1892. DBG_UNREFERENCED_PARAMETER(szUserCaption);
  1893. pdhStatus = PdhpWriteSQLCounters(pLog);
  1894. if (pLog->dwRecord1Size == 0) {
  1895. // we also need to write the DisplayToID record at this point
  1896. // allocate an hstmt
  1897. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  1898. if (! SQLSUCCEEDED(rc)) {
  1899. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  1900. goto Cleanup;
  1901. }
  1902. dwSQLStmt = MAX_PATH;
  1903. if (pLog->szCommentSQL != NULL) dwSQLStmt += lstrlenW(pLog->szCommentSQL);
  1904. if (dwSQLStmt < SQLSTMTSIZE) dwSQLStmt = SQLSTMTSIZE;
  1905. szSQLStmt = G_ALLOC(dwSQLStmt * sizeof(WCHAR));
  1906. if (szSQLStmt == NULL) {
  1907. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1908. goto Cleanup;
  1909. }
  1910. StringCchPrintfW(szSQLStmt, dwSQLStmt,
  1911. L"insert into DisplayToID values ('%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x',%d,'%ws',0,0,0,0,'')",
  1912. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  1913. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  1914. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  1915. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7],
  1916. pLog->iRunidSQL,
  1917. pLog->szCommentSQL);
  1918. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  1919. if (! SQLSUCCEEDED(rc)) {
  1920. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  1921. goto Cleanup;
  1922. }
  1923. }
  1924. Cleanup:
  1925. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  1926. G_FREE(szSQLStmt);
  1927. return pdhStatus;
  1928. }
  1929. PDH_FUNCTION
  1930. PdhiWriteOneSQLRecord(
  1931. PPDHI_LOG pLog,
  1932. PPDHI_COUNTER pCounter,
  1933. DWORD dwCounterID,
  1934. PPDH_RAW_COUNTER pThisValue,
  1935. PPDH_FMT_COUNTERVALUE pFmtValue,
  1936. SYSTEMTIME * stTimeStamp,
  1937. LPWSTR szDateTime,
  1938. DWORD dwDateTime
  1939. )
  1940. {
  1941. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1942. RETCODE rc;
  1943. SYSTEMTIME st;
  1944. PDH_FMT_COUNTERVALUE pdhValue;
  1945. PPDH_SQL_BULK_COPY pBulk = PdhiBindBulkCopyStructure(pLog);
  1946. if (pThisValue->CStatus != ERROR_SUCCESS || (pThisValue->TimeStamp.dwLowDateTime == 0
  1947. && pThisValue->TimeStamp.dwHighDateTime == 0)) {
  1948. SystemTimeToFileTime(stTimeStamp, & pThisValue->TimeStamp);
  1949. }
  1950. PdhpConvertFileTimeToSQLString(& (pThisValue->TimeStamp), szDateTime, dwDateTime);
  1951. FileTimeToSystemTime(& (pThisValue->TimeStamp), & st);
  1952. if (pBulk == NULL) {
  1953. pdhStatus = GetLastError();
  1954. goto Cleanup;
  1955. }
  1956. pBulk->dbCounterId = dwCounterID;
  1957. pBulk->dbRecordIndex = pLog->dwNextRecordIdToWrite;
  1958. pBulk->dbFirstValueA = LODWORD(pThisValue->FirstValue);
  1959. pBulk->dbFirstValueB = HIDWORD(pThisValue->FirstValue);
  1960. pBulk->dbSecondValueA = LODWORD(pThisValue->SecondValue);
  1961. pBulk->dbSecondValueB = HIDWORD(pThisValue->SecondValue);
  1962. pBulk->dbMultiCount = (pCounter->plCounterInfo.dwCounterType == PERF_DOUBLE_RAW)
  1963. ? MULTI_COUNT_DOUBLE_RAW : pThisValue->MultiCount;
  1964. StringCchPrintfA(pBulk->dbDateTime, TIME_FIELD_BUFF_SIZE,
  1965. "%04d-%02d-%02d %02d:%02d:%02d.%03d",
  1966. st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
  1967. pBulk->dbCounterValue = pFmtValue->doubleValue;
  1968. rc = bcp_sendrow(pLog->hdbcSQL);
  1969. if (rc == FAIL) {
  1970. TRACE((PDH_DBG_TRACE_ERROR),
  1971. (__LINE__,
  1972. PDH_LOGSQL,
  1973. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_STR, 2),
  1974. PDH_SQL_EXEC_DIRECT_FAILED,
  1975. TRACE_WSTR(pCounter->szFullName),
  1976. TRACE_STR(pBulk->dbDateTime),
  1977. TRACE_DWORD(pBulk->dbCounterId),
  1978. TRACE_DWORD(pBulk->dbRecordIndex),
  1979. TRACE_DWORD(rc),
  1980. TRACE_DWORD(pBulk->dwRecordCount),
  1981. NULL));
  1982. pdhStatus = ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
  1983. }
  1984. else {
  1985. pBulk->dwRecordCount ++;
  1986. if (pBulk->dwRecordCount == PDH_SQL_BULK_COPY_REC) {
  1987. DBINT rcBCP = bcp_batch(pLog->hdbcSQL);
  1988. if (rcBCP < 0) {
  1989. TRACE((PDH_DBG_TRACE_ERROR),
  1990. (__LINE__,
  1991. PDH_LOGSQL,
  1992. 0,
  1993. PDH_SQL_EXEC_DIRECT_FAILED,
  1994. TRACE_DWORD(rcBCP),
  1995. TRACE_DWORD(pBulk->dwRecordCount),
  1996. NULL));
  1997. pdhStatus = ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
  1998. }
  1999. pBulk->dwRecordCount = 0;
  2000. }
  2001. }
  2002. Cleanup:
  2003. return pdhStatus;
  2004. }
  2005. PDH_FUNCTION
  2006. PdhiWriteSQLLogRecord(
  2007. PPDHI_LOG pLog,
  2008. SYSTEMTIME *stTimeStamp,
  2009. LPCWSTR szUserString
  2010. )
  2011. // write multiple CounterData rows - one for each counter. use the
  2012. // SQLCounterID from PDHI_COUNTER, pLog->pQuery->pCounterListHead to
  2013. // get the counterid for this entry.
  2014. {
  2015. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2016. PPDHI_COUNTER pThisCounter;
  2017. LPWSTR szSQLStmt = NULL;
  2018. HSTMT hstmt = NULL;
  2019. RETCODE rc;
  2020. WCHAR szDateTime[TIME_FIELD_BUFF_SIZE];
  2021. DWORD dwReturn;
  2022. DWORD dwCounterID;
  2023. WCHAR * pTimeZone;
  2024. TIME_ZONE_INFORMATION TimeZone;
  2025. LONG lMinutesToUTC = 0;
  2026. DBINT rcBCP;
  2027. PPDH_SQL_BULK_COPY pBulk;
  2028. PDH_FMT_COUNTERVALUE PdhValue;
  2029. PPDHI_LOG_COUNTER pSqlCounter;
  2030. ULONGLONG ThisTimeStamp;
  2031. UNREFERENCED_PARAMETER(stTimeStamp);
  2032. UNREFERENCED_PARAMETER(szUserString);
  2033. // see if we've written to many records already
  2034. if (0 < pLog->llMaxSize) { // ok we have a limit
  2035. if (pLog->llMaxSize < pLog->dwNextRecordIdToWrite) {
  2036. pdhStatus = PDH_LOG_FILE_TOO_SMALL;
  2037. goto Cleanup;
  2038. }
  2039. }
  2040. // check each counter in the list of counters for this query and
  2041. // write them to the file
  2042. pThisCounter = pLog->pQuery ? pLog->pQuery->pCounterListHead : NULL;
  2043. if (pThisCounter != NULL) {
  2044. // lock the query while we read the data so the values
  2045. // written to the log will all be from the same sample
  2046. WAIT_FOR_AND_LOCK_MUTEX(pThisCounter->pOwner->hMutex);
  2047. do {
  2048. if ((pThisCounter->dwFlags & PDHIC_MULTI_INSTANCE) != 0) {
  2049. DWORD dwSize;
  2050. DWORD dwItem;
  2051. if (pThisCounter->pLastObject != NULL && pThisCounter->pLastObject != pThisCounter->pThisObject) {
  2052. G_FREE(pThisCounter->pLastObject);
  2053. }
  2054. pThisCounter->pLastObject = pThisCounter->pThisObject;
  2055. pThisCounter->LastValue.MultiCount = pThisCounter->ThisValue.MultiCount;
  2056. pThisCounter->pThisObject = NULL;
  2057. pThisCounter->ThisValue.MultiCount = 0;
  2058. dwSize = 0;
  2059. pdhStatus = PDH_MORE_DATA;
  2060. while (pdhStatus == PDH_MORE_DATA) {
  2061. pdhStatus = PdhiSqlGetCounterArray(
  2062. pThisCounter, & dwSize, & dwItem, (LPVOID) pThisCounter->pThisObject);
  2063. if (pdhStatus == PDH_MORE_DATA) {
  2064. LPVOID pTemp = pThisCounter->pThisObject;
  2065. if (pTemp != NULL) {
  2066. pThisCounter->pThisObject = G_REALLOC(pTemp, dwSize);
  2067. if (pThisCounter->pThisObject == NULL) {
  2068. G_FREE(pTemp);
  2069. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2070. }
  2071. }
  2072. else {
  2073. pThisCounter->pThisObject = G_ALLOC(dwSize);
  2074. if (pThisCounter->pThisObject == NULL) {
  2075. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2076. }
  2077. }
  2078. }
  2079. }
  2080. if (pdhStatus == ERROR_SUCCESS) {
  2081. PPDH_RAW_COUNTER pRawValue;
  2082. PPDH_FMT_COUNTERVALUE_ITEM_W pFmtValue;
  2083. DWORD dwNewName = 0;
  2084. DWORD dwCurrentName = 0;
  2085. DWORD dwInstanceName = 0;
  2086. DWORD dwParentName = 0;
  2087. DWORD dwInstanceIndex = 0;
  2088. LPWSTR szInstanceName = NULL;
  2089. LPWSTR szParentName = NULL;
  2090. LPWSTR szTmp;
  2091. pThisCounter->ThisValue.MultiCount = dwItem;
  2092. pRawValue = (PPDH_RAW_COUNTER) (pThisCounter->pThisObject);
  2093. pFmtValue = (PPDH_FMT_COUNTERVALUE_ITEM_W)
  2094. (((LPBYTE) pThisCounter->pThisObject) + sizeof(PDH_RAW_COUNTER) * dwItem);
  2095. for (dwSize = 0; dwSize < dwItem; dwSize ++) {
  2096. dwNewName = lstrlenW(pFmtValue->szName) + 1;
  2097. if (dwNewName > dwCurrentName) {
  2098. if (dwNewName < MAX_PATH) {
  2099. dwNewName = MAX_PATH;
  2100. }
  2101. dwCurrentName = dwNewName;
  2102. if (szInstanceName == NULL) {
  2103. szInstanceName = G_ALLOC(sizeof(WCHAR) * dwNewName);
  2104. }
  2105. else {
  2106. szTmp = szInstanceName;
  2107. szInstanceName = G_REALLOC(szTmp, sizeof(WCHAR) * dwNewName);
  2108. if (szInstanceName == NULL) {
  2109. G_FREE(szTmp);
  2110. }
  2111. }
  2112. if (szParentName == NULL) {
  2113. szParentName = G_ALLOC(sizeof(WCHAR) * dwNewName);
  2114. }
  2115. else {
  2116. szTmp = szParentName;
  2117. szParentName = G_REALLOC(szTmp, sizeof(WCHAR) * dwNewName);
  2118. if (szParentName == NULL) {
  2119. G_FREE(szTmp);
  2120. }
  2121. }
  2122. }
  2123. if (szInstanceName != NULL && szParentName != NULL) {
  2124. dwInstanceName = dwParentName = dwCurrentName;
  2125. dwInstanceIndex = 0;
  2126. PdhParseInstanceNameW(pFmtValue->szName,
  2127. szInstanceName,
  2128. & dwInstanceName,
  2129. szParentName,
  2130. & dwParentName,
  2131. & dwInstanceIndex);
  2132. pSqlCounter = PdhiSqlFindCounter(pLog,
  2133. (PPDHI_LOG_MACHINE *) (& (pLog->pPerfmonInfo)),
  2134. pThisCounter->pCounterPath->szMachineName,
  2135. pThisCounter->pCounterPath->szObjectName,
  2136. pThisCounter->pCounterPath->szCounterName,
  2137. pThisCounter->plCounterInfo.dwCounterType,
  2138. pThisCounter->plCounterInfo.lDefaultScale,
  2139. szInstanceName,
  2140. dwInstanceIndex,
  2141. szParentName,
  2142. pThisCounter->plCounterInfo.dwParentObjectId,
  2143. pThisCounter->TimeBase,
  2144. FALSE,
  2145. TRUE);
  2146. ThisTimeStamp = MAKELONGLONG(pRawValue->TimeStamp.dwLowDateTime,
  2147. pRawValue->TimeStamp.dwHighDateTime);
  2148. if (pSqlCounter != NULL) {
  2149. if (pSqlCounter->dwCounterType == PERF_DOUBLE_RAW) {
  2150. pSqlCounter->dwCounterType = pThisCounter->plCounterInfo.dwCounterType;
  2151. pSqlCounter->TimeBase = pThisCounter->TimeBase;
  2152. pdhStatus = PdhiSQLUpdateCounterDetailTimeBase(pLog,
  2153. pSqlCounter->dwCounterID,
  2154. pThisCounter->TimeBase,
  2155. FALSE);
  2156. if (pdhStatus != ERROR_SUCCESS) {
  2157. pSqlCounter->dwCounterType = PERF_DOUBLE_RAW;
  2158. pSqlCounter->TimeBase = 0;
  2159. }
  2160. }
  2161. if (pSqlCounter->TimeStamp < ThisTimeStamp) {
  2162. dwCounterID = pSqlCounter->dwCounterID;
  2163. pSqlCounter->TimeStamp = ThisTimeStamp;
  2164. if (dwCounterID == 0) {
  2165. TRACE((PDH_DBG_TRACE_WARNING),
  2166. (__LINE__,
  2167. PDH_LOGSQL,
  2168. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_WSTR, 3),
  2169. ERROR_SUCCESS,
  2170. TRACE_WSTR(pThisCounter->pCounterPath->szCounterName),
  2171. TRACE_WSTR(szInstanceName),
  2172. TRACE_WSTR(szParentName),
  2173. TRACE_DWORD(dwInstanceIndex),
  2174. NULL));
  2175. }
  2176. pdhStatus = PdhiWriteOneSQLRecord(pLog,
  2177. pThisCounter,
  2178. dwCounterID,
  2179. pRawValue,
  2180. & (pFmtValue->FmtValue),
  2181. stTimeStamp,
  2182. szDateTime, TIME_FIELD_BUFF_SIZE);
  2183. }
  2184. else {
  2185. TRACE((PDH_DBG_TRACE_WARNING),
  2186. (__LINE__,
  2187. PDH_LOGSQL,
  2188. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_ULONG64, 3),
  2189. ERROR_SUCCESS,
  2190. TRACE_WSTR(pThisCounter->szFullName),
  2191. TRACE_WSTR(szInstanceName),
  2192. TRACE_LONG64(ThisTimeStamp),
  2193. TRACE_DWORD(pThisCounter->plCounterInfo.dwSQLCounterId),
  2194. NULL));
  2195. }
  2196. }
  2197. else {
  2198. TRACE((PDH_DBG_TRACE_WARNING),
  2199. (__LINE__,
  2200. PDH_LOGSQL,
  2201. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_ULONG64, 3),
  2202. ERROR_SUCCESS,
  2203. TRACE_WSTR(pThisCounter->szFullName),
  2204. TRACE_WSTR(szInstanceName),
  2205. TRACE_LONG64(ThisTimeStamp),
  2206. NULL));
  2207. }
  2208. }
  2209. else {
  2210. G_FREE(szInstanceName);
  2211. G_FREE(szParentName);
  2212. szInstanceName = szParentName = NULL;
  2213. dwCurrentName = dwNewName = 0;
  2214. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2215. }
  2216. pRawValue = (PPDH_RAW_COUNTER)
  2217. (((LPBYTE) pRawValue) + sizeof(PDH_RAW_COUNTER));
  2218. pFmtValue = (PPDH_FMT_COUNTERVALUE_ITEM_W)
  2219. (((LPBYTE) pFmtValue) + sizeof(PDH_FMT_COUNTERVALUE_ITEM_W));
  2220. }
  2221. G_FREE(szInstanceName);
  2222. G_FREE(szParentName);
  2223. }
  2224. }
  2225. else {
  2226. pSqlCounter = (PPDHI_LOG_COUNTER) pThisCounter->pBTreeNode;
  2227. ThisTimeStamp = MAKELONGLONG(pThisCounter->ThisValue.TimeStamp.dwLowDateTime,
  2228. pThisCounter->ThisValue.TimeStamp.dwHighDateTime);
  2229. if (pSqlCounter != NULL) {
  2230. if (pSqlCounter->TimeStamp < ThisTimeStamp) {
  2231. dwCounterID = pThisCounter->plCounterInfo.dwSQLCounterId;
  2232. pSqlCounter->TimeStamp = ThisTimeStamp;
  2233. pdhStatus = PdhiComputeFormattedValue(pThisCounter->CalcFunc,
  2234. pThisCounter->plCounterInfo.dwCounterType,
  2235. pThisCounter->lScale,
  2236. PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
  2237. & (pThisCounter->ThisValue),
  2238. & (pThisCounter->LastValue),
  2239. & (pThisCounter->TimeBase),
  2240. 0L,
  2241. & PdhValue);
  2242. if ((pdhStatus != ERROR_SUCCESS) || ( (PdhValue.CStatus != PDH_CSTATUS_VALID_DATA)
  2243. && (PdhValue.CStatus != PDH_CSTATUS_NEW_DATA))) {
  2244. PdhValue.doubleValue = 0.0;
  2245. }
  2246. if (dwCounterID == 0) {
  2247. TRACE((PDH_DBG_TRACE_WARNING),
  2248. (__LINE__,
  2249. PDH_LOGSQL,
  2250. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_WSTR, 3),
  2251. ERROR_SUCCESS,
  2252. TRACE_WSTR(pThisCounter->pCounterPath->szCounterName),
  2253. TRACE_WSTR(pThisCounter->pCounterPath->szInstanceName),
  2254. TRACE_WSTR(pThisCounter->pCounterPath->szParentName),
  2255. TRACE_DWORD(pThisCounter->pCounterPath->dwIndex),
  2256. NULL));
  2257. }
  2258. pdhStatus = PdhiWriteOneSQLRecord(pLog,
  2259. pThisCounter,
  2260. dwCounterID,
  2261. & (pThisCounter->ThisValue),
  2262. & PdhValue,
  2263. stTimeStamp,
  2264. szDateTime, TIME_FIELD_BUFF_SIZE);
  2265. }
  2266. else {
  2267. TRACE((PDH_DBG_TRACE_WARNING),
  2268. (__LINE__,
  2269. PDH_LOGSQL,
  2270. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_ULONG64, 2),
  2271. ERROR_SUCCESS,
  2272. TRACE_WSTR(pThisCounter->szFullName),
  2273. TRACE_LONG64(ThisTimeStamp),
  2274. TRACE_DWORD(pThisCounter->plCounterInfo.dwSQLCounterId),
  2275. NULL));
  2276. }
  2277. }
  2278. else {
  2279. TRACE((PDH_DBG_TRACE_WARNING),
  2280. (__LINE__,
  2281. PDH_LOGSQL,
  2282. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_ULONG64, 2),
  2283. ERROR_SUCCESS,
  2284. TRACE_WSTR(pThisCounter->szFullName),
  2285. TRACE_LONG64(ThisTimeStamp),
  2286. NULL));
  2287. }
  2288. }
  2289. pThisCounter = pThisCounter->next.flink; // go to next in list
  2290. }
  2291. while (pThisCounter != pLog->pQuery->pCounterListHead);
  2292. // free (i.e. unlock) the query
  2293. rcBCP = bcp_batch(pLog->hdbcSQL);
  2294. if (rcBCP < 0) {
  2295. pBulk = (PPDH_SQL_BULK_COPY) pLog->lpMappedFileBase;
  2296. if (pBulk != NULL) {
  2297. TRACE((PDH_DBG_TRACE_WARNING),
  2298. (__LINE__,
  2299. PDH_LOGSQL,
  2300. 0,
  2301. PDH_SQL_EXEC_DIRECT_FAILED,
  2302. TRACE_DWORD(rcBCP),
  2303. TRACE_DWORD(pBulk->dwRecordCount),
  2304. NULL));
  2305. pBulk->dwRecordCount = 0;
  2306. }
  2307. pdhStatus = ReportSQLError(pLog, SQL_ERROR, NULL, PDH_SQL_EXEC_DIRECT_FAILED);
  2308. }
  2309. RELEASE_MUTEX(pThisCounter->pOwner->hMutex);
  2310. pLog->dwNextRecordIdToWrite++;
  2311. }
  2312. szSQLStmt = (LPWSTR) G_ALLOC(SQLSTMTSIZE * sizeof(WCHAR));
  2313. if (szSQLStmt == NULL) {
  2314. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2315. goto Cleanup;
  2316. }
  2317. // if this is the first record then save the start time in DisplayToID
  2318. // we also need to write the DisplayToID record at this point (we just incremented
  2319. // so check for 2)
  2320. if (2 == pLog->dwNextRecordIdToWrite) {
  2321. // allocate an hstmt
  2322. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  2323. if (! SQLSUCCEEDED(rc)) {
  2324. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  2325. }
  2326. else {
  2327. // szDateTime should have the correct date & time in it from above.
  2328. // get MinutesToUTC
  2329. //
  2330. dwReturn = GetTimeZoneInformation(& TimeZone);
  2331. if (dwReturn != TIME_ZONE_ID_INVALID) {
  2332. if (dwReturn == TIME_ZONE_ID_DAYLIGHT) {
  2333. pTimeZone = TimeZone.DaylightName;
  2334. lMinutesToUTC = TimeZone.Bias + TimeZone.DaylightBias;
  2335. }
  2336. else {
  2337. pTimeZone = TimeZone.StandardName;
  2338. lMinutesToUTC = TimeZone.Bias + TimeZone.StandardBias;
  2339. }
  2340. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  2341. L"update DisplayToID set LogStartTime = '%ws', MinutesToUTC = %d, TimeZoneName = '%ws' where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
  2342. szDateTime, lMinutesToUTC,pTimeZone,
  2343. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  2344. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  2345. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  2346. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
  2347. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  2348. if (! SQLSUCCEEDED(rc)) {
  2349. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  2350. }
  2351. SQLFreeStmt(hstmt, SQL_DROP);
  2352. }
  2353. else {
  2354. pdhStatus = PDH_LOG_FILE_CREATE_ERROR;
  2355. }
  2356. }
  2357. }
  2358. if (pdhStatus == ERROR_SUCCESS) {
  2359. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  2360. if (! SQLSUCCEEDED(rc)) {
  2361. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  2362. }
  2363. else {
  2364. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  2365. L"update DisplayToID set LogStopTime = '%ws', NumberOfRecords = %d where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
  2366. szDateTime,
  2367. (pLog->dwNextRecordIdToWrite - 1),
  2368. pLog->guidSQL.Data1,
  2369. pLog->guidSQL.Data2,
  2370. pLog->guidSQL.Data3,
  2371. pLog->guidSQL.Data4[0],
  2372. pLog->guidSQL.Data4[1],
  2373. pLog->guidSQL.Data4[2],
  2374. pLog->guidSQL.Data4[3],
  2375. pLog->guidSQL.Data4[4],
  2376. pLog->guidSQL.Data4[5],
  2377. pLog->guidSQL.Data4[6],
  2378. pLog->guidSQL.Data4[7]);
  2379. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  2380. if (! SQLSUCCEEDED(rc)) {
  2381. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  2382. }
  2383. SQLFreeStmt(hstmt, SQL_DROP);
  2384. }
  2385. }
  2386. Cleanup:
  2387. G_FREE(szSQLStmt);
  2388. return pdhStatus;
  2389. }
  2390. PDH_FUNCTION
  2391. PdhiEnumMachinesFromSQLLog(
  2392. PPDHI_LOG pLog,
  2393. LPVOID pBuffer,
  2394. LPDWORD lpdwBufferSize,
  2395. BOOL bUnicodeDest
  2396. )
  2397. {
  2398. PDH_STATUS Status = ERROR_SUCCESS;
  2399. Status = PdhpGetSQLLogHeader(pLog);
  2400. if (Status == ERROR_SUCCESS) {
  2401. PPDHI_SQL_LOG_INFO pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
  2402. if (pLogInfo == NULL) {
  2403. Status = PDH_LOG_FILE_OPEN_ERROR;
  2404. }
  2405. else {
  2406. Status = PdhiEnumCachedMachines(pLogInfo->MachineList, pBuffer, lpdwBufferSize, bUnicodeDest);
  2407. }
  2408. }
  2409. return Status;
  2410. }
  2411. PDH_FUNCTION
  2412. PdhiEnumObjectsFromSQLLog(
  2413. PPDHI_LOG pLog,
  2414. LPCWSTR szMachineName,
  2415. LPVOID pBuffer,
  2416. LPDWORD lpdwBufferSize,
  2417. DWORD dwDetailLevel,
  2418. BOOL bUnicodeDest
  2419. )
  2420. {
  2421. PDH_STATUS Status = ERROR_SUCCESS;
  2422. Status = PdhpGetSQLLogHeader(pLog);
  2423. if (Status == ERROR_SUCCESS) {
  2424. PPDHI_SQL_LOG_INFO pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
  2425. if (pLogInfo == NULL) {
  2426. Status = PDH_LOG_FILE_OPEN_ERROR;
  2427. }
  2428. else {
  2429. Status = PdhiEnumCachedObjects(
  2430. pLogInfo->MachineList, szMachineName, pBuffer, lpdwBufferSize, dwDetailLevel, bUnicodeDest);
  2431. }
  2432. }
  2433. return Status;
  2434. }
  2435. PDH_FUNCTION
  2436. PdhiEnumObjectItemsFromSQLLog(
  2437. PPDHI_LOG pLog,
  2438. LPCWSTR szMachineName,
  2439. LPCWSTR szObjectName,
  2440. PDHI_COUNTER_TABLE CounterTable,
  2441. DWORD dwDetailLevel,
  2442. DWORD dwFlags
  2443. )
  2444. {
  2445. PDH_STATUS Status = ERROR_SUCCESS;
  2446. Status = PdhpGetSQLLogHeader(pLog);
  2447. if (Status == ERROR_SUCCESS) {
  2448. PPDHI_SQL_LOG_INFO pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
  2449. if (pLogInfo == NULL) {
  2450. Status = PDH_LOG_FILE_OPEN_ERROR;
  2451. }
  2452. else {
  2453. Status = PdhiEnumCachedObjectItems(
  2454. pLogInfo->MachineList, szMachineName, szObjectName, CounterTable, dwDetailLevel, dwFlags);
  2455. }
  2456. }
  2457. return Status;
  2458. }
  2459. PDH_FUNCTION
  2460. PdhiGetMatchingSQLLogRecord(
  2461. PPDHI_LOG pLog,
  2462. LONGLONG * pStartTime,
  2463. LPDWORD pdwIndex
  2464. )
  2465. {
  2466. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2467. LPWSTR szSQLStmt = NULL;
  2468. HSTMT hstmt = NULL;
  2469. RETCODE rc;
  2470. DWORD dwRecordIndex;
  2471. LONGLONG locStartTime = (* pStartTime) - 10;
  2472. WCHAR szStartDate[TIME_FIELD_BUFF_SIZE];
  2473. szSQLStmt = (LPWSTR) G_ALLOC(SQLSTMTSIZE * sizeof(WCHAR));
  2474. if (szSQLStmt == NULL) {
  2475. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2476. goto Cleanup;
  2477. }
  2478. PdhpConvertFileTimeToSQLString((LPFILETIME) (& locStartTime), szStartDate, TIME_FIELD_BUFF_SIZE);
  2479. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  2480. L"select MIN(RecordIndex) from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x' and CounterDateTime >= '%ws'",
  2481. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  2482. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  2483. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  2484. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7], szStartDate);
  2485. // allocate an hstmt
  2486. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  2487. if (! SQLSUCCEEDED(rc)) {
  2488. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  2489. goto Cleanup;
  2490. }
  2491. rc = SQLBindCol(hstmt, 1, SQL_C_LONG, & dwRecordIndex, 0, NULL);
  2492. if (! SQLSUCCEEDED(rc)) {
  2493. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2494. goto Cleanup;
  2495. }
  2496. // execute the select statement
  2497. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  2498. if (! SQLSUCCEEDED(rc)) {
  2499. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  2500. goto Cleanup;
  2501. }
  2502. rc = SQLFetch(hstmt);
  2503. if (! SQLSUCCEEDED(rc)) {
  2504. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  2505. goto Cleanup;
  2506. }
  2507. if (SQL_NO_DATA == rc) {
  2508. pdhStatus = PDH_NO_DATA;
  2509. goto Cleanup;
  2510. }
  2511. pLog->dwLastRecordRead = dwRecordIndex;
  2512. * pdwIndex = dwRecordIndex;
  2513. Cleanup:
  2514. if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
  2515. G_FREE(szSQLStmt);
  2516. return pdhStatus;
  2517. }
  2518. PDH_FUNCTION
  2519. PdhiBuildCounterCacheFromSQLLog(
  2520. PPDHI_LOG pLog,
  2521. PPDHI_SQL_LOG_INFO pLogInfo,
  2522. DWORD dwIndex
  2523. )
  2524. {
  2525. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2526. PPDHI_QUERY pQuery = NULL;
  2527. PPDHI_COUNTER pCounter = NULL;
  2528. DWORD dwRequest = 0;
  2529. DWORD dwIncrease = 0;
  2530. DWORD dwTotal = 0;
  2531. LPWSTR szSQLStmt = NULL;
  2532. LPWSTR szCurrent;
  2533. HSTMT hstmt = NULL;
  2534. RETCODE rc;
  2535. FILETIME ftCounterDateTime;
  2536. BOOL bCounterDateTime = FALSE;
  2537. DWORD dwCounterId;
  2538. LARGE_INTEGER i64FirstValue;
  2539. LARGE_INTEGER i64SecondValue;
  2540. DWORD dwMultiCount;
  2541. DOUBLE dCounterValue = 0.0;
  2542. WCHAR szCounterDateTime[TIME_FIELD_BUFF_SIZE];
  2543. SQLLEN dwCounterIdSize = 0;
  2544. SQLLEN dwLowFirstValueSize = 0;
  2545. SQLLEN dwHighFirstValueSize = 0;
  2546. SQLLEN dwLowSecondValueSize = 0;
  2547. SQLLEN dwHighSecondValueSize = 0;
  2548. SQLLEN dwMultiCountSize = 0;
  2549. SQLLEN dwCounterValueSize = 0;
  2550. SQLLEN dwDateTimeSize = 0;
  2551. PPDHI_SQL_LOG_DATA pLogData;
  2552. BOOL bNewStmt;
  2553. BOOL bQueryNow;
  2554. if (pLogInfo->dwRunId == dwIndex) {
  2555. return ERROR_SUCCESS;
  2556. }
  2557. else if (dwIndex >= pLog->dwNextRecordIdToWrite) {
  2558. return PDH_NO_MORE_DATA;
  2559. }
  2560. else {
  2561. pQuery = pLog->pQuery;
  2562. if (pQuery == NULL) return PDH_INVALID_HANDLE;
  2563. }
  2564. pCounter = pQuery->pCounterListHead;
  2565. if (pCounter == NULL) goto Cleanup;
  2566. szSQLStmt = (LPWSTR) G_ALLOC(SQLSTMTSIZE * sizeof(WCHAR));
  2567. if (szSQLStmt == NULL) {
  2568. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2569. goto Cleanup;
  2570. }
  2571. bNewStmt = TRUE;
  2572. bQueryNow = FALSE;
  2573. do {
  2574. if (bNewStmt) {
  2575. ZeroMemory(szSQLStmt, SQLSTMTSIZE * sizeof(WCHAR));
  2576. szCurrent = szSQLStmt;
  2577. StringCchPrintfW(szCurrent, SQLSTMTSIZE,
  2578. L"select CounterID, FirstValueA, FirstValueB, SecondValueA, SecondValueB, MultiCount, CounterDateTime, CounterValue from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x' and RecordIndex = %d and CounterID IN (",
  2579. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  2580. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  2581. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  2582. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7],
  2583. dwIndex);
  2584. dwTotal = lstrlenW(szCurrent);
  2585. szCurrent = szSQLStmt + dwTotal;
  2586. StringCchPrintfW(szCurrent, SQLSTMTSIZE - dwTotal, L"%d", pCounter->plCounterInfo.dwSQLCounterId);
  2587. dwIncrease = lstrlenW(szCurrent);
  2588. bNewStmt = FALSE;
  2589. bQueryNow = FALSE;
  2590. }
  2591. else if (dwTotal + SQL_COUNTER_ID_SIZE < SQLSTMTSIZE) {
  2592. szCurrent = szSQLStmt + dwTotal;
  2593. StringCchPrintfW(szCurrent, SQLSTMTSIZE - dwTotal, L",%d", pCounter->plCounterInfo.dwSQLCounterId);
  2594. dwIncrease = lstrlenW(szCurrent);
  2595. }
  2596. else {
  2597. bQueryNow = TRUE;
  2598. dwIncrease = 0;
  2599. }
  2600. pCounter = pCounter->next.flink;
  2601. dwTotal += dwIncrease;
  2602. if (bQueryNow != TRUE && pCounter != NULL && pCounter != pQuery->pCounterListHead) continue;
  2603. szCurrent = szSQLStmt + dwTotal;
  2604. StringCchCopyW(szCurrent, SQLSTMTSIZE - dwTotal, L")");
  2605. dwIncrease = lstrlenW(szCurrent);
  2606. bNewStmt = TRUE;
  2607. bQueryNow = FALSE;
  2608. // allocate an hstmt
  2609. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  2610. if (! SQLSUCCEEDED(rc)) {
  2611. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  2612. goto Cleanup;
  2613. }
  2614. // bind the columns
  2615. rc = SQLBindCol(hstmt, 1, SQL_C_LONG, & dwCounterId, 0, & dwCounterIdSize);
  2616. if (! SQLSUCCEEDED(rc)) {
  2617. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2618. goto Cleanup;
  2619. }
  2620. rc = SQLBindCol(hstmt, 2, SQL_C_LONG, & i64FirstValue.LowPart, 0, & dwLowFirstValueSize);
  2621. if (! SQLSUCCEEDED(rc)) {
  2622. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2623. goto Cleanup;
  2624. }
  2625. rc = SQLBindCol(hstmt, 3, SQL_C_LONG, & i64FirstValue.HighPart, 0, & dwHighFirstValueSize);
  2626. if (! SQLSUCCEEDED(rc)) {
  2627. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2628. goto Cleanup;
  2629. }
  2630. rc = SQLBindCol(hstmt, 4, SQL_C_LONG, & i64SecondValue.LowPart, 0, & dwLowSecondValueSize);
  2631. if (! SQLSUCCEEDED(rc)) {
  2632. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2633. goto Cleanup;
  2634. }
  2635. rc = SQLBindCol(hstmt, 5, SQL_C_LONG, & i64SecondValue.HighPart, 0, & dwHighSecondValueSize);
  2636. if (! SQLSUCCEEDED(rc)) {
  2637. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2638. goto Cleanup;
  2639. }
  2640. rc = SQLBindCol(hstmt, 6, SQL_C_LONG, & dwMultiCount, 0, & dwMultiCountSize);
  2641. if (! SQLSUCCEEDED(rc)) {
  2642. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2643. goto Cleanup;
  2644. }
  2645. rc = SQLBindCol(hstmt, 7, SQL_C_WCHAR, szCounterDateTime, sizeof(szCounterDateTime), & dwDateTimeSize);
  2646. if (! SQLSUCCEEDED(rc)) {
  2647. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2648. goto Cleanup;
  2649. }
  2650. rc = SQLBindCol(hstmt, 8, SQL_C_DOUBLE, & dCounterValue, 0, & dwCounterValueSize);
  2651. if (! SQLSUCCEEDED(rc)) {
  2652. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2653. goto Cleanup;
  2654. }
  2655. // execute the select statement
  2656. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  2657. if (! SQLSUCCEEDED(rc)) {
  2658. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  2659. goto Cleanup;
  2660. }
  2661. rc = SQLFetch(hstmt);
  2662. while (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
  2663. PdhpConvertSQLStringToFileTime(szCounterDateTime, & ftCounterDateTime);
  2664. bCounterDateTime = TRUE;
  2665. if (dwCounterId >= pLogInfo->dwMinCounter && dwCounterId <= pLogInfo->dwMaxCounter) {
  2666. pLogData = pLogInfo->LogData[dwCounterId - pLogInfo->dwMinCounter];
  2667. if (pLogData == NULL) {
  2668. pLogData = (PPDHI_SQL_LOG_DATA) G_ALLOC(sizeof(PDHI_SQL_LOG_DATA));
  2669. if (pLogData != NULL) {
  2670. pLogInfo->LogData[dwCounterId - pLogInfo->dwMinCounter] = pLogData;
  2671. }
  2672. else {
  2673. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2674. goto Cleanup;
  2675. }
  2676. }
  2677. pLogData->dwRunId = dwIndex;
  2678. pLogData->RawData.CStatus = PDH_CSTATUS_VALID_DATA;
  2679. pLogData->RawData.FirstValue = i64FirstValue.QuadPart;
  2680. pLogData->RawData.MultiCount = dwMultiCount;
  2681. pLogData->RawData.SecondValue = i64SecondValue.QuadPart;
  2682. pLogData->dFormattedValue = dCounterValue;
  2683. pLogData->RawData.TimeStamp = ftCounterDateTime;
  2684. }
  2685. rc = SQLFetch(hstmt);
  2686. }
  2687. if (SQL_NO_DATA == rc) {
  2688. }
  2689. else if (! SQLSUCCEEDED(rc)) {
  2690. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  2691. goto Cleanup;
  2692. }
  2693. if (hstmt) {
  2694. SQLFreeStmt(hstmt, SQL_DROP);
  2695. hstmt = NULL;
  2696. }
  2697. }
  2698. while (pCounter != NULL && pCounter != pQuery->pCounterListHead);
  2699. if (bCounterDateTime) {
  2700. pLogInfo->dwRunId = dwIndex;
  2701. pLogInfo->RecordTime = ftCounterDateTime;
  2702. }
  2703. Cleanup:
  2704. if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
  2705. G_FREE(szSQLStmt);
  2706. return pdhStatus;
  2707. }
  2708. PDH_FUNCTION
  2709. PdhiGetCounterValueFromSQLLog(
  2710. PPDHI_LOG pLog,
  2711. DWORD dwIndex,
  2712. PPDHI_COUNTER pCounter,
  2713. PPDH_RAW_COUNTER pValue
  2714. )
  2715. {
  2716. PDH_STATUS Status = ERROR_SUCCESS;
  2717. PPDHI_SQL_LOG_INFO pLogInfo = NULL;
  2718. DWORD dwCtrIndex = 0;
  2719. PPDHI_SQL_LOG_DATA pLogData = NULL;
  2720. Status = PdhpGetSQLLogHeader(pLog);
  2721. if (Status != ERROR_SUCCESS) goto Cleanup;
  2722. pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
  2723. if (pLogInfo == NULL) {
  2724. Status = PDH_LOG_FILE_OPEN_ERROR;
  2725. goto Cleanup;
  2726. }
  2727. Status = PdhiBuildCounterCacheFromSQLLog(pLog, pLogInfo, dwIndex);
  2728. if (Status != ERROR_SUCCESS) goto Cleanup;
  2729. dwCtrIndex = pCounter->plCounterInfo.dwSQLCounterId;
  2730. if (dwCtrIndex >= pLogInfo->dwMinCounter && dwCtrIndex <= pLogInfo->dwMaxCounter) {
  2731. pLogData = pLogInfo->LogData[dwCtrIndex - pLogInfo->dwMinCounter];
  2732. if (pLogData != NULL && pLogData->dwRunId == dwIndex) {
  2733. RtlCopyMemory(pValue, & pLogData->RawData, sizeof(PDH_RAW_COUNTER));
  2734. if (pLogData->RawData.MultiCount == MULTI_COUNT_DOUBLE_RAW) {
  2735. pCounter->plCounterInfo.dwCounterType = PERF_DOUBLE_RAW;
  2736. pValue->MultiCount = 1;
  2737. }
  2738. else if (pCounter->plCounterInfo.dwCounterType == PERF_DOUBLE_RAW) {
  2739. (double) pValue->FirstValue = pLogData->dFormattedValue;
  2740. pValue->SecondValue = 0;
  2741. pValue->MultiCount = 1;
  2742. }
  2743. }
  2744. else {
  2745. pValue->CStatus = PDH_CSTATUS_INVALID_DATA;
  2746. pValue->TimeStamp = pLogInfo->RecordTime;
  2747. pValue->FirstValue = 0;
  2748. pValue->SecondValue = 0;
  2749. pValue->MultiCount = 1;
  2750. }
  2751. }
  2752. else {
  2753. Status = PDH_CSTATUS_NO_COUNTER;
  2754. }
  2755. Cleanup:
  2756. return Status;
  2757. }
  2758. PDH_FUNCTION
  2759. PdhiGetTimeRangeFromSQLLog(
  2760. PPDHI_LOG pLog,
  2761. LPDWORD pdwNumEntries,
  2762. PPDH_TIME_INFO pInfo,
  2763. LPDWORD pdwBufferSize
  2764. )
  2765. {
  2766. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2767. LONGLONG llStartTime = MAX_TIME_VALUE;
  2768. LONGLONG llEndTime = MIN_TIME_VALUE;
  2769. SQLLEN dwStartTimeStat;
  2770. SQLLEN dwEndTimeStat;
  2771. HSTMT hstmt = NULL;
  2772. RETCODE rc;
  2773. WCHAR szStartTime[TIME_FIELD_BUFF_SIZE];
  2774. WCHAR szEndTime[TIME_FIELD_BUFF_SIZE];
  2775. DWORD dwNumberOfRecords;
  2776. SQLLEN dwNumRecStat;
  2777. LPWSTR szSQLStmt = NULL;
  2778. szSQLStmt = (LPWSTR) G_ALLOC(SQLSTMTSIZE * sizeof(WCHAR));
  2779. if (szSQLStmt == NULL) {
  2780. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2781. goto Cleanup;
  2782. }
  2783. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  2784. L"select LogStartTime, LogStopTime, NumberOfRecords from DisplayToID where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
  2785. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  2786. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  2787. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  2788. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
  2789. // allocate an hstmt
  2790. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  2791. if (! SQLSUCCEEDED(rc)) {
  2792. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  2793. goto Cleanup;
  2794. }
  2795. // bind the date columns column
  2796. rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szStartTime, TIME_FIELD_BUFF_SIZE * sizeof(WCHAR), & dwStartTimeStat);
  2797. if (! SQLSUCCEEDED(rc)) {
  2798. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2799. goto Cleanup;
  2800. }
  2801. rc = SQLBindCol(hstmt, 2, SQL_C_WCHAR, szEndTime, TIME_FIELD_BUFF_SIZE * sizeof(WCHAR), & dwEndTimeStat);
  2802. if (! SQLSUCCEEDED(rc)) {
  2803. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2804. goto Cleanup;
  2805. }
  2806. rc = SQLBindCol(hstmt, 3, SQL_C_LONG, &dwNumberOfRecords, 0, & dwNumRecStat);
  2807. if (! SQLSUCCEEDED(rc)) {
  2808. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2809. goto Cleanup;
  2810. }
  2811. // execute the select statement
  2812. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  2813. if (! SQLSUCCEEDED(rc)) {
  2814. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  2815. goto Cleanup;
  2816. }
  2817. rc = SQLFetch(hstmt);
  2818. if (SQL_NO_DATA == rc) {
  2819. pdhStatus = PDH_NO_DATA;
  2820. goto Cleanup;
  2821. }
  2822. // if anything is missing - could try and re-create from existing log file
  2823. if (SQL_NULL_DATA == dwStartTimeStat || SQL_NULL_DATA == dwEndTimeStat || SQL_NULL_DATA == dwNumRecStat) {
  2824. pdhStatus = PDH_INVALID_DATA;
  2825. goto Cleanup;
  2826. }
  2827. // convert the dates
  2828. PdhpConvertSQLStringToFileTime(szStartTime, (LPFILETIME) & llStartTime);
  2829. PdhpConvertSQLStringToFileTime(szEndTime, (LPFILETIME) & llEndTime);
  2830. // we have the info so update the args.
  2831. if (* pdwBufferSize >= sizeof(PDH_TIME_INFO)) {
  2832. * (LONGLONG *) (& pInfo->StartTime) = llStartTime;
  2833. * (LONGLONG *) (& pInfo->EndTime) = llEndTime;
  2834. pInfo->SampleCount = dwNumberOfRecords;
  2835. * pdwBufferSize = sizeof(PDH_TIME_INFO);
  2836. * pdwNumEntries = 1;
  2837. }
  2838. Cleanup:
  2839. if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
  2840. G_FREE(szSQLStmt);
  2841. return pdhStatus;
  2842. }
  2843. PDH_FUNCTION
  2844. PdhiReadRawSQLLogRecord(
  2845. PPDHI_LOG pLog,
  2846. FILETIME * ftRecord,
  2847. PPDH_RAW_LOG_RECORD pBuffer,
  2848. LPDWORD pdwBufferLength
  2849. )
  2850. {
  2851. UNREFERENCED_PARAMETER(pLog);
  2852. UNREFERENCED_PARAMETER(ftRecord);
  2853. UNREFERENCED_PARAMETER(pBuffer);
  2854. UNREFERENCED_PARAMETER(pdwBufferLength);
  2855. return PDH_NOT_IMPLEMENTED;
  2856. }
  2857. PDH_FUNCTION
  2858. PdhpGetSQLLogHeader(
  2859. PPDHI_LOG pLog
  2860. )
  2861. {
  2862. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2863. PPDHI_SQL_LOG_INFO pLogInfo;
  2864. HSTMT hstmt = NULL;
  2865. RETCODE rc;
  2866. LPWSTR szSQLStmt = NULL;
  2867. LPWSTR szMachineNamel = NULL;
  2868. LPWSTR szObjectNamel = NULL;
  2869. LPWSTR szCounterNamel = NULL;
  2870. LPWSTR szInstanceNamel = NULL;
  2871. LPWSTR szParentNamel = NULL;
  2872. DWORD dwInstanceIndexl;
  2873. DWORD dwParentObjIdl;
  2874. DWORD dwSQLCounterIdl;
  2875. DWORD dwCounterTypel;
  2876. LARGE_INTEGER lTimeBase;
  2877. LONG lDefaultScalel;
  2878. SQLLEN dwMachineNameLen;
  2879. SQLLEN dwObjectNameLen;
  2880. SQLLEN dwCounterNameLen;
  2881. SQLLEN dwInstanceNameLen;
  2882. SQLLEN dwParentNameLen;
  2883. SQLLEN dwInstanceIndexStat;
  2884. SQLLEN dwParentObjIdStat;
  2885. SQLLEN dwTimeBaseA;
  2886. SQLLEN dwTimeBaseB;
  2887. SQLLEN dwSQLCounterId;
  2888. if (pLog->pPerfmonInfo != NULL) return ERROR_SUCCESS;
  2889. pLogInfo = (PPDHI_SQL_LOG_INFO) G_ALLOC(sizeof(PDHI_SQL_LOG_INFO));
  2890. szSQLStmt = (LPWSTR) G_ALLOC((SQLSTMTSIZE + 5 * PDH_SQL_STRING_SIZE) * sizeof(WCHAR));
  2891. if (pLogInfo == NULL || szSQLStmt == NULL) {
  2892. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2893. goto Cleanup;
  2894. }
  2895. pLog->pPerfmonInfo = pLogInfo;
  2896. szMachineNamel = szSQLStmt + SQLSTMTSIZE;
  2897. szObjectNamel = szMachineNamel + PDH_SQL_STRING_SIZE;
  2898. szCounterNamel = szObjectNamel + PDH_SQL_STRING_SIZE;
  2899. szInstanceNamel = szCounterNamel + PDH_SQL_STRING_SIZE;
  2900. szParentNamel = szInstanceNamel + PDH_SQL_STRING_SIZE;
  2901. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  2902. if (! SQLSUCCEEDED(rc)) {
  2903. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  2904. goto Cleanup;
  2905. }
  2906. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  2907. L"select MAX(CounterID) from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x' ",
  2908. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  2909. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  2910. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  2911. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
  2912. rc = SQLBindCol(hstmt, 1, SQL_C_LONG, & pLogInfo->dwMaxCounter, 0, & dwSQLCounterId);
  2913. if (! SQLSUCCEEDED(rc)) {
  2914. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2915. goto Cleanup;
  2916. }
  2917. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  2918. if (! SQLSUCCEEDED(rc)) {
  2919. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  2920. goto Cleanup;
  2921. }
  2922. rc = SQLFetch(hstmt);
  2923. if (! SQLSUCCEEDED(rc)) {
  2924. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  2925. goto Cleanup;
  2926. }
  2927. SQLFreeStmt(hstmt, SQL_DROP);
  2928. hstmt = NULL;
  2929. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  2930. if (! SQLSUCCEEDED(rc)) {
  2931. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  2932. goto Cleanup;
  2933. }
  2934. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  2935. L"select MIN(CounterID) from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x' ",
  2936. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  2937. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  2938. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  2939. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
  2940. rc = SQLBindCol(hstmt, 1, SQL_C_LONG, & pLogInfo->dwMinCounter, 0, & dwSQLCounterId);
  2941. if (! SQLSUCCEEDED(rc)) {
  2942. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2943. goto Cleanup;
  2944. }
  2945. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  2946. if (! SQLSUCCEEDED(rc)) {
  2947. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  2948. goto Cleanup;
  2949. }
  2950. rc = SQLFetch(hstmt);
  2951. if (! SQLSUCCEEDED(rc)) {
  2952. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  2953. goto Cleanup;
  2954. }
  2955. SQLFreeStmt(hstmt, SQL_DROP);
  2956. hstmt = NULL;
  2957. pLogInfo->LogData = (PPDHI_SQL_LOG_DATA * )
  2958. G_ALLOC((pLogInfo->dwMaxCounter - pLogInfo->dwMinCounter + 1) * sizeof(PPDHI_SQL_LOG_DATA));
  2959. if (pLogInfo->LogData == NULL) {
  2960. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2961. goto Cleanup;
  2962. }
  2963. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  2964. if (! SQLSUCCEEDED(rc)) {
  2965. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  2966. goto Cleanup;
  2967. }
  2968. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  2969. L"select distinct MachineName, ObjectName, CounterName, CounterType, DefaultScale, InstanceName, InstanceIndex, ParentName, ParentObjectID, CounterID, TimeBaseA, TimeBaseB from CounterDetails where CounterID in (select distinct CounterID from CounterData where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x') Order by MachineName, ObjectName, CounterName, InstanceName, InstanceIndex ",
  2970. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  2971. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  2972. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  2973. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
  2974. // note SQL returns the size in bytes without the terminating character
  2975. rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szMachineNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwMachineNameLen);
  2976. if (! SQLSUCCEEDED(rc)) {
  2977. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2978. goto Cleanup;
  2979. }
  2980. rc = SQLBindCol(hstmt, 2, SQL_C_WCHAR, szObjectNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwObjectNameLen);
  2981. if (! SQLSUCCEEDED(rc)) {
  2982. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2983. goto Cleanup;
  2984. }
  2985. rc = SQLBindCol(hstmt, 3, SQL_C_WCHAR, szCounterNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwCounterNameLen);
  2986. if (! SQLSUCCEEDED(rc)) {
  2987. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2988. goto Cleanup;
  2989. }
  2990. rc = SQLBindCol(hstmt, 4, SQL_C_LONG, & dwCounterTypel, 0, NULL);
  2991. if (! SQLSUCCEEDED(rc)) {
  2992. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2993. goto Cleanup;
  2994. }
  2995. rc = SQLBindCol(hstmt, 5, SQL_C_LONG, & lDefaultScalel, 0, NULL);
  2996. if (! SQLSUCCEEDED(rc)) {
  2997. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  2998. goto Cleanup;
  2999. }
  3000. // check for SQL_NULL_DATA on the index's and on Instance Name & Parent Name
  3001. rc = SQLBindCol(hstmt, 6, SQL_C_WCHAR, szInstanceNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwInstanceNameLen);
  3002. if (! SQLSUCCEEDED(rc)) {
  3003. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  3004. goto Cleanup;
  3005. }
  3006. rc = SQLBindCol(hstmt, 7, SQL_C_LONG, & dwInstanceIndexl, 0, & dwInstanceIndexStat);
  3007. if (! SQLSUCCEEDED(rc)) {
  3008. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  3009. goto Cleanup;
  3010. }
  3011. rc = SQLBindCol(hstmt, 8, SQL_C_WCHAR, szParentNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwParentNameLen);
  3012. if (! SQLSUCCEEDED(rc)) {
  3013. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  3014. goto Cleanup;
  3015. }
  3016. rc = SQLBindCol(hstmt, 9, SQL_C_LONG, & dwParentObjIdl, 0, & dwParentObjIdStat);
  3017. if (! SQLSUCCEEDED(rc)) {
  3018. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  3019. goto Cleanup;
  3020. }
  3021. rc = SQLBindCol(hstmt, 10, SQL_C_LONG, & dwSQLCounterIdl, 0, & dwSQLCounterId);
  3022. if (! SQLSUCCEEDED(rc)) {
  3023. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  3024. goto Cleanup;
  3025. }
  3026. rc = SQLBindCol(hstmt, 11, SQL_C_LONG, & lTimeBase.LowPart, 0, & dwTimeBaseA);
  3027. if (! SQLSUCCEEDED(rc)) {
  3028. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  3029. goto Cleanup;
  3030. }
  3031. rc = SQLBindCol(hstmt, 12, SQL_C_LONG, & lTimeBase.HighPart, 0, & dwTimeBaseB);
  3032. if (! SQLSUCCEEDED(rc)) {
  3033. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_BIND_FAILED);
  3034. goto Cleanup;
  3035. }
  3036. // execute the sql command
  3037. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  3038. if (! SQLSUCCEEDED(rc)) {
  3039. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  3040. goto Cleanup;
  3041. }
  3042. rc = SQLFetch(hstmt);
  3043. while (rc != SQL_NO_DATA) {
  3044. PPDHI_LOG_COUNTER pCounter;
  3045. if (! SQLSUCCEEDED(rc)) {
  3046. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_FETCH_FAILED);
  3047. break;
  3048. }
  3049. else {
  3050. LPWSTR szInstance = (dwInstanceNameLen != SQL_NULL_DATA) ? (szInstanceNamel) : (NULL);
  3051. LPWSTR szParent = (dwParentNameLen != SQL_NULL_DATA) ? (szParentNamel) : (NULL);
  3052. if (dwInstanceIndexStat == SQL_NULL_DATA) dwInstanceIndexl = 0;
  3053. if (dwParentObjIdStat == SQL_NULL_DATA) dwParentObjIdl = 0;
  3054. pCounter = PdhiFindLogCounter(pLog,
  3055. & pLogInfo->MachineList,
  3056. szMachineNamel,
  3057. szObjectNamel,
  3058. szCounterNamel,
  3059. dwCounterTypel,
  3060. lDefaultScalel,
  3061. szInstance,
  3062. dwInstanceIndexl,
  3063. szParent,
  3064. dwParentObjIdl,
  3065. & dwSQLCounterIdl,
  3066. TRUE);
  3067. if (pCounter == NULL) {
  3068. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_CSTATUS_NO_COUNTER);
  3069. break;
  3070. }
  3071. if (dwTimeBaseA != SQL_NULL_DATA && dwTimeBaseB != SQL_NULL_DATA) {
  3072. pCounter->TimeBase = lTimeBase.QuadPart;
  3073. }
  3074. else {
  3075. pCounter->dwCounterType = PERF_DOUBLE_RAW;
  3076. pCounter->TimeBase = 0;
  3077. pCounter->dwDefaultScale = 0;
  3078. }
  3079. }
  3080. rc = SQLFetch(hstmt);
  3081. }
  3082. Cleanup:
  3083. if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
  3084. G_FREE(szSQLStmt);
  3085. if (pdhStatus != ERROR_SUCCESS) {
  3086. G_FREE(pLogInfo);
  3087. pLog->pPerfmonInfo = NULL;
  3088. }
  3089. return pdhStatus;
  3090. }
  3091. PDH_FUNCTION
  3092. PdhiVerifySQLDB(
  3093. LPCWSTR szDataSource
  3094. )
  3095. {
  3096. // INTERNAL FUNCTION to
  3097. // Check that a DSN points to a database that contains the correct Perfmon tables.
  3098. // select from the tables and check for an error
  3099. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3100. HSTMT hstmt = NULL;
  3101. RETCODE rc;
  3102. PDHI_LOG Log; // a fake log structure - just to make opens work ok
  3103. LPWSTR szSQLStmt = NULL;
  3104. LPWSTR szMachineNamel = NULL;
  3105. LPWSTR szObjectNamel = NULL;
  3106. LPWSTR szCounterNamel = NULL;
  3107. LPWSTR szInstanceNamel = NULL;
  3108. LPWSTR szParentNamel = NULL;
  3109. SQLLEN dwMachineNameLen;
  3110. SQLLEN dwObjectNameLen;
  3111. SQLLEN dwCounterNameLen;
  3112. SQLLEN dwInstanceNameLen;
  3113. SQLLEN dwParentNameLen;
  3114. DWORD dwInstanceIndexl;
  3115. DWORD dwParentObjIdl;
  3116. SQLLEN dwInstanceIndexStat;
  3117. SQLLEN dwParentObjIdStat;
  3118. DWORD dwSQLCounterIdl;
  3119. DWORD dwCounterTypel;
  3120. LONG lDefaultScalel;
  3121. LONG lMinutesToUTC = 0;
  3122. WCHAR szTimeZoneName[TIMEZONE_BUFF_SIZE];
  3123. SQLLEN dwTimeZoneLen;
  3124. DWORD dwNumOfRecs;
  3125. double dblCounterValuel;
  3126. DWORD dwMultiCount;
  3127. WCHAR szCounterDateTime[TIME_FIELD_BUFF_SIZE];
  3128. LARGE_INTEGER i64FirstValue, i64SecondValue;
  3129. ZeroMemory((void *)(& Log), sizeof(PDHI_LOG));
  3130. szSQLStmt = (LPWSTR) G_ALLOC((SQLSTMTSIZE + 5 * PDH_SQL_STRING_SIZE) * sizeof(WCHAR));
  3131. if (szSQLStmt == NULL) {
  3132. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3133. goto CleanupExit;
  3134. }
  3135. szMachineNamel = szSQLStmt + SQLSTMTSIZE;
  3136. szObjectNamel = szMachineNamel + PDH_SQL_STRING_SIZE;
  3137. szCounterNamel = szObjectNamel + PDH_SQL_STRING_SIZE;
  3138. szInstanceNamel = szCounterNamel + PDH_SQL_STRING_SIZE;
  3139. szParentNamel = szInstanceNamel + PDH_SQL_STRING_SIZE;
  3140. // open the database
  3141. //////////////////////////////////////////////////////////////
  3142. // obtain the ODBC environment and connection
  3143. //
  3144. rc = SQLAllocEnv(& Log.henvSQL);
  3145. if (! SQLSUCCEEDED(rc)) {
  3146. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOC_FAILED);
  3147. goto CleanupExit;
  3148. }
  3149. rc = SQLAllocConnect(Log.henvSQL, & Log.hdbcSQL);
  3150. if (! SQLSUCCEEDED(rc)) {
  3151. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOCCON_FAILED);
  3152. goto CleanupExit;
  3153. }
  3154. rc = SQLSetConnectAttr(Log.hdbcSQL, SQL_COPT_SS_BCP, (SQLPOINTER) SQL_BCP_ON, SQL_IS_INTEGER);
  3155. if (! SQLSUCCEEDED(rc)) {
  3156. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOCCON_FAILED);
  3157. goto CleanupExit;
  3158. }
  3159. rc = SQLConnectW(Log.hdbcSQL, (SQLWCHAR *) szDataSource, SQL_NTS, NULL, SQL_NULL_DATA, NULL, SQL_NULL_DATA);
  3160. if (! SQLSUCCEEDED(rc)) {
  3161. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_CONNECT_FAILED);
  3162. pdhStatus = PDH_INVALID_DATASOURCE;
  3163. goto CleanupExit;
  3164. }
  3165. // do a select on the CounterDetails Table
  3166. StringCchCopyW(szSQLStmt, SQLSTMTSIZE,
  3167. L"select MachineName, ObjectName, CounterName, CounterType, DefaultScale, InstanceName, InstanceIndex, ParentName, ParentObjectID, CounterID from CounterDetails");
  3168. // allocate an hstmt
  3169. rc = SQLAllocStmt(Log.hdbcSQL, & hstmt);
  3170. if (! SQLSUCCEEDED(rc)) {
  3171. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  3172. goto CleanupExit;
  3173. }
  3174. // note SQL returns the size in bytes without the terminating character
  3175. rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szMachineNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwMachineNameLen);
  3176. if (! SQLSUCCEEDED(rc)) {
  3177. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3178. goto CleanupExit;
  3179. }
  3180. rc = SQLBindCol(hstmt, 2, SQL_C_WCHAR, szObjectNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwObjectNameLen);
  3181. if (! SQLSUCCEEDED(rc)) {
  3182. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3183. goto CleanupExit;
  3184. }
  3185. rc = SQLBindCol(hstmt, 3, SQL_C_WCHAR, szCounterNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwCounterNameLen);
  3186. if (! SQLSUCCEEDED(rc)) {
  3187. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3188. goto CleanupExit;
  3189. }
  3190. rc = SQLBindCol(hstmt, 4, SQL_C_LONG, & dwCounterTypel, 0, NULL);
  3191. if (! SQLSUCCEEDED(rc)) {
  3192. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3193. goto CleanupExit;
  3194. }
  3195. rc = SQLBindCol(hstmt, 5, SQL_C_LONG, & lDefaultScalel, 0, NULL);
  3196. if (! SQLSUCCEEDED(rc)) {
  3197. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3198. goto CleanupExit;
  3199. }
  3200. rc = SQLBindCol(hstmt, 6, SQL_C_WCHAR, szInstanceNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwInstanceNameLen);
  3201. if (! SQLSUCCEEDED(rc)) {
  3202. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3203. goto CleanupExit;
  3204. }
  3205. rc = SQLBindCol(hstmt, 7, SQL_C_LONG, & dwInstanceIndexl, 0, & dwInstanceIndexStat);
  3206. if (! SQLSUCCEEDED(rc)) {
  3207. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3208. goto CleanupExit;
  3209. }
  3210. rc = SQLBindCol(hstmt, 8, SQL_C_WCHAR, szParentNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwParentNameLen);
  3211. if (! SQLSUCCEEDED(rc)) {
  3212. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3213. goto CleanupExit;
  3214. }
  3215. rc = SQLBindCol(hstmt, 9, SQL_C_LONG, & dwParentObjIdl, 0, & dwParentObjIdStat);
  3216. if (! SQLSUCCEEDED(rc)) {
  3217. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3218. goto CleanupExit;
  3219. }
  3220. rc = SQLBindCol(hstmt, 10, SQL_C_LONG, & dwSQLCounterIdl, 0, NULL);
  3221. if (! SQLSUCCEEDED(rc)) {
  3222. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3223. goto CleanupExit;
  3224. }
  3225. // execute the sql command
  3226. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  3227. if (! SQLSUCCEEDED(rc)) {
  3228. pdhStatus = PDH_INVALID_SQLDB;
  3229. goto CleanupExit;
  3230. }
  3231. SQLFreeStmt(hstmt, SQL_DROP);
  3232. hstmt = NULL;
  3233. // do a select on the DisplayToID Table
  3234. StringCchCopyW(szSQLStmt, SQLSTMTSIZE,
  3235. L"select GUID, RunID, DisplayString, LogStartTime, LogStopTime, NumberOfRecords, MinutesToUTC, TimeZoneName from DisplayToID");
  3236. // allocate an hstmt
  3237. rc = SQLAllocStmt(Log.hdbcSQL, & hstmt);
  3238. if (! SQLSUCCEEDED(rc)) {
  3239. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  3240. goto CleanupExit;
  3241. }
  3242. // bind the column names - reuse local strings as needed
  3243. rc = SQLBindCol(hstmt, 1, SQL_C_GUID, & Log.guidSQL, 0, NULL);
  3244. if (! SQLSUCCEEDED(rc)) {
  3245. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3246. goto CleanupExit;
  3247. }
  3248. rc = SQLBindCol(hstmt, 2, SQL_C_LONG, & Log.iRunidSQL, 0, NULL);
  3249. if (! SQLSUCCEEDED(rc)) {
  3250. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3251. goto CleanupExit;
  3252. }
  3253. // DislayString
  3254. rc = SQLBindCol(hstmt, 3, SQL_C_WCHAR, szMachineNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwMachineNameLen);
  3255. if (! SQLSUCCEEDED(rc)) {
  3256. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3257. goto CleanupExit;
  3258. }
  3259. //LogStartTime
  3260. rc = SQLBindCol(hstmt, 4, SQL_C_WCHAR, szObjectNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwObjectNameLen);
  3261. if (! SQLSUCCEEDED(rc)) {
  3262. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3263. goto CleanupExit;
  3264. }
  3265. //LogStopTime
  3266. rc = SQLBindCol(hstmt, 5, SQL_C_WCHAR, szCounterNamel, PDH_SQL_STRING_SIZE * sizeof(WCHAR), & dwCounterNameLen);
  3267. if (! SQLSUCCEEDED(rc)) {
  3268. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3269. goto CleanupExit;
  3270. }
  3271. rc = SQLBindCol(hstmt, 6, SQL_C_LONG, & dwNumOfRecs, 0, NULL);
  3272. if (! SQLSUCCEEDED(rc)) {
  3273. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3274. goto CleanupExit;
  3275. }
  3276. rc = SQLBindCol(hstmt, 7, SQL_C_LONG, & lMinutesToUTC, 0, NULL);
  3277. if (! SQLSUCCEEDED(rc)) {
  3278. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3279. goto CleanupExit;
  3280. }
  3281. rc = SQLBindCol(hstmt, 8, SQL_C_WCHAR, szTimeZoneName, TIMEZONE_BUFF_SIZE * sizeof(WCHAR), & dwTimeZoneLen);
  3282. if (! SQLSUCCEEDED(rc)) {
  3283. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3284. goto CleanupExit;
  3285. }
  3286. // execute the sql command
  3287. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  3288. if (! SQLSUCCEEDED(rc)) {
  3289. pdhStatus = PDH_INVALID_SQLDB;
  3290. goto CleanupExit;
  3291. }
  3292. SQLFreeStmt(hstmt, SQL_DROP);
  3293. hstmt = NULL;
  3294. // do a select on the CounterData Table
  3295. StringCchCopyW(szSQLStmt, SQLSTMTSIZE,
  3296. L"select GUID, CounterID, RecordIndex, CounterDateTime, CounterValue, FirstValueA, FirstValueB, SecondValueA, SecondValueB, MultiCount from CounterData");
  3297. // allocate an hstmt
  3298. rc = SQLAllocStmt(Log.hdbcSQL, & hstmt);
  3299. if (! SQLSUCCEEDED(rc)) {
  3300. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  3301. goto CleanupExit;
  3302. }
  3303. // bind the columns
  3304. rc = SQLBindCol(hstmt, 1, SQL_C_GUID, & Log.guidSQL, 0, NULL);
  3305. if (! SQLSUCCEEDED(rc)) {
  3306. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3307. goto CleanupExit;
  3308. }
  3309. rc = SQLBindCol(hstmt, 2, SQL_C_LONG, & dwSQLCounterIdl, 0, NULL);
  3310. if (! SQLSUCCEEDED(rc)) {
  3311. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3312. goto CleanupExit;
  3313. }
  3314. // record index
  3315. rc = SQLBindCol(hstmt, 3, SQL_C_LONG, & dwNumOfRecs, 0, NULL);
  3316. if (! SQLSUCCEEDED(rc)) {
  3317. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3318. goto CleanupExit;
  3319. }
  3320. rc = SQLBindCol(hstmt, 4, SQL_C_WCHAR, szCounterDateTime, TIME_FIELD_BUFF_SIZE * sizeof(WCHAR), NULL);
  3321. if (! SQLSUCCEEDED(rc)) {
  3322. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3323. goto CleanupExit;
  3324. }
  3325. rc = SQLBindCol(hstmt, 5, SQL_C_DOUBLE, & dblCounterValuel, 0, NULL);
  3326. if (! SQLSUCCEEDED(rc)) {
  3327. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3328. goto CleanupExit;
  3329. }
  3330. rc = SQLBindCol(hstmt, 6, SQL_C_LONG, & i64FirstValue.LowPart, 0, NULL);
  3331. if (! SQLSUCCEEDED(rc)) {
  3332. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3333. goto CleanupExit;
  3334. }
  3335. rc = SQLBindCol(hstmt, 7, SQL_C_LONG, & i64FirstValue.HighPart, 0, NULL);
  3336. if (! SQLSUCCEEDED(rc)) {
  3337. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3338. goto CleanupExit;
  3339. }
  3340. rc = SQLBindCol(hstmt, 8, SQL_C_LONG, & i64SecondValue.LowPart, 0, NULL);
  3341. if (! SQLSUCCEEDED(rc)) {
  3342. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3343. goto CleanupExit;
  3344. }
  3345. rc = SQLBindCol(hstmt, 9, SQL_C_LONG, & i64SecondValue.HighPart, 0, NULL);
  3346. if (! SQLSUCCEEDED(rc)) {
  3347. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3348. goto CleanupExit;
  3349. }
  3350. rc = SQLBindCol(hstmt, 10, SQL_C_LONG, & dwMultiCount, 0, NULL);
  3351. if (! SQLSUCCEEDED(rc)) {
  3352. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3353. goto CleanupExit;
  3354. }
  3355. // execute the select statement
  3356. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  3357. if (! SQLSUCCEEDED(rc)) {
  3358. pdhStatus = E_FAIL; // PDH_INVALID_SQLDB
  3359. goto CleanupExit;
  3360. }
  3361. // close the database
  3362. CleanupExit: // verify db
  3363. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  3364. if (Log.hdbcSQL != NULL) {
  3365. SQLDisconnect(Log.hdbcSQL);
  3366. SQLFreeHandle(SQL_HANDLE_DBC, Log.hdbcSQL);
  3367. }
  3368. if (Log.henvSQL != NULL) SQLFreeHandle(SQL_HANDLE_ENV, Log.henvSQL);
  3369. G_FREE(szSQLStmt);
  3370. return pdhStatus;
  3371. }
  3372. PDH_FUNCTION
  3373. PdhVerifySQLDBA(
  3374. IN LPCSTR szDataSource
  3375. )
  3376. {
  3377. //Check that a DSN points to a database that contains the correct Perfmon tables.
  3378. PDH_STATUS pdhStatus = PDH_INVALID_ARGUMENT;
  3379. LPWSTR wszDataSource = NULL;
  3380. __try {
  3381. // check args
  3382. if (szDataSource != NULL) {
  3383. if (* szDataSource != '\0' && lstrlenA(szDataSource) <= PDH_MAX_DATASOURCE_PATH) {
  3384. wszDataSource = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szDataSource);
  3385. if (wszDataSource != NULL) {
  3386. pdhStatus = PdhiVerifySQLDB(wszDataSource);
  3387. G_FREE(wszDataSource);
  3388. }
  3389. else {
  3390. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3391. }
  3392. }
  3393. }
  3394. }
  3395. __except (EXCEPTION_EXECUTE_HANDLER) {
  3396. pdhStatus = PDH_INVALID_ARGUMENT;
  3397. }
  3398. return pdhStatus;
  3399. }
  3400. PDH_FUNCTION
  3401. PdhVerifySQLDBW(
  3402. IN LPCWSTR szDataSource
  3403. )
  3404. {
  3405. //Check that a DSN points to a database that contains the correct Perfmon tables.
  3406. PDH_STATUS pdhStatus = PDH_INVALID_ARGUMENT;
  3407. __try {
  3408. if (szDataSource != NULL) {
  3409. if (* szDataSource != L'\0' && lstrlenW(szDataSource) <= PDH_MAX_DATASOURCE_PATH) {
  3410. pdhStatus = PdhiVerifySQLDB(szDataSource);
  3411. }
  3412. }
  3413. }
  3414. __except (EXCEPTION_EXECUTE_HANDLER) {
  3415. pdhStatus = PDH_INVALID_ARGUMENT;
  3416. }
  3417. return pdhStatus;
  3418. }
  3419. PDH_FUNCTION
  3420. PdhiCreateSQLTables(
  3421. LPCWSTR szDataSource
  3422. )
  3423. {
  3424. // INTERNAL FUNCTION to
  3425. //Create the correct perfmon tables in the database pointed to by a DSN.
  3426. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3427. RETCODE rc;
  3428. PDHI_LOG Log; // a fake log structure - just to make opens work ok
  3429. ZeroMemory((void *)(& Log), sizeof(PDHI_LOG));
  3430. // open the database
  3431. //////////////////////////////////////////////////////////////
  3432. // obtain the ODBC environment and connection
  3433. //
  3434. rc = SQLAllocEnv(& Log.henvSQL);
  3435. if (! SQLSUCCEEDED(rc)) {
  3436. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOC_FAILED);
  3437. goto CleanupExit;
  3438. }
  3439. rc = SQLAllocConnect(Log.henvSQL, & Log.hdbcSQL);
  3440. if (! SQLSUCCEEDED(rc)) {
  3441. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOCCON_FAILED);
  3442. goto CleanupExit;
  3443. }
  3444. rc = SQLSetConnectAttr(Log.hdbcSQL, SQL_COPT_SS_BCP, (SQLPOINTER) SQL_BCP_ON, SQL_IS_INTEGER);
  3445. if (! SQLSUCCEEDED(rc)) {
  3446. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOCCON_FAILED);
  3447. goto CleanupExit;
  3448. }
  3449. rc = SQLConnectW(Log.hdbcSQL, (SQLWCHAR *) szDataSource, SQL_NTS, NULL, SQL_NULL_DATA, NULL, SQL_NULL_DATA);
  3450. if (! SQLSUCCEEDED(rc)) {
  3451. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_CONNECT_FAILED);
  3452. goto CleanupExit;
  3453. }
  3454. // actually create the tables
  3455. pdhStatus = PdhpCreateSQLTables(& Log);
  3456. CleanupExit:
  3457. if (Log.hdbcSQL != NULL) {
  3458. SQLDisconnect(Log.hdbcSQL);
  3459. SQLFreeHandle(SQL_HANDLE_DBC, Log.hdbcSQL);
  3460. }
  3461. if (Log.henvSQL != NULL) SQLFreeHandle(SQL_HANDLE_ENV, Log.henvSQL);
  3462. return pdhStatus;
  3463. }
  3464. PDH_FUNCTION
  3465. PdhCreateSQLTablesA(
  3466. IN LPCSTR szDataSource
  3467. )
  3468. {
  3469. //Create the correct perfmon tables in the database pointed to by a DSN.
  3470. PDH_STATUS pdhStatus = PDH_INVALID_ARGUMENT;
  3471. LPWSTR wszDataSource = NULL;
  3472. __try {
  3473. // check args
  3474. if (szDataSource != NULL) {
  3475. if (* szDataSource != '\0' && lstrlenA(szDataSource) <= PDH_MAX_DATASOURCE_PATH) {
  3476. wszDataSource = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szDataSource);
  3477. if (wszDataSource != NULL) {
  3478. pdhStatus = PdhiCreateSQLTables(wszDataSource);
  3479. G_FREE(wszDataSource);
  3480. }
  3481. else {
  3482. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3483. }
  3484. }
  3485. }
  3486. }
  3487. __except (EXCEPTION_EXECUTE_HANDLER) {
  3488. pdhStatus = PDH_INVALID_ARGUMENT;
  3489. }
  3490. return pdhStatus;
  3491. }
  3492. PDH_FUNCTION
  3493. PdhCreateSQLTablesW(
  3494. IN LPCWSTR szDataSource
  3495. )
  3496. {
  3497. //Create the correct perfmon tables in the database pointed to by a DSN.
  3498. PDH_STATUS pdhStatus = PDH_INVALID_ARGUMENT;
  3499. __try {
  3500. if (szDataSource != NULL) {
  3501. if (* szDataSource != L'\0' && lstrlenW(szDataSource) <= PDH_MAX_DATASOURCE_PATH) {
  3502. pdhStatus = PdhiCreateSQLTables(szDataSource);
  3503. }
  3504. }
  3505. }
  3506. __except (EXCEPTION_EXECUTE_HANDLER) {
  3507. pdhStatus = PDH_INVALID_ARGUMENT;
  3508. }
  3509. return pdhStatus;
  3510. }
  3511. PDH_FUNCTION
  3512. PdhiEnumLogSetNames(
  3513. LPCWSTR szDataSource,
  3514. LPVOID mszDataSetNameList,
  3515. LPDWORD pcchBufferLength,
  3516. BOOL bUnicodeDest
  3517. )
  3518. {
  3519. //Return the list of Log set names in the database pointed to by the DSN.
  3520. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3521. PDH_STATUS pdhBuffStatus = ERROR_SUCCESS;
  3522. HSTMT hstmt = NULL;
  3523. RETCODE rc;
  3524. PDHI_LOG Log; // a fake log structure - just to make opens work ok
  3525. LPWSTR szSQLStmt = NULL;
  3526. LPWSTR szDisplayStringl = NULL;
  3527. SQLLEN dwDisplayStringLen;
  3528. DWORD dwNewBuffer;
  3529. DWORD dwListUsed;
  3530. ZeroMemory((void *) (& Log), sizeof(PDHI_LOG));
  3531. szSQLStmt = (LPWSTR) G_ALLOC((SQLSTMTSIZE + PDH_SQL_STRING_SIZE + 1) * sizeof(WCHAR));
  3532. if (szSQLStmt == NULL) {
  3533. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3534. goto CleanupExit;
  3535. }
  3536. szDisplayStringl = szSQLStmt + SQLSTMTSIZE;
  3537. // open the database
  3538. //////////////////////////////////////////////////////////////
  3539. // obtain the ODBC environment and connection
  3540. //
  3541. rc = SQLAllocEnv(& Log.henvSQL);
  3542. if (! SQLSUCCEEDED(rc)) {
  3543. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOC_FAILED);
  3544. goto CleanupExit;
  3545. }
  3546. rc = SQLAllocConnect(Log.henvSQL, & Log.hdbcSQL);
  3547. if (! SQLSUCCEEDED(rc)) {
  3548. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOCCON_FAILED);
  3549. goto CleanupExit;
  3550. }
  3551. rc = SQLSetConnectAttr(Log.hdbcSQL, SQL_COPT_SS_BCP, (SQLPOINTER) SQL_BCP_ON, SQL_IS_INTEGER);
  3552. if (! SQLSUCCEEDED(rc)) {
  3553. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_ALLOCCON_FAILED);
  3554. goto CleanupExit;
  3555. }
  3556. rc = SQLConnectW(Log.hdbcSQL, (SQLWCHAR *) szDataSource, SQL_NTS, NULL, SQL_NULL_DATA, NULL, SQL_NULL_DATA);
  3557. if (! SQLSUCCEEDED(rc)) {
  3558. pdhStatus = ReportSQLError(& Log, rc, NULL, PDH_SQL_CONNECT_FAILED);
  3559. goto CleanupExit;
  3560. }
  3561. // do a select
  3562. // loop around in a fetch and
  3563. // build the list of names
  3564. StringCchCopyW(szSQLStmt, SQLSTMTSIZE, L"select DisplayString from DisplayToID");
  3565. // allocate an hstmt
  3566. rc = SQLAllocStmt(Log.hdbcSQL, & hstmt);
  3567. if (! SQLSUCCEEDED(rc)) {
  3568. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  3569. goto CleanupExit;
  3570. }
  3571. // bind the machine name column
  3572. rc = SQLBindCol(hstmt, 1, SQL_C_WCHAR, szDisplayStringl, (PDH_SQL_STRING_SIZE + 1) * sizeof(WCHAR), & dwDisplayStringLen);
  3573. if (! SQLSUCCEEDED(rc)) {
  3574. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_BIND_FAILED);
  3575. goto CleanupExit;
  3576. }
  3577. // execute the select statement
  3578. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  3579. if (! SQLSUCCEEDED(rc)) {
  3580. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  3581. goto CleanupExit;
  3582. }
  3583. dwListUsed = 0; // include the null terminator to start
  3584. // loop around the result set using fetch
  3585. while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA) {
  3586. if (! SQLSUCCEEDED(rc)) {
  3587. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_FETCH_FAILED);
  3588. goto CleanupExit;
  3589. }
  3590. // Append the DisplayName to the returned list
  3591. dwNewBuffer = lstrlenW(szDisplayStringl) + 1;
  3592. if (mszDataSetNameList != NULL && (dwListUsed + dwNewBuffer) <= * pcchBufferLength) {
  3593. // add the display name
  3594. pdhBuffStatus = AddUniqueWideStringToMultiSz((LPVOID) mszDataSetNameList,
  3595. (LPWSTR) szDisplayStringl,
  3596. * pcchBufferLength - dwListUsed,
  3597. & dwNewBuffer,
  3598. bUnicodeDest);
  3599. if (pdhBuffStatus == ERROR_SUCCESS) {
  3600. if (dwNewBuffer != 0) { // if it got added returned new length in TCHAR
  3601. dwListUsed = dwNewBuffer;
  3602. }
  3603. }
  3604. else if (pdhBuffStatus == PDH_MORE_DATA) {
  3605. dwListUsed += dwNewBuffer;
  3606. }
  3607. else {
  3608. pdhStatus = pdhBuffStatus;
  3609. goto CleanupExit;
  3610. }
  3611. }
  3612. else {
  3613. // SQL won't let non unique LogSet names into the database
  3614. // so we don't really have to worry about duplicates
  3615. pdhBuffStatus = PDH_MORE_DATA;
  3616. dwListUsed += dwNewBuffer;
  3617. }
  3618. } // end of while fetch
  3619. if (! SQLSUCCEEDED(rc)) {
  3620. pdhStatus = ReportSQLError(& Log, rc, hstmt, PDH_SQL_FETCH_FAILED);
  3621. goto CleanupExit;
  3622. }
  3623. if (pdhBuffStatus == PDH_MORE_DATA) {
  3624. dwListUsed ++;
  3625. }
  3626. * pcchBufferLength = dwListUsed;
  3627. pdhStatus = pdhBuffStatus;
  3628. // close the database
  3629. CleanupExit:
  3630. if (hstmt != NULL) SQLFreeStmt(hstmt, SQL_DROP);
  3631. if (Log.hdbcSQL) {
  3632. SQLDisconnect(Log.hdbcSQL);
  3633. SQLFreeHandle(SQL_HANDLE_DBC, Log.hdbcSQL);
  3634. }
  3635. if (Log.henvSQL) SQLFreeHandle(SQL_HANDLE_ENV, Log.henvSQL);
  3636. G_FREE(szSQLStmt);
  3637. return pdhStatus;
  3638. }
  3639. PDH_FUNCTION
  3640. PdhEnumLogSetNamesA(
  3641. IN LPCSTR szDataSource,
  3642. IN LPSTR mszDataSetNameList,
  3643. IN LPDWORD pcchBufferLength
  3644. )
  3645. {
  3646. //Return the list of Log set names in the database pointed to by the DSN.
  3647. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3648. DWORD dwBufferSize;
  3649. LPWSTR wszDataSource = NULL;
  3650. if (szDataSource == NULL || pcchBufferLength == NULL) {
  3651. pdhStatus = PDH_INVALID_ARGUMENT;
  3652. }
  3653. else {
  3654. __try {
  3655. // check args
  3656. dwBufferSize = * pcchBufferLength;
  3657. if (mszDataSetNameList != NULL) {
  3658. mszDataSetNameList[0] = '\0';
  3659. if (dwBufferSize > 1) {
  3660. mszDataSetNameList[dwBufferSize - 1] = '\0';
  3661. }
  3662. }
  3663. if (* szDataSource != '\0' && lstrlenA(szDataSource) <= PDH_MAX_DATASOURCE_PATH) {
  3664. wszDataSource = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szDataSource);
  3665. if (wszDataSource != NULL) {
  3666. pdhStatus = PdhiEnumLogSetNames(wszDataSource, mszDataSetNameList, pcchBufferLength, FALSE);
  3667. G_FREE(wszDataSource);
  3668. }
  3669. else {
  3670. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3671. }
  3672. }
  3673. else {
  3674. pdhStatus = PDH_INVALID_ARGUMENT;
  3675. }
  3676. }
  3677. __except(EXCEPTION_EXECUTE_HANDLER) {
  3678. pdhStatus = PDH_INVALID_ARGUMENT;
  3679. }
  3680. }
  3681. return pdhStatus;
  3682. }
  3683. PDH_FUNCTION
  3684. PdhEnumLogSetNamesW(
  3685. IN LPCWSTR szDataSource,
  3686. IN LPWSTR mszDataSetNameList,
  3687. IN LPDWORD pcchBufferLength
  3688. )
  3689. {
  3690. //Return the list of Log set names in the database pointed to by the DSN.
  3691. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3692. DWORD dwBufferSize;
  3693. if (szDataSource == NULL || pcchBufferLength == NULL) {
  3694. pdhStatus = PDH_INVALID_ARGUMENT;
  3695. }
  3696. else {
  3697. __try {
  3698. // check args
  3699. dwBufferSize = * pcchBufferLength;
  3700. if (mszDataSetNameList != NULL) {
  3701. mszDataSetNameList[0] = L'\0';
  3702. if (dwBufferSize > 1) {
  3703. mszDataSetNameList[dwBufferSize - 1] = L'\0';
  3704. }
  3705. }
  3706. if (* szDataSource == L'\0' || lstrlenW(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
  3707. pdhStatus = PDH_INVALID_ARGUMENT;
  3708. }
  3709. if (pdhStatus == ERROR_SUCCESS) {
  3710. pdhStatus = PdhiEnumLogSetNames(szDataSource, mszDataSetNameList, pcchBufferLength, TRUE);
  3711. }
  3712. }
  3713. __except (EXCEPTION_EXECUTE_HANDLER) {
  3714. pdhStatus = PDH_INVALID_ARGUMENT;
  3715. }
  3716. }
  3717. return pdhStatus;
  3718. }
  3719. PDH_FUNCTION
  3720. PdhGetLogSetGUID(
  3721. IN PDH_HLOG hLog,
  3722. IN GUID * pGuid,
  3723. IN int * pRunId
  3724. )
  3725. {
  3726. //Retrieve the GUID for an open Log Set
  3727. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3728. PPDHI_LOG pLog;
  3729. if (IsValidLogHandle(hLog)) {
  3730. pLog = (PPDHI_LOG) hLog;
  3731. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  3732. if (pdhStatus == ERROR_SUCCESS) {
  3733. // make sure it's still valid as it could have
  3734. // been deleted while we were waiting
  3735. if (IsValidLogHandle(hLog)) {
  3736. pLog = (PPDHI_LOG) hLog;
  3737. __try {
  3738. // test the parameters before continuing
  3739. if (pGuid == NULL && pRunId == NULL) {
  3740. pdhStatus = PDH_INVALID_ARGUMENT;
  3741. }
  3742. else {
  3743. if (pGuid != NULL) {
  3744. // if not NULL, it must be valid
  3745. * pGuid = pLog->guidSQL;
  3746. }
  3747. if (pRunId != NULL) {
  3748. // if not NULL, it must be valid
  3749. * pRunId = pLog->iRunidSQL;
  3750. }
  3751. }
  3752. }
  3753. __except (EXCEPTION_EXECUTE_HANDLER) {
  3754. // something failed so give up here
  3755. pdhStatus = PDH_INVALID_ARGUMENT;
  3756. }
  3757. }
  3758. else {
  3759. pdhStatus = PDH_INVALID_HANDLE;
  3760. }
  3761. RELEASE_MUTEX(pLog->hLogMutex);
  3762. }
  3763. }
  3764. else {
  3765. pdhStatus = PDH_INVALID_HANDLE;
  3766. }
  3767. return pdhStatus;
  3768. }
  3769. PDH_FUNCTION
  3770. PdhiSetLogSetRunID(
  3771. PPDHI_LOG pLog,
  3772. int RunId
  3773. )
  3774. {
  3775. //Set the RunID for an open Log Set
  3776. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3777. HSTMT hstmt = NULL;
  3778. RETCODE rc;
  3779. LPWSTR szSQLStmt = NULL;
  3780. szSQLStmt = (LPWSTR) G_ALLOC(SQLSTMTSIZE * sizeof(WCHAR));
  3781. if (szSQLStmt == NULL) {
  3782. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3783. goto Cleanup;
  3784. }
  3785. pLog->iRunidSQL = RunId;
  3786. // allocate an hstmt
  3787. rc = SQLAllocStmt(pLog->hdbcSQL, & hstmt);
  3788. if (! SQLSUCCEEDED(rc)) {
  3789. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_ALLOC_FAILED);
  3790. goto Cleanup;
  3791. }
  3792. StringCchPrintfW(szSQLStmt, SQLSTMTSIZE,
  3793. L"update DisplayToID set RunID = %d where GUID = '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x'",
  3794. RunId,
  3795. pLog->guidSQL.Data1, pLog->guidSQL.Data2, pLog->guidSQL.Data3,
  3796. pLog->guidSQL.Data4[0], pLog->guidSQL.Data4[1], pLog->guidSQL.Data4[2],
  3797. pLog->guidSQL.Data4[3], pLog->guidSQL.Data4[4], pLog->guidSQL.Data4[5],
  3798. pLog->guidSQL.Data4[6], pLog->guidSQL.Data4[7]);
  3799. rc = SQLExecDirectW(hstmt, szSQLStmt, SQL_NTS);
  3800. if (! SQLSUCCEEDED(rc)) {
  3801. pdhStatus = ReportSQLError(pLog, rc, hstmt, PDH_SQL_EXEC_DIRECT_FAILED);
  3802. goto Cleanup;
  3803. }
  3804. Cleanup:
  3805. if (hstmt) SQLFreeStmt(hstmt, SQL_DROP);
  3806. G_FREE(szSQLStmt);
  3807. return pdhStatus;
  3808. }
  3809. PDH_FUNCTION
  3810. PdhSetLogSetRunID(
  3811. IN PDH_HLOG hLog,
  3812. IN int RunId
  3813. )
  3814. {
  3815. //Set the RunID for an open Log Set
  3816. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3817. PPDHI_LOG pLog;
  3818. if (IsValidLogHandle(hLog)) {
  3819. pLog = (PPDHI_LOG) hLog;
  3820. WAIT_FOR_AND_LOCK_MUTEX(pLog->hLogMutex);
  3821. // make sure it's still valid as it could have
  3822. // been deleted while we were waiting
  3823. if (IsValidLogHandle(hLog)) {
  3824. pLog = (PPDHI_LOG) hLog;
  3825. pdhStatus = PdhiSetLogSetRunID(pLog, RunId);
  3826. }
  3827. else {
  3828. pdhStatus = PDH_INVALID_HANDLE;
  3829. }
  3830. RELEASE_MUTEX(pLog->hLogMutex);
  3831. }
  3832. else {
  3833. pdhStatus = PDH_INVALID_HANDLE;
  3834. }
  3835. return pdhStatus;
  3836. }
  3837. PDH_FUNCTION
  3838. PdhiListHeaderFromSQLLog(
  3839. PPDHI_LOG pLog,
  3840. LPVOID pBufferArg,
  3841. LPDWORD pcchBufferSize,
  3842. BOOL bUnicode
  3843. )
  3844. {
  3845. PPDHI_SQL_LOG_INFO pLogInfo;
  3846. PPDHI_LOG_MACHINE pMachine;
  3847. PPDHI_LOG_OBJECT pObject;
  3848. PPDHI_LOG_COUNTER pCounter;
  3849. PDH_COUNTER_PATH_ELEMENTS_W pdhPathElem;
  3850. WCHAR szPathString[SMALL_BUFFER_SIZE];
  3851. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3852. DWORD dwNewBuffer = 0;
  3853. DWORD dwBufferUsed = 0;
  3854. DWORD nItemCount = 0;
  3855. if (pcchBufferSize == NULL) {
  3856. pdhStatus = PDH_INVALID_ARGUMENT;
  3857. goto Cleanup;
  3858. }
  3859. pdhStatus = PdhpGetSQLLogHeader(pLog);
  3860. if (pdhStatus != ERROR_SUCCESS) goto Cleanup;
  3861. pLogInfo = (PPDHI_SQL_LOG_INFO) pLog->pPerfmonInfo;
  3862. if (pLogInfo == NULL) {
  3863. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  3864. goto Cleanup;
  3865. }
  3866. for (pMachine = pLogInfo->MachineList; pMachine != NULL; pMachine = pMachine->next) {
  3867. for (pObject = pMachine->ObjList; pObject != NULL; pObject = pObject->next) {
  3868. for (pCounter = pObject->CtrList; pCounter != NULL; pCounter = pCounter->next) {
  3869. ZeroMemory(szPathString, SMALL_BUFFER_SIZE * sizeof(WCHAR));
  3870. dwNewBuffer = SMALL_BUFFER_SIZE;
  3871. ZeroMemory(& pdhPathElem, sizeof(PDH_COUNTER_PATH_ELEMENTS_W));
  3872. pdhPathElem.szMachineName = pMachine->szMachine;
  3873. pdhPathElem.szObjectName = pObject->szObject;
  3874. pdhPathElem.szCounterName = pCounter->szCounter;
  3875. pdhPathElem.szInstanceName = pCounter->szInstance;
  3876. pdhPathElem.szParentInstance = pCounter->szParent;
  3877. pdhPathElem.dwInstanceIndex = (pCounter->dwInstance != 0)
  3878. ? (pCounter->dwInstance) : (PERF_NO_UNIQUE_ID);
  3879. pdhStatus = PdhMakeCounterPathW(& pdhPathElem, szPathString, & dwNewBuffer, 0);
  3880. if (pdhStatus != ERROR_SUCCESS || dwNewBuffer == 0) continue;
  3881. if (pBufferArg != NULL && (dwBufferUsed + dwNewBuffer) < * pcchBufferSize) {
  3882. pdhStatus = AddUniqueWideStringToMultiSz((LPVOID) pBufferArg,
  3883. szPathString,
  3884. * pcchBufferSize - dwBufferUsed,
  3885. & dwNewBuffer,
  3886. bUnicode);
  3887. if (pdhStatus == ERROR_SUCCESS) {
  3888. if (dwNewBuffer != 0) { // if it got added returned new length in TCHAR
  3889. dwBufferUsed = dwNewBuffer;
  3890. }
  3891. }
  3892. else if (pdhStatus == PDH_MORE_DATA) {
  3893. dwBufferUsed += dwNewBuffer;
  3894. }
  3895. else {
  3896. goto Cleanup;
  3897. }
  3898. }
  3899. else {
  3900. dwBufferUsed += dwNewBuffer;
  3901. pdhStatus = PDH_MORE_DATA;
  3902. }
  3903. nItemCount ++;
  3904. }
  3905. }
  3906. }
  3907. if (nItemCount > 0 && pdhStatus != PDH_MORE_DATA) {
  3908. pdhStatus = ERROR_SUCCESS;
  3909. }
  3910. if (pBufferArg == NULL) {
  3911. dwBufferUsed ++;
  3912. }
  3913. * pcchBufferSize = dwBufferUsed;
  3914. Cleanup:
  3915. return pdhStatus;
  3916. }