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.

1827 lines
56 KiB

  1. /*++
  2. Copyright (c) 1991-1999 Microsoft Corporation
  3. Module Name:
  4. unlodctr.c
  5. Abstract:
  6. Program to remove the counter names belonging to the driver specified
  7. in the command line and update the registry accordingly
  8. Author:
  9. Bob Watson (a-robw) 12 Feb 93
  10. Revision History:
  11. Bob Watson (bobw) 10 Mar 99 added event log messages
  12. --*/
  13. #ifndef UNICODE
  14. #define UNICODE 1
  15. #endif
  16. #ifndef _UNICODE
  17. #define _UNICODE 1
  18. #endif
  19. //
  20. // "C" Include files
  21. //
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <malloc.h>
  26. //
  27. // Windows Include files
  28. //
  29. #include <windows.h>
  30. #define __LOADPERF__
  31. #include <loadperf.h>
  32. #include <tchar.h>
  33. #include "wmistr.h"
  34. #include "evntrace.h"
  35. //
  36. // local include files
  37. //
  38. #include "winperfp.h"
  39. #include "common.h"
  40. #include "unlodctr.h"
  41. #include "mofcomp.h"
  42. #include "ldprfmsg.h"
  43. // version number for NT 1.0
  44. #define OLD_VERSION 0x010000
  45. static DWORD dwSystemVersion; // PerfLib version number
  46. static DWORD dwHelpItems; // number of explain text items
  47. static DWORD dwCounterItems; // number of counter text items
  48. static DWORD dwLastCounter;
  49. static DWORD dwLastHelp;
  50. static TCHAR ComputerName[MAX_PATH];
  51. static HKEY hPerfData; // handle to remote machine HKEY_PERFORMANCE_DATA
  52. static BOOL bQuietMode = TRUE; // quiet means no _tprintf's
  53. #define OUTPUT_MESSAGE if (!bQuietMode) _tprintf
  54. static
  55. LPTSTR
  56. *BuildNameTable(
  57. IN HKEY hKeyPerflib, // handle to perflib key with counter names
  58. IN LPTSTR lpszLangId, // unicode value of Language subkey
  59. OUT PDWORD pdwLastItem, // size of array in elements
  60. OUT HKEY *hKeyNames,
  61. OUT LPTSTR CounterNameBuffer, // New version counter name key
  62. OUT LPTSTR HelpNameBuffer // New version help name key
  63. )
  64. /*++
  65. BuildNameTable
  66. Caches the counter names and explain text to accelerate name lookups
  67. for display.
  68. Arguments:
  69. hKeyPerflib
  70. Handle to an open registry (this can be local or remote.) and
  71. is the value returned by RegConnectRegistry or a default key.
  72. lpszLangId
  73. The unicode id of the language to look up. (default is 009)
  74. pdwLastItem
  75. The last array element
  76. Return Value:
  77. pointer to an allocated table. (the caller must free it when finished!)
  78. the table is an array of pointers to zero terminated TEXT strings.
  79. A NULL pointer is returned if an error occured. (error value is
  80. available using the GetLastError function).
  81. The structure of the buffer returned is:
  82. Array of pointers to zero terminated strings consisting of
  83. pdwLastItem elements
  84. MULTI_SZ string containing counter id's and names returned from
  85. registry for the specified language
  86. MULTI_SZ string containing explain text id's and explain text strings
  87. as returned by the registry for the specified language
  88. The structures listed above are contiguous so that they may be freed
  89. by a single "free" call when finished with them, however only the
  90. array elements are intended to be used.
  91. --*/
  92. {
  93. LPTSTR *lpReturnValue; // returned pointer to buffer
  94. LPTSTR *lpCounterId; //
  95. LPTSTR lpCounterNames; // pointer to Names buffer returned by reg.
  96. LPTSTR lpHelpText ; // pointet to exlpain buffer returned by reg.
  97. LPTSTR lpThisName; // working pointer
  98. BOOL bStatus; // return status from TRUE/FALSE fn. calls
  99. LONG lWin32Status; // return status from fn. calls
  100. DWORD dwValueType; // value type of buffer returned by reg.
  101. DWORD dwArraySize; // size of pointer array in bytes
  102. DWORD dwBufferSize; // size of total buffer in bytes
  103. DWORD dwCounterSize; // size of counter text buffer in bytes
  104. DWORD dwHelpSize; // size of help text buffer in bytes
  105. DWORD dwThisCounter; // working counter
  106. DWORD dwLastId; // largest ID value used by explain/counter text
  107. DWORD dwLastCounterIdUsed;
  108. DWORD dwLastHelpIdUsed;
  109. LPTSTR lpValueNameString; // pointer to buffer conatining subkey name
  110. //initialize pointers to NULL
  111. lpValueNameString = NULL;
  112. lpReturnValue = NULL;
  113. // check for null arguments and insert defaults if necessary
  114. if (!lpszLangId) {
  115. lpszLangId = (LPTSTR)DefaultLangId;
  116. }
  117. if (hKeyNames) {
  118. *hKeyNames = NULL;
  119. } else {
  120. SetLastError (ERROR_BAD_ARGUMENTS);
  121. return NULL;
  122. }
  123. // use the greater of Help items or Counter Items to size array
  124. if (dwHelpItems >= dwCounterItems) {
  125. dwLastId = dwHelpItems;
  126. } else {
  127. dwLastId = dwCounterItems;
  128. }
  129. // array size is # of elements (+ 1, since names are "1" based)
  130. // times the size of a pointer
  131. dwArraySize = (dwLastId + 1) * sizeof(LPTSTR);
  132. // allocate string buffer for language ID key string
  133. lpValueNameString = malloc (
  134. lstrlen(NamesKey) * sizeof (TCHAR) +
  135. lstrlen(Slash) * sizeof (TCHAR) +
  136. lstrlen(lpszLangId) * sizeof (TCHAR) +
  137. sizeof (TCHAR));
  138. if (!lpValueNameString) {
  139. lWin32Status = ERROR_OUTOFMEMORY;
  140. ReportLoadPerfEvent(
  141. EVENTLOG_ERROR_TYPE, // error type
  142. (DWORD) LDPRFMSG_MEMORY_ALLOCATION_FAILURE, // event,
  143. 0, 0, 0, 0,
  144. 0, NULL, NULL, NULL);
  145. TRACE((WINPERF_DBG_TRACE_ERROR),
  146. (& LoadPerfGuid,
  147. __LINE__,
  148. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  149. 0,
  150. lWin32Status,
  151. NULL));
  152. goto BNT_BAILOUT;
  153. }
  154. if (dwSystemVersion == OLD_VERSION) {
  155. lWin32Status = RegOpenKeyEx ( // get handle to this key in the
  156. hKeyPerflib, // registry
  157. lpszLangId,
  158. RESERVED,
  159. KEY_READ | KEY_WRITE,
  160. hKeyNames);
  161. } else {
  162. // *hKeyNames = HKEY_PERFORMANCE_DATA;
  163. *hKeyNames = hPerfData;
  164. lstrcpy (CounterNameBuffer, CounterNameStr);
  165. lstrcat (CounterNameBuffer, lpszLangId);
  166. lstrcpy (HelpNameBuffer, HelpNameStr);
  167. lstrcat (HelpNameBuffer, lpszLangId);
  168. lWin32Status = ERROR_SUCCESS;
  169. }
  170. if (lWin32Status != ERROR_SUCCESS) {
  171. ReportLoadPerfEvent(
  172. EVENTLOG_ERROR_TYPE, // error type
  173. (DWORD) LDPRFMSG_UNABLE_ACCESS_STRINGS, // event,
  174. 1, lWin32Status, 0, 0,
  175. 1, lpszLangId, NULL, NULL);
  176. TRACE((WINPERF_DBG_TRACE_ERROR),
  177. (& LoadPerfGuid,
  178. __LINE__,
  179. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  180. ARG_DEF(ARG_TYPE_WSTR, 1),
  181. lWin32Status,
  182. TRACE_WSTR(lpszLangId),
  183. NULL));
  184. goto BNT_BAILOUT;
  185. }
  186. // get size of counter names
  187. dwBufferSize = 0;
  188. lWin32Status = RegQueryValueEx (
  189. *hKeyNames,
  190. dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer,
  191. RESERVED,
  192. &dwValueType,
  193. NULL,
  194. &dwBufferSize);
  195. if (lWin32Status != ERROR_SUCCESS) {
  196. ReportLoadPerfEvent(
  197. EVENTLOG_ERROR_TYPE, // error type
  198. (DWORD) LDPRFMSG_UNABLE_READ_COUNTER_STRINGS, // event,
  199. 1, lWin32Status, 0, 0,
  200. 1, lpszLangId, NULL, NULL);
  201. TRACE((WINPERF_DBG_TRACE_ERROR),
  202. (& LoadPerfGuid,
  203. __LINE__,
  204. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  205. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  206. lWin32Status,
  207. TRACE_WSTR(lpszLangId),
  208. TRACE_WSTR(Counters),
  209. TRACE_DWORD(dwSystemVersion),
  210. TRACE_DWORD(dwBufferSize),
  211. NULL));
  212. goto BNT_BAILOUT;
  213. }
  214. dwCounterSize = dwBufferSize;
  215. // get size of help text
  216. dwBufferSize = 0;
  217. lWin32Status = RegQueryValueEx (
  218. *hKeyNames,
  219. dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer,
  220. RESERVED,
  221. &dwValueType,
  222. NULL,
  223. &dwBufferSize);
  224. if (lWin32Status != ERROR_SUCCESS) {
  225. ReportLoadPerfEvent(
  226. EVENTLOG_ERROR_TYPE, // error type
  227. (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event,
  228. 1, lWin32Status, 0, 0,
  229. 1, lpszLangId, NULL, NULL);
  230. TRACE((WINPERF_DBG_TRACE_ERROR),
  231. (& LoadPerfGuid,
  232. __LINE__,
  233. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  234. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  235. lWin32Status,
  236. TRACE_WSTR(lpszLangId),
  237. TRACE_WSTR(Help),
  238. TRACE_DWORD(dwSystemVersion),
  239. TRACE_DWORD(dwBufferSize),
  240. NULL));
  241. goto BNT_BAILOUT;
  242. }
  243. dwHelpSize = dwBufferSize;
  244. // allocate buffer with room for pointer array, counter name
  245. // strings and help name strings
  246. lpReturnValue = malloc (dwArraySize + dwCounterSize + dwHelpSize);
  247. if (!lpReturnValue) {
  248. ReportLoadPerfEvent(
  249. EVENTLOG_ERROR_TYPE, // error type
  250. (DWORD) LDPRFMSG_MEMORY_ALLOCATION_FAILURE, // event,
  251. 0, 0, 0, 0,
  252. 0, NULL, NULL, NULL);
  253. lWin32Status = ERROR_OUTOFMEMORY;
  254. TRACE((WINPERF_DBG_TRACE_ERROR),
  255. (& LoadPerfGuid,
  256. __LINE__,
  257. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  258. 0,
  259. lWin32Status,
  260. TRACE_DWORD(dwArraySize),
  261. TRACE_DWORD(dwCounterSize),
  262. TRACE_DWORD(dwHelpSize),
  263. NULL));
  264. goto BNT_BAILOUT;
  265. }
  266. // initialize buffer
  267. memset (lpReturnValue, 0, _msize(lpReturnValue));
  268. // initialize pointers into buffer
  269. lpCounterId = lpReturnValue;
  270. lpCounterNames = (LPTSTR)((LPBYTE)lpCounterId + dwArraySize);
  271. lpHelpText = (LPTSTR)((LPBYTE)lpCounterNames + dwCounterSize);
  272. // read counter names into buffer. Counter names will be stored as
  273. // a MULTI_SZ string in the format of "###" "Name"
  274. dwBufferSize = dwCounterSize;
  275. lWin32Status = RegQueryValueEx (
  276. *hKeyNames,
  277. dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer,
  278. RESERVED,
  279. &dwValueType,
  280. (LPVOID)lpCounterNames,
  281. &dwBufferSize);
  282. if (lWin32Status != ERROR_SUCCESS) {
  283. ReportLoadPerfEvent(
  284. EVENTLOG_ERROR_TYPE, // error type
  285. (DWORD) LDPRFMSG_UNABLE_READ_COUNTER_STRINGS, // event,
  286. 1, lWin32Status, 0, 0,
  287. 1, lpszLangId, NULL, NULL);
  288. TRACE((WINPERF_DBG_TRACE_ERROR),
  289. (& LoadPerfGuid,
  290. __LINE__,
  291. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  292. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  293. lWin32Status,
  294. TRACE_WSTR(lpszLangId),
  295. TRACE_WSTR(Counters),
  296. TRACE_DWORD(dwSystemVersion),
  297. TRACE_DWORD(dwBufferSize),
  298. NULL));
  299. goto BNT_BAILOUT;
  300. }
  301. // read explain text into buffer. Counter names will be stored as
  302. // a MULTI_SZ string in the format of "###" "Text..."
  303. dwBufferSize = dwHelpSize;
  304. lWin32Status = RegQueryValueEx (
  305. *hKeyNames,
  306. dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer,
  307. RESERVED,
  308. &dwValueType,
  309. (LPVOID)lpHelpText,
  310. &dwBufferSize);
  311. if (lWin32Status != ERROR_SUCCESS) {
  312. ReportLoadPerfEvent(
  313. EVENTLOG_ERROR_TYPE, // error type
  314. (DWORD) LDPRFMSG_UNABLE_READ_HELP_STRINGS, // event,
  315. 1, lWin32Status, 0, 0,
  316. 1, lpszLangId, NULL, NULL);
  317. TRACE((WINPERF_DBG_TRACE_ERROR),
  318. (& LoadPerfGuid,
  319. __LINE__,
  320. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  321. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  322. lWin32Status,
  323. TRACE_WSTR(lpszLangId),
  324. TRACE_WSTR(Help),
  325. TRACE_DWORD(dwSystemVersion),
  326. TRACE_DWORD(dwBufferSize),
  327. NULL));
  328. goto BNT_BAILOUT;
  329. }
  330. dwLastCounterIdUsed = 0;
  331. dwLastHelpIdUsed = 0;
  332. // load counter array items, by locating each text string
  333. // in the returned buffer and loading the
  334. // address of it in the corresponding pointer array element.
  335. for (lpThisName = lpCounterNames;
  336. *lpThisName;
  337. lpThisName += (lstrlen(lpThisName)+1) ) {
  338. // first string should be an integer (in decimal digit characters)
  339. // so translate to an integer for use in array element identification
  340. do {
  341. bStatus = StringToInt (lpThisName, &dwThisCounter);
  342. if (!bStatus) {
  343. ReportLoadPerfEvent(
  344. EVENTLOG_WARNING_TYPE, // error type
  345. (DWORD) LDPRFMSG_REGISTRY_CORRUPT_MULTI_SZ, // event,
  346. 0, 0, 0, 0,
  347. 2, CounterNameBuffer, lpThisName, NULL);
  348. TRACE((WINPERF_DBG_TRACE_WARNING),
  349. (& LoadPerfGuid,
  350. __LINE__,
  351. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  352. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  353. ERROR_BADKEY,
  354. TRACE_WSTR(Counters),
  355. TRACE_WSTR(lpThisName),
  356. NULL));
  357. lpThisName += (lstrlen(lpThisName) + 1);
  358. }
  359. }
  360. while ((! bStatus) && (* lpThisName));
  361. if (! bStatus) {
  362. lWin32Status = ERROR_BADKEY;
  363. goto BNT_BAILOUT; // bad entry
  364. }
  365. // point to corresponding counter name which follows the id number
  366. // string.
  367. lpThisName += (lstrlen(lpThisName)+1);
  368. // and load array element with pointer to string
  369. lpCounterId[dwThisCounter] = lpThisName;
  370. if (dwThisCounter > dwLastCounterIdUsed) dwLastCounterIdUsed = dwThisCounter;
  371. }
  372. // repeat the above for the explain text strings
  373. for (lpThisName = lpHelpText;
  374. *lpThisName;
  375. lpThisName += (lstrlen(lpThisName)+1) ) {
  376. // first string should be an integer (in decimal unicode digits)
  377. do {
  378. bStatus = StringToInt (lpThisName, &dwThisCounter);
  379. if (! bStatus) {
  380. ReportLoadPerfEvent(
  381. EVENTLOG_WARNING_TYPE, // error type
  382. (DWORD) LDPRFMSG_REGISTRY_CORRUPT_MULTI_SZ, // event,
  383. 0, 0, 0, 0,
  384. 2, HelpNameBuffer, lpThisName, NULL);
  385. TRACE((WINPERF_DBG_TRACE_WARNING),
  386. (& LoadPerfGuid,
  387. __LINE__,
  388. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  389. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  390. ERROR_BADKEY,
  391. TRACE_WSTR(Help),
  392. TRACE_WSTR(lpThisName),
  393. NULL));
  394. lpThisName += (lstrlen(lpThisName) + 1);
  395. }
  396. }
  397. while ((! bStatus) && (* lpThisName));
  398. if (!bStatus) {
  399. lWin32Status = ERROR_BADKEY;
  400. goto BNT_BAILOUT; // bad entry
  401. }
  402. // point to corresponding counter name
  403. lpThisName += (lstrlen(lpThisName)+1);
  404. // and load array element;
  405. lpCounterId[dwThisCounter] = lpThisName;
  406. if (dwThisCounter > dwLastHelpIdUsed) dwLastHelpIdUsed= dwThisCounter;
  407. }
  408. TRACE((WINPERF_DBG_TRACE_INFO),
  409. (& LoadPerfGuid,
  410. __LINE__,
  411. LOADPERF_UNLODCTR_BUILDNAMETABLE,
  412. 0,
  413. ERROR_SUCCESS,
  414. TRACE_DWORD(dwLastId),
  415. TRACE_DWORD(dwLastCounterIdUsed),
  416. TRACE_DWORD(dwLastHelpIdUsed),
  417. TRACE_DWORD(dwCounterItems),
  418. TRACE_DWORD(dwHelpItems),
  419. NULL));
  420. if (dwLastHelpIdUsed > dwLastId) {
  421. ReportLoadPerfEvent(
  422. EVENTLOG_ERROR_TYPE, // error type
  423. (DWORD) LDPRFMSG_REGISTRY_INDEX_CORRUPT, // event,
  424. 2, dwLastId, dwLastHelpIdUsed, 0,
  425. 0, NULL, NULL, NULL);
  426. lWin32Status = ERROR_BADKEY;
  427. goto BNT_BAILOUT; // bad registry
  428. }
  429. // if the last item arugment was used, then load the last ID value in it
  430. if (pdwLastItem) *pdwLastItem = dwLastId;
  431. // free the temporary buffer used
  432. if (lpValueNameString) {
  433. free ((LPVOID)lpValueNameString);
  434. }
  435. // exit returning the pointer to the buffer
  436. return lpReturnValue;
  437. BNT_BAILOUT:
  438. if (lWin32Status != ERROR_SUCCESS) {
  439. // if lWin32Status has error, then set last error value to it,
  440. // otherwise assume that last error already has value in it
  441. SetLastError (lWin32Status);
  442. }
  443. // free buffers used by this routine
  444. if (lpValueNameString) {
  445. free ((LPVOID)lpValueNameString);
  446. }
  447. if (lpReturnValue) {
  448. free ((LPVOID)lpReturnValue);
  449. }
  450. return NULL;
  451. } // BuildNameTable
  452. static
  453. BOOL
  454. GetDriverFromCommandLine (
  455. LPTSTR lpCommandLine,
  456. HKEY *hKeyMachine,
  457. LPTSTR lpDriverName,
  458. HKEY *hDriverPerf
  459. )
  460. /*++
  461. GetDriverFromCommandLine
  462. locates the first argument in the command line string (after the
  463. image name) and checks to see if
  464. a) it's there
  465. b) it's the name of a device driver listed in the
  466. Registry\Machine\System\CurrentControlSet\Services key
  467. in the registry and it has a "Performance" subkey
  468. c) that the "First Counter" value under the Performance subkey
  469. is defined.
  470. if all these criteria are true, then the routine returns TRUE and
  471. passes the pointer to the driver name back in the argument. If any
  472. one of them fail, then NULL is returned in the DriverName arg and
  473. the routine returns FALSE
  474. Arguments
  475. lpDriverName
  476. the address of a LPTSTR to recive the pointer to the driver name
  477. hDriverPerf
  478. the key to the driver's performance subkey
  479. Return Value
  480. TRUE if a valid driver was found in the command line
  481. FALSE if not (see above)
  482. --*/
  483. {
  484. LPTSTR lpDriverKey; // buffer to build driver key name in
  485. LONG lStatus;
  486. DWORD dwFirstCounter;
  487. DWORD dwSize;
  488. DWORD dwType;
  489. TCHAR LocalComputerName[MAX_PATH];
  490. DWORD NameBuffer;
  491. INT iNumArgs;
  492. BOOL bComputerName = FALSE;
  493. BOOL bReturn = FALSE;
  494. if (!lpDriverName || !hDriverPerf) {
  495. SetLastError (ERROR_BAD_ARGUMENTS);
  496. goto Cleanup;
  497. }
  498. *hDriverPerf = NULL;
  499. // an argument was found so see if it's a driver
  500. lpDriverKey = malloc (MAX_PATH * sizeof (TCHAR));
  501. if (!lpDriverKey) {
  502. SetLastError (ERROR_OUTOFMEMORY);
  503. goto Cleanup;
  504. }
  505. lstrcpy (lpDriverName, GetItemFromString (lpCommandLine, 3, TEXT(' ')));
  506. lstrcpy (ComputerName, GetItemFromString (lpCommandLine, 2, TEXT(' ')));
  507. // check for usage
  508. if (ComputerName[1] == TEXT('?')) {
  509. if (!bQuietMode) {
  510. DisplayCommandHelp (UC_FIRST_CMD_HELP, UC_LAST_CMD_HELP);
  511. }
  512. SetLastError (ERROR_SUCCESS);
  513. goto Cleanup;
  514. }
  515. // no /? so process args read
  516. if (lstrlen(lpDriverName) == 0) {
  517. // then no computer name is specifed so assume the local computer
  518. // and the driver name is listed in the computer name param
  519. if (lstrlen(ComputerName) == 0) {
  520. iNumArgs = 1; // command line only
  521. } else {
  522. lstrcpy (lpDriverName, ComputerName);
  523. ComputerName[0] = 0;
  524. ComputerName[1] = 0;
  525. iNumArgs = 2;
  526. }
  527. } else {
  528. if (lstrlen(ComputerName) == 0) {
  529. // this case is impossible since the driver name is after the computer name
  530. iNumArgs = 1;
  531. } else {
  532. iNumArgs = 3;
  533. }
  534. }
  535. // check if there is any computer name
  536. if (ComputerName[0] == TEXT('\\') &&
  537. ComputerName[1] == TEXT('\\')) {
  538. // see if the specified computer is THIS computer and remove
  539. // name if it is
  540. NameBuffer = sizeof (LocalComputerName) / sizeof (TCHAR);
  541. GetComputerName(LocalComputerName, &NameBuffer);
  542. if (!lstrcmpi(LocalComputerName, &ComputerName[2])) {
  543. // same name as local computer name
  544. ComputerName[0] = TEXT('\0');
  545. }
  546. bComputerName = TRUE;
  547. } else {
  548. // this is a driver name
  549. ComputerName[0] = TEXT('\0');
  550. }
  551. if (iNumArgs >= 2) {
  552. if (ComputerName[0]) {
  553. lStatus = !ERROR_SUCCESS;
  554. try {
  555. lStatus = RegConnectRegistry (
  556. (LPTSTR)ComputerName,
  557. HKEY_LOCAL_MACHINE,
  558. hKeyMachine);
  559. } finally {
  560. if (lStatus != ERROR_SUCCESS) {
  561. SetLastError (lStatus);
  562. *hKeyMachine = NULL;
  563. OUTPUT_MESSAGE (GetFormatResource(UC_CONNECT_PROBLEM),
  564. ComputerName, lStatus);
  565. }
  566. }
  567. if (lStatus != ERROR_SUCCESS)
  568. goto Cleanup;
  569. } else {
  570. *hKeyMachine = HKEY_LOCAL_MACHINE;
  571. }
  572. if (lstrlen(lpDriverName) > (MAX_PATH / 2)) {
  573. // then it's too long to make a path out of
  574. dwSize = 0;
  575. } else {
  576. lstrcpy (lpDriverKey, DriverPathRoot);
  577. lstrcat (lpDriverKey, Slash);
  578. lstrcat (lpDriverKey, lpDriverName);
  579. lstrcat (lpDriverKey, Slash);
  580. lstrcat (lpDriverKey, Performance);
  581. dwSize = lstrlen(lpDriverKey);
  582. }
  583. if ((dwSize > 0) && (dwSize < MAX_PATH)) {
  584. lStatus = RegOpenKeyEx (
  585. *hKeyMachine,
  586. lpDriverKey,
  587. RESERVED,
  588. KEY_READ | KEY_WRITE,
  589. hDriverPerf);
  590. } else {
  591. // driver name is too long
  592. lStatus = ERROR_INVALID_PARAMETER;
  593. }
  594. if (lStatus == ERROR_SUCCESS) {
  595. //
  596. // this driver has a performance section so see if its
  597. // counters are installed by checking the First Counter
  598. // value key for a valid return. If it returns a value
  599. // then chances are, it has some counters installed, if
  600. // not, then display a message and quit.
  601. //
  602. free (lpDriverKey); // don't need this any more
  603. dwType = 0;
  604. dwSize = sizeof (dwFirstCounter);
  605. lStatus = RegQueryValueEx (
  606. *hDriverPerf,
  607. cszFirstCounter,
  608. RESERVED,
  609. &dwType,
  610. (LPBYTE)&dwFirstCounter,
  611. &dwSize);
  612. if (lStatus == ERROR_SUCCESS) {
  613. // counter names are installed so return success
  614. SetLastError (ERROR_SUCCESS);
  615. bReturn = TRUE;
  616. } else {
  617. // counter names are probably not installed so return FALSE
  618. OUTPUT_MESSAGE (GetFormatResource (UC_NOTINSTALLED), lpDriverName);
  619. *lpDriverName = TEXT('\0'); // remove driver name
  620. SetLastError (ERROR_BADKEY);
  621. }
  622. } else { // key not found
  623. if (lStatus != ERROR_INVALID_PARAMETER) {
  624. OUTPUT_MESSAGE (GetFormatResource (UC_DRIVERNOTFOUND),
  625. lpDriverKey, lStatus);
  626. } else {
  627. OUTPUT_MESSAGE (GetFormatResource (UC_BAD_DRIVER_NAME), 0);
  628. }
  629. SetLastError (lStatus);
  630. free (lpDriverKey);
  631. }
  632. } else {
  633. if (!bQuietMode) {
  634. DisplayCommandHelp (UC_FIRST_CMD_HELP, UC_LAST_CMD_HELP);
  635. }
  636. SetLastError (ERROR_INVALID_PARAMETER);
  637. }
  638. Cleanup:
  639. if (bReturn) {
  640. TRACE((WINPERF_DBG_TRACE_INFO),
  641. (& LoadPerfGuid,
  642. __LINE__,
  643. LOADPERF_GETDRIVERFROMCOMMANDLINE,
  644. ARG_DEF(ARG_TYPE_WSTR, 1),
  645. ERROR_SUCCESS,
  646. TRACE_WSTR(lpDriverName),
  647. NULL));
  648. }
  649. else {
  650. TRACE((WINPERF_DBG_TRACE_ERROR),
  651. (& LoadPerfGuid,
  652. __LINE__,
  653. LOADPERF_GETDRIVERFROMCOMMANDLINE,
  654. 0,
  655. GetLastError(),
  656. NULL));
  657. }
  658. return bReturn;
  659. }
  660. static
  661. LONG
  662. FixNames (
  663. HANDLE hKeyLang,
  664. LPTSTR *lpOldNameTable,
  665. IN LPTSTR lpszLangId, // unicode value of Language subkey
  666. DWORD dwLastItem,
  667. DWORD dwFirstNameToRemove,
  668. DWORD dwLastNameToRemove
  669. )
  670. {
  671. LONG lStatus;
  672. LPTSTR lpNameBuffer = NULL;
  673. LPTSTR lpHelpBuffer = NULL;
  674. DWORD dwTextIndex, dwSize, dwValueType;
  675. LPTSTR lpNextHelpText;
  676. LPTSTR lpNextNameText;
  677. TCHAR AddHelpNameBuffer[40];
  678. TCHAR AddCounterNameBuffer[40];
  679. // allocate space for the array of new text it will point
  680. // into the text buffer returned in the lpOldNameTable buffer)
  681. lpNameBuffer = malloc (_msize(lpOldNameTable));
  682. lpHelpBuffer = malloc (_msize(lpOldNameTable));
  683. if (!lpNameBuffer || !lpHelpBuffer) {
  684. lStatus = ERROR_OUTOFMEMORY;
  685. goto UCN_FinishLang;
  686. }
  687. // remove this driver's counters from array
  688. for (dwTextIndex = dwFirstNameToRemove;
  689. dwTextIndex <= dwLastNameToRemove;
  690. dwTextIndex++) {
  691. if (dwTextIndex > dwLastItem)
  692. break;
  693. lpOldNameTable[dwTextIndex] = NULL;
  694. }
  695. lpNextHelpText = lpHelpBuffer;
  696. lpNextNameText = lpNameBuffer;
  697. // build new Multi_SZ strings from New Table
  698. for (dwTextIndex = 0; dwTextIndex <= dwLastItem; dwTextIndex++){
  699. if (lpOldNameTable[dwTextIndex]) {
  700. // if there's a text string at that index, then ...
  701. if ((dwTextIndex & 0x1) && dwTextIndex != 1) { // ODD number == Help Text
  702. lpNextHelpText +=
  703. _stprintf (lpNextHelpText, (LPCTSTR)TEXT("%d"), dwTextIndex) + 1;
  704. lpNextHelpText +=
  705. _stprintf (lpNextHelpText, (LPCTSTR)TEXT("%s"),
  706. lpOldNameTable[dwTextIndex]) + 1;
  707. if (dwTextIndex > dwLastHelp){
  708. dwLastHelp = dwTextIndex;
  709. }
  710. } else { // EVEN number == counter name text
  711. lpNextNameText +=
  712. _stprintf (lpNextNameText, (LPCTSTR)TEXT("%d"), dwTextIndex) + 1;
  713. lpNextNameText +=
  714. _stprintf (lpNextNameText, (LPCTSTR)TEXT("%s"),
  715. lpOldNameTable[dwTextIndex]) + 1;
  716. if (dwTextIndex > dwLastCounter){
  717. dwLastCounter = dwTextIndex;
  718. }
  719. }
  720. }
  721. } // for dwTextIndex
  722. TRACE((WINPERF_DBG_TRACE_INFO),
  723. (& LoadPerfGuid,
  724. __LINE__,
  725. LOADPERF_FIXNAMES,
  726. ARG_DEF(ARG_TYPE_WSTR, 1),
  727. ERROR_SUCCESS,
  728. TRACE_WSTR(lpszLangId),
  729. TRACE_DWORD(dwLastItem),
  730. TRACE_DWORD(dwLastCounter),
  731. TRACE_DWORD(dwLastHelp),
  732. TRACE_DWORD(dwCounterItems),
  733. TRACE_DWORD(dwHelpItems),
  734. TRACE_DWORD(dwFirstNameToRemove),
  735. TRACE_DWORD(dwLastNameToRemove),
  736. NULL));
  737. if ( (dwLastCounter < PERFLIB_BASE_INDEX - 1)
  738. || (dwLastHelp < PERFLIB_BASE_INDEX)) {
  739. ReportLoadPerfEvent(
  740. EVENTLOG_ERROR_TYPE, // error type
  741. (DWORD) LDPRFMSG_REGISTRY_BASEINDEX_CORRUPT, // event,
  742. 3, PERFLIB_BASE_INDEX, dwLastCounter, dwLastHelp,
  743. 0, NULL, NULL, NULL);
  744. lStatus = ERROR_BADKEY;
  745. goto UCN_FinishLang;
  746. }
  747. // add MULTI_SZ terminating NULL
  748. *lpNextNameText++ = TEXT ('\0');
  749. *lpNextHelpText++ = TEXT ('\0');
  750. // update counter name text buffer
  751. dwSize = (DWORD)((LPBYTE)lpNextNameText - (LPBYTE)lpNameBuffer);
  752. if (dwSystemVersion == OLD_VERSION) {
  753. lStatus = RegSetValueEx (
  754. hKeyLang,
  755. Counters,
  756. RESERVED,
  757. REG_MULTI_SZ,
  758. (LPBYTE)lpNameBuffer,
  759. dwSize);
  760. } else {
  761. lstrcpy (AddCounterNameBuffer, AddCounterNameStr);
  762. lstrcat (AddCounterNameBuffer, lpszLangId);
  763. lStatus = RegQueryValueEx (
  764. hKeyLang,
  765. AddCounterNameBuffer,
  766. RESERVED,
  767. &dwValueType,
  768. (LPBYTE)lpNameBuffer,
  769. &dwSize);
  770. }
  771. if (lStatus != ERROR_SUCCESS) {
  772. ReportLoadPerfEvent(
  773. EVENTLOG_ERROR_TYPE, // error type
  774. (DWORD) LDPRFMSG_UNABLE_UPDATE_COUNTER_STRINGS, // event,
  775. 1, lStatus, 0, 0,
  776. 1, lpszLangId, NULL, NULL);
  777. OUTPUT_MESSAGE (GetFormatResource(UC_UNABLELOADLANG),
  778. Counters, lpszLangId, lStatus);
  779. TRACE((WINPERF_DBG_TRACE_ERROR),
  780. (& LoadPerfGuid,
  781. __LINE__,
  782. LOADPERF_FIXNAMES,
  783. ARG_DEF(ARG_TYPE_WSTR, 1),
  784. lStatus,
  785. TRACE_WSTR(Counters),
  786. TRACE_DWORD(dwSize),
  787. NULL));
  788. goto UCN_FinishLang;
  789. }
  790. dwSize = (DWORD)((LPBYTE)lpNextHelpText - (LPBYTE)lpHelpBuffer);
  791. if (dwSystemVersion == OLD_VERSION) {
  792. lStatus = RegSetValueEx (
  793. hKeyLang,
  794. Help,
  795. RESERVED,
  796. REG_MULTI_SZ,
  797. (LPBYTE)lpHelpBuffer,
  798. dwSize);
  799. } else {
  800. lstrcpy (AddHelpNameBuffer, AddHelpNameStr);
  801. lstrcat (AddHelpNameBuffer, lpszLangId);
  802. lStatus = RegQueryValueEx (
  803. hKeyLang,
  804. AddHelpNameBuffer,
  805. RESERVED,
  806. &dwValueType,
  807. (LPBYTE)lpHelpBuffer,
  808. &dwSize);
  809. }
  810. if (lStatus != ERROR_SUCCESS) {
  811. ReportLoadPerfEvent(
  812. EVENTLOG_ERROR_TYPE, // error type
  813. (DWORD) LDPRFMSG_UNABLE_UPDATE_HELP_STRINGS, // event,
  814. 1, lStatus, 0, 0,
  815. 1, lpszLangId, NULL, NULL);
  816. OUTPUT_MESSAGE (GetFormatResource(UC_UNABLELOADLANG),
  817. Help, lpszLangId, lStatus);
  818. TRACE((WINPERF_DBG_TRACE_ERROR),
  819. (& LoadPerfGuid,
  820. __LINE__,
  821. LOADPERF_FIXNAMES,
  822. ARG_DEF(ARG_TYPE_WSTR, 1),
  823. lStatus,
  824. TRACE_WSTR(Help),
  825. TRACE_DWORD(dwSize),
  826. NULL));
  827. goto UCN_FinishLang;
  828. }
  829. UCN_FinishLang:
  830. if (lpNameBuffer)
  831. free (lpNameBuffer);
  832. if (lpHelpBuffer)
  833. free (lpHelpBuffer);
  834. free (lpOldNameTable);
  835. if (dwSystemVersion == OLD_VERSION) {
  836. RegCloseKey (hKeyLang);
  837. }
  838. return lStatus;
  839. }
  840. static
  841. LONG
  842. UnloadCounterNames (
  843. HKEY hKeyMachine,
  844. HKEY hDriverPerf,
  845. LPTSTR lpDriverName
  846. )
  847. /*++
  848. UnloadCounterNames
  849. removes the names and explain text for the driver referenced by
  850. hDriverPerf and updates the first and last counter values accordingly
  851. update process:
  852. - set "updating" flag under Perflib to name of driver being modified
  853. - FOR each language under perflib key
  854. -- load current counter names and explain text into array of
  855. pointers
  856. -- look at all drivers and copy their names and text into a new
  857. buffer adjusting for the removed counter's entries keeping
  858. track of the lowest entry copied. (the names for the driver
  859. to be removed will not be copied, of course)
  860. -- update each driver's "first" and "last" index values
  861. -- copy all other entries from 0 to the lowest copied (i.e. the
  862. system counters)
  863. -- build a new MULIT_SZ string of help text and counter names
  864. -- load new strings into registry
  865. - update perflibl "last" counters
  866. - delete updating flag
  867. ******************************************************
  868. * *
  869. * NOTE: FUNDAMENTAL ASSUMPTION..... *
  870. * *
  871. * this routine assumes that: *
  872. * *
  873. * ALL COUNTER NAMES are even numbered and *
  874. * ALL HELP TEXT STRINGS are odd numbered *
  875. * *
  876. ******************************************************
  877. Arguments
  878. hKeyMachine
  879. handle to HKEY_LOCAL_MACHINE node of registry on system to
  880. remove counters from
  881. hDrivefPerf
  882. handle to registry key of driver to be de-installed
  883. lpDriverName
  884. name of driver being de-installed
  885. Return Value
  886. DOS Error code.
  887. ERROR_SUCCESS if all went OK
  888. error value if not.
  889. --*/
  890. {
  891. HKEY hPerflib;
  892. HKEY hServices;
  893. HKEY hKeyLang;
  894. LONG lStatus;
  895. DWORD dwLangIndex;
  896. DWORD dwSize;
  897. DWORD dwType;
  898. DWORD dwLastItem;
  899. DWORD dwRemLastDriverCounter;
  900. DWORD dwRemFirstDriverCounter;
  901. DWORD dwRemLastDriverHelp;
  902. DWORD dwRemFirstDriverHelp;
  903. DWORD dwFirstNameToRemove;
  904. DWORD dwLastNameToRemove;
  905. DWORD dwLastNameInTable;
  906. LPTSTR *lpOldNameTable;
  907. LPTSTR lpLangName = NULL;
  908. LPTSTR lpThisDriver = NULL;
  909. BOOL bPerflibUpdated = FALSE;
  910. DWORD dwBufferSize; // size of total buffer in bytes
  911. TCHAR CounterNameBuffer [40];
  912. TCHAR HelpNameBuffer [40];
  913. HANDLE hFileMapping = NULL;
  914. DWORD MapFileSize;
  915. SECURITY_ATTRIBUTES SecAttr;
  916. TCHAR MapFileName[] = TEXT("Perflib Busy");
  917. DWORD *lpData;
  918. LONG_PTR TempFileHandle = -1;
  919. if (LoadPerfGrabMutex() == FALSE) {
  920. return (GetLastError());
  921. }
  922. lStatus = RegOpenKeyEx (
  923. hKeyMachine,
  924. DriverPathRoot,
  925. RESERVED,
  926. KEY_READ | KEY_WRITE,
  927. &hServices);
  928. if (lStatus != ERROR_SUCCESS) {
  929. ReportLoadPerfEvent(
  930. EVENTLOG_ERROR_TYPE, // error type
  931. (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event,
  932. 1, lStatus, 0, 0,
  933. 1, (LPWSTR) DriverPathRoot, NULL, NULL);
  934. OUTPUT_MESSAGE (GetFormatResource(UC_UNABLEOPENKEY),
  935. DriverPathRoot, lStatus);
  936. TRACE((WINPERF_DBG_TRACE_ERROR),
  937. (& LoadPerfGuid,
  938. __LINE__,
  939. LOADPERF_UNLOADCOUNTERNAMES,
  940. ARG_DEF(ARG_TYPE_WSTR, 1),
  941. lStatus,
  942. TRACE_WSTR(DriverPathRoot),
  943. NULL));
  944. ReleaseMutex(hLoadPerfMutex);
  945. return lStatus;
  946. }
  947. // open registry handle to perflib key
  948. lStatus = RegOpenKeyEx (
  949. hKeyMachine,
  950. NamesKey,
  951. RESERVED,
  952. KEY_READ | KEY_WRITE,
  953. &hPerflib);
  954. if (lStatus != ERROR_SUCCESS) {
  955. ReportLoadPerfEvent(
  956. EVENTLOG_ERROR_TYPE, // error type
  957. (DWORD) LDPRFMSG_UNABLE_OPEN_KEY, // event,
  958. 1, lStatus, 0, 0,
  959. 1, (LPWSTR) NamesKey, NULL, NULL);
  960. OUTPUT_MESSAGE (GetFormatResource(UC_UNABLEOPENKEY),
  961. NamesKey, lStatus);
  962. TRACE((WINPERF_DBG_TRACE_ERROR),
  963. (& LoadPerfGuid,
  964. __LINE__,
  965. LOADPERF_UNLOADCOUNTERNAMES,
  966. ARG_DEF(ARG_TYPE_WSTR, 1),
  967. lStatus,
  968. TRACE_WSTR(NamesKey),
  969. NULL));
  970. ReleaseMutex(hLoadPerfMutex);
  971. return lStatus;
  972. }
  973. lStatus = RegSetValueEx (
  974. hPerflib,
  975. Busy,
  976. RESERVED,
  977. REG_SZ,
  978. (LPBYTE)lpDriverName,
  979. lstrlen(lpDriverName) * sizeof(TCHAR));
  980. if (lStatus != ERROR_SUCCESS) {
  981. OUTPUT_MESSAGE (GetFormatResource(UC_UNABLESETVALUE),
  982. Busy, NamesKey, lStatus);
  983. TRACE((WINPERF_DBG_TRACE_ERROR),
  984. (& LoadPerfGuid,
  985. __LINE__,
  986. LOADPERF_UNLOADCOUNTERNAMES,
  987. ARG_DEF(ARG_TYPE_WSTR, 1),
  988. lStatus,
  989. TRACE_WSTR(Busy),
  990. NULL));
  991. RegCloseKey (hPerflib);
  992. ReleaseMutex(hLoadPerfMutex);
  993. return lStatus;
  994. }
  995. // query registry to get number of Explain text items
  996. dwBufferSize = sizeof (dwHelpItems);
  997. lStatus = RegQueryValueEx (
  998. hPerflib,
  999. LastHelp,
  1000. RESERVED,
  1001. &dwType,
  1002. (LPBYTE)&dwHelpItems,
  1003. &dwBufferSize);
  1004. if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
  1005. ReportLoadPerfEvent(
  1006. EVENTLOG_ERROR_TYPE, // error type
  1007. (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event,
  1008. 1, lStatus, 0, 0,
  1009. 1, (LPWSTR) LastHelp, NULL, NULL);
  1010. TRACE((WINPERF_DBG_TRACE_ERROR),
  1011. (& LoadPerfGuid,
  1012. __LINE__,
  1013. LOADPERF_UNLOADCOUNTERNAMES,
  1014. ARG_DEF(ARG_TYPE_WSTR, 1),
  1015. lStatus,
  1016. TRACE_WSTR(LastHelp),
  1017. NULL));
  1018. RegCloseKey (hPerflib);
  1019. ReleaseMutex(hLoadPerfMutex);
  1020. return lStatus;
  1021. }
  1022. // query registry to get number of counter and object name items
  1023. dwBufferSize = sizeof (dwCounterItems);
  1024. lStatus = RegQueryValueEx (
  1025. hPerflib,
  1026. LastCounter,
  1027. RESERVED,
  1028. &dwType,
  1029. (LPBYTE)&dwCounterItems,
  1030. &dwBufferSize);
  1031. if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
  1032. ReportLoadPerfEvent(
  1033. EVENTLOG_ERROR_TYPE, // error type
  1034. (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event,
  1035. 1, lStatus, 0, 0,
  1036. 1, (LPWSTR) LastCounter, NULL, NULL);
  1037. TRACE((WINPERF_DBG_TRACE_ERROR),
  1038. (& LoadPerfGuid,
  1039. __LINE__,
  1040. LOADPERF_UNLOADCOUNTERNAMES,
  1041. ARG_DEF(ARG_TYPE_WSTR, 1),
  1042. lStatus,
  1043. TRACE_WSTR(LastCounter),
  1044. NULL));
  1045. RegCloseKey (hPerflib);
  1046. ReleaseMutex(hLoadPerfMutex);
  1047. return lStatus;
  1048. }
  1049. dwLastNameInTable = dwHelpItems;
  1050. if (dwLastNameInTable < dwCounterItems) dwLastNameInTable = dwCounterItems;
  1051. // query registry to get PerfLib system version
  1052. dwBufferSize = sizeof (dwSystemVersion);
  1053. lStatus = RegQueryValueEx (
  1054. hPerflib,
  1055. VersionStr,
  1056. RESERVED,
  1057. &dwType,
  1058. (LPBYTE)&dwSystemVersion,
  1059. &dwBufferSize);
  1060. if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
  1061. // Key not there, must be NT 1.0 version
  1062. dwSystemVersion = OLD_VERSION;
  1063. }
  1064. // set the hPerfData to HKEY_PERFORMANCE_DATA for new version
  1065. // if remote machine, then need to connect to it.
  1066. if (dwSystemVersion != OLD_VERSION) {
  1067. lStatus = !ERROR_SUCCESS;
  1068. hPerfData = HKEY_PERFORMANCE_DATA;
  1069. if (ComputerName[0]) {
  1070. // have to do it the old faction way
  1071. dwSystemVersion = OLD_VERSION;
  1072. lStatus = ERROR_SUCCESS;
  1073. }
  1074. } // NEW_VERSION
  1075. // allocate temporary String buffer
  1076. lpLangName = malloc (MAX_PATH * sizeof(TCHAR));
  1077. lpThisDriver = malloc (MAX_PATH * sizeof(TCHAR));
  1078. if (!lpLangName || !lpThisDriver) {
  1079. ReportLoadPerfEvent(
  1080. EVENTLOG_ERROR_TYPE, // error type
  1081. (DWORD) LDPRFMSG_MEMORY_ALLOCATION_FAILURE, // event,
  1082. 0, 0, 0, 0,
  1083. 0, NULL, NULL, NULL);
  1084. TRACE((WINPERF_DBG_TRACE_ERROR),
  1085. (& LoadPerfGuid,
  1086. __LINE__,
  1087. LOADPERF_UNLOADCOUNTERNAMES,
  1088. 0,
  1089. ERROR_OUTOFMEMORY,
  1090. NULL));
  1091. lStatus = ERROR_OUTOFMEMORY;
  1092. goto UCN_ExitPoint;
  1093. }
  1094. // Get the values that are in use by the driver to be removed
  1095. dwSize = sizeof (dwRemLastDriverCounter);
  1096. lStatus = RegQueryValueEx (
  1097. hDriverPerf,
  1098. LastCounter,
  1099. RESERVED,
  1100. &dwType,
  1101. (LPBYTE)&dwRemLastDriverCounter,
  1102. &dwSize);
  1103. if (lStatus != ERROR_SUCCESS) {
  1104. ReportLoadPerfEvent(
  1105. EVENTLOG_ERROR_TYPE, // error type
  1106. (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event,
  1107. 1, lStatus, 0, 0,
  1108. 1, (LPWSTR) LastCounter, NULL, NULL);
  1109. OUTPUT_MESSAGE (GetFormatResource (UC_UNABLEREADVALUE),
  1110. lpDriverName, LastCounter, lStatus);
  1111. TRACE((WINPERF_DBG_TRACE_ERROR),
  1112. (& LoadPerfGuid,
  1113. __LINE__,
  1114. LOADPERF_UNLOADCOUNTERNAMES,
  1115. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  1116. lStatus,
  1117. TRACE_WSTR(lpDriverName),
  1118. TRACE_WSTR(LastCounter),
  1119. NULL));
  1120. goto UCN_ExitPoint;
  1121. }
  1122. dwSize = sizeof (dwRemFirstDriverCounter);
  1123. lStatus = RegQueryValueEx (
  1124. hDriverPerf,
  1125. cszFirstCounter,
  1126. RESERVED,
  1127. &dwType,
  1128. (LPBYTE)&dwRemFirstDriverCounter,
  1129. &dwSize);
  1130. if (lStatus != ERROR_SUCCESS) {
  1131. ReportLoadPerfEvent(
  1132. EVENTLOG_ERROR_TYPE, // error type
  1133. (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event,
  1134. 1, lStatus, 0, 0,
  1135. 1, (LPWSTR) cszFirstCounter, NULL, NULL);
  1136. OUTPUT_MESSAGE (GetFormatResource (UC_UNABLEREADVALUE),
  1137. lpDriverName, cszFirstCounter, lStatus);
  1138. TRACE((WINPERF_DBG_TRACE_ERROR),
  1139. (& LoadPerfGuid,
  1140. __LINE__,
  1141. LOADPERF_UNLOADCOUNTERNAMES,
  1142. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  1143. lStatus,
  1144. TRACE_WSTR(lpDriverName),
  1145. TRACE_WSTR(cszFirstCounter),
  1146. NULL));
  1147. goto UCN_ExitPoint;
  1148. }
  1149. dwSize = sizeof (dwRemLastDriverHelp);
  1150. lStatus = RegQueryValueEx (
  1151. hDriverPerf,
  1152. LastHelp,
  1153. RESERVED,
  1154. &dwType,
  1155. (LPBYTE)&dwRemLastDriverHelp,
  1156. &dwSize);
  1157. if (lStatus != ERROR_SUCCESS) {
  1158. ReportLoadPerfEvent(
  1159. EVENTLOG_ERROR_TYPE, // error type
  1160. (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event,
  1161. 1, lStatus, 0, 0,
  1162. 1, (LPWSTR) LastHelp, NULL, NULL);
  1163. OUTPUT_MESSAGE (GetFormatResource (UC_UNABLEREADVALUE),
  1164. lpDriverName, LastHelp, lStatus);
  1165. TRACE((WINPERF_DBG_TRACE_ERROR),
  1166. (& LoadPerfGuid,
  1167. __LINE__,
  1168. LOADPERF_UNLOADCOUNTERNAMES,
  1169. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  1170. lStatus,
  1171. TRACE_WSTR(lpDriverName),
  1172. TRACE_WSTR(LastHelp),
  1173. NULL));
  1174. goto UCN_ExitPoint;
  1175. }
  1176. dwSize = sizeof (dwRemFirstDriverHelp);
  1177. lStatus = RegQueryValueEx (
  1178. hDriverPerf,
  1179. FirstHelp,
  1180. RESERVED,
  1181. &dwType,
  1182. (LPBYTE)&dwRemFirstDriverHelp,
  1183. &dwSize);
  1184. if (lStatus != ERROR_SUCCESS) {
  1185. ReportLoadPerfEvent(
  1186. EVENTLOG_ERROR_TYPE, // error type
  1187. (DWORD) LDPRFMSG_UNABLE_READ_VALUE, // event,
  1188. 1, lStatus, 0, 0,
  1189. 1, (LPWSTR) FirstHelp, NULL, NULL);
  1190. OUTPUT_MESSAGE (GetFormatResource (UC_UNABLEREADVALUE),
  1191. lpDriverName, FirstHelp, lStatus);
  1192. TRACE((WINPERF_DBG_TRACE_ERROR),
  1193. (& LoadPerfGuid,
  1194. __LINE__,
  1195. LOADPERF_UNLOADCOUNTERNAMES,
  1196. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  1197. lStatus,
  1198. TRACE_WSTR(lpDriverName),
  1199. TRACE_WSTR(FirstHelp),
  1200. NULL));
  1201. goto UCN_ExitPoint;
  1202. }
  1203. TRACE((WINPERF_DBG_TRACE_INFO),
  1204. (& LoadPerfGuid,
  1205. __LINE__,
  1206. LOADPERF_UNLOADCOUNTERNAMES,
  1207. ARG_DEF(ARG_TYPE_WSTR, 1),
  1208. lStatus,
  1209. TRACE_WSTR(lpDriverName),
  1210. TRACE_DWORD(dwLastNameInTable),
  1211. TRACE_DWORD(dwCounterItems),
  1212. TRACE_DWORD(dwHelpItems),
  1213. TRACE_DWORD(dwRemFirstDriverCounter),
  1214. TRACE_DWORD(dwRemLastDriverCounter),
  1215. TRACE_DWORD(dwRemFirstDriverHelp),
  1216. TRACE_DWORD(dwRemLastDriverHelp),
  1217. NULL));
  1218. // get the first and last counters to define block of names used
  1219. // by this device
  1220. dwFirstNameToRemove = (dwRemFirstDriverCounter <= dwRemFirstDriverHelp ?
  1221. dwRemFirstDriverCounter : dwRemFirstDriverHelp);
  1222. dwLastNameToRemove = (dwRemLastDriverCounter >= dwRemLastDriverHelp ?
  1223. dwRemLastDriverCounter : dwRemLastDriverHelp);
  1224. dwLastCounter = dwLastHelp = 0;
  1225. // create the file mapping
  1226. SecAttr.nLength = sizeof (SecAttr);
  1227. SecAttr.bInheritHandle = TRUE;
  1228. SecAttr.lpSecurityDescriptor = NULL;
  1229. MapFileSize = sizeof(DWORD);
  1230. hFileMapping = CreateFileMapping ((HANDLE)TempFileHandle, &SecAttr,
  1231. PAGE_READWRITE, (DWORD_PTR)0, MapFileSize, (LPCTSTR)MapFileName);
  1232. if (hFileMapping) {
  1233. lpData = MapViewOfFile (hFileMapping,
  1234. FILE_MAP_ALL_ACCESS, 0L, 0L, 0L);
  1235. if (lpData) {
  1236. *lpData = 1L;
  1237. UnmapViewOfFile (lpData);
  1238. } else {
  1239. lStatus = GetLastError();
  1240. }
  1241. } else {
  1242. lStatus = GetLastError();
  1243. }
  1244. if (lStatus != ERROR_SUCCESS) {
  1245. OUTPUT_MESSAGE (GetFormatResource (UC_UNABLEREADVALUE),
  1246. lpDriverName, FirstHelp, lStatus);
  1247. TRACE((WINPERF_DBG_TRACE_ERROR),
  1248. (& LoadPerfGuid,
  1249. __LINE__,
  1250. LOADPERF_UNLOADCOUNTERNAMES,
  1251. ARG_DEF(ARG_TYPE_WSTR, 1),
  1252. lStatus,
  1253. TRACE_WSTR(lpDriverName),
  1254. NULL));
  1255. goto UCN_ExitPoint;
  1256. }
  1257. // do each language under perflib
  1258. if (dwSystemVersion == OLD_VERSION) {
  1259. for (dwLangIndex = 0, dwSize = _msize(lpLangName);
  1260. (RegEnumKey(hPerflib, dwLangIndex, lpLangName, dwSize)) == ERROR_SUCCESS;
  1261. dwLangIndex++, dwSize = _msize(lpLangName)) {
  1262. OUTPUT_MESSAGE (GetFormatResource (UC_DOINGLANG), lpLangName);
  1263. lpOldNameTable = BuildNameTable (hPerflib, lpLangName,
  1264. &dwLastItem, &hKeyLang, CounterNameBuffer, HelpNameBuffer);
  1265. if (lpOldNameTable) {
  1266. if (dwLastItem <= dwLastNameInTable) {
  1267. // registry is OK so continue
  1268. if ((lStatus = FixNames (
  1269. hKeyLang,
  1270. lpOldNameTable,
  1271. lpLangName,
  1272. dwLastItem,
  1273. dwFirstNameToRemove,
  1274. dwLastNameToRemove)) == ERROR_SUCCESS) {
  1275. bPerflibUpdated = TRUE;
  1276. }
  1277. } else {
  1278. // registry has been corrupted so abort
  1279. lStatus = ERROR_BADDB;
  1280. break;
  1281. }
  1282. } else { // unable to unload names for this language
  1283. // display error message
  1284. lStatus = GetLastError();
  1285. }
  1286. } // end for (more languages)
  1287. } // end of OLD_VERSION
  1288. else {
  1289. CHAR *pSystemRoot;
  1290. WIN32_FIND_DATA FindFileInfo ;
  1291. HANDLE hFindFile ;
  1292. CHAR FileName[128];
  1293. WCHAR wFileName[128];
  1294. WCHAR LangId[10];
  1295. WCHAR *pLangId;
  1296. DWORD dwIdx;
  1297. pSystemRoot = getenv ("SystemRoot");
  1298. if (pSystemRoot == NULL) {
  1299. // unable to find systemroot so try windir
  1300. pSystemRoot = getenv ("windir");
  1301. }
  1302. if (pSystemRoot != NULL) {
  1303. strcpy(FileName, pSystemRoot);
  1304. strcat(FileName, "\\system32\\perfc???.dat");
  1305. } else {
  1306. // unable to look up the windows directory so
  1307. // try searching from the root of the boot drive
  1308. strcpy(FileName, "C:\\perfc???.dat");
  1309. }
  1310. mbstowcs(wFileName, FileName, strlen(FileName) + 1);
  1311. hFindFile = FindFirstFile ((LPCTSTR)wFileName, &FindFileInfo) ;
  1312. if (!hFindFile || hFindFile == INVALID_HANDLE_VALUE) {
  1313. lStatus = GetLastError();
  1314. } else {
  1315. do {
  1316. // get langid
  1317. // start at lang id # of file name based on the format
  1318. // perfxyyy.dat
  1319. // where x= h for help file, c for counter names
  1320. // y= hex digits of language ID
  1321. //
  1322. dwIdx = 0;
  1323. pLangId = &FindFileInfo.cFileName[0];
  1324. // go to lang ID code in filename (yyy above)
  1325. for (dwIdx = 0; (dwIdx < 5) && (*pLangId++ > 0); dwIdx++);
  1326. if (*pLangId > 0) {
  1327. // get lang ID from file name
  1328. LangId[0] = *pLangId++;
  1329. LangId[1] = *pLangId++;
  1330. LangId[2] = *pLangId++;
  1331. LangId[3] = L'\0';
  1332. } else {
  1333. continue; // on to next file
  1334. }
  1335. OUTPUT_MESSAGE (GetFormatResource (UC_DOINGLANG), LangId);
  1336. lpOldNameTable = BuildNameTable (hPerflib, LangId,
  1337. &dwLastItem, &hKeyLang, CounterNameBuffer, HelpNameBuffer);
  1338. if (lpOldNameTable) {
  1339. if (dwLastItem <= dwLastNameInTable) {
  1340. // registry is OK so continue
  1341. if ((lStatus = FixNames (
  1342. hKeyLang,
  1343. lpOldNameTable,
  1344. LangId,
  1345. dwLastItem,
  1346. dwFirstNameToRemove,
  1347. dwLastNameToRemove)) == ERROR_SUCCESS) {
  1348. bPerflibUpdated = TRUE;
  1349. }
  1350. } else {
  1351. lStatus = ERROR_BADDB;
  1352. break;
  1353. }
  1354. } else { // unable to unload names for this language
  1355. lStatus = GetLastError();
  1356. }
  1357. } while (FindNextFile(hFindFile, &FindFileInfo));
  1358. }
  1359. FindClose (hFindFile);
  1360. } // end of NEW_VERSION
  1361. if ((bPerflibUpdated) && (lStatus == ERROR_SUCCESS)) {
  1362. // update perflib's "last" values
  1363. dwSize = sizeof (dwLastCounter);
  1364. lStatus = RegSetValueEx (
  1365. hPerflib,
  1366. LastCounter,
  1367. RESERVED,
  1368. REG_DWORD,
  1369. (LPBYTE) & dwLastCounter,
  1370. dwSize);
  1371. if (lStatus == ERROR_SUCCESS) {
  1372. dwSize = sizeof (dwLastHelp);
  1373. lStatus = RegSetValueEx (
  1374. hPerflib,
  1375. LastHelp,
  1376. RESERVED,
  1377. REG_DWORD,
  1378. (LPBYTE) & dwLastHelp,
  1379. dwSize);
  1380. if (lStatus != ERROR_SUCCESS) {
  1381. ReportLoadPerfEvent(
  1382. EVENTLOG_ERROR_TYPE, // error type
  1383. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  1384. 2, lStatus, dwLastHelp, 0,
  1385. 2, (LPWSTR) LastHelp, (LPWSTR) NamesKey, NULL);
  1386. TRACE((WINPERF_DBG_TRACE_ERROR),
  1387. (& LoadPerfGuid,
  1388. __LINE__,
  1389. LOADPERF_UNLOADCOUNTERNAMES,
  1390. ARG_DEF(ARG_TYPE_WSTR, 1),
  1391. lStatus,
  1392. TRACE_WSTR(LastHelp),
  1393. TRACE_DWORD(dwLastHelp),
  1394. NULL));
  1395. }
  1396. }
  1397. else {
  1398. ReportLoadPerfEvent(
  1399. EVENTLOG_ERROR_TYPE, // error type
  1400. (DWORD) LDPRFMSG_UNABLE_UPDATE_VALUE, // event,
  1401. 2, lStatus, dwLastCounter, 0,
  1402. 2, (LPWSTR) LastCounter, (LPWSTR) NamesKey, NULL);
  1403. TRACE((WINPERF_DBG_TRACE_ERROR),
  1404. (& LoadPerfGuid,
  1405. __LINE__,
  1406. LOADPERF_UNLOADCOUNTERNAMES,
  1407. ARG_DEF(ARG_TYPE_WSTR, 1),
  1408. lStatus,
  1409. TRACE_WSTR(LastCounter),
  1410. TRACE_DWORD(dwLastCounter),
  1411. NULL));
  1412. }
  1413. if (lStatus == ERROR_SUCCESS) {
  1414. ReportLoadPerfEvent(
  1415. EVENTLOG_INFORMATION_TYPE, // error type
  1416. (DWORD) LDPRFMSG_UNLOAD_SUCCESS, // event,
  1417. 2, dwLastCounter, dwLastHelp, 0,
  1418. 1, (LPWSTR) lpDriverName, NULL, NULL);
  1419. TRACE((WINPERF_DBG_TRACE_INFO),
  1420. (& LoadPerfGuid,
  1421. __LINE__,
  1422. LOADPERF_UNLOADCOUNTERNAMES,
  1423. ARG_DEF(ARG_TYPE_WSTR, 1),
  1424. lStatus,
  1425. TRACE_WSTR(lpDriverName),
  1426. TRACE_DWORD(dwLastCounter),
  1427. TRACE_DWORD(dwLastHelp),
  1428. NULL));
  1429. RegDeleteValue (hDriverPerf, cszFirstCounter);
  1430. RegDeleteValue (hDriverPerf, LastCounter);
  1431. RegDeleteValue (hDriverPerf, FirstHelp);
  1432. RegDeleteValue (hDriverPerf, LastHelp);
  1433. RegDeleteValue (hDriverPerf, szObjectList);
  1434. RegDeleteValue (hDriverPerf, szLibraryValidationCode);
  1435. }
  1436. }
  1437. UCN_ExitPoint:
  1438. RegDeleteValue (hPerflib, Busy);
  1439. RegCloseKey (hPerflib);
  1440. RegCloseKey (hServices);
  1441. if (lpLangName) free (lpLangName);
  1442. if (lpThisDriver) free (lpThisDriver);
  1443. if (hFileMapping) {
  1444. CloseHandle (hFileMapping);
  1445. }
  1446. if (lStatus != ERROR_SUCCESS) {
  1447. ReportLoadPerfEvent(
  1448. EVENTLOG_ERROR_TYPE, // error type
  1449. (DWORD) LDPRFMSG_UNLOAD_FAILURE, // event,
  1450. 1, lStatus, 0, 0,
  1451. 1, (LPWSTR) lpDriverName, NULL, NULL);
  1452. TRACE((WINPERF_DBG_TRACE_ERROR),
  1453. (& LoadPerfGuid,
  1454. __LINE__,
  1455. LOADPERF_UNLOADCOUNTERNAMES,
  1456. ARG_DEF(ARG_TYPE_WSTR, 1),
  1457. lStatus,
  1458. TRACE_WSTR(lpDriverName),
  1459. NULL));
  1460. }
  1461. ReleaseMutex(hLoadPerfMutex);
  1462. return lStatus;
  1463. }
  1464. LOADPERF_FUNCTION
  1465. UnloadPerfCounterTextStringsW (
  1466. IN LPWSTR lpCommandLine,
  1467. IN BOOL bQuietModeArg
  1468. )
  1469. /*++
  1470. UnloadPerfCounterTextStringsW
  1471. entry point to Counter Name Unloader
  1472. Arguments
  1473. command line string in the format:
  1474. "/?" displays the usage help
  1475. "driver" driver containing the performance counters
  1476. "\\machine driver" removes the counters from the driver on \\machine
  1477. ReturnValue
  1478. 0 (ERROR_SUCCESS) if command was processed
  1479. Non-Zero if command error was detected.
  1480. --*/
  1481. {
  1482. LPTSTR lpDriverName=NULL; // name of driver to delete from perflib
  1483. HKEY hDriverPerf=NULL; // handle to performance sub-key of driver
  1484. HKEY hMachineKey=NULL; // handle to remote machine HKEY_LOCAL_MACHINE
  1485. DWORD dwStatus = ERROR_SUCCESS; // return status of fn. calls
  1486. WinPerfStartTrace(NULL);
  1487. lpDriverName = (LPTSTR)malloc(MAX_PATH * sizeof(TCHAR));
  1488. bQuietMode = bQuietModeArg;
  1489. if (lpDriverName != NULL) {
  1490. if (!GetDriverFromCommandLine (
  1491. lpCommandLine, &hMachineKey, lpDriverName, &hDriverPerf)) {
  1492. // error message was printed in routine if there was an error
  1493. dwStatus = GetLastError();
  1494. goto Exit0;
  1495. }
  1496. } else {
  1497. dwStatus = ERROR_OUTOFMEMORY;
  1498. goto Exit0;
  1499. }
  1500. OUTPUT_MESSAGE(GetFormatResource(UC_REMOVINGDRIVER), lpDriverName);
  1501. // removes names and explain text for driver in lpDriverName
  1502. // displays error messages for errors encountered
  1503. dwStatus = (DWORD)UnloadCounterNames(hMachineKey,
  1504. hDriverPerf, lpDriverName);
  1505. if (dwStatus == ERROR_SUCCESS) {
  1506. SignalWmiWithNewData (WMI_UNLODCTR_EVENT);
  1507. }
  1508. Exit0:
  1509. TRACE((WINPERF_DBG_TRACE_INFO),
  1510. (& LoadPerfGuid,
  1511. __LINE__,
  1512. LOADPERF_UNLOADPERFCOUNTERTEXTSTRINGS,
  1513. ARG_DEF(ARG_TYPE_WSTR, 1),
  1514. dwStatus,
  1515. TRACE_WSTR(lpDriverName),
  1516. NULL));
  1517. if (lpDriverName != NULL) free (lpDriverName);
  1518. if (hDriverPerf)
  1519. RegCloseKey (hDriverPerf);
  1520. if (hMachineKey != HKEY_LOCAL_MACHINE && hMachineKey != NULL) {
  1521. RegCloseKey (hMachineKey);
  1522. }
  1523. if (hPerfData != HKEY_PERFORMANCE_DATA && hPerfData != NULL) {
  1524. RegCloseKey (hPerfData);
  1525. }
  1526. return dwStatus;
  1527. }
  1528. LOADPERF_FUNCTION
  1529. UnloadPerfCounterTextStringsA (
  1530. IN LPSTR lpAnsiCommandLine,
  1531. IN BOOL bQuietModeArg
  1532. )
  1533. {
  1534. LPWSTR lpWideCommandLine;
  1535. DWORD dwStrLen;
  1536. DWORD lReturn;
  1537. if (lpAnsiCommandLine != 0) { // to catch bogus parameters
  1538. //length of string including terminator
  1539. dwStrLen = lstrlenA(lpAnsiCommandLine) + 1;
  1540. lpWideCommandLine = GlobalAlloc (GPTR, (dwStrLen * sizeof(WCHAR)));
  1541. if (lpWideCommandLine != NULL) {
  1542. mbstowcs (lpWideCommandLine, lpAnsiCommandLine, dwStrLen);
  1543. lReturn = UnloadPerfCounterTextStringsW(lpWideCommandLine,
  1544. bQuietModeArg );
  1545. GlobalFree (lpWideCommandLine);
  1546. } else {
  1547. lReturn = GetLastError();
  1548. }
  1549. } else {
  1550. lReturn = ERROR_INVALID_PARAMETER;
  1551. }
  1552. return lReturn;
  1553. }