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.

1181 lines
41 KiB

  1. /*++
  2. Copyright (C) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. log_ctrl.c
  5. Abstract:
  6. Log file control interface helper functions
  7. --*/
  8. #include <windows.h>
  9. #include <stdlib.h>
  10. #include <assert.h>
  11. #include <pdh.h>
  12. #include "pdhidef.h"
  13. #include "pdhmsg.h"
  14. #include "strings.h"
  15. #define PDH_LOGSVC_CTRL_FNMASK ((DWORD)(PDH_LOGSVC_CTRL_ADD \
  16. | PDH_LOGSVC_CTRL_REMOVE \
  17. | PDH_LOGSVC_CTRL_INFO \
  18. ))
  19. //
  20. // Internal Logging utility functions
  21. //
  22. LONG
  23. GetCurrentServiceState (
  24. SC_HANDLE hService,
  25. BOOL * bStopped,
  26. BOOL * bPaused)
  27. {
  28. SERVICE_STATUS ssData;
  29. LONG lStatus = ERROR_SUCCESS;
  30. BOOL bServiceStopped = FALSE;
  31. BOOL bServicePaused = FALSE;
  32. if (ControlService (
  33. hService, SERVICE_CONTROL_INTERROGATE,
  34. &ssData)) {
  35. switch (ssData.dwCurrentState) {
  36. case SERVICE_STOPPED:
  37. bServiceStopped = TRUE;
  38. bServicePaused = FALSE;
  39. break;
  40. case SERVICE_START_PENDING:
  41. bServiceStopped = TRUE;
  42. bServicePaused = FALSE;
  43. break;
  44. case SERVICE_STOP_PENDING:
  45. bServiceStopped = FALSE;
  46. bServicePaused = FALSE;
  47. break;
  48. case SERVICE_RUNNING:
  49. bServiceStopped = FALSE;
  50. bServicePaused = FALSE;
  51. break;
  52. case SERVICE_CONTINUE_PENDING:
  53. bServiceStopped = FALSE;
  54. bServicePaused = FALSE;
  55. break;
  56. case SERVICE_PAUSE_PENDING:
  57. bServiceStopped = FALSE;
  58. bServicePaused = FALSE;
  59. break;
  60. case SERVICE_PAUSED:
  61. bServiceStopped = FALSE;
  62. bServicePaused = TRUE;
  63. break;
  64. default:
  65. ;// no op
  66. }
  67. } else {
  68. bServiceStopped = TRUE;
  69. bServicePaused = TRUE;
  70. }
  71. *bStopped = bServiceStopped;
  72. *bPaused = bServicePaused;
  73. return lStatus;
  74. }
  75. STATIC_PDH_FUNCTION
  76. PdhiSetLogQueryState (
  77. IN LPCWSTR szMachineName,
  78. IN LPCWSTR szQueryName,
  79. IN DWORD dwFlags
  80. )
  81. {
  82. DBG_UNREFERENCED_PARAMETER(szMachineName);
  83. DBG_UNREFERENCED_PARAMETER(szQueryName);
  84. DBG_UNREFERENCED_PARAMETER(dwFlags);
  85. return ERROR_SUCCESS;
  86. }
  87. STATIC_PDH_FUNCTION
  88. PdhiGetLogQueryState (
  89. IN SC_HANDLE hService,
  90. IN LPCWSTR szMachineName,
  91. IN LPCWSTR szQueryName,
  92. IN LPDWORD pdwFlags
  93. )
  94. {
  95. BOOL bStopped, bPaused;
  96. DWORD dwStatus;
  97. UNREFERENCED_PARAMETER(szMachineName);
  98. UNREFERENCED_PARAMETER(szQueryName);
  99. // first get service status
  100. GetCurrentServiceState (hService, &bStopped, &bPaused);
  101. if (bStopped) {
  102. dwStatus = PDH_LOGSVC_STATUS_STOPPED;
  103. } else if (bPaused) {
  104. dwStatus = PDH_LOGSVC_STATUS_PAUSED;
  105. } else {
  106. dwStatus = PDH_LOGSVC_STATUS_RUNNING;
  107. }
  108. if (dwStatus == PDH_LOGSVC_STATUS_RUNNING) {
  109. // get status of specific query
  110. // connect to machine, if necssary
  111. // open registry key of log service
  112. // read value of query status
  113. // adjust status, if necessary
  114. }
  115. // return status of query
  116. *pdwFlags = dwStatus;
  117. return ERROR_SUCCESS;
  118. }
  119. STATIC_PDH_FUNCTION
  120. PdhiLogServiceAddCommandT (
  121. IN LPCWSTR szMachineName,
  122. IN LPCWSTR szQueryName,
  123. IN DWORD dwFlags,
  124. IN LPVOID pInfoBuffer,
  125. IN LPDWORD pdwBufferSize,
  126. IN BOOL bWideChar
  127. )
  128. {
  129. UNREFERENCED_PARAMETER(szMachineName);
  130. UNREFERENCED_PARAMETER(szQueryName);
  131. UNREFERENCED_PARAMETER(dwFlags);
  132. UNREFERENCED_PARAMETER(pInfoBuffer);
  133. UNREFERENCED_PARAMETER(pdwBufferSize);
  134. UNREFERENCED_PARAMETER(bWideChar);
  135. return PDH_NOT_IMPLEMENTED;
  136. }
  137. STATIC_PDH_FUNCTION
  138. PdhiLogServiceRemoveCommandT (
  139. IN LPCWSTR szMachineName,
  140. IN LPCWSTR szQueryName,
  141. IN DWORD dwFlags,
  142. IN LPVOID pInfoBuffer,
  143. IN LPDWORD pdwBufferSize,
  144. IN BOOL bWideChar
  145. )
  146. {
  147. UNREFERENCED_PARAMETER(szMachineName);
  148. UNREFERENCED_PARAMETER(szQueryName);
  149. UNREFERENCED_PARAMETER(dwFlags);
  150. UNREFERENCED_PARAMETER(pInfoBuffer);
  151. UNREFERENCED_PARAMETER(pdwBufferSize);
  152. UNREFERENCED_PARAMETER(bWideChar);
  153. return PDH_NOT_IMPLEMENTED;
  154. }
  155. STATIC_PDH_FUNCTION
  156. PdhiLogServiceInfoCommandT (
  157. IN LPCWSTR szMachineName,
  158. IN LPCWSTR szQueryName,
  159. IN DWORD dwFlags,
  160. IN LPVOID pInfoBuffer,
  161. IN LPDWORD pdwBufferSize,
  162. IN BOOL bWideChar
  163. )
  164. {
  165. LONG lStatus = ERROR_SUCCESS;
  166. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  167. DWORD dwRegValType;
  168. DWORD dwRegValue;
  169. DWORD dwRegValueSize;
  170. WCHAR szTempFilePath[MAX_PATH];
  171. WCHAR szRegString[MAX_PATH];
  172. WCHAR szDriveName[MAX_PATH];
  173. HKEY hKeyMachine = NULL;
  174. HKEY hKeyLogSettings = NULL;
  175. HKEY hKeyLogQuery = NULL;
  176. CHAR *pNextChar = NULL;
  177. WCHAR *pNextWideChar = NULL;
  178. DWORD dwCharSize;
  179. DWORD dwSize;
  180. DWORD dwRequiredSize = sizeof(PDH_LOG_SERVICE_QUERY_INFO_W);
  181. DWORD dwRemainingSize = 0;
  182. UNREFERENCED_PARAMETER(dwFlags);
  183. dwCharSize = bWideChar ? sizeof(WCHAR) : sizeof(CHAR);
  184. setlocale( LC_ALL, "" ); // to make wcstombs work predictably
  185. if (*pdwBufferSize < sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  186. // then then this is either too small or a size request in either
  187. // case we won't copy any data and only estimate the size required
  188. dwRemainingSize = 0;
  189. } else {
  190. dwRemainingSize = *pdwBufferSize - sizeof(PDH_LOG_SERVICE_QUERY_INFO_W);
  191. }
  192. // get root key to registry
  193. if (szMachineName != NULL) {
  194. lStatus = RegConnectRegistryW (
  195. (LPWSTR)szMachineName,
  196. HKEY_LOCAL_MACHINE,
  197. &hKeyMachine);
  198. if (lStatus != ERROR_SUCCESS) {
  199. pdhStatus = PDH_CANNOT_CONNECT_MACHINE;
  200. }
  201. } else {
  202. // use predefined key handle
  203. hKeyMachine = HKEY_LOCAL_MACHINE;
  204. lStatus = ERROR_SUCCESS;
  205. }
  206. if (pInfoBuffer == NULL) {
  207. if (pdhStatus == ERROR_SUCCESS) {
  208. pdhStatus = PDH_INVALID_ARGUMENT;
  209. }
  210. lStatus = ERROR_INVALID_PARAMETER;
  211. }
  212. if (lStatus == ERROR_SUCCESS) {
  213. // open registry key to service
  214. lStatus = RegOpenKeyExW (
  215. hKeyMachine,
  216. cszLogQueries,
  217. 0,
  218. KEY_READ,
  219. &hKeyLogSettings);
  220. if (lStatus != ERROR_SUCCESS) {
  221. pdhStatus = PDH_LOGSVC_NOT_OPENED;
  222. }
  223. }
  224. if (lStatus == ERROR_SUCCESS) {
  225. // open registry to specified log query
  226. lStatus = RegOpenKeyExW (
  227. hKeyLogSettings,
  228. (szQueryName != NULL ? szQueryName : cszDefault),
  229. 0,
  230. KEY_READ,
  231. &hKeyLogQuery);
  232. if (lStatus != ERROR_SUCCESS) {
  233. pdhStatus = PDH_LOGSVC_QUERY_NOT_FOUND;
  234. }
  235. }
  236. // continue
  237. if (lStatus == ERROR_SUCCESS) {
  238. // initialize string pointers
  239. if (bWideChar && (pInfoBuffer != NULL)) {
  240. pNextWideChar = (WCHAR *)(&((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)[1]);
  241. } else {
  242. pNextChar = (CHAR *)(&((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)[1]);
  243. }
  244. // read log file format
  245. dwRegValType = 0;
  246. dwRegValue = 0;
  247. dwRegValueSize = sizeof(DWORD);
  248. lStatus = RegQueryValueExW (
  249. hKeyLogQuery,
  250. cszLogFileType,
  251. NULL,
  252. &dwRegValType,
  253. (LPBYTE)&dwRegValue,
  254. &dwRegValueSize);
  255. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  256. // this data goes into the fixed portion of the structure
  257. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_DWORD)) {
  258. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->dwFileType = dwRegValue;
  259. } else {
  260. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->dwFileType = PDH_LOG_TYPE_UNDEFINED;
  261. }
  262. }
  263. //read sample interval
  264. dwRegValType = 0;
  265. dwRegValue = 0;
  266. dwRegValueSize = sizeof(DWORD);
  267. lStatus = RegQueryValueExW (
  268. hKeyLogQuery,
  269. cszAutoNameInterval,
  270. NULL,
  271. &dwRegValType,
  272. (LPBYTE)&dwRegValue,
  273. &dwRegValueSize);
  274. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  275. // this data goes into the fixed portion of the structure
  276. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_DWORD)) {
  277. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameInterval = dwRegValue;
  278. } else {
  279. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameInterval = 0;
  280. dwRegValue = 0;
  281. }
  282. }
  283. if (dwRegValue == 0) {
  284. // initialize the rest of the manual name field(s)
  285. dwRegValType = 0;
  286. dwRegValueSize = MAX_PATH * sizeof(WCHAR);
  287. memset (szRegString, 0, dwRegValueSize);
  288. lStatus = RegQueryValueExW (
  289. hKeyLogQuery,
  290. cszLogFileName,
  291. NULL,
  292. &dwRegValType,
  293. (LPBYTE)&szRegString[0],
  294. &dwRegValueSize);
  295. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
  296. dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  297. if (dwRequiredSize <= *pdwBufferSize) {
  298. if (bWideChar) {
  299. // copy widestrings
  300. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = pNextWideChar;
  301. lstrcpyW (pNextWideChar, szRegString);
  302. pNextWideChar += dwRegValueSize / sizeof (WCHAR);
  303. } else {
  304. // convert to ansi char
  305. ((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->szBaseFileName = pNextChar;
  306. wcstombs (pNextChar, szRegString, (dwRegValueSize /sizeof(WCHAR)));
  307. pNextChar += dwRegValueSize / sizeof (WCHAR);
  308. }
  309. dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  310. } else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  311. // no room for this string, but keep the required
  312. // total;
  313. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = NULL;
  314. } else {
  315. // it's an empty buffer
  316. }
  317. } else {
  318. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  319. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = NULL;
  320. }
  321. }
  322. // if the filename doesn't specify a directory, then use the
  323. lstrcpyW (szTempFilePath, szRegString);
  324. _wsplitpath ((LPCWSTR)szTempFilePath, szDriveName, szRegString,
  325. NULL, NULL);
  326. if ((lstrlenW(szDriveName) == 0) && (lstrlenW(szRegString) == 0)) {
  327. // default log file directory
  328. dwRegValType = 0;
  329. dwRegValueSize = MAX_PATH * sizeof(WCHAR);
  330. memset (szRegString, 0, dwRegValueSize);
  331. lStatus = RegQueryValueExW (
  332. hKeyLogQuery,
  333. cszLogDefaultDir,
  334. NULL,
  335. &dwRegValType,
  336. (LPBYTE)&szRegString[0],
  337. &dwRegValueSize);
  338. } else {
  339. // the file parsing function leaves the trailing backslash
  340. // so remove it before concatenating it.
  341. dwSize = lstrlenW(szRegString);
  342. if (dwSize > 0) {
  343. if (szRegString[dwSize-1] == L'\\') {
  344. szRegString[dwSize-1] = 0;
  345. }
  346. lStatus = ERROR_SUCCESS;
  347. dwRegValType = REG_SZ;
  348. dwRegValueSize = dwSize;
  349. } else {
  350. lStatus = ERROR_FILE_NOT_FOUND;
  351. }
  352. }
  353. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
  354. dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  355. if (dwRequiredSize <= *pdwBufferSize) {
  356. if (bWideChar) {
  357. // copy widestrings
  358. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = pNextWideChar;
  359. lstrcpyW (pNextWideChar, szRegString);
  360. pNextWideChar += dwRegValueSize / sizeof (WCHAR);
  361. } else {
  362. // convert to ansi char
  363. ((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->szDefaultDir = pNextChar;
  364. wcstombs (pNextChar, szRegString, (dwRegValueSize /sizeof(WCHAR)));
  365. pNextChar += dwRegValueSize / sizeof (WCHAR);
  366. }
  367. dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  368. } else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  369. // no room for this string, but keep the required
  370. // total;
  371. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = NULL;
  372. } else {
  373. // no buffer for this
  374. }
  375. } else {
  376. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  377. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = NULL;
  378. }
  379. }
  380. } else {
  381. // get values for controls
  382. dwRegValType = 0;
  383. dwRegValueSize = MAX_PATH * sizeof(WCHAR);
  384. memset (szRegString, 0, dwRegValueSize);
  385. lStatus = RegQueryValueExW (
  386. hKeyLogQuery,
  387. cszLogDefaultDir,
  388. NULL,
  389. &dwRegValType,
  390. (LPBYTE)&szRegString[0],
  391. &dwRegValueSize);
  392. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
  393. dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  394. if (dwRequiredSize <= *pdwBufferSize) {
  395. if (bWideChar) {
  396. // copy widestrings
  397. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = pNextWideChar;
  398. lstrcpyW (pNextWideChar, szRegString);
  399. pNextWideChar += dwRegValueSize / sizeof (WCHAR);
  400. } else {
  401. // convert to ansi char
  402. ((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->szDefaultDir = pNextChar;
  403. wcstombs (pNextChar, szRegString, (dwRegValueSize/sizeof(WCHAR)));
  404. pNextChar += dwRegValueSize / sizeof (WCHAR);
  405. }
  406. dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  407. } else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  408. // no room for this string, but keep the required
  409. // total;
  410. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = NULL;
  411. } else {
  412. // no room for anything
  413. }
  414. } else {
  415. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  416. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szDefaultDir = NULL;
  417. }
  418. }
  419. // base filename
  420. dwRegValType = 0;
  421. dwRegValueSize = MAX_PATH * sizeof(WCHAR);
  422. memset (szRegString, 0, dwRegValueSize);
  423. lStatus = RegQueryValueExW (
  424. hKeyLogQuery,
  425. cszBaseFileName,
  426. NULL,
  427. &dwRegValType,
  428. (LPBYTE)&szRegString[0],
  429. &dwRegValueSize);
  430. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
  431. dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  432. if (dwRequiredSize <= *pdwBufferSize) {
  433. if (bWideChar) {
  434. // copy widestrings
  435. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = pNextWideChar;
  436. lstrcpyW (pNextWideChar, szRegString);
  437. pNextWideChar += dwRegValueSize / sizeof (WCHAR);
  438. } else {
  439. // convert to ansi char
  440. ((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->szBaseFileName = pNextChar;
  441. wcstombs (pNextChar, szRegString, (dwRegValueSize/sizeof(WCHAR)));
  442. pNextChar += dwRegValueSize / sizeof (WCHAR);
  443. }
  444. dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  445. } else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  446. // no room for this string, but keep the required
  447. // total;
  448. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = NULL;
  449. } else {
  450. // no buffer
  451. }
  452. } else {
  453. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  454. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->szBaseFileName = NULL;
  455. }
  456. }
  457. // get auto name format
  458. dwRegValType = 0;
  459. dwRegValue = 0;
  460. dwRegValueSize = sizeof(DWORD);
  461. lStatus = RegQueryValueExW (
  462. hKeyLogQuery,
  463. cszLogFileAutoFormat,
  464. NULL,
  465. &dwRegValType,
  466. (LPBYTE)&dwRegValue,
  467. &dwRegValueSize);
  468. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  469. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_DWORD)) {
  470. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameFormat = dwRegValue;
  471. } else {
  472. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameFormat = PDH_LOGSVC_NAME_UNDEFINED;
  473. }
  474. }
  475. dwRegValType = 0;
  476. dwRegValue = 0;
  477. dwRegValueSize = sizeof(DWORD);
  478. lStatus = RegQueryValueExW (
  479. hKeyLogQuery,
  480. cszAutoRenameUnits,
  481. NULL,
  482. &dwRegValType,
  483. (LPBYTE)&dwRegValue,
  484. &dwRegValueSize);
  485. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  486. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_DWORD)) {
  487. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameUnits = dwRegValue;
  488. } else {
  489. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlAutoNameUnits = PDH_LOGSVC_RENAME_UNDEFINED;
  490. }
  491. }
  492. dwRegValType = 0;
  493. dwRegValueSize = MAX_PATH * sizeof(WCHAR);
  494. memset (szRegString, 0, dwRegValueSize);
  495. lStatus = RegQueryValueExW (
  496. hKeyLogQuery,
  497. cszCommandFile,
  498. NULL,
  499. &dwRegValType,
  500. (LPBYTE)&szRegString[0],
  501. &dwRegValueSize);
  502. if ((lStatus == ERROR_SUCCESS) && (dwRegValType == REG_SZ)) {
  503. dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  504. if (dwRequiredSize <= *pdwBufferSize) {
  505. if (bWideChar) {
  506. // copy widestrings
  507. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCommandFilename = pNextWideChar;
  508. lstrcpyW (pNextWideChar, szRegString);
  509. pNextWideChar += dwRegValueSize / sizeof (WCHAR);
  510. } else {
  511. // convert to ansi char
  512. ((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->PdlCommandFilename = pNextChar;
  513. wcstombs (pNextChar, szRegString, (dwRegValueSize/sizeof(WCHAR)));
  514. pNextChar += dwRegValueSize / sizeof (WCHAR);
  515. }
  516. dwRemainingSize -= dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  517. } else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  518. // no room for this string, but keep the required
  519. // total;
  520. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCommandFilename = NULL;
  521. } else {
  522. // no buffer
  523. }
  524. } else {
  525. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  526. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCommandFilename = NULL;
  527. }
  528. }
  529. }
  530. // get counter string!
  531. // find out buffer size required
  532. dwRegValType = 0;
  533. dwRegValue = 0;
  534. dwRegValueSize = 0;
  535. lStatus = RegQueryValueExW (
  536. hKeyLogQuery,
  537. cszCounterList,
  538. NULL,
  539. &dwRegValType,
  540. NULL,
  541. &dwRegValueSize);
  542. if (dwRegValueSize > 0) {
  543. // there's room in the caller's buffer so go ahead and
  544. // fill it
  545. dwRequiredSize += dwRegValueSize / (sizeof(WCHAR) / dwCharSize);
  546. if (dwRequiredSize <= *pdwBufferSize) {
  547. dwRegValueSize = dwRemainingSize;
  548. dwRegValType = 0;
  549. dwRegValue = 0;
  550. if (bWideChar) {
  551. lStatus = RegQueryValueExW (
  552. hKeyLogQuery,
  553. cszCounterList,
  554. NULL,
  555. &dwRegValType,
  556. (LPBYTE)pNextWideChar,
  557. &dwRegValueSize);
  558. if (lStatus == ERROR_SUCCESS) {
  559. // assign pointer to buffer
  560. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCounterList = pNextWideChar;
  561. pNextWideChar += dwRegValueSize / sizeof (WCHAR);
  562. dwRemainingSize -= dwRegValueSize;
  563. } else {
  564. // assign null pointer
  565. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCounterList = NULL;
  566. }
  567. } else {
  568. lStatus = RegQueryValueExA (
  569. hKeyLogQuery,
  570. caszCounterList,
  571. NULL,
  572. &dwRegValType,
  573. (LPBYTE)pNextChar,
  574. &dwRegValueSize);
  575. if (lStatus == ERROR_SUCCESS) {
  576. // assign pointer to buffer
  577. ((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->PdlCounterList = pNextChar;
  578. pNextChar += dwRegValueSize;
  579. dwRemainingSize -= dwRegValueSize;
  580. } else {
  581. // assign null pointer
  582. ((PPDH_LOG_SERVICE_QUERY_INFO_A)pInfoBuffer)->PdlCounterList = NULL;
  583. }
  584. }
  585. } else {
  586. // no room so don't copy anything
  587. }
  588. } else if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  589. // no counters defined so return NULL
  590. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->PdlCounterList = NULL;
  591. } else {
  592. // no buffer
  593. }
  594. } //end if registry opened ok
  595. // close open registry keys
  596. if (hKeyMachine != NULL) RegCloseKey (hKeyMachine);
  597. if (hKeyLogSettings != NULL) RegCloseKey (hKeyLogSettings);
  598. if (hKeyLogQuery != NULL) RegCloseKey (hKeyLogQuery);
  599. // test to see if the buffer estimate and pointer location line up
  600. // assuming it was big enough in the first place
  601. assert ((dwRequiredSize <= *pdwBufferSize) ?
  602. ((pNextChar != NULL) ? (dwRequiredSize == ((DWORD)pNextChar - (DWORD)pInfoBuffer)) :
  603. (dwRequiredSize == ((DWORD)pNextWideChar - (DWORD)pInfoBuffer))) : TRUE);
  604. if (lStatus == ERROR_SUCCESS) {
  605. if (*pdwBufferSize >= sizeof(PDH_LOG_SERVICE_QUERY_INFO_W)) {
  606. // if there's enough buffer to write this...
  607. if (*pdwBufferSize >= dwRequiredSize) {
  608. // and there was enough for the requested data
  609. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->dwSize = dwRequiredSize;
  610. } else {
  611. // return the amount used
  612. ((PPDH_LOG_SERVICE_QUERY_INFO_W)pInfoBuffer)->dwSize = *pdwBufferSize;
  613. }
  614. }
  615. }
  616. // save required size
  617. *pdwBufferSize = dwRequiredSize;
  618. return pdhStatus;
  619. }
  620. PDH_FUNCTION
  621. PdhLogServiceCommandA (
  622. IN LPCSTR szMachineName,
  623. IN LPCSTR szQueryName,
  624. IN DWORD dwFlags,
  625. IN LPDWORD pdwStatus
  626. )
  627. {
  628. LPWSTR wszQueryName = NULL;
  629. LPWSTR wszMachineName = NULL;
  630. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  631. // test access to query name
  632. if (szQueryName != NULL) {
  633. DWORD dwNameLength = 0;
  634. try {
  635. CHAR cTest;
  636. cTest = szQueryName[0];
  637. dwNameLength = lstrlenA (szQueryName);
  638. } except (EXCEPTION_EXECUTE_HANDLER) {
  639. // unable to access name argument
  640. pdhStatus = PDH_INVALID_ARGUMENT;
  641. }
  642. if (pdhStatus == ERROR_SUCCESS) {
  643. // allocate wide name buffer
  644. wszQueryName = G_ALLOC ((dwNameLength + 1) * sizeof (WCHAR));
  645. if (wszQueryName != NULL) {
  646. mbstowcs (wszQueryName, szQueryName, dwNameLength);
  647. } else {
  648. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  649. }
  650. }
  651. } else {
  652. // make a null arg for the function
  653. wszQueryName = NULL;
  654. }
  655. if ((szMachineName != NULL) && (pdhStatus == ERROR_SUCCESS)) {
  656. DWORD dwNameLength = 0;
  657. try {
  658. CHAR cTest;
  659. cTest = szMachineName[0];
  660. dwNameLength = lstrlenA (szMachineName);
  661. } except (EXCEPTION_EXECUTE_HANDLER) {
  662. // unable to access name argument
  663. pdhStatus = PDH_INVALID_ARGUMENT;
  664. }
  665. if (pdhStatus == ERROR_SUCCESS) {
  666. // allocate wide name buffer
  667. wszMachineName = G_ALLOC ((dwNameLength + 1) * sizeof (WCHAR));
  668. if (wszMachineName != NULL) {
  669. mbstowcs (wszMachineName, szMachineName, dwNameLength);
  670. } else {
  671. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  672. }
  673. }
  674. } else {
  675. // make a null arg for the function
  676. wszMachineName = NULL;
  677. }
  678. if (pdhStatus == ERROR_SUCCESS) {
  679. // call wide string version
  680. pdhStatus = PdhLogServiceCommandW (
  681. wszMachineName,
  682. wszQueryName,
  683. dwFlags,
  684. pdwStatus);
  685. }
  686. if (wszQueryName != NULL) G_FREE (wszQueryName);
  687. if (wszMachineName != NULL) G_FREE (wszMachineName);
  688. return pdhStatus;
  689. }
  690. PDH_FUNCTION
  691. PdhLogServiceCommandW (
  692. IN LPCWSTR szMachineName,
  693. IN LPCWSTR szQueryName,
  694. IN DWORD dwFlags,
  695. IN LPDWORD pdwStatus
  696. )
  697. {
  698. SC_HANDLE hSC = NULL;
  699. SC_HANDLE hService = NULL;
  700. SERVICE_STATUS ssData;
  701. DWORD dwTimeout;
  702. DWORD dwStatus;
  703. BOOL bStopped = FALSE;
  704. BOOL bPaused = FALSE;
  705. LONG lStatus = ERROR_SUCCESS;
  706. BOOL bWait;
  707. LPWSTR szLocalQueryName = NULL;
  708. // test arguments
  709. try {
  710. WCHAR wcTest;
  711. DWORD dwTest;
  712. if (szMachineName != NULL) {
  713. wcTest = szMachineName[0];
  714. } // null is valid for the local machine
  715. if (szQueryName != NULL) {
  716. wcTest = szQueryName[0];
  717. } // null is a valid query name.
  718. if (pdwStatus != NULL) {
  719. dwTest = *pdwStatus;
  720. *pdwStatus = 0;
  721. *pdwStatus = dwTest;
  722. }
  723. } except (EXCEPTION_EXECUTE_HANDLER) {
  724. lStatus = PDH_INVALID_ARGUMENT;
  725. }
  726. if (lStatus == ERROR_SUCCESS) {
  727. if ((dwFlags & PDH_LOGSVC_TRACE_LOG) == PDH_LOGSVC_TRACE_LOG) {
  728. lStatus = PDH_NOT_IMPLEMENTED;
  729. } else {
  730. // this must be a perf log command
  731. // open SC database
  732. hSC = OpenSCManagerW (szMachineName, NULL, SC_MANAGER_ALL_ACCESS);
  733. if (hSC == NULL) {
  734. // open service
  735. hService = OpenServiceW (hSC, cszPerfDataLog,
  736. SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL);
  737. } // else hService will still be NULL so get the last error below
  738. if (hService != NULL) {
  739. // determine wait flag value
  740. bWait = (dwFlags & PDH_LOGSVC_NO_WAIT) ? FALSE : TRUE;
  741. if (szQueryName == NULL) {
  742. if ((dwFlags & PDH_LOGSVC_ALL_QUERIES) == PDH_LOGSVC_ALL_QUERIES) {
  743. // start / stop the service and all log queries
  744. if ((dwFlags & PDH_LOGSVC_CMD_START) == PDH_LOGSVC_CMD_START) {
  745. // start the service and start all logs set to run
  746. StartService (hService, 0, NULL);
  747. if ( bWait ) {
  748. // wait for the service to start before returning
  749. dwTimeout = 20;
  750. while (dwTimeout) {
  751. GetCurrentServiceState (hService, &bStopped, &bPaused);
  752. if (bStopped) {
  753. Sleep(500);
  754. } else {
  755. break;
  756. }
  757. --dwTimeout;
  758. }
  759. if (bStopped) {
  760. dwStatus = PDH_LOGSVC_STATUS_STOPPED;
  761. } else if (bPaused) {
  762. dwStatus = PDH_LOGSVC_STATUS_PAUSED;
  763. } else {
  764. dwStatus = PDH_LOGSVC_STATUS_RUNNING;
  765. }
  766. } else {
  767. dwStatus = PDH_LOGSVC_STATUS_PENDING;
  768. }
  769. } else if ((dwFlags & PDH_LOGSVC_CMD_STOP) == PDH_LOGSVC_CMD_STOP) {
  770. ControlService (hService, SERVICE_CONTROL_STOP, &ssData);
  771. if ( bWait ) {
  772. // wait for the service to stop before returning
  773. dwTimeout = 20;
  774. while (dwTimeout) {
  775. GetCurrentServiceState (hService, &bStopped, &bPaused);
  776. if (!bStopped) {
  777. Sleep(500);
  778. } else {
  779. break;
  780. }
  781. --dwTimeout;
  782. }
  783. if (bStopped) {
  784. dwStatus = PDH_LOGSVC_STATUS_STOPPED;
  785. } else if (bPaused) {
  786. dwStatus = PDH_LOGSVC_STATUS_PAUSED;
  787. } else {
  788. dwStatus = PDH_LOGSVC_STATUS_RUNNING;
  789. }
  790. }
  791. } else {
  792. // unknown operation
  793. lStatus = PDH_UNKNOWN_LOGSVC_COMMAND;
  794. }
  795. } else {
  796. // this is just a generic log command.
  797. szLocalQueryName = (LPWSTR)cszDefault;
  798. }
  799. }
  800. if (szLocalQueryName != NULL) {
  801. // then this command is for a named service
  802. lStatus = PdhiSetLogQueryState (
  803. szMachineName,
  804. szLocalQueryName,
  805. (dwFlags & (PDH_LOGSVC_CMD_START | PDH_LOGSVC_CMD_STOP)));
  806. if (lStatus == ERROR_SUCCESS) {
  807. // service entry was updated to desired status
  808. if (!ControlService (hService,
  809. SERVICE_CONTROL_PARAMCHANGE, &ssData)) {
  810. lStatus = GetLastError ();
  811. }
  812. lStatus = PdhiGetLogQueryState (
  813. hService, szMachineName,
  814. szLocalQueryName, &dwStatus);
  815. }
  816. }
  817. CloseServiceHandle (hService);
  818. } else {
  819. lStatus = GetLastError();
  820. assert (lStatus != 0);
  821. }
  822. // close handles
  823. if (hSC != NULL) CloseServiceHandle (hSC);
  824. }
  825. }
  826. return lStatus;
  827. }
  828. PDH_FUNCTION
  829. PdhLogServiceControlA (
  830. IN LPCSTR szMachineName,
  831. IN LPCSTR szQueryName,
  832. IN DWORD dwFlags,
  833. IN PPDH_LOG_SERVICE_QUERY_INFO_A pInfoBuffer,
  834. IN LPDWORD pdwBufferSize
  835. )
  836. {
  837. LPWSTR wszQueryName = NULL;
  838. LPWSTR wszMachineName = NULL;
  839. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  840. DWORD dwCmdFn;
  841. // test access to query name
  842. if (szQueryName != NULL) {
  843. DWORD dwNameLength = 0;
  844. try {
  845. CHAR cTest;
  846. cTest = szQueryName[0];
  847. dwNameLength = lstrlenA (szQueryName);
  848. } except (EXCEPTION_EXECUTE_HANDLER) {
  849. // unable to access name argument
  850. pdhStatus = PDH_INVALID_ARGUMENT;
  851. }
  852. if (pdhStatus == ERROR_SUCCESS) {
  853. // allocate wide name buffer
  854. wszQueryName = G_ALLOC ((dwNameLength + 1) * sizeof (WCHAR));
  855. if (wszQueryName != NULL) {
  856. mbstowcs (wszQueryName, szQueryName, dwNameLength);
  857. } else {
  858. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  859. }
  860. }
  861. } else {
  862. // make a null arg for the function
  863. wszQueryName = NULL;
  864. }
  865. if ((szMachineName != NULL) && (pdhStatus == ERROR_SUCCESS)) {
  866. DWORD dwNameLength = 0;
  867. try {
  868. CHAR cTest;
  869. cTest = szMachineName[0];
  870. dwNameLength = lstrlenA (szMachineName);
  871. } except (EXCEPTION_EXECUTE_HANDLER) {
  872. // unable to access name argument
  873. pdhStatus = PDH_INVALID_ARGUMENT;
  874. }
  875. if (pdhStatus == ERROR_SUCCESS) {
  876. // allocate wide name buffer
  877. wszMachineName = G_ALLOC ((dwNameLength + 1) * sizeof (WCHAR));
  878. if (wszMachineName != NULL) {
  879. mbstowcs (wszMachineName, szMachineName, dwNameLength);
  880. } else {
  881. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  882. }
  883. }
  884. } else {
  885. // make a null arg for the function
  886. wszMachineName = NULL;
  887. }
  888. if (pdhStatus == ERROR_SUCCESS) {
  889. try {
  890. DWORD dwTest;
  891. if (pdwBufferSize != NULL) {
  892. dwTest = *pdwBufferSize;
  893. *pdwBufferSize = 0;
  894. *pdwBufferSize = dwTest;
  895. } else {
  896. // null is NOT valid
  897. pdhStatus = PDH_INVALID_ARGUMENT;
  898. }
  899. } except (EXCEPTION_EXECUTE_HANDLER) {
  900. pdhStatus = PDH_INVALID_ARGUMENT;
  901. }
  902. }
  903. if (pdhStatus == ERROR_SUCCESS) {
  904. // dispatch to "action" function based on command code
  905. dwCmdFn = dwFlags & PDH_LOGSVC_CTRL_FNMASK;
  906. switch (dwCmdFn) {
  907. case PDH_LOGSVC_CTRL_ADD:
  908. // call universal string version
  909. pdhStatus = PdhiLogServiceAddCommandT (
  910. wszMachineName,
  911. wszQueryName,
  912. dwFlags,
  913. (LPVOID)pInfoBuffer,
  914. pdwBufferSize,
  915. FALSE);
  916. break;
  917. case PDH_LOGSVC_CTRL_REMOVE:
  918. // call universal string version
  919. pdhStatus = PdhiLogServiceRemoveCommandT (
  920. wszMachineName,
  921. wszQueryName,
  922. dwFlags,
  923. (LPVOID)pInfoBuffer,
  924. pdwBufferSize,
  925. FALSE);
  926. break;
  927. case PDH_LOGSVC_CTRL_INFO:
  928. // call universal string version
  929. pdhStatus = PdhiLogServiceInfoCommandT (
  930. wszMachineName,
  931. wszQueryName,
  932. dwFlags,
  933. (LPVOID)pInfoBuffer,
  934. pdwBufferSize,
  935. FALSE);
  936. break;
  937. default:
  938. pdhStatus = PDH_INVALID_ARGUMENT;
  939. break;
  940. }
  941. }
  942. if (wszQueryName != NULL) G_FREE (wszQueryName);
  943. if (wszMachineName != NULL) G_FREE (wszMachineName);
  944. return pdhStatus;
  945. }
  946. PDH_FUNCTION
  947. PdhLogServiceControlW (
  948. IN LPCWSTR szMachineName,
  949. IN LPCWSTR szQueryName,
  950. IN DWORD dwFlags,
  951. IN PPDH_LOG_SERVICE_QUERY_INFO_W pInfoBuffer,
  952. IN LPDWORD pdwBufferSize
  953. )
  954. {
  955. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  956. DWORD dwCmdFn;
  957. // test access to query name
  958. if (szQueryName != NULL) {
  959. WCHAR cTest;
  960. try {
  961. cTest = szQueryName[0];
  962. if (cTest == 0) {
  963. pdhStatus = PDH_INVALID_ARGUMENT;
  964. }
  965. } except (EXCEPTION_EXECUTE_HANDLER) {
  966. // unable to access name argument
  967. pdhStatus = PDH_INVALID_ARGUMENT;
  968. }
  969. } else {
  970. // NULL is OK
  971. }
  972. // test access to machine name
  973. if ((szMachineName != NULL) && (pdhStatus == ERROR_SUCCESS)) {
  974. WCHAR cTest;
  975. try {
  976. cTest = szMachineName[0];
  977. if (cTest == 0) {
  978. pdhStatus = PDH_INVALID_ARGUMENT;
  979. }
  980. } except (EXCEPTION_EXECUTE_HANDLER) {
  981. // unable to access name argument
  982. pdhStatus = PDH_INVALID_ARGUMENT;
  983. }
  984. } else {
  985. // NULL is OK
  986. }
  987. if (pdhStatus == ERROR_SUCCESS) {
  988. try {
  989. DWORD dwTest;
  990. if (pdwBufferSize != NULL) {
  991. dwTest = *pdwBufferSize;
  992. *pdwBufferSize = 0;
  993. *pdwBufferSize = dwTest;
  994. } else {
  995. // null is NOT valid
  996. pdhStatus = PDH_INVALID_ARGUMENT;
  997. }
  998. } except (EXCEPTION_EXECUTE_HANDLER) {
  999. pdhStatus = PDH_INVALID_ARGUMENT;
  1000. }
  1001. }
  1002. if (pdhStatus == ERROR_SUCCESS) {
  1003. // dispatch to "action" function based on command code
  1004. dwCmdFn = dwFlags & PDH_LOGSVC_CTRL_FNMASK;
  1005. switch (dwCmdFn) {
  1006. case PDH_LOGSVC_CTRL_ADD:
  1007. // call universal string version
  1008. pdhStatus = PdhiLogServiceAddCommandT (
  1009. szMachineName,
  1010. szQueryName,
  1011. dwFlags,
  1012. (LPVOID)pInfoBuffer,
  1013. pdwBufferSize,
  1014. TRUE);
  1015. break;
  1016. case PDH_LOGSVC_CTRL_REMOVE:
  1017. // call universal string version
  1018. pdhStatus = PdhiLogServiceRemoveCommandT (
  1019. szMachineName,
  1020. szQueryName,
  1021. dwFlags,
  1022. (LPVOID)pInfoBuffer,
  1023. pdwBufferSize,
  1024. TRUE);
  1025. break;
  1026. case PDH_LOGSVC_CTRL_INFO:
  1027. // call universal string version
  1028. pdhStatus = PdhiLogServiceInfoCommandT (
  1029. szMachineName,
  1030. szQueryName,
  1031. dwFlags,
  1032. (LPVOID)pInfoBuffer,
  1033. pdwBufferSize,
  1034. TRUE);
  1035. break;
  1036. default:
  1037. pdhStatus = PDH_INVALID_ARGUMENT;
  1038. break;
  1039. }
  1040. }
  1041. return pdhStatus;
  1042. }