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

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