Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1022 lines
27 KiB

  1. /*++
  2. Copyright (c) 1991-1993 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. --*/
  12. #define UNICODE 1
  13. #define _UNICODE 1
  14. //
  15. // "C" Include files
  16. //
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <malloc.h>
  21. //
  22. // Windows Include files
  23. //
  24. #include <windows.h>
  25. #include <winperf.h>
  26. #include <tchar.h>
  27. //
  28. // local include files
  29. //
  30. //#define _INITIALIZE_GLOBALS_ 1 // to define & init global buffers
  31. #include "common.h"
  32. //#undef _INITIALIZE_GLOBALS_
  33. #include "nwcfg.hxx"
  34. // version number for NT 1.0
  35. #define OLD_VERSION 0x010000
  36. DWORD dwSystemVersion; // PerfLib version number
  37. DWORD dwHelpItems; // number of explain text items
  38. DWORD dwCounterItems; // number of counter text items
  39. DWORD dwLastCounter;
  40. DWORD dwLastHelp;
  41. LPTSTR
  42. *BuildNameTable(
  43. IN HKEY hKeyPerflib, // handle to perflib key with counter names
  44. IN LPTSTR lpszLangId, // unicode value of Language subkey
  45. OUT PDWORD pdwLastItem, // size of array in elements
  46. OUT HKEY *hKeyNames,
  47. OUT LPTSTR CounterNameBuffer, // New version counter name key
  48. OUT LPTSTR HelpNameBuffer // New version help name key
  49. )
  50. /*++
  51. BuildNameTable
  52. Caches the counter names and explain text to accelerate name lookups
  53. for display.
  54. Arguments:
  55. hKeyPerflib
  56. Handle to an open registry (this can be local or remote.) and
  57. is the value returned by RegConnectRegistry or a default key.
  58. lpszLangId
  59. The unicode id of the language to look up. (default is 009)
  60. pdwLastItem
  61. The last array element
  62. Return Value:
  63. pointer to an allocated table. (the caller must free it when finished!)
  64. the table is an array of pointers to zero terminated TEXT strings.
  65. A NULL pointer is returned if an error occured. (error value is
  66. available using the GetLastError function).
  67. The structure of the buffer returned is:
  68. Array of pointers to zero terminated strings consisting of
  69. pdwLastItem elements
  70. MULTI_SZ string containing counter id's and names returned from
  71. registry for the specified language
  72. MULTI_SZ string containing explain text id's and explain text strings
  73. as returned by the registry for the specified language
  74. The structures listed above are contiguous so that they may be freed
  75. by a single "free" call when finished with them, however only the
  76. array elements are intended to be used.
  77. --*/
  78. {
  79. LPTSTR *lpReturnValue; // returned pointer to buffer
  80. LPTSTR *lpCounterId; //
  81. LPTSTR lpCounterNames; // pointer to Names buffer returned by reg.
  82. LPTSTR lpHelpText ; // pointet to exlpain buffer returned by reg.
  83. LPTSTR lpThisName; // working pointer
  84. BOOL bStatus; // return status from TRUE/FALSE fn. calls
  85. LONG lWin32Status; // return status from fn. calls
  86. DWORD dwValueType; // value type of buffer returned by reg.
  87. DWORD dwArraySize; // size of pointer array in bytes
  88. DWORD dwBufferSize; // size of total buffer in bytes
  89. DWORD dwCounterSize; // size of counter text buffer in bytes
  90. DWORD dwHelpSize; // size of help text buffer in bytes
  91. DWORD dwThisCounter; // working counter
  92. DWORD dwLastId; // largest ID value used by explain/counter text
  93. LPTSTR lpValueNameString; // pointer to buffer conatining subkey name
  94. //initialize pointers to NULL
  95. lpValueNameString = NULL;
  96. lpReturnValue = NULL;
  97. // check for null arguments and insert defaults if necessary
  98. if (!lpszLangId) {
  99. lpszLangId = DefaultLangId;
  100. }
  101. if (hKeyNames) {
  102. *hKeyNames = NULL;
  103. } else {
  104. SetLastError (ERROR_BAD_ARGUMENTS);
  105. return NULL;
  106. }
  107. // use the greater of Help items or Counter Items to size array
  108. if (dwHelpItems >= dwCounterItems) {
  109. dwLastId = dwHelpItems;
  110. } else {
  111. dwLastId = dwCounterItems;
  112. }
  113. // array size is # of elements (+ 1, since names are "1" based)
  114. // times the size of a pointer
  115. dwArraySize = (dwLastId + 1) * sizeof(LPTSTR);
  116. // allocate string buffer for language ID key string
  117. lpValueNameString = malloc (
  118. lstrlen(NamesKey) * sizeof (TCHAR) +
  119. lstrlen(Slash) * sizeof (TCHAR) +
  120. lstrlen(lpszLangId) * sizeof (TCHAR) +
  121. sizeof (TCHAR));
  122. if (!lpValueNameString) {
  123. lWin32Status = ERROR_OUTOFMEMORY;
  124. goto BNT_BAILOUT;
  125. }
  126. lWin32Status = RegOpenKeyEx ( // get handle to this key in the
  127. hKeyPerflib, // registry
  128. lpszLangId,
  129. RESERVED,
  130. KEY_READ | KEY_WRITE,
  131. hKeyNames);
  132. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  133. // get size of counter names
  134. dwBufferSize = 0;
  135. lWin32Status = RegQueryValueEx (
  136. *hKeyNames,
  137. Counters,
  138. RESERVED,
  139. &dwValueType,
  140. NULL,
  141. &dwBufferSize);
  142. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  143. dwCounterSize = dwBufferSize;
  144. // get size of help text
  145. dwBufferSize = 0;
  146. lWin32Status = RegQueryValueEx (
  147. *hKeyNames,
  148. Help,
  149. RESERVED,
  150. &dwValueType,
  151. NULL,
  152. &dwBufferSize);
  153. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  154. dwHelpSize = dwBufferSize;
  155. // allocate buffer with room for pointer array, counter name
  156. // strings and help name strings
  157. lpReturnValue = malloc (dwArraySize + dwCounterSize + dwHelpSize);
  158. if (!lpReturnValue) {
  159. lWin32Status = ERROR_OUTOFMEMORY;
  160. goto BNT_BAILOUT;
  161. }
  162. // initialize buffer
  163. memset (lpReturnValue, 0, _msize(lpReturnValue));
  164. // initialize pointers into buffer
  165. lpCounterId = lpReturnValue;
  166. lpCounterNames = (LPTSTR)((LPBYTE)lpCounterId + dwArraySize);
  167. lpHelpText = (LPTSTR)((LPBYTE)lpCounterNames + dwCounterSize);
  168. // read counter names into buffer. Counter names will be stored as
  169. // a MULTI_SZ string in the format of "###" "Name"
  170. dwBufferSize = dwCounterSize;
  171. lWin32Status = RegQueryValueEx (
  172. *hKeyNames,
  173. Counters,
  174. RESERVED,
  175. &dwValueType,
  176. (LPVOID)lpCounterNames,
  177. &dwBufferSize);
  178. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  179. // read explain text into buffer. Counter names will be stored as
  180. // a MULTI_SZ string in the format of "###" "Text..."
  181. dwBufferSize = dwHelpSize;
  182. lWin32Status = RegQueryValueEx (
  183. *hKeyNames,
  184. Help,
  185. RESERVED,
  186. &dwValueType,
  187. (LPVOID)lpHelpText,
  188. &dwBufferSize);
  189. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  190. // load counter array items, by locating each text string
  191. // in the returned buffer and loading the
  192. // address of it in the corresponding pointer array element.
  193. for (lpThisName = lpCounterNames;
  194. *lpThisName;
  195. lpThisName += (lstrlen(lpThisName)+1) ) {
  196. // first string should be an integer (in decimal digit characters)
  197. // so translate to an integer for use in array element identification
  198. bStatus = StringToInt (lpThisName, &dwThisCounter);
  199. if (!bStatus) {
  200. // error is in GetLastError
  201. goto BNT_BAILOUT; // bad entry
  202. }
  203. // point to corresponding counter name which follows the id number
  204. // string.
  205. lpThisName += (lstrlen(lpThisName)+1);
  206. // and load array element with pointer to string
  207. lpCounterId[dwThisCounter] = lpThisName;
  208. }
  209. // repeat the above for the explain text strings
  210. for (lpThisName = lpHelpText;
  211. *lpThisName;
  212. lpThisName += (lstrlen(lpThisName)+1) ) {
  213. // first string should be an integer (in decimal unicode digits)
  214. bStatus = StringToInt (lpThisName, &dwThisCounter);
  215. if (!bStatus) {
  216. // error is in GetLastError
  217. goto BNT_BAILOUT; // bad entry
  218. }
  219. // point to corresponding counter name
  220. lpThisName += (lstrlen(lpThisName)+1);
  221. // and load array element;
  222. lpCounterId[dwThisCounter] = lpThisName;
  223. }
  224. // if the last item arugment was used, then load the last ID value in it
  225. if (pdwLastItem) *pdwLastItem = dwLastId;
  226. // free the temporary buffer used
  227. if (lpValueNameString) {
  228. free ((LPVOID)lpValueNameString);
  229. }
  230. // exit returning the pointer to the buffer
  231. return lpReturnValue;
  232. BNT_BAILOUT:
  233. if (lWin32Status != ERROR_SUCCESS) {
  234. // if lWin32Status has error, then set last error value to it,
  235. // otherwise assume that last error already has value in it
  236. SetLastError (lWin32Status);
  237. }
  238. // free buffers used by this routine
  239. if (lpValueNameString) {
  240. free ((LPVOID)lpValueNameString);
  241. }
  242. if (lpReturnValue) {
  243. free ((LPVOID)lpReturnValue);
  244. }
  245. return NULL;
  246. } // BuildNameTable
  247. BOOL
  248. GetDriverFromCommandLine (
  249. HKEY hKeyMachine,
  250. LPTSTR *lpDriverName,
  251. HKEY *hDriverPerf,
  252. LPSTR argv[]
  253. )
  254. /*++
  255. GetDriverFromCommandLine
  256. locates the first argument in the command line string (after the
  257. image name) and checks to see if
  258. a) it's there
  259. b) it's the name of a device driver listed in the
  260. Registry\Machine\System\CurrentControlSet\Services key
  261. in the registry and it has a "Performance" subkey
  262. c) that the "First Counter" value under the Performance subkey
  263. is defined.
  264. if all these criteria are true, then the routine returns TRUE and
  265. passes the pointer to the driver name back in the argument. If any
  266. one of them fail, then NULL is returned in the DriverName arg and
  267. the routine returns FALSE
  268. Arguments
  269. lpDriverName
  270. the address of a LPTSTR to recive the pointer to the driver name
  271. hDriverPerf
  272. the key to the driver's performance subkey
  273. Return Value
  274. TRUE if a valid driver was found in the command line
  275. FALSE if not (see above)
  276. --*/
  277. {
  278. LPTSTR lpDriverKey; // buffer to build driver key name in
  279. LPTSTR lpThisChar;
  280. LONG lStatus;
  281. DWORD dwFirstCounter;
  282. DWORD dwSize;
  283. DWORD dwType;
  284. if (!lpDriverName || !hDriverPerf) {
  285. SetLastError (ERROR_BAD_ARGUMENTS);
  286. return FALSE;
  287. }
  288. *lpDriverName = NULL; // initialize to NULL
  289. *hDriverPerf = NULL;
  290. lpThisChar = malloc( MAX_PATH * sizeof(TCHAR));
  291. if (lpThisChar == NULL) {
  292. SetLastError (ERROR_OUTOFMEMORY);
  293. return FALSE;
  294. }
  295. *lpThisChar = 0;
  296. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, argv[0], -1, lpThisChar, MAX_PATH);
  297. if (*lpThisChar) {
  298. // an argument was found so see if it's a driver
  299. lpDriverKey = malloc (MAX_PATH * sizeof (TCHAR));
  300. if (!lpDriverKey) {
  301. SetLastError (ERROR_OUTOFMEMORY);
  302. if ( lpThisChar ) free (lpThisChar);
  303. return FALSE;
  304. }
  305. lstrcpy (lpDriverKey, DriverPathRoot);
  306. lstrcat (lpDriverKey, Slash);
  307. lstrcat (lpDriverKey, lpThisChar);
  308. lstrcat (lpDriverKey, Slash);
  309. lstrcat (lpDriverKey, Performance);
  310. lStatus = RegOpenKeyEx (
  311. hKeyMachine,
  312. lpDriverKey,
  313. RESERVED,
  314. KEY_READ | KEY_WRITE,
  315. hDriverPerf);
  316. if (lStatus == ERROR_SUCCESS) {
  317. //
  318. // this driver has a performance section so see if its
  319. // counters are installed by checking the First Counter
  320. // value key for a valid return. If it returns a value
  321. // then chances are, it has some counters installed, if
  322. // not, then display a message and quit.
  323. //
  324. free (lpDriverKey); // don't need this any more
  325. dwType = 0;
  326. dwSize = sizeof (dwFirstCounter);
  327. lStatus = RegQueryValueEx (
  328. *hDriverPerf,
  329. FirstCounter,
  330. RESERVED,
  331. &dwType,
  332. (LPBYTE)&dwFirstCounter,
  333. &dwSize);
  334. if (lStatus == ERROR_SUCCESS) {
  335. // counter names are installed so return success
  336. *lpDriverName = lpThisChar;
  337. SetLastError (ERROR_SUCCESS);
  338. if ( lpThisChar ) free (lpThisChar);
  339. return TRUE;
  340. } else {
  341. SetLastError (ERROR_BADKEY);
  342. if ( lpThisChar ) free (lpThisChar);
  343. return FALSE;
  344. }
  345. } else { // key not found
  346. SetLastError (lStatus);
  347. free (lpDriverKey);
  348. if ( lpThisChar ) free (lpThisChar);
  349. return FALSE;
  350. }
  351. } else {
  352. SetLastError (ERROR_INVALID_PARAMETER);
  353. if ( lpThisChar ) free (lpThisChar);
  354. return FALSE;
  355. }
  356. }
  357. LONG
  358. FixNames (
  359. HANDLE hKeyLang,
  360. LPTSTR *lpOldNameTable,
  361. IN LPTSTR lpszLangId, // unicode value of Language subkey
  362. DWORD dwLastItem,
  363. DWORD dwFirstNameToRemove,
  364. DWORD dwLastNameToRemove
  365. )
  366. {
  367. LONG lStatus;
  368. LPTSTR lpNameBuffer = NULL;
  369. LPTSTR lpHelpBuffer = NULL;
  370. DWORD dwTextIndex, dwSize;
  371. LPTSTR lpNextHelpText;
  372. LPTSTR lpNextNameText;
  373. // allocate space for the array of new text it will point
  374. // into the text buffer returned in the lpOldNameTable buffer)
  375. lpNameBuffer = malloc (_msize(lpOldNameTable));
  376. lpHelpBuffer = malloc (_msize(lpOldNameTable));
  377. if (!lpNameBuffer || !lpHelpBuffer) {
  378. if (lpNameBuffer) {
  379. free(lpNameBuffer);
  380. }
  381. if (lpHelpBuffer) {
  382. free(lpHelpBuffer);
  383. }
  384. lStatus = ERROR_OUTOFMEMORY;
  385. return lStatus;
  386. }
  387. // remove this driver's counters from array
  388. for (dwTextIndex = dwFirstNameToRemove;
  389. dwTextIndex <= dwLastNameToRemove;
  390. dwTextIndex++) {
  391. if (dwTextIndex > dwLastItem)
  392. break;
  393. lpOldNameTable[dwTextIndex] = NULL;
  394. }
  395. lpNextHelpText = lpHelpBuffer;
  396. lpNextNameText = lpNameBuffer;
  397. // build new Multi_SZ strings from New Table
  398. for (dwTextIndex = 0; dwTextIndex <= dwLastItem; dwTextIndex++){
  399. if (lpOldNameTable[dwTextIndex]) {
  400. // if there's a text string at that index, then ...
  401. if (dwTextIndex & 0x1) { // ODD number == Help Text
  402. lpNextHelpText +=
  403. _stprintf (lpNextHelpText, TEXT("%d"), dwTextIndex) + 1;
  404. lpNextHelpText +=
  405. _stprintf (lpNextHelpText, TEXT("%s"),
  406. lpOldNameTable[dwTextIndex]) + 1;
  407. if (dwTextIndex > dwLastHelp){
  408. dwLastHelp = dwTextIndex;
  409. }
  410. } else { // EVEN number == counter name text
  411. lpNextNameText +=
  412. _stprintf (lpNextNameText, TEXT("%d"), dwTextIndex) + 1;
  413. lpNextNameText +=
  414. _stprintf (lpNextNameText, TEXT("%s"),
  415. lpOldNameTable[dwTextIndex]) + 1;
  416. if (dwTextIndex > dwLastCounter){
  417. dwLastCounter = dwTextIndex;
  418. }
  419. }
  420. }
  421. } // for dwTextIndex
  422. // add MULTI_SZ terminating NULL
  423. *lpNextNameText++ = TEXT ('\0');
  424. *lpNextHelpText++ = TEXT ('\0');
  425. // update counter name text buffer
  426. dwSize = (DWORD)((LPBYTE)lpNextNameText - (LPBYTE)lpNameBuffer);
  427. lStatus = RegSetValueEx (
  428. hKeyLang,
  429. Counters,
  430. RESERVED,
  431. REG_MULTI_SZ,
  432. (LPBYTE)lpNameBuffer,
  433. dwSize);
  434. if (lStatus != ERROR_SUCCESS) {
  435. // printf (GetFormatResource(UC_UNABLELOADLANG),
  436. // Counters, lpLangName, lStatus);
  437. goto UCN_FinishLang;
  438. }
  439. dwSize = (DWORD)((LPBYTE)lpNextHelpText - (LPBYTE)lpHelpBuffer);
  440. lStatus = RegSetValueEx (
  441. hKeyLang,
  442. Help,
  443. RESERVED,
  444. REG_MULTI_SZ,
  445. (LPBYTE)lpHelpBuffer,
  446. dwSize);
  447. if (lStatus != ERROR_SUCCESS) {
  448. // printf (GetFormatResource(UC_UNABLELOADLANG),
  449. // Help, lpLangName, lStatus);
  450. goto UCN_FinishLang;
  451. }
  452. UCN_FinishLang:
  453. free (lpNameBuffer);
  454. free (lpHelpBuffer);
  455. free (lpOldNameTable);
  456. RegCloseKey (hKeyLang);
  457. return lStatus;
  458. }
  459. LONG
  460. UnloadCounterNames (
  461. HKEY hKeyMachine,
  462. HKEY hDriverPerf,
  463. LPTSTR lpDriverName
  464. )
  465. /*++
  466. UnloadCounterNames
  467. removes the names and explain text for the driver referenced by
  468. hDriverPerf and updates the first and last counter values accordingly
  469. update process:
  470. - set "updating" flag under Perflib to name of driver being modified
  471. - FOR each language under perflib key
  472. -- load current counter names and explain text into array of
  473. pointers
  474. -- look at all drivers and copy their names and text into a new
  475. buffer adjusting for the removed counter's entries keeping
  476. track of the lowest entry copied. (the names for the driver
  477. to be removed will not be copied, of course)
  478. -- update each driver's "first" and "last" index values
  479. -- copy all other entries from 0 to the lowest copied (i.e. the
  480. system counters)
  481. -- build a new MULIT_SZ string of help text and counter names
  482. -- load new strings into registry
  483. - update perflibl "last" counters
  484. - delete updating flag
  485. ******************************************************
  486. * *
  487. * NOTE: FUNDAMENTAL ASSUMPTION..... *
  488. * *
  489. * this routine assumes that: *
  490. * *
  491. * ALL COUNTER NAMES are even numbered and *
  492. * ALL HELP TEXT STRINGS are odd numbered *
  493. * *
  494. ******************************************************
  495. Arguments
  496. hKeyMachine
  497. handle to HKEY_LOCAL_MACHINE node of registry on system to
  498. remove counters from
  499. hDrivefPerf
  500. handle to registry key of driver to be de-installed
  501. lpDriverName
  502. name of driver being de-installed
  503. Return Value
  504. DOS Error code.
  505. ERROR_SUCCESS if all went OK
  506. error value if not.
  507. --*/
  508. {
  509. HKEY hPerflib;
  510. HKEY hServices;
  511. HKEY hKeyLang;
  512. LONG lStatus;
  513. DWORD dwLangIndex;
  514. //
  515. // dfergus 19 Apr 2001 - 295153
  516. // Init dwSize
  517. //
  518. DWORD dwSize = 0;
  519. DWORD dwType;
  520. DWORD dwLastItem;
  521. DWORD dwRemLastDriverCounter;
  522. DWORD dwRemFirstDriverCounter;
  523. DWORD dwRemLastDriverHelp;
  524. DWORD dwRemFirstDriverHelp;
  525. DWORD dwFirstNameToRemove;
  526. DWORD dwLastNameToRemove;
  527. LPTSTR *lpOldNameTable;
  528. LPTSTR lpLangName = NULL;
  529. LPTSTR lpThisDriver = NULL;
  530. BOOL bPerflibUpdated = FALSE;
  531. BOOL bDriversShuffled = FALSE;
  532. DWORD dwBufferSize; // size of total buffer in bytes
  533. TCHAR CounterNameBuffer [40];
  534. TCHAR HelpNameBuffer [40];
  535. lStatus = RegOpenKeyEx (
  536. hKeyMachine,
  537. DriverPathRoot,
  538. RESERVED,
  539. KEY_READ | KEY_WRITE,
  540. &hServices);
  541. if (lStatus != ERROR_SUCCESS) {
  542. return lStatus;
  543. }
  544. // open registry handle to perflib key
  545. lStatus = RegOpenKeyEx (
  546. hKeyMachine,
  547. NamesKey,
  548. RESERVED,
  549. KEY_READ | KEY_WRITE,
  550. &hPerflib);
  551. if (lStatus != ERROR_SUCCESS) {
  552. return lStatus;
  553. }
  554. // check & set Busy flag...
  555. lStatus = RegQueryValueEx (
  556. hPerflib,
  557. Busy,
  558. RESERVED,
  559. &dwType,
  560. NULL,
  561. &dwSize);
  562. if (lStatus == ERROR_SUCCESS) { // perflib is in use at the moment
  563. return ERROR_BUSY;
  564. }
  565. lStatus = RegSetValueEx (
  566. hPerflib,
  567. Busy,
  568. RESERVED,
  569. REG_SZ,
  570. (LPBYTE)lpDriverName,
  571. lstrlen(lpDriverName) * sizeof(TCHAR));
  572. if (lStatus != ERROR_SUCCESS) {
  573. RegCloseKey (hPerflib);
  574. return lStatus;
  575. }
  576. // query registry to get number of Explain text items
  577. dwBufferSize = sizeof (dwHelpItems);
  578. lStatus = RegQueryValueEx (
  579. hPerflib,
  580. LastHelp,
  581. RESERVED,
  582. &dwType,
  583. (LPBYTE)&dwHelpItems,
  584. &dwBufferSize);
  585. if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
  586. RegCloseKey (hPerflib);
  587. return lStatus;
  588. }
  589. // query registry to get number of counter and object name items
  590. dwBufferSize = sizeof (dwCounterItems);
  591. lStatus = RegQueryValueEx (
  592. hPerflib,
  593. LastCounter,
  594. RESERVED,
  595. &dwType,
  596. (LPBYTE)&dwCounterItems,
  597. &dwBufferSize);
  598. if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
  599. RegCloseKey (hPerflib);
  600. return lStatus;
  601. }
  602. // query registry to get PerfLib system version
  603. dwBufferSize = sizeof (dwSystemVersion);
  604. lStatus = RegQueryValueEx (
  605. hPerflib,
  606. VersionStr,
  607. RESERVED,
  608. &dwType,
  609. (LPBYTE)&dwSystemVersion,
  610. &dwBufferSize);
  611. if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
  612. // Key not there, must be NT 1.0 version
  613. dwSystemVersion = OLD_VERSION;
  614. }
  615. if ( dwSystemVersion != OLD_VERSION )
  616. {
  617. // ERROR. The caller should check the version before calling me.
  618. // let return busy for now...
  619. return(ERROR_BUSY);
  620. }
  621. // allocate temporary String buffer
  622. lpLangName = malloc (MAX_PATH * sizeof(TCHAR));
  623. lpThisDriver = malloc (MAX_PATH * sizeof(TCHAR));
  624. if (!lpLangName || !lpThisDriver) {
  625. lStatus = ERROR_OUTOFMEMORY;
  626. goto UCN_ExitPoint;
  627. }
  628. // Get the values that are in use by the driver to be removed
  629. dwSize = sizeof (dwRemLastDriverCounter);
  630. lStatus = RegQueryValueEx (
  631. hDriverPerf,
  632. LastCounter,
  633. RESERVED,
  634. &dwType,
  635. (LPBYTE)&dwRemLastDriverCounter,
  636. &dwSize);
  637. if (lStatus != ERROR_SUCCESS) {
  638. goto UCN_ExitPoint;
  639. }
  640. dwSize = sizeof (dwRemFirstDriverCounter);
  641. lStatus = RegQueryValueEx (
  642. hDriverPerf,
  643. FirstCounter,
  644. RESERVED,
  645. &dwType,
  646. (LPBYTE)&dwRemFirstDriverCounter,
  647. &dwSize);
  648. if (lStatus != ERROR_SUCCESS) {
  649. goto UCN_ExitPoint;
  650. }
  651. dwSize = sizeof (dwRemLastDriverHelp);
  652. lStatus = RegQueryValueEx (
  653. hDriverPerf,
  654. LastHelp,
  655. RESERVED,
  656. &dwType,
  657. (LPBYTE)&dwRemLastDriverHelp,
  658. &dwSize);
  659. if (lStatus != ERROR_SUCCESS) {
  660. goto UCN_ExitPoint;
  661. }
  662. dwSize = sizeof (dwRemFirstDriverHelp);
  663. lStatus = RegQueryValueEx (
  664. hDriverPerf,
  665. FirstHelp,
  666. RESERVED,
  667. &dwType,
  668. (LPBYTE)&dwRemFirstDriverHelp,
  669. &dwSize);
  670. if (lStatus != ERROR_SUCCESS) {
  671. goto UCN_ExitPoint;
  672. }
  673. // get the first and last counters to define block of names used
  674. // by this device
  675. dwFirstNameToRemove = (dwRemFirstDriverCounter <= dwRemFirstDriverHelp ?
  676. dwRemFirstDriverCounter : dwRemFirstDriverHelp);
  677. dwLastNameToRemove = (dwRemLastDriverCounter >= dwRemLastDriverHelp ?
  678. dwRemLastDriverCounter : dwRemLastDriverHelp);
  679. dwLastCounter = dwLastHelp = 0;
  680. // do each language under perflib
  681. for (dwLangIndex = 0, dwSize = _msize(lpLangName);
  682. (RegEnumKey(hPerflib, dwLangIndex, lpLangName, dwSize)) == ERROR_SUCCESS;
  683. dwLangIndex++, dwSize = _msize(lpLangName)) {
  684. lpOldNameTable = BuildNameTable (hPerflib, lpLangName,
  685. &dwLastItem, &hKeyLang, CounterNameBuffer, HelpNameBuffer);
  686. if (lpOldNameTable) {
  687. if (!FixNames (
  688. hKeyLang,
  689. lpOldNameTable,
  690. lpLangName,
  691. dwLastItem,
  692. dwFirstNameToRemove,
  693. dwLastNameToRemove)) {
  694. bPerflibUpdated = TRUE;
  695. }
  696. } else { // unable to unload names for this language
  697. // display error message
  698. }
  699. } // end for (more languages)
  700. if (bPerflibUpdated) {
  701. // update perflib's "last" values
  702. dwSize = sizeof (dwLastCounter);
  703. lStatus = RegSetValueEx (
  704. hPerflib,
  705. LastCounter,
  706. RESERVED,
  707. REG_DWORD,
  708. (LPBYTE)&dwLastCounter,
  709. dwSize);
  710. dwSize = sizeof (dwLastHelp);
  711. lStatus = RegSetValueEx (
  712. hPerflib,
  713. LastHelp,
  714. RESERVED,
  715. REG_DWORD,
  716. (LPBYTE)&dwLastHelp,
  717. dwSize);
  718. // update "driver"s values (i.e. remove them)
  719. RegDeleteValue (hDriverPerf, FirstCounter);
  720. RegDeleteValue (hDriverPerf, LastCounter);
  721. RegDeleteValue (hDriverPerf, FirstHelp);
  722. RegDeleteValue (hDriverPerf, LastHelp);
  723. }
  724. UCN_ExitPoint:
  725. RegDeleteValue (hPerflib, Busy);
  726. RegCloseKey (hPerflib);
  727. RegCloseKey (hServices);
  728. if (lpLangName) free (lpLangName);
  729. if (lpThisDriver) free (lpThisDriver);
  730. return lStatus;
  731. }
  732. BOOL FAR PASCAL unlodctr(DWORD argc,LPSTR argv[], LPSTR *ppszResult )
  733. /*++
  734. main
  735. entry point to Counter Name Unloader
  736. Arguments
  737. argc
  738. # of command line arguments present
  739. argv
  740. array of pointers to command line strings
  741. (note that these are obtained from the GetCommandLine function in
  742. order to work with both UNICODE and ANSI strings.)
  743. ReturnValue
  744. 0 (ERROR_SUCCESS) if command was processed
  745. Non-Zero if command error was detected.
  746. --*/
  747. {
  748. LPTSTR lpDriverName; // name of driver to delete from perflib
  749. HKEY hDriverPerf; // handle to performance sub-key of driver
  750. DWORD dwStatus; // return status of fn. calls
  751. *ppszResult = achBuff;
  752. wsprintfA( achBuff, "{\"NO_ERROR\"}");
  753. if (!GetDriverFromCommandLine (
  754. HKEY_LOCAL_MACHINE, &lpDriverName, &hDriverPerf, argv)) {
  755. // error message was printed in routine if there was an error
  756. wsprintfA( achBuff,"{\"ERROR\"}");
  757. return (FALSE);
  758. }
  759. // removes names and explain text for driver in lpDriverName
  760. // displays error messages for errors encountered
  761. dwStatus = (DWORD)UnloadCounterNames (HKEY_LOCAL_MACHINE,
  762. hDriverPerf, lpDriverName);
  763. RegCloseKey (hDriverPerf);
  764. if ( dwStatus != ERROR_SUCCESS )
  765. {
  766. wsprintfA( achBuff,"{\"ERROR\"}");
  767. }
  768. return (dwStatus==ERROR_SUCCESS);
  769. }