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.

1764 lines
46 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. diskperf.c
  5. Abstract:
  6. Program to display and/or update the current value of the Diskperf
  7. driver startup value
  8. Author:
  9. Bob Watson (a-robw) 4 Dec 92
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <ntconfig.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <windows.h>
  20. #include <regstr.h> // for REGSTR_VAL_UPPERFILTERS
  21. #include <tchar.h>
  22. #include <locale.h>
  23. #include "diskperf.h" // include text string id constancts
  24. #include <ntdddisk.h>
  25. #include <mountmgr.h>
  26. LANGID WINAPI MySetThreadUILanguage(
  27. WORD wReserved);
  28. #define SWITCH_CHAR '-' // is there a system call to get this?
  29. #define ENABLE_CHAR 'Y' // command will be upcased
  30. #define DISABLE_CHAR 'N'
  31. #define ENHANCED_CHAR 'E'
  32. #define LOCAL_CHANGE 2 // number of commands in a local change command
  33. #define REMOTE_CHANGE 3 // number of commands in a remote change command
  34. //
  35. // note these values are arbitrarily based on the whims of the people
  36. // developing the disk drive drivers that belong to the "Filter" group.
  37. //
  38. #define TAG_NORMAL 4 // diskperf starts AFTER ftdisk
  39. #define TAG_ENHANCED 2 // diskperf starts BEFORE ftdisk
  40. #define IRP_STACK_ENABLED 5 // size of IRP stack when diskperf is enabled
  41. #define IRP_STACK_DISABLED 4 // size of IRP stack when diskperf is enabled
  42. #define IRP_STACK_DEFAULT 8 // default IRP stack size in W2K
  43. #define IRP_STACK_NODISKPERF 7
  44. #define DISKPERF_SERVICE_NAME TEXT("DiskPerf")
  45. LPCTSTR lpwszDiskPerfKey = TEXT("SYSTEM\\CurrentControlSet\\Services\\Diskperf");
  46. LPCTSTR lpwszIOSystemKey = TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\I/O System");
  47. LPCTSTR lpwszOsVersionKey = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
  48. LPCTSTR lpwszBuildNumber = TEXT("CurrentBuildNumber");
  49. LPCTSTR lpwszOsVersion = TEXT("CurrentVersion");
  50. #define ENABLE_DISKDRIVE 0x0001
  51. #define ENABLE_VOLUME 0x0002
  52. #define ENABLE_PERMANENT 0x0004
  53. #define ENABLE_PERMANENT_IOCTL 0x0008
  54. LPCTSTR lpwszDiskDriveKey
  55. = TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E967-E325-11CE-BFC1-08002BE10318}");
  56. LPCTSTR lpwszVolumeKey
  57. = TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{71A27CDD-812A-11D0-BEC7-08002BE2092F}");
  58. LPCTSTR lpwszPartmgrKey = TEXT("SYSTEM\\CurrentControlSet\\Services\\Partmgr");
  59. LPCTSTR lpwszEnableCounterValue = TEXT("EnableCounterForIoctl");
  60. ULONG
  61. OpenRegKeys(
  62. IN LPCTSTR lpszMachine,
  63. OUT PHKEY hRegistry,
  64. OUT PHKEY hDiskKey,
  65. OUT PHKEY hVolumeKey,
  66. OUT PHKEY hServiceKey
  67. );
  68. ULONG
  69. SetFilter(
  70. IN HKEY hKey,
  71. IN LPTSTR strFilterString,
  72. IN DWORD dwSize
  73. );
  74. ULONG
  75. GetFilter(
  76. IN HKEY hKey,
  77. OUT LPTSTR strFilterString,
  78. IN DWORD dwSize
  79. );
  80. ULONG
  81. CheckFilter(
  82. IN TCHAR *Buffer
  83. );
  84. ULONG
  85. GetEnableFlag(
  86. IN HKEY hDiskKey,
  87. IN HKEY hVolumeKey
  88. );
  89. ULONG
  90. AddToFilter(
  91. IN HKEY hKey
  92. );
  93. ULONG
  94. RemoveFromFilter(
  95. IN HKEY hKey
  96. );
  97. void
  98. PrintStatus(
  99. IN BOOL bCurrent,
  100. IN ULONG EnableFlag,
  101. IN LPCTSTR cMachineName
  102. );
  103. int __cdecl
  104. Dp_wprintf(
  105. const wchar_t *format,
  106. ...
  107. );
  108. int __cdecl
  109. Dp_fwprintf(
  110. FILE *str,
  111. const wchar_t *format,
  112. ...
  113. );
  114. int __cdecl
  115. Dp_vfwprintf(
  116. FILE *str,
  117. const wchar_t *format,
  118. va_list argptr
  119. );
  120. BOOL
  121. IsBeyondW2K(
  122. IN LPCTSTR lpszMachine,
  123. OUT PDWORD EnableCounter);
  124. ULONG
  125. EnableForIoctl(
  126. IN LPWSTR lpszMachineName
  127. );
  128. ULONG
  129. DisableForIoctl(
  130. IN LPWSTR lpszMachineName,
  131. IN ULONG Request
  132. );
  133. #if DBG
  134. void
  135. DbgPrintMultiSz(
  136. TCHAR *String,
  137. ULONG Size
  138. );
  139. #endif
  140. #define REG_TO_DP_INDEX(reg_idx) (DP_LOAD_STATUS_BASE + (\
  141. (reg_idx == SERVICE_BOOT_START) ? DP_BOOT_START : \
  142. (reg_idx == SERVICE_SYSTEM_START) ? DP_SYSTEM_START : \
  143. (reg_idx == SERVICE_AUTO_START) ? DP_AUTO_START : \
  144. (reg_idx == SERVICE_DEMAND_START) ? DP_DEMAND_START : \
  145. (reg_idx == SERVICE_DISABLED) ? DP_NEVER_START : DP_UNDEFINED))
  146. #define MAX_MACHINE_NAME_LEN 32
  147. // command line arguments
  148. #define CMD_SHOW_LOCAL_STATUS 1
  149. #define CMD_DO_COMMAND 2
  150. #define ArgIsSystem(arg) (*(arg) == '\\' ? TRUE : FALSE)
  151. //
  152. // global buffer for help text display strings
  153. //
  154. #define DISP_BUFF_LEN 256
  155. #define NUM_STRING_BUFFS 2
  156. LPCTSTR BlankString = TEXT(" ");
  157. LPCTSTR StartKey = TEXT("Start");
  158. LPCTSTR TagKey = TEXT("Tag");
  159. LPCTSTR EmptyString = TEXT("");
  160. LPCTSTR LargeIrps = TEXT("LargeIrpStackLocations");
  161. HINSTANCE hMod = NULL;
  162. DWORD dwLastError;
  163. LPCTSTR
  164. GetStringResource (
  165. UINT wStringId
  166. )
  167. {
  168. static TCHAR DisplayStringBuffer[NUM_STRING_BUFFS][DISP_BUFF_LEN];
  169. static DWORD dwBuffIndex;
  170. LPTSTR szReturnBuffer;
  171. dwBuffIndex++;
  172. dwBuffIndex %= NUM_STRING_BUFFS;
  173. szReturnBuffer = (LPTSTR)&DisplayStringBuffer[dwBuffIndex][0];
  174. if (!hMod) {
  175. hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
  176. }
  177. if (hMod) {
  178. if ((LoadString(hMod, wStringId, szReturnBuffer, DISP_BUFF_LEN)) > 0) {
  179. return (LPCTSTR)szReturnBuffer;
  180. } else {
  181. dwLastError = GetLastError();
  182. return EmptyString;
  183. }
  184. } else {
  185. return EmptyString;
  186. }
  187. }
  188. LPCTSTR
  189. GetFormatResource (
  190. UINT wStringId
  191. )
  192. {
  193. static TCHAR TextFormat[DISP_BUFF_LEN];
  194. if (!hMod) {
  195. hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
  196. }
  197. if (hMod) {
  198. if ((LoadString(hMod, wStringId, TextFormat, DISP_BUFF_LEN)) > 0) {
  199. return (LPCTSTR)&TextFormat[0];
  200. } else {
  201. dwLastError = GetLastError();
  202. return BlankString;
  203. }
  204. } else {
  205. return BlankString;
  206. }
  207. }
  208. VOID
  209. DisplayChangeCmd (
  210. )
  211. {
  212. UINT wID;
  213. TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
  214. TCHAR DisplayStringBuffer[DISP_BUFF_LEN];
  215. if (hMod) {
  216. if ((LoadString(hMod, DP_TEXT_FORMAT, DisplayStringBuffer, DISP_BUFF_LEN)) > 0) {
  217. for (wID=DP_CMD_HELP_START; wID <= DP_CMD_HELP_END; wID++) {
  218. if ((LoadString(hMod, wID, DisplayStringBuffer, DISP_BUFF_LEN)) > 0) {
  219. Dp_wprintf(DisplayStringBuffer);
  220. }
  221. }
  222. }
  223. }
  224. }
  225. VOID
  226. DisplayCmdHelp(
  227. )
  228. {
  229. UINT wID;
  230. TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
  231. TCHAR DisplayStringBuffer[DISP_BUFF_LEN];
  232. if (hMod) {
  233. if ((LoadString(hMod, DP_TEXT_FORMAT, DisplayStringBuffer, DISP_BUFF_LEN)) > 0) {
  234. for (wID=DP_HELP_TEXT_START; wID <= DP_HELP_TEXT_END; wID++) {
  235. if ((LoadString(hMod, wID, DisplayStringBuffer, DISP_BUFF_LEN)) > 0) {
  236. Dp_wprintf(DisplayStringBuffer);
  237. }
  238. }
  239. }
  240. }
  241. DisplayChangeCmd();
  242. }
  243. ULONG
  244. DisplayStatus (
  245. LPTSTR lpszMachine
  246. )
  247. {
  248. ULONG Status;
  249. HKEY hRegistry;
  250. HKEY hDiskPerfKey;
  251. HKEY hDiskKey;
  252. HKEY hVolumeKey;
  253. DWORD dwValue, dwValueSize, dwTag;
  254. TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
  255. TCHAR cMachineName[MAX_MACHINE_NAME_LEN];
  256. PTCHAR pThisWideChar;
  257. PTCHAR pThisChar;
  258. INT iCharCount;
  259. DWORD EnableCounter;
  260. pThisChar = lpszMachine;
  261. pThisWideChar = cMachineName;
  262. iCharCount = 0;
  263. if (pThisChar) { // if machine is not NULL, then copy
  264. while (*pThisChar) {
  265. *pThisWideChar++ = (TCHAR)(*pThisChar++);
  266. if (++iCharCount >= MAX_MACHINE_NAME_LEN) break;
  267. }
  268. *pThisWideChar = 0;
  269. }
  270. if (!lpszMachine) {
  271. lstrcpy(cMachineName,
  272. GetStringResource(DP_THIS_SYSTEM));
  273. }
  274. if (IsBeyondW2K(lpszMachine, &EnableCounter)) {
  275. if (EnableCounter) {
  276. PrintStatus(TRUE, ENABLE_PERMANENT_IOCTL, cMachineName);
  277. }
  278. else {
  279. PrintStatus(TRUE, ENABLE_PERMANENT, cMachineName);
  280. }
  281. return ERROR_SUCCESS;
  282. }
  283. Status = OpenRegKeys(
  284. lpszMachine,
  285. &hRegistry,
  286. &hDiskKey,
  287. &hVolumeKey,
  288. &hDiskPerfKey);
  289. if (Status != ERROR_SUCCESS) {
  290. #if DBG
  291. fprintf(stderr,
  292. "DisplayStatus: Cannot open HKLM on target machine: %d\n",
  293. Status);
  294. #endif
  295. Dp_wprintf(GetFormatResource(DP_UNABLE_READ_REGISTRY));
  296. return Status;
  297. }
  298. dwTag = GetEnableFlag(hDiskKey, hVolumeKey);
  299. dwValue = (dwTag == 0) ? SERVICE_DISABLED : SERVICE_BOOT_START;
  300. dwValueSize = sizeof(dwValue);
  301. Status = RegQueryValueEx (
  302. hDiskPerfKey,
  303. StartKey,
  304. NULL,
  305. NULL,
  306. (LPBYTE)&dwValue,
  307. &dwValueSize);
  308. if (Status != ERROR_SUCCESS) {
  309. Dp_wprintf(GetFormatResource(DP_UNABLE_READ_START));
  310. goto DisplayStatusCleanup;
  311. }
  312. PrintStatus(TRUE, dwTag, cMachineName);
  313. DisplayStatusCleanup:
  314. RegCloseKey(hDiskKey);
  315. RegCloseKey(hVolumeKey);
  316. RegCloseKey(hDiskPerfKey);
  317. RegCloseKey(hRegistry);
  318. if (Status != ERROR_SUCCESS) {
  319. Dp_wprintf(GetFormatResource(DP_STATUS_FORMAT), Status);
  320. }
  321. return Status;
  322. }
  323. ULONG
  324. DoChangeCommand (
  325. LPTSTR lpszCommand,
  326. LPTSTR lpszMachine
  327. )
  328. {
  329. // connect to registry on local machine with read/write access
  330. ULONG Status;
  331. HKEY hRegistry;
  332. HKEY hDiskPerfKey;
  333. HKEY hDiskKey;
  334. HKEY hVolumeKey;
  335. DWORD dwValue, dwValueSize, dwOrigValue, dwTag, dwOrigTag;
  336. TCHAR cMachineName[MAX_MACHINE_NAME_LEN];
  337. PTCHAR pThisWideChar;
  338. PTCHAR pThisChar;
  339. INT iCharCount;
  340. PTCHAR pCmdChar;
  341. TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
  342. HKEY hIOSystemKey;
  343. DWORD dwDisposition;
  344. DWORD dwIrpValue;
  345. ULONG EnableRequest, DisableRequest;
  346. ULONG EnableFlag, EndFlag = 0;
  347. BOOL bModified, bIrpStackReg;
  348. LONG nIrpStack, nIrpStackReg, nIncrement;
  349. DWORD EnableCounter;
  350. // check command to see if it's valid
  351. _tcsupr (lpszCommand);
  352. pCmdChar = lpszCommand;
  353. dwValue = 0;
  354. EnableRequest = DisableRequest = 0;
  355. if (*pCmdChar++ == SWITCH_CHAR ) {
  356. if (!_tcscmp(pCmdChar, _T("Y")) ||
  357. !_tcscmp(pCmdChar, _T("YA")) ||
  358. !_tcscmp(pCmdChar, _T("YALL"))) {
  359. EnableRequest = ENABLE_DISKDRIVE | ENABLE_VOLUME;
  360. }
  361. else if (!_tcscmp(pCmdChar, _T("N")) ||
  362. !_tcscmp(pCmdChar, _T("NA")) ||
  363. !_tcscmp(pCmdChar, _T("NALL")) ) {
  364. DisableRequest = ENABLE_DISKDRIVE | ENABLE_VOLUME;
  365. }
  366. else if (!_tcscmp(pCmdChar, _T("YD")) ||
  367. !_tcscmp(pCmdChar, _T("YDISK")) ) {
  368. EnableRequest = ENABLE_DISKDRIVE;
  369. }
  370. else if (!_tcscmp(pCmdChar, _T("YV")) ||
  371. !_tcscmp(pCmdChar, _T("YVOLUME")) ) {
  372. EnableRequest = ENABLE_VOLUME;
  373. }
  374. else if (!_tcscmp(pCmdChar, _T("ND")) ||
  375. !_tcscmp(pCmdChar, _T("NDISK")) ) {
  376. DisableRequest = ENABLE_DISKDRIVE;
  377. }
  378. else if (!_tcscmp(pCmdChar, _T("NV")) ||
  379. !_tcscmp(pCmdChar, _T("NVOLUME")) ) {
  380. DisableRequest = ENABLE_VOLUME;
  381. } else {
  382. DisplayCmdHelp();
  383. return ERROR_SUCCESS;
  384. }
  385. } else {
  386. DisplayChangeCmd();
  387. return ERROR_SUCCESS;
  388. }
  389. // if command OK then convert machine to wide string for connection
  390. pThisChar = lpszMachine;
  391. pThisWideChar = cMachineName;
  392. iCharCount = 0;
  393. if (pThisChar) {
  394. while (*pThisChar) {
  395. *pThisWideChar++ = (TCHAR)(*pThisChar++);
  396. if (++iCharCount >= MAX_MACHINE_NAME_LEN) break;
  397. }
  398. *pThisWideChar = 0; // null terminate
  399. }
  400. if (!lpszMachine) {
  401. lstrcpy (cMachineName,
  402. GetStringResource(DP_THIS_SYSTEM));
  403. }
  404. if (IsBeyondW2K(lpszMachine, &EnableCounter)) {
  405. if (EnableRequest != 0) {
  406. EnableForIoctl(lpszMachine);
  407. PrintStatus(TRUE, ENABLE_PERMANENT_IOCTL, cMachineName);
  408. }
  409. else if (DisableRequest != 0) {
  410. DisableForIoctl(lpszMachine, DisableRequest);
  411. PrintStatus(TRUE, ENABLE_PERMANENT, cMachineName);
  412. }
  413. return ERROR_SUCCESS;
  414. }
  415. // connect to registry
  416. Status = OpenRegKeys(
  417. lpszMachine,
  418. &hRegistry,
  419. &hDiskKey,
  420. &hVolumeKey,
  421. &hDiskPerfKey);
  422. if (Status != ERROR_SUCCESS) {
  423. #if DBG
  424. fprintf(stderr,
  425. "DoChangeCommand: Cannot connect to registry: Status=%d\n",
  426. Status);
  427. #endif
  428. Dp_wprintf(GetFormatResource(DP_UNABLE_READ_REGISTRY));
  429. return Status;
  430. }
  431. hIOSystemKey = NULL;
  432. nIrpStackReg = 0;
  433. bIrpStackReg = FALSE; // no registry key prior to this
  434. Status = RegCreateKeyEx (
  435. hRegistry,
  436. lpwszIOSystemKey,
  437. 0L, //Reserved
  438. NULL,
  439. 0L, // no special options
  440. KEY_WRITE | KEY_READ, // desired access
  441. NULL, // default security
  442. &hIOSystemKey,
  443. &dwDisposition);
  444. if (Status != ERROR_SUCCESS) {
  445. if ((Status == ERROR_ALREADY_EXISTS) &&
  446. (dwDisposition == REG_OPENED_EXISTING_KEY)) {
  447. // then this key is already in the registry so this is OK
  448. Status = ERROR_SUCCESS;
  449. }
  450. else {
  451. Dp_wprintf(GetFormatResource(DP_UNABLE_READ_REGISTRY));
  452. goto DoChangeCommandCleanup;
  453. }
  454. }
  455. if ( (Status == ERROR_SUCCESS) && (dwDisposition == REG_OPENED_EXISTING_KEY)) {
  456. DWORD dwSize;
  457. dwSize = sizeof(DWORD);
  458. Status = RegQueryValueEx (
  459. hIOSystemKey,
  460. LargeIrps,
  461. 0L,
  462. NULL,
  463. (LPBYTE)&dwIrpValue,
  464. &dwSize);
  465. if (Status == ERROR_SUCCESS) {
  466. #if DBG
  467. fprintf(stderr, "Registry LargeIrpStack=%d\n", dwIrpValue);
  468. #endif
  469. nIrpStackReg = dwIrpValue;
  470. bIrpStackReg = TRUE;
  471. }
  472. }
  473. EnableFlag = GetEnableFlag(hDiskKey, hVolumeKey);
  474. #if DBG
  475. fprintf(stderr, "DoChangeCommand: EnableFlag is %x\n", EnableFlag);
  476. #endif
  477. bModified = FALSE;
  478. nIncrement = 0;
  479. if ( (EnableRequest & ENABLE_DISKDRIVE) &&
  480. !(EnableFlag & ENABLE_DISKDRIVE) ) {
  481. // Turn on filter for disk drives
  482. if (AddToFilter(hDiskKey) == ERROR_SUCCESS) {
  483. bModified = TRUE;
  484. nIncrement++;
  485. }
  486. }
  487. if ( (EnableRequest & ENABLE_VOLUME) &&
  488. !(EnableFlag & ENABLE_VOLUME) ) {
  489. // Turn on filter for volumes
  490. if (AddToFilter(hVolumeKey) == ERROR_SUCCESS) {
  491. bModified = TRUE;
  492. nIncrement++;
  493. }
  494. }
  495. if ( (DisableRequest & ENABLE_DISKDRIVE) &&
  496. (EnableFlag & ENABLE_DISKDRIVE) ) {
  497. // Turn off filter for disk drives
  498. if (RemoveFromFilter(hDiskKey) == ERROR_SUCCESS) {
  499. bModified = TRUE;
  500. nIncrement--;
  501. }
  502. }
  503. if ( (DisableRequest & ENABLE_VOLUME) &&
  504. (EnableFlag & ENABLE_VOLUME) ) {
  505. // Turn off filter for volumes
  506. if (RemoveFromFilter(hVolumeKey) == ERROR_SUCCESS) {
  507. bModified = TRUE;
  508. nIncrement--;
  509. }
  510. }
  511. nIrpStack = 0;
  512. EndFlag = GetEnableFlag(hDiskKey, hVolumeKey);
  513. if (bModified) { // we have modified the registry
  514. dwValue = (EndFlag == 0) ? SERVICE_DISABLED : SERVICE_BOOT_START;
  515. Status = RegSetValueEx(
  516. hDiskPerfKey,
  517. StartKey,
  518. 0L,
  519. REG_DWORD,
  520. (LPBYTE)&dwValue,
  521. sizeof(dwValue));
  522. //
  523. // First update service registry entries
  524. //
  525. if (DisableRequest != 0) {
  526. nIrpStack = nIrpStackReg + nIncrement;
  527. if (EndFlag == 0) {
  528. //
  529. // Turn off service completely
  530. //
  531. // Set Irp stack size to original value or default
  532. if (nIrpStack < IRP_STACK_NODISKPERF)
  533. nIrpStack = IRP_STACK_NODISKPERF;
  534. }
  535. else { // else, there is only one stack left
  536. if (nIrpStack < IRP_STACK_NODISKPERF+1)
  537. nIrpStack = IRP_STACK_NODISKPERF+1;
  538. }
  539. }
  540. else if (EnableRequest != 0) {
  541. nIrpStack = nIrpStackReg + nIncrement;
  542. //
  543. // Set proper Irp stack size
  544. //
  545. if (EndFlag == (ENABLE_DISKDRIVE | ENABLE_VOLUME)) {
  546. if (nIrpStack < IRP_STACK_NODISKPERF+2) // a value is set
  547. nIrpStack = IRP_STACK_NODISKPERF+2;
  548. }
  549. else { // at least one is enabled
  550. if (nIrpStack < IRP_STACK_NODISKPERF+1)
  551. nIrpStack = IRP_STACK_NODISKPERF+1;
  552. }
  553. }
  554. }
  555. else {
  556. //
  557. // No action taken. Should tell the user the state.
  558. //
  559. PrintStatus(TRUE, EndFlag, cMachineName);
  560. Dp_wprintf(GetFormatResource(DP_NOCHANGE));
  561. }
  562. #if DBG
  563. fprintf(stderr, "New LargeIrp is %d\n", nIrpStack);
  564. #endif
  565. if (hIOSystemKey != NULL && Status == ERROR_SUCCESS) {
  566. if (bModified) {
  567. Status = RegSetValueEx (
  568. hIOSystemKey,
  569. LargeIrps,
  570. 0L,
  571. REG_DWORD,
  572. (LPBYTE)&nIrpStack,
  573. sizeof(DWORD));
  574. if (Status == ERROR_SUCCESS) {
  575. PrintStatus(FALSE, EndFlag, cMachineName);
  576. }
  577. else {
  578. Dp_wprintf(GetFormatResource(DP_UNABLE_MODIFY_VALUE));
  579. }
  580. }
  581. RegCloseKey(hIOSystemKey);
  582. }
  583. DoChangeCommandCleanup:
  584. if (hDiskPerfKey != NULL) {
  585. RegCloseKey(hDiskPerfKey);
  586. }
  587. if (hDiskKey != NULL) {
  588. RegCloseKey(hDiskKey);
  589. }
  590. if (hVolumeKey != NULL) {
  591. RegCloseKey(hVolumeKey);
  592. }
  593. if (hRegistry != NULL) {
  594. RegCloseKey(hRegistry);
  595. }
  596. if (Status != ERROR_SUCCESS) {
  597. Dp_wprintf(GetFormatResource(DP_STATUS_FORMAT), Status);
  598. }
  599. return Status;
  600. }
  601. ULONG
  602. OpenRegKeys(
  603. IN LPCTSTR lpszMachine,
  604. OUT PHKEY hRegistry,
  605. OUT PHKEY hDiskKey,
  606. OUT PHKEY hVolumeKey,
  607. OUT PHKEY hServiceKey
  608. )
  609. {
  610. ULONG status;
  611. if (hRegistry == NULL)
  612. return ERROR_INVALID_PARAMETER;
  613. *hRegistry = NULL;
  614. status = RegConnectRegistry(
  615. lpszMachine,
  616. HKEY_LOCAL_MACHINE,
  617. hRegistry);
  618. if (status != ERROR_SUCCESS)
  619. return status;
  620. if (*hRegistry == NULL)
  621. return ERROR_INVALID_PARAMETER; // Avoid PREFIX error
  622. if (hDiskKey) {
  623. *hDiskKey = NULL;
  624. if (status == ERROR_SUCCESS) {
  625. status = RegOpenKeyEx(
  626. *hRegistry,
  627. lpwszDiskDriveKey,
  628. (DWORD) 0,
  629. KEY_SET_VALUE | KEY_QUERY_VALUE,
  630. hDiskKey);
  631. }
  632. }
  633. if (hVolumeKey) {
  634. *hVolumeKey = NULL;
  635. if (status == ERROR_SUCCESS) {
  636. status = RegOpenKeyEx(
  637. *hRegistry,
  638. lpwszVolumeKey,
  639. (DWORD) 0,
  640. KEY_SET_VALUE | KEY_QUERY_VALUE,
  641. hVolumeKey);
  642. }
  643. }
  644. if (hServiceKey) {
  645. *hServiceKey = NULL;
  646. if (status == ERROR_SUCCESS) {
  647. status = RegOpenKeyEx(
  648. *hRegistry,
  649. lpwszDiskPerfKey,
  650. (DWORD) 0,
  651. KEY_SET_VALUE | KEY_QUERY_VALUE,
  652. hServiceKey);
  653. }
  654. }
  655. if ( (status != ERROR_SUCCESS) && (hDiskKey != NULL) ) {
  656. if (*hDiskKey != NULL)
  657. RegCloseKey(*hDiskKey);
  658. *hDiskKey = NULL;
  659. }
  660. if ( (status != ERROR_SUCCESS) && (hVolumeKey != NULL) ) {
  661. if (*hVolumeKey != NULL)
  662. RegCloseKey(*hVolumeKey);
  663. *hVolumeKey = NULL;
  664. }
  665. if ( (status != ERROR_SUCCESS) && (hServiceKey != NULL) ) {
  666. if (*hServiceKey != NULL)
  667. RegCloseKey(*hServiceKey);
  668. *hServiceKey = NULL;
  669. }
  670. return status;
  671. }
  672. ULONG
  673. SetFilter(
  674. IN HKEY hKey,
  675. IN LPTSTR strFilterString,
  676. IN DWORD dwSize
  677. )
  678. {
  679. ULONG status;
  680. LONG len;
  681. DWORD dwType = REG_MULTI_SZ;
  682. if (hKey == NULL)
  683. return ERROR_BADKEY;
  684. //
  685. // NOTE: Assumes that strFilterString is always MAX_PATH, NULL padded
  686. //
  687. len = dwSize / sizeof(TCHAR);
  688. if (len < 2) {
  689. dwSize = 2 * sizeof(TCHAR);
  690. #if DBG
  691. fprintf(stderr, "SetFilter: Length %d dwSize %d\n", len, dwSize);
  692. #endif
  693. }
  694. else { // ensures 2 null character always
  695. if (strFilterString[len-1] != 0) { // no trailing null
  696. len += 2;
  697. strFilterString[len] = 0;
  698. strFilterString[len+1] = 0;
  699. #if DBG
  700. fprintf(stderr, "SetFilter: New length(+2) %d\n", len);
  701. #endif
  702. }
  703. else if (strFilterString[len-2] != 0) { // only one trailing null
  704. len += 1;
  705. strFilterString[len+1] = 0;
  706. #if DBG
  707. fprintf(stderr, "SetFilter: New length(+1) %d\n", len);
  708. #endif
  709. }
  710. dwSize = len * sizeof(TCHAR);
  711. }
  712. if (len <= 2) {
  713. status = RegDeleteValue(hKey, REGSTR_VAL_UPPERFILTERS);
  714. #if DBG
  715. fprintf(stderr, "Delete status = %d\n", status);
  716. #endif
  717. return status;
  718. }
  719. status = RegSetValueEx(
  720. hKey,
  721. REGSTR_VAL_UPPERFILTERS,
  722. (DWORD) 0,
  723. dwType,
  724. (BYTE*)strFilterString,
  725. dwSize);
  726. #if DBG
  727. if (status != ERROR_SUCCESS) {
  728. _ftprintf(stderr, _T("SetFilter: Cannot query key %s status=%d\n"),
  729. REGSTR_VAL_UPPERFILTERS, status);
  730. }
  731. else {
  732. fprintf(stderr, "SetFilter: ");
  733. DbgPrintMultiSz(strFilterString, dwSize);
  734. fprintf(stderr, "\n");
  735. }
  736. #endif
  737. return status;
  738. }
  739. ULONG
  740. GetFilter(
  741. IN HKEY hKey,
  742. OUT LPTSTR strFilterString,
  743. IN DWORD dwSize
  744. )
  745. // Returns size of strFilterString
  746. {
  747. ULONG status;
  748. if (hKey == NULL)
  749. return ERROR_BADKEY;
  750. status = RegQueryValueEx(
  751. hKey,
  752. REGSTR_VAL_UPPERFILTERS,
  753. NULL,
  754. NULL,
  755. (BYTE*)strFilterString,
  756. &dwSize);
  757. if (status != ERROR_SUCCESS) {
  758. #if DBG
  759. _ftprintf(stderr, _T("GetFilter: Cannot query key %s status=%d\n"),
  760. REGSTR_VAL_UPPERFILTERS, status);
  761. #endif
  762. return 0;
  763. }
  764. #if DBG
  765. else {
  766. fprintf(stderr, "GetFilter: ");
  767. DbgPrintMultiSz(strFilterString, dwSize);
  768. fprintf(stderr, "\n");
  769. }
  770. #endif
  771. return dwSize;
  772. }
  773. ULONG
  774. CheckFilter(TCHAR *Buffer)
  775. {
  776. TCHAR *string = Buffer;
  777. ULONG stringLength, diskperfLen, result;
  778. if (string == NULL)
  779. return 0;
  780. stringLength = _tcslen(string);
  781. diskperfLen = _tcslen(DISKPERF_SERVICE_NAME);
  782. result = FALSE;
  783. while(stringLength != 0) {
  784. if ((diskperfLen == stringLength) &&
  785. (_tcsicmp(string, DISKPERF_SERVICE_NAME) == 0)) {
  786. #if DBG
  787. fprintf(stderr,
  788. "CheckFilter: string found at offset %d\n",
  789. (string - Buffer));
  790. #endif
  791. result = TRUE;
  792. break;
  793. } else {
  794. string += stringLength + 1;
  795. stringLength = _tcslen(string);
  796. }
  797. }
  798. return result;
  799. }
  800. ULONG
  801. GetEnableFlag(
  802. IN HKEY hDiskKey,
  803. IN HKEY hVolumeKey
  804. )
  805. // Returns the flags indicating what is enabled
  806. {
  807. ULONG bFlag = 0;
  808. TCHAR strFilter[MAX_PATH+1] = {0};
  809. DWORD dwSize;
  810. ULONG status;
  811. dwSize = sizeof(TCHAR) * (MAX_PATH+1);
  812. if (GetFilter(hDiskKey, strFilter, dwSize) > 0) {
  813. if (CheckFilter(strFilter))
  814. bFlag |= ENABLE_DISKDRIVE;
  815. }
  816. #if DBG
  817. else
  818. fprintf(stderr, "GetEnableFlag: No filters for disk drive\n");
  819. #endif
  820. dwSize = sizeof(TCHAR) * (MAX_PATH+1);
  821. if (GetFilter(hVolumeKey, strFilter, dwSize) > 0) {
  822. if (CheckFilter(strFilter))
  823. bFlag |= ENABLE_VOLUME;
  824. }
  825. #if DBG
  826. else
  827. fprintf(stderr, "GetEnableFlag: No filters for volume\n");
  828. #endif
  829. return bFlag;
  830. }
  831. ULONG
  832. AddToFilter(
  833. IN HKEY hKey
  834. )
  835. {
  836. TCHAR *string, buffer[MAX_PATH+1];
  837. ULONG dataLength;
  838. DWORD dwType, dwSize;
  839. dwSize = sizeof(TCHAR) * MAX_PATH;
  840. RtlZeroMemory(buffer, dwSize + sizeof(TCHAR));
  841. string = buffer;
  842. dataLength = GetFilter(hKey, buffer, dwSize);
  843. dwSize = dataLength;
  844. #if DBG
  845. if (dataLength > 0) {
  846. fprintf(stderr, "AddToFilter: Original string ");
  847. DbgPrintMultiSz(buffer, dataLength);
  848. fprintf(stderr, "\n");
  849. }
  850. else fprintf(stderr, "AddToFilter: Cannot get original string\n");
  851. #endif
  852. dataLength /= sizeof(TCHAR);
  853. if (dataLength != 0) {
  854. dataLength -= 1;
  855. }
  856. _tcscpy(&(string[dataLength]), DISKPERF_SERVICE_NAME);
  857. dwSize += (_tcslen(DISKPERF_SERVICE_NAME)+1) * sizeof(TCHAR);
  858. #if DBG
  859. fprintf(stderr, "AddToFilter: New string ");
  860. DbgPrintMultiSz(buffer, dataLength + _tcslen(DISKPERF_SERVICE_NAME)+1);
  861. fprintf(stderr, "\n");
  862. #endif
  863. return SetFilter(hKey, buffer, dwSize);
  864. }
  865. void
  866. PrintStatus(
  867. IN BOOL bCurrent,
  868. IN ULONG EnableFlag,
  869. IN LPCTSTR cMachineName
  870. )
  871. {
  872. DWORD dwValue;
  873. TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
  874. dwValue = (EnableFlag == 0) ? SERVICE_DISABLED : SERVICE_BOOT_START;
  875. if ((EnableFlag & ENABLE_PERMANENT) | (EnableFlag & ENABLE_PERMANENT_IOCTL)) {
  876. _stprintf(OemDisplayStringBuffer,
  877. GetFormatResource(DP_PERMANENT_FORMAT),
  878. cMachineName);
  879. if (EnableFlag & ENABLE_PERMANENT_IOCTL) {
  880. Dp_wprintf(OemDisplayStringBuffer);
  881. _stprintf(OemDisplayStringBuffer,
  882. GetFormatResource(DP_PERMANENT_IOCTL),
  883. cMachineName);
  884. }
  885. else {
  886. Dp_wprintf(OemDisplayStringBuffer);
  887. _stprintf(OemDisplayStringBuffer,
  888. GetFormatResource(DP_PERMANENT_FORMAT1),
  889. cMachineName);
  890. Dp_wprintf(OemDisplayStringBuffer);
  891. _stprintf(OemDisplayStringBuffer,
  892. GetFormatResource(DP_PERMANENT_FORMAT2),
  893. cMachineName);
  894. }
  895. }
  896. else if ( (EnableFlag == (ENABLE_DISKDRIVE | ENABLE_VOLUME)) ||
  897. (EnableFlag == 0) ) {
  898. _stprintf(OemDisplayStringBuffer,
  899. bCurrent ? GetFormatResource (DP_CURRENT_FORMAT1)
  900. : GetFormatResource (DP_NEW_DISKPERF_STATUS1),
  901. cMachineName,
  902. GetStringResource(REG_TO_DP_INDEX(dwValue)));
  903. }
  904. else {
  905. _stprintf (OemDisplayStringBuffer,
  906. bCurrent ? GetFormatResource (DP_CURRENT_FORMAT)
  907. : GetFormatResource (DP_NEW_DISKPERF_STATUS),
  908. (EnableFlag == ENABLE_DISKDRIVE) ?
  909. GetStringResource(DP_PHYSICAL) :
  910. GetStringResource(DP_LOGICAL),
  911. cMachineName,
  912. GetStringResource(REG_TO_DP_INDEX(dwValue)));
  913. }
  914. Dp_wprintf(OemDisplayStringBuffer);
  915. }
  916. ULONG
  917. RemoveFromFilter(
  918. IN HKEY hKey
  919. )
  920. {
  921. TCHAR *string, buffer[MAX_PATH+1];
  922. ULONG dataLength, stringLength, diskperfLen, found;
  923. ULONG removeSize;
  924. dataLength = sizeof(TCHAR) * (MAX_PATH+1);
  925. RtlZeroMemory(buffer, sizeof(TCHAR) * MAX_PATH);
  926. dataLength = GetFilter(hKey, buffer, dataLength);
  927. if (dataLength == 0)
  928. return 0;
  929. #if DBG
  930. fprintf(stderr, "RemoveFromFilter: Original string ");
  931. DbgPrintMultiSz(buffer, dataLength);
  932. fprintf(stderr, "'\n");
  933. #endif
  934. string = (TCHAR *) buffer;
  935. if(dataLength != 0) {
  936. dataLength -= sizeof(TCHAR);
  937. }
  938. //
  939. // now, find DiskPerf from the entry to remove it
  940. //
  941. stringLength = _tcslen(string);
  942. diskperfLen = _tcslen(DISKPERF_SERVICE_NAME); // includes NULL
  943. removeSize = (diskperfLen+1) * sizeof(TCHAR);
  944. #if DBG
  945. fprintf(stderr, "RemoveFromFilter: diskperfLen=%d removeSize=%d\n",
  946. diskperfLen, removeSize);
  947. #endif
  948. found = FALSE;
  949. while(stringLength != 0 && !found) {
  950. #if DBG
  951. fprintf(stderr,
  952. "RemoveFromFilter: Loop stringLength=%d\n", stringLength);
  953. #endif
  954. if (diskperfLen == stringLength) {
  955. if(_tcsicmp(string, DISKPERF_SERVICE_NAME) == 0) {
  956. //
  957. // found it, so we will remove it right now
  958. //
  959. if (dataLength > removeSize) {
  960. RtlCopyMemory(
  961. string,
  962. string+stringLength+1,
  963. dataLength - removeSize);
  964. RtlZeroMemory(
  965. buffer + dataLength - removeSize,
  966. removeSize);
  967. }
  968. else {
  969. RtlZeroMemory( buffer, removeSize);
  970. }
  971. found = TRUE;
  972. }
  973. } else { // else, try the next entry
  974. string += stringLength + 1;
  975. stringLength = _tcslen(string);
  976. }
  977. }
  978. dataLength = dataLength + sizeof(TCHAR) - removeSize;
  979. buffer[dataLength] = 0;
  980. /* if (dataLength == sizeof(TCHAR)) {
  981. dataLength += sizeof(TCHAR);
  982. buffer[dataLength] = 0;
  983. } */
  984. #if DBG
  985. fprintf(stderr, "RemoveFromFilter: New string ");
  986. DbgPrintMultiSz(buffer, dataLength);
  987. fprintf(stderr, "\n");
  988. #endif
  989. return SetFilter(hKey, buffer, dataLength);
  990. }
  991. /***
  992. * Dp_wprintf(format) - print formatted data
  993. *
  994. * Prints Unicode formatted string to console window using WriteConsoleW.
  995. * Note: This Dp_wprintf() is used to workaround the problem in c-runtime
  996. * which looks up LC_CTYPE even for Unicode string.
  997. *
  998. */
  999. int __cdecl
  1000. Dp_wprintf(
  1001. const wchar_t *format,
  1002. ...
  1003. )
  1004. {
  1005. DWORD cchWChar;
  1006. va_list args;
  1007. va_start( args, format );
  1008. cchWChar = Dp_vfwprintf(stdout, format, args);
  1009. va_end(args);
  1010. return cchWChar;
  1011. }
  1012. /***
  1013. * Dp_fwprintf(stream, format) - print formatted data
  1014. *
  1015. * Prints Unicode formatted string to console window using WriteConsoleW.
  1016. * Note: This Dp_fwprintf() is used to workaround the problem in c-runtime
  1017. * which looks up LC_CTYPE even for Unicode string.
  1018. *
  1019. */
  1020. int __cdecl
  1021. Dp_fwprintf(
  1022. FILE *str,
  1023. const wchar_t *format,
  1024. ...
  1025. )
  1026. {
  1027. DWORD cchWChar;
  1028. va_list args;
  1029. va_start( args, format );
  1030. cchWChar = Dp_vfwprintf(str, format, args);
  1031. va_end(args);
  1032. return cchWChar;
  1033. }
  1034. int __cdecl
  1035. Dp_vfwprintf(
  1036. FILE *str,
  1037. const wchar_t *format,
  1038. va_list argptr
  1039. )
  1040. {
  1041. HANDLE hOut;
  1042. if (str == stderr) {
  1043. hOut = GetStdHandle(STD_ERROR_HANDLE);
  1044. }
  1045. else {
  1046. hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  1047. }
  1048. if ((GetFileType(hOut) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR) {
  1049. DWORD cchWChar;
  1050. WCHAR szBufferMessage[1024];
  1051. vswprintf( szBufferMessage, format, argptr );
  1052. cchWChar = wcslen(szBufferMessage);
  1053. WriteConsoleW(hOut, szBufferMessage, cchWChar, &cchWChar, NULL);
  1054. return cchWChar;
  1055. }
  1056. return vfwprintf(str, format, argptr);
  1057. }
  1058. #if DBG
  1059. void
  1060. DbgPrintMultiSz(
  1061. TCHAR *String,
  1062. ULONG Size
  1063. )
  1064. {
  1065. ULONG len;
  1066. #if DBG
  1067. fprintf(stderr, "%d ", Size);
  1068. #endif
  1069. len = _tcslen(String);
  1070. while (len > 0) {
  1071. _ftprintf(stderr, _T("'%s' "), String);
  1072. String += len+1;
  1073. len = _tcslen(String);
  1074. }
  1075. }
  1076. #endif
  1077. void
  1078. SplitCommandLine(
  1079. LPTSTR CommandLine,
  1080. LPTSTR* pArgv
  1081. )
  1082. {
  1083. LPTSTR arg;
  1084. int i = 0;
  1085. arg = _tcstok( CommandLine, _T(" \t"));
  1086. while( arg != NULL ){
  1087. _tcscpy(pArgv[i++], arg);
  1088. arg = _tcstok(NULL, _T(" \t"));
  1089. }
  1090. }
  1091. int
  1092. __cdecl main(
  1093. int argc,
  1094. char **argv
  1095. )
  1096. {
  1097. LPTSTR *targv,*commandLine;
  1098. ULONG Status = ERROR_SUCCESS;
  1099. int i;
  1100. setlocale(LC_ALL, ".OCP");
  1101. MySetThreadUILanguage(0);
  1102. commandLine = (LPTSTR*)malloc( argc * sizeof(LPTSTR) );
  1103. if (!commandLine)
  1104. exit(1);
  1105. for(i=0;i<argc;i++){
  1106. commandLine[i] = (LPTSTR)malloc( (strlen(argv[i])+1) * sizeof(LPTSTR));
  1107. if (!commandLine[i])
  1108. exit(1);
  1109. }
  1110. SplitCommandLine( GetCommandLine(), commandLine );
  1111. targv = commandLine;
  1112. hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
  1113. // check for command arguments
  1114. if (argc == CMD_SHOW_LOCAL_STATUS) {
  1115. Status = DisplayStatus(NULL);
  1116. // if (Status == ERROR_SUCCESS) {
  1117. // DisplayChangeCmd();
  1118. // }
  1119. } else if (argc >= CMD_DO_COMMAND) {
  1120. if (ArgIsSystem(targv[1])) {
  1121. Status = DisplayStatus (targv[1]);
  1122. // if (Status != ERROR_SUCCESS) {
  1123. // DisplayChangeCmd();
  1124. // }
  1125. } else { // do change command
  1126. if (argc == LOCAL_CHANGE) {
  1127. DoChangeCommand (targv[1], NULL);
  1128. } else if (argc == REMOTE_CHANGE) {
  1129. DoChangeCommand(targv[1], targv[2]);
  1130. } else {
  1131. DisplayChangeCmd();
  1132. }
  1133. }
  1134. } else {
  1135. DisplayCmdHelp();
  1136. }
  1137. Dp_wprintf(_T("\n"));
  1138. for(i=0;i<argc;i++){
  1139. free(commandLine[i]);
  1140. commandLine[i] = NULL;
  1141. }
  1142. free(commandLine);
  1143. return 0;
  1144. }
  1145. BOOL
  1146. IsBeyondW2K(
  1147. IN LPCTSTR lpszMachine,
  1148. OUT PDWORD EnableCounter
  1149. )
  1150. {
  1151. OSVERSIONINFO OsVersion;
  1152. HKEY hRegistry, hKey;
  1153. TCHAR szBuildNumber[32];
  1154. TCHAR szVersion[32];
  1155. DWORD dwBuildNumber, dwMajor, status, dwSize;
  1156. BOOL bRet = FALSE;
  1157. *EnableCounter = 0;
  1158. if (lpszMachine != NULL) {
  1159. if (*lpszMachine != 0) {
  1160. status = RegConnectRegistry(
  1161. lpszMachine,
  1162. HKEY_LOCAL_MACHINE,
  1163. &hRegistry);
  1164. if (status != ERROR_SUCCESS)
  1165. return FALSE;
  1166. status = RegOpenKeyEx(
  1167. hRegistry,
  1168. lpwszOsVersionKey,
  1169. (DWORD) 0,
  1170. KEY_QUERY_VALUE,
  1171. &hKey);
  1172. if (status != ERROR_SUCCESS) {
  1173. RegCloseKey(hRegistry);
  1174. return FALSE;
  1175. }
  1176. dwSize = sizeof(TCHAR) * 32;
  1177. status = RegQueryValueEx(
  1178. hKey,
  1179. lpwszBuildNumber,
  1180. NULL,
  1181. NULL,
  1182. (BYTE*)szBuildNumber,
  1183. &dwSize);
  1184. if (status != ERROR_SUCCESS) {
  1185. RegCloseKey(hKey);
  1186. RegCloseKey(hRegistry);
  1187. return FALSE;
  1188. }
  1189. status = RegQueryValueEx(
  1190. hKey,
  1191. lpwszOsVersion,
  1192. NULL,
  1193. NULL,
  1194. (BYTE*)szVersion,
  1195. &dwSize);
  1196. if (status != ERROR_SUCCESS) {
  1197. RegCloseKey(hKey);
  1198. RegCloseKey(hRegistry);
  1199. return FALSE;
  1200. }
  1201. RegCloseKey(hKey);
  1202. status = RegOpenKeyEx(
  1203. hRegistry,
  1204. lpwszPartmgrKey,
  1205. (DWORD) 0,
  1206. KEY_QUERY_VALUE,
  1207. &hKey);
  1208. if (status == ERROR_SUCCESS) {
  1209. *EnableCounter = 0;
  1210. status = RegQueryValueEx(
  1211. hKey,
  1212. lpwszEnableCounterValue,
  1213. NULL,
  1214. NULL,
  1215. (BYTE*) EnableCounter,
  1216. &dwSize);
  1217. if ((status != ERROR_SUCCESS) || (dwSize != sizeof(DWORD))) {
  1218. *EnableCounter = 0;
  1219. }
  1220. }
  1221. dwBuildNumber = _ttoi(szBuildNumber);
  1222. dwMajor = _ttoi(szVersion);
  1223. if ((dwMajor >= 5) && (dwBuildNumber > 2195)) {
  1224. bRet = TRUE;
  1225. status = RegOpenKeyEx(
  1226. hRegistry,
  1227. lpwszPartmgrKey,
  1228. (DWORD) 0,
  1229. KEY_QUERY_VALUE,
  1230. &hKey);
  1231. if (status == ERROR_SUCCESS) {
  1232. status = RegQueryValueEx(
  1233. hKey,
  1234. lpwszEnableCounterValue,
  1235. NULL,
  1236. NULL,
  1237. (BYTE*) EnableCounter,
  1238. &dwSize);
  1239. if ((status != ERROR_SUCCESS) || (dwSize != sizeof(DWORD))) {
  1240. *EnableCounter = 0;
  1241. }
  1242. RegCloseKey(hKey);
  1243. }
  1244. }
  1245. RegCloseKey(hRegistry);
  1246. }
  1247. }
  1248. OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1249. if (GetVersionEx(&OsVersion)) {
  1250. if ((OsVersion.dwMajorVersion >= 5) &&
  1251. (OsVersion.dwMinorVersion > 0) &&
  1252. (OsVersion.dwBuildNumber > 2195))
  1253. return TRUE;
  1254. }
  1255. return FALSE;
  1256. }
  1257. ULONG
  1258. EnableForIoctl(
  1259. IN LPWSTR lpszMachineName
  1260. )
  1261. {
  1262. DWORD status;
  1263. HKEY hRegistry, hKey;
  1264. DWORD dwValue = 1;
  1265. hRegistry = NULL;
  1266. status = RegConnectRegistry(
  1267. lpszMachineName,
  1268. HKEY_LOCAL_MACHINE,
  1269. &hRegistry);
  1270. if (status != ERROR_SUCCESS)
  1271. return status;
  1272. if (hRegistry == NULL)
  1273. return ERROR_INVALID_PARAMETER;
  1274. hKey = NULL;
  1275. status = RegOpenKeyEx(
  1276. hRegistry,
  1277. lpwszPartmgrKey,
  1278. (DWORD) 0,
  1279. KEY_SET_VALUE | KEY_QUERY_VALUE,
  1280. &hKey);
  1281. if (status != ERROR_SUCCESS) {
  1282. RegCloseKey(hRegistry);
  1283. return status;
  1284. }
  1285. status = RegSetValueEx(
  1286. hKey,
  1287. lpwszEnableCounterValue,
  1288. 0L,
  1289. REG_DWORD,
  1290. (LPBYTE)&dwValue,
  1291. sizeof(dwValue));
  1292. RegCloseKey(hKey);
  1293. RegCloseKey(hRegistry);
  1294. return 0;
  1295. }
  1296. ULONG
  1297. DisableForIoctl(
  1298. IN LPWSTR lpszMachineName,
  1299. IN ULONG Request
  1300. )
  1301. {
  1302. ULONG nDisk, i;
  1303. SYSTEM_DEVICE_INFORMATION DeviceInfo;
  1304. NTSTATUS status;
  1305. UNICODE_STRING UnicodeName;
  1306. OBJECT_ATTRIBUTES ObjectAttributes;
  1307. IO_STATUS_BLOCK IoStatus;
  1308. WCHAR devname[256];
  1309. PWCHAR s;
  1310. HANDLE PartitionHandle, MountMgrHandle, VolumeHandle;
  1311. DWORD ReturnedBytes;
  1312. DWORD MountError;
  1313. HKEY hRegistry, hKey;
  1314. status = RegConnectRegistry(
  1315. lpszMachineName,
  1316. HKEY_LOCAL_MACHINE,
  1317. &hRegistry);
  1318. if (status != ERROR_SUCCESS)
  1319. return status;
  1320. if (hRegistry == NULL)
  1321. return ERROR_INVALID_PARAMETER;
  1322. status = RegOpenKeyEx(
  1323. hRegistry,
  1324. lpwszPartmgrKey,
  1325. (DWORD) 0,
  1326. KEY_SET_VALUE | KEY_QUERY_VALUE,
  1327. &hKey);
  1328. if (status != ERROR_SUCCESS) {
  1329. RegCloseKey(hRegistry);
  1330. return status;
  1331. }
  1332. RegDeleteValue(hKey, lpwszEnableCounterValue);
  1333. RegCloseKey(hKey);
  1334. RegCloseKey(hRegistry);
  1335. if (!(Request & ENABLE_DISKDRIVE)) goto DisableVolume;
  1336. status = NtQuerySystemInformation(SystemDeviceInformation, &DeviceInfo, sizeof(DeviceInfo), NULL);
  1337. if (!NT_SUCCESS(status)) {
  1338. return 0;
  1339. }
  1340. nDisk = DeviceInfo.NumberOfDisks;
  1341. // for each physical disk
  1342. for (i = 0; i < nDisk; i++) {
  1343. swprintf(devname, L"\\Device\\Harddisk%d\\Partition0", i);
  1344. RtlInitUnicodeString(&UnicodeName, devname);
  1345. InitializeObjectAttributes(
  1346. &ObjectAttributes,
  1347. &UnicodeName,
  1348. OBJ_CASE_INSENSITIVE,
  1349. NULL,
  1350. NULL
  1351. );
  1352. // opening a partition handle for physical drives
  1353. status = NtOpenFile(
  1354. &PartitionHandle,
  1355. FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  1356. &ObjectAttributes,
  1357. &IoStatus,
  1358. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1359. FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
  1360. );
  1361. if ( !NT_SUCCESS(status) ) {
  1362. continue;
  1363. }
  1364. // sending IOCTL over to Partition Handle
  1365. if (!DeviceIoControl(PartitionHandle,
  1366. IOCTL_DISK_PERFORMANCE_OFF,
  1367. NULL,
  1368. 0,
  1369. NULL,
  1370. 0,
  1371. &ReturnedBytes,
  1372. NULL
  1373. )) {
  1374. #if DBG
  1375. printf("IOCTL failed for %ws\n", devname);
  1376. #endif
  1377. }
  1378. NtClose(PartitionHandle);
  1379. }
  1380. DisableVolume:
  1381. if (!(Request | ENABLE_VOLUME)) {
  1382. return 0;
  1383. }
  1384. MountMgrHandle = FindFirstVolumeW(devname, sizeof(devname));
  1385. if (MountMgrHandle == NULL) {
  1386. #if DBG
  1387. printf("Cannot find first volume\n");
  1388. #endif
  1389. return 0;
  1390. }
  1391. s = (PWCHAR) &devname[wcslen(devname)-1];
  1392. if (*s == L'\\') {
  1393. *s = UNICODE_NULL;
  1394. }
  1395. VolumeHandle = CreateFile(devname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
  1396. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
  1397. if (VolumeHandle != INVALID_HANDLE_VALUE) {
  1398. #if DBG
  1399. printf("Opened with success\n");
  1400. #endif
  1401. // sending IOCTL over to a volume handle
  1402. if (!DeviceIoControl(VolumeHandle,
  1403. IOCTL_DISK_PERFORMANCE_OFF,
  1404. NULL,
  1405. 0,
  1406. NULL,
  1407. 0,
  1408. &ReturnedBytes,
  1409. NULL
  1410. )) {
  1411. #if DBG
  1412. printf("IOCTL failed for %ws\n", devname);
  1413. #endif
  1414. }
  1415. CloseHandle(VolumeHandle);
  1416. }
  1417. while (FindNextVolumeW(MountMgrHandle, devname, sizeof(devname))) {
  1418. s = (PWCHAR) &devname[wcslen(devname)-1];
  1419. if (*s == L'\\') {
  1420. *s = UNICODE_NULL;
  1421. }
  1422. VolumeHandle = CreateFile(devname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
  1423. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
  1424. if (VolumeHandle != INVALID_HANDLE_VALUE) {
  1425. #if DBG
  1426. printf("Opened with success\n");
  1427. #endif
  1428. if (!DeviceIoControl(VolumeHandle,
  1429. IOCTL_DISK_PERFORMANCE_OFF,
  1430. NULL,
  1431. 0,
  1432. NULL,
  1433. 0,
  1434. &ReturnedBytes,
  1435. NULL
  1436. )) {
  1437. #if DBG
  1438. printf("IOCTL failed for %ws\n", devname);
  1439. #endif
  1440. }
  1441. CloseHandle(VolumeHandle);
  1442. }
  1443. }
  1444. FindVolumeClose(MountMgrHandle);
  1445. return 0;
  1446. }
  1447. ////////////////////////////////////////////////////////////////////////////
  1448. //
  1449. // MySetThreadUILanguage
  1450. //
  1451. // This routine sets the thread UI language based on the console codepage.
  1452. //
  1453. // 9-29-00 WeiWu Created.
  1454. // Copied from Base\Win32\Winnls so that it works in W2K as well
  1455. ////////////////////////////////////////////////////////////////////////////
  1456. LANGID WINAPI MySetThreadUILanguage(
  1457. WORD wReserved)
  1458. {
  1459. //
  1460. // Cache system locale and CP info
  1461. //
  1462. static LCID s_lidSystem = 0;
  1463. static UINT s_uiSysCp = 0;
  1464. static UINT s_uiSysOEMCp = 0;
  1465. ULONG uiUserUICp;
  1466. ULONG uiUserUIOEMCp;
  1467. WCHAR szData[16];
  1468. UNICODE_STRING ucStr;
  1469. LANGID lidUserUI = GetUserDefaultUILanguage();
  1470. LCID lcidThreadOld = GetThreadLocale();
  1471. //
  1472. // Set default thread locale to EN-US
  1473. //
  1474. // This allow us to fall back to English UI to avoid trashed characters
  1475. // when console doesn't meet the criteria of rendering native UI.
  1476. //
  1477. LCID lcidThread = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  1478. UINT uiConsoleCp = GetConsoleOutputCP();
  1479. //
  1480. // Make sure nobody uses it yet
  1481. //
  1482. ASSERT(wReserved == 0);
  1483. //
  1484. // Get cached system locale and CP info.
  1485. //
  1486. if (!s_uiSysCp)
  1487. {
  1488. LCID lcidSystem = GetSystemDefaultLCID();
  1489. if (lcidSystem)
  1490. {
  1491. //
  1492. // Get ANSI CP
  1493. //
  1494. GetLocaleInfoW(lcidSystem, LOCALE_IDEFAULTANSICODEPAGE, szData, sizeof(szData)/sizeof(WCHAR));
  1495. RtlInitUnicodeString(&ucStr, szData);
  1496. RtlUnicodeStringToInteger(&ucStr, 10, &uiUserUICp);
  1497. //
  1498. // Get OEM CP
  1499. //
  1500. GetLocaleInfoW(lcidSystem, LOCALE_IDEFAULTCODEPAGE, szData, sizeof(szData)/sizeof(WCHAR));
  1501. RtlInitUnicodeString(&ucStr, szData);
  1502. RtlUnicodeStringToInteger(&ucStr, 10, &s_uiSysOEMCp);
  1503. //
  1504. // Cache system primary langauge
  1505. //
  1506. s_lidSystem = PRIMARYLANGID(LANGIDFROMLCID(lcidSystem));
  1507. }
  1508. }
  1509. //
  1510. // Don't cache user UI language and CP info, UI language can be changed without system reboot.
  1511. //
  1512. if (lidUserUI)
  1513. {
  1514. GetLocaleInfoW(MAKELCID(lidUserUI,SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, szData, sizeof(szData)/sizeof(WCHAR));
  1515. RtlInitUnicodeString(&ucStr, szData);
  1516. RtlUnicodeStringToInteger(&ucStr, 10, &uiUserUICp);
  1517. GetLocaleInfoW(MAKELCID(lidUserUI,SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, szData, sizeof(szData)/sizeof(WCHAR));
  1518. RtlInitUnicodeString(&ucStr, szData);
  1519. RtlUnicodeStringToInteger(&ucStr, 10, &uiUserUIOEMCp);
  1520. }
  1521. //
  1522. // Complex scripts cannot be rendered in the console, so we
  1523. // force the English (US) resource.
  1524. //
  1525. if (uiConsoleCp &&
  1526. s_lidSystem != LANG_ARABIC &&
  1527. s_lidSystem != LANG_HEBREW &&
  1528. s_lidSystem != LANG_VIETNAMESE &&
  1529. s_lidSystem != LANG_THAI)
  1530. {
  1531. //
  1532. // Use UI language for console only when console CP, system CP and UI language CP match.
  1533. //
  1534. if ((uiConsoleCp == s_uiSysCp || uiConsoleCp == s_uiSysOEMCp) &&
  1535. (uiConsoleCp == uiUserUICp || uiConsoleCp == uiUserUIOEMCp))
  1536. {
  1537. lcidThread = MAKELCID(lidUserUI, SORT_DEFAULT);
  1538. }
  1539. }
  1540. //
  1541. // Set the thread locale if it's different from the currently set
  1542. // thread locale.
  1543. //
  1544. if ((lcidThread != lcidThreadOld) && (!SetThreadLocale(lcidThread)))
  1545. {
  1546. lcidThread = lcidThreadOld;
  1547. }
  1548. //
  1549. // Return the thread locale that was set.
  1550. //
  1551. return (LANGIDFROMLCID(lcidThread));
  1552. }