1765 lines
46 KiB
C
1765 lines
46 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
diskperf.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Program to display and/or update the current value of the Diskperf
|
|||
|
driver startup value
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Bob Watson (a-robw) 4 Dec 92
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <ntconfig.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <regstr.h> // for REGSTR_VAL_UPPERFILTERS
|
|||
|
#include <tchar.h>
|
|||
|
#include <locale.h>
|
|||
|
|
|||
|
#include "diskperf.h" // include text string id constancts
|
|||
|
#include <ntdddisk.h>
|
|||
|
#include <mountmgr.h>
|
|||
|
|
|||
|
LANGID WINAPI MySetThreadUILanguage(
|
|||
|
WORD wReserved);
|
|||
|
|
|||
|
#define SWITCH_CHAR '-' // is there a system call to get this?
|
|||
|
#define ENABLE_CHAR 'Y' // command will be upcased
|
|||
|
#define DISABLE_CHAR 'N'
|
|||
|
#define ENHANCED_CHAR 'E'
|
|||
|
|
|||
|
#define LOCAL_CHANGE 2 // number of commands in a local change command
|
|||
|
#define REMOTE_CHANGE 3 // number of commands in a remote change command
|
|||
|
|
|||
|
//
|
|||
|
// note these values are arbitrarily based on the whims of the people
|
|||
|
// developing the disk drive drivers that belong to the "Filter" group.
|
|||
|
//
|
|||
|
#define TAG_NORMAL 4 // diskperf starts AFTER ftdisk
|
|||
|
#define TAG_ENHANCED 2 // diskperf starts BEFORE ftdisk
|
|||
|
|
|||
|
#define IRP_STACK_ENABLED 5 // size of IRP stack when diskperf is enabled
|
|||
|
#define IRP_STACK_DISABLED 4 // size of IRP stack when diskperf is enabled
|
|||
|
|
|||
|
#define IRP_STACK_DEFAULT 8 // default IRP stack size in W2K
|
|||
|
#define IRP_STACK_NODISKPERF 7
|
|||
|
|
|||
|
#define DISKPERF_SERVICE_NAME TEXT("DiskPerf")
|
|||
|
|
|||
|
LPCTSTR lpwszDiskPerfKey = TEXT("SYSTEM\\CurrentControlSet\\Services\\Diskperf");
|
|||
|
LPCTSTR lpwszIOSystemKey = TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\I/O System");
|
|||
|
LPCTSTR lpwszOsVersionKey = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
|
|||
|
LPCTSTR lpwszBuildNumber = TEXT("CurrentBuildNumber");
|
|||
|
LPCTSTR lpwszOsVersion = TEXT("CurrentVersion");
|
|||
|
|
|||
|
#define ENABLE_DISKDRIVE 0x0001
|
|||
|
#define ENABLE_VOLUME 0x0002
|
|||
|
#define ENABLE_PERMANENT 0x0004
|
|||
|
#define ENABLE_PERMANENT_IOCTL 0x0008
|
|||
|
|
|||
|
LPCTSTR lpwszDiskDriveKey
|
|||
|
= TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E967-E325-11CE-BFC1-08002BE10318}");
|
|||
|
LPCTSTR lpwszVolumeKey
|
|||
|
= TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{71A27CDD-812A-11D0-BEC7-08002BE2092F}");
|
|||
|
|
|||
|
LPCTSTR lpwszPartmgrKey = TEXT("SYSTEM\\CurrentControlSet\\Services\\Partmgr");
|
|||
|
LPCTSTR lpwszEnableCounterValue = TEXT("EnableCounterForIoctl");
|
|||
|
|
|||
|
ULONG
|
|||
|
OpenRegKeys(
|
|||
|
IN LPCTSTR lpszMachine,
|
|||
|
OUT PHKEY hRegistry,
|
|||
|
OUT PHKEY hDiskKey,
|
|||
|
OUT PHKEY hVolumeKey,
|
|||
|
OUT PHKEY hServiceKey
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
SetFilter(
|
|||
|
IN HKEY hKey,
|
|||
|
IN LPTSTR strFilterString,
|
|||
|
IN DWORD dwSize
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
GetFilter(
|
|||
|
IN HKEY hKey,
|
|||
|
OUT LPTSTR strFilterString,
|
|||
|
IN DWORD dwSize
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
CheckFilter(
|
|||
|
IN TCHAR *Buffer
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
GetEnableFlag(
|
|||
|
IN HKEY hDiskKey,
|
|||
|
IN HKEY hVolumeKey
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
AddToFilter(
|
|||
|
IN HKEY hKey
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
RemoveFromFilter(
|
|||
|
IN HKEY hKey
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
PrintStatus(
|
|||
|
IN BOOL bCurrent,
|
|||
|
IN ULONG EnableFlag,
|
|||
|
IN LPCTSTR cMachineName
|
|||
|
);
|
|||
|
|
|||
|
int __cdecl
|
|||
|
Dp_wprintf(
|
|||
|
const wchar_t *format,
|
|||
|
...
|
|||
|
);
|
|||
|
|
|||
|
int __cdecl
|
|||
|
Dp_fwprintf(
|
|||
|
FILE *str,
|
|||
|
const wchar_t *format,
|
|||
|
...
|
|||
|
);
|
|||
|
|
|||
|
int __cdecl
|
|||
|
Dp_vfwprintf(
|
|||
|
FILE *str,
|
|||
|
const wchar_t *format,
|
|||
|
va_list argptr
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
IsBeyondW2K(
|
|||
|
IN LPCTSTR lpszMachine,
|
|||
|
OUT PDWORD EnableCounter);
|
|||
|
|
|||
|
ULONG
|
|||
|
EnableForIoctl(
|
|||
|
IN LPWSTR lpszMachineName
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
DisableForIoctl(
|
|||
|
IN LPWSTR lpszMachineName,
|
|||
|
IN ULONG Request
|
|||
|
);
|
|||
|
|
|||
|
#if DBG
|
|||
|
void
|
|||
|
DbgPrintMultiSz(
|
|||
|
TCHAR *String,
|
|||
|
ULONG Size
|
|||
|
);
|
|||
|
#endif
|
|||
|
|
|||
|
#define REG_TO_DP_INDEX(reg_idx) (DP_LOAD_STATUS_BASE + (\
|
|||
|
(reg_idx == SERVICE_BOOT_START) ? DP_BOOT_START : \
|
|||
|
(reg_idx == SERVICE_SYSTEM_START) ? DP_SYSTEM_START : \
|
|||
|
(reg_idx == SERVICE_AUTO_START) ? DP_AUTO_START : \
|
|||
|
(reg_idx == SERVICE_DEMAND_START) ? DP_DEMAND_START : \
|
|||
|
(reg_idx == SERVICE_DISABLED) ? DP_NEVER_START : DP_UNDEFINED))
|
|||
|
|
|||
|
#define MAX_MACHINE_NAME_LEN 32
|
|||
|
|
|||
|
// command line arguments
|
|||
|
|
|||
|
#define CMD_SHOW_LOCAL_STATUS 1
|
|||
|
#define CMD_DO_COMMAND 2
|
|||
|
|
|||
|
#define ArgIsSystem(arg) (*(arg) == '\\' ? TRUE : FALSE)
|
|||
|
|
|||
|
//
|
|||
|
// global buffer for help text display strings
|
|||
|
//
|
|||
|
#define DISP_BUFF_LEN 256
|
|||
|
#define NUM_STRING_BUFFS 2
|
|||
|
LPCTSTR BlankString = TEXT(" ");
|
|||
|
LPCTSTR StartKey = TEXT("Start");
|
|||
|
LPCTSTR TagKey = TEXT("Tag");
|
|||
|
LPCTSTR EmptyString = TEXT("");
|
|||
|
LPCTSTR LargeIrps = TEXT("LargeIrpStackLocations");
|
|||
|
|
|||
|
HINSTANCE hMod = NULL;
|
|||
|
DWORD dwLastError;
|
|||
|
|
|||
|
|
|||
|
LPCTSTR
|
|||
|
GetStringResource (
|
|||
|
UINT wStringId
|
|||
|
)
|
|||
|
{
|
|||
|
static TCHAR DisplayStringBuffer[NUM_STRING_BUFFS][DISP_BUFF_LEN];
|
|||
|
static DWORD dwBuffIndex;
|
|||
|
LPTSTR szReturnBuffer;
|
|||
|
|
|||
|
dwBuffIndex++;
|
|||
|
dwBuffIndex %= NUM_STRING_BUFFS;
|
|||
|
szReturnBuffer = (LPTSTR)&DisplayStringBuffer[dwBuffIndex][0];
|
|||
|
|
|||
|
if (!hMod) {
|
|||
|
hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
|
|||
|
}
|
|||
|
|
|||
|
if (hMod) {
|
|||
|
if ((LoadString(hMod, wStringId, szReturnBuffer, DISP_BUFF_LEN)) > 0) {
|
|||
|
return (LPCTSTR)szReturnBuffer;
|
|||
|
} else {
|
|||
|
dwLastError = GetLastError();
|
|||
|
return EmptyString;
|
|||
|
}
|
|||
|
} else {
|
|||
|
return EmptyString;
|
|||
|
}
|
|||
|
}
|
|||
|
LPCTSTR
|
|||
|
GetFormatResource (
|
|||
|
UINT wStringId
|
|||
|
)
|
|||
|
{
|
|||
|
static TCHAR TextFormat[DISP_BUFF_LEN];
|
|||
|
|
|||
|
if (!hMod) {
|
|||
|
hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
|
|||
|
}
|
|||
|
|
|||
|
if (hMod) {
|
|||
|
if ((LoadString(hMod, wStringId, TextFormat, DISP_BUFF_LEN)) > 0) {
|
|||
|
return (LPCTSTR)&TextFormat[0];
|
|||
|
} else {
|
|||
|
dwLastError = GetLastError();
|
|||
|
return BlankString;
|
|||
|
}
|
|||
|
} else {
|
|||
|
return BlankString;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
DisplayChangeCmd (
|
|||
|
)
|
|||
|
{
|
|||
|
UINT wID;
|
|||
|
TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
|
|||
|
TCHAR DisplayStringBuffer[DISP_BUFF_LEN];
|
|||
|
|
|||
|
if (hMod) {
|
|||
|
if ((LoadString(hMod, DP_TEXT_FORMAT, DisplayStringBuffer, DISP_BUFF_LEN)) > 0) {
|
|||
|
for (wID=DP_CMD_HELP_START; wID <= DP_CMD_HELP_END; wID++) {
|
|||
|
if ((LoadString(hMod, wID, DisplayStringBuffer, DISP_BUFF_LEN)) > 0) {
|
|||
|
Dp_wprintf(DisplayStringBuffer);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
VOID
|
|||
|
DisplayCmdHelp(
|
|||
|
)
|
|||
|
{
|
|||
|
UINT wID;
|
|||
|
TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
|
|||
|
TCHAR DisplayStringBuffer[DISP_BUFF_LEN];
|
|||
|
|
|||
|
if (hMod) {
|
|||
|
if ((LoadString(hMod, DP_TEXT_FORMAT, DisplayStringBuffer, DISP_BUFF_LEN)) > 0) {
|
|||
|
for (wID=DP_HELP_TEXT_START; wID <= DP_HELP_TEXT_END; wID++) {
|
|||
|
if ((LoadString(hMod, wID, DisplayStringBuffer, DISP_BUFF_LEN)) > 0) {
|
|||
|
Dp_wprintf(DisplayStringBuffer);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
DisplayChangeCmd();
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
DisplayStatus (
|
|||
|
LPTSTR lpszMachine
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Status;
|
|||
|
HKEY hRegistry;
|
|||
|
HKEY hDiskPerfKey;
|
|||
|
HKEY hDiskKey;
|
|||
|
HKEY hVolumeKey;
|
|||
|
DWORD dwValue, dwValueSize, dwTag;
|
|||
|
TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
|
|||
|
|
|||
|
TCHAR cMachineName[MAX_MACHINE_NAME_LEN];
|
|||
|
PTCHAR pThisWideChar;
|
|||
|
PTCHAR pThisChar;
|
|||
|
INT iCharCount;
|
|||
|
DWORD EnableCounter;
|
|||
|
|
|||
|
pThisChar = lpszMachine;
|
|||
|
pThisWideChar = cMachineName;
|
|||
|
iCharCount = 0;
|
|||
|
|
|||
|
if (pThisChar) { // if machine is not NULL, then copy
|
|||
|
while (*pThisChar) {
|
|||
|
*pThisWideChar++ = (TCHAR)(*pThisChar++);
|
|||
|
if (++iCharCount >= MAX_MACHINE_NAME_LEN) break;
|
|||
|
}
|
|||
|
*pThisWideChar = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (!lpszMachine) {
|
|||
|
lstrcpy(cMachineName,
|
|||
|
GetStringResource(DP_THIS_SYSTEM));
|
|||
|
}
|
|||
|
|
|||
|
if (IsBeyondW2K(lpszMachine, &EnableCounter)) {
|
|||
|
if (EnableCounter) {
|
|||
|
PrintStatus(TRUE, ENABLE_PERMANENT_IOCTL, cMachineName);
|
|||
|
}
|
|||
|
else {
|
|||
|
PrintStatus(TRUE, ENABLE_PERMANENT, cMachineName);
|
|||
|
}
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
Status = OpenRegKeys(
|
|||
|
lpszMachine,
|
|||
|
&hRegistry,
|
|||
|
&hDiskKey,
|
|||
|
&hVolumeKey,
|
|||
|
&hDiskPerfKey);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
#if DBG
|
|||
|
fprintf(stderr,
|
|||
|
"DisplayStatus: Cannot open HKLM on target machine: %d\n",
|
|||
|
Status);
|
|||
|
#endif
|
|||
|
Dp_wprintf(GetFormatResource(DP_UNABLE_READ_REGISTRY));
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
dwTag = GetEnableFlag(hDiskKey, hVolumeKey);
|
|||
|
dwValue = (dwTag == 0) ? SERVICE_DISABLED : SERVICE_BOOT_START;
|
|||
|
dwValueSize = sizeof(dwValue);
|
|||
|
Status = RegQueryValueEx (
|
|||
|
hDiskPerfKey,
|
|||
|
StartKey,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
(LPBYTE)&dwValue,
|
|||
|
&dwValueSize);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
Dp_wprintf(GetFormatResource(DP_UNABLE_READ_START));
|
|||
|
goto DisplayStatusCleanup;
|
|||
|
}
|
|||
|
|
|||
|
PrintStatus(TRUE, dwTag, cMachineName);
|
|||
|
|
|||
|
DisplayStatusCleanup:
|
|||
|
RegCloseKey(hDiskKey);
|
|||
|
RegCloseKey(hVolumeKey);
|
|||
|
RegCloseKey(hDiskPerfKey);
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
Dp_wprintf(GetFormatResource(DP_STATUS_FORMAT), Status);
|
|||
|
|
|||
|
}
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
DoChangeCommand (
|
|||
|
LPTSTR lpszCommand,
|
|||
|
LPTSTR lpszMachine
|
|||
|
)
|
|||
|
{
|
|||
|
// connect to registry on local machine with read/write access
|
|||
|
ULONG Status;
|
|||
|
HKEY hRegistry;
|
|||
|
HKEY hDiskPerfKey;
|
|||
|
HKEY hDiskKey;
|
|||
|
HKEY hVolumeKey;
|
|||
|
DWORD dwValue, dwValueSize, dwOrigValue, dwTag, dwOrigTag;
|
|||
|
|
|||
|
TCHAR cMachineName[MAX_MACHINE_NAME_LEN];
|
|||
|
PTCHAR pThisWideChar;
|
|||
|
PTCHAR pThisChar;
|
|||
|
INT iCharCount;
|
|||
|
PTCHAR pCmdChar;
|
|||
|
|
|||
|
TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
|
|||
|
|
|||
|
HKEY hIOSystemKey;
|
|||
|
DWORD dwDisposition;
|
|||
|
DWORD dwIrpValue;
|
|||
|
ULONG EnableRequest, DisableRequest;
|
|||
|
ULONG EnableFlag, EndFlag = 0;
|
|||
|
BOOL bModified, bIrpStackReg;
|
|||
|
LONG nIrpStack, nIrpStackReg, nIncrement;
|
|||
|
DWORD EnableCounter;
|
|||
|
|
|||
|
// check command to see if it's valid
|
|||
|
|
|||
|
_tcsupr (lpszCommand);
|
|||
|
|
|||
|
pCmdChar = lpszCommand;
|
|||
|
dwValue = 0;
|
|||
|
EnableRequest = DisableRequest = 0;
|
|||
|
|
|||
|
if (*pCmdChar++ == SWITCH_CHAR ) {
|
|||
|
if (!_tcscmp(pCmdChar, _T("Y")) ||
|
|||
|
!_tcscmp(pCmdChar, _T("YA")) ||
|
|||
|
!_tcscmp(pCmdChar, _T("YALL"))) {
|
|||
|
EnableRequest = ENABLE_DISKDRIVE | ENABLE_VOLUME;
|
|||
|
}
|
|||
|
else if (!_tcscmp(pCmdChar, _T("N")) ||
|
|||
|
!_tcscmp(pCmdChar, _T("NA")) ||
|
|||
|
!_tcscmp(pCmdChar, _T("NALL")) ) {
|
|||
|
DisableRequest = ENABLE_DISKDRIVE | ENABLE_VOLUME;
|
|||
|
}
|
|||
|
else if (!_tcscmp(pCmdChar, _T("YD")) ||
|
|||
|
!_tcscmp(pCmdChar, _T("YDISK")) ) {
|
|||
|
EnableRequest = ENABLE_DISKDRIVE;
|
|||
|
}
|
|||
|
else if (!_tcscmp(pCmdChar, _T("YV")) ||
|
|||
|
!_tcscmp(pCmdChar, _T("YVOLUME")) ) {
|
|||
|
EnableRequest = ENABLE_VOLUME;
|
|||
|
}
|
|||
|
else if (!_tcscmp(pCmdChar, _T("ND")) ||
|
|||
|
!_tcscmp(pCmdChar, _T("NDISK")) ) {
|
|||
|
DisableRequest = ENABLE_DISKDRIVE;
|
|||
|
}
|
|||
|
else if (!_tcscmp(pCmdChar, _T("NV")) ||
|
|||
|
!_tcscmp(pCmdChar, _T("NVOLUME")) ) {
|
|||
|
DisableRequest = ENABLE_VOLUME;
|
|||
|
} else {
|
|||
|
DisplayCmdHelp();
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
} else {
|
|||
|
DisplayChangeCmd();
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
// if command OK then convert machine to wide string for connection
|
|||
|
|
|||
|
pThisChar = lpszMachine;
|
|||
|
pThisWideChar = cMachineName;
|
|||
|
iCharCount = 0;
|
|||
|
|
|||
|
if (pThisChar) {
|
|||
|
while (*pThisChar) {
|
|||
|
*pThisWideChar++ = (TCHAR)(*pThisChar++);
|
|||
|
if (++iCharCount >= MAX_MACHINE_NAME_LEN) break;
|
|||
|
}
|
|||
|
*pThisWideChar = 0; // null terminate
|
|||
|
}
|
|||
|
|
|||
|
if (!lpszMachine) {
|
|||
|
lstrcpy (cMachineName,
|
|||
|
GetStringResource(DP_THIS_SYSTEM));
|
|||
|
}
|
|||
|
|
|||
|
if (IsBeyondW2K(lpszMachine, &EnableCounter)) {
|
|||
|
if (EnableRequest != 0) {
|
|||
|
EnableForIoctl(lpszMachine);
|
|||
|
PrintStatus(TRUE, ENABLE_PERMANENT_IOCTL, cMachineName);
|
|||
|
}
|
|||
|
else if (DisableRequest != 0) {
|
|||
|
DisableForIoctl(lpszMachine, DisableRequest);
|
|||
|
PrintStatus(TRUE, ENABLE_PERMANENT, cMachineName);
|
|||
|
}
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
// connect to registry
|
|||
|
Status = OpenRegKeys(
|
|||
|
lpszMachine,
|
|||
|
&hRegistry,
|
|||
|
&hDiskKey,
|
|||
|
&hVolumeKey,
|
|||
|
&hDiskPerfKey);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
#if DBG
|
|||
|
fprintf(stderr,
|
|||
|
"DoChangeCommand: Cannot connect to registry: Status=%d\n",
|
|||
|
Status);
|
|||
|
#endif
|
|||
|
Dp_wprintf(GetFormatResource(DP_UNABLE_READ_REGISTRY));
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
hIOSystemKey = NULL;
|
|||
|
nIrpStackReg = 0;
|
|||
|
bIrpStackReg = FALSE; // no registry key prior to this
|
|||
|
Status = RegCreateKeyEx (
|
|||
|
hRegistry,
|
|||
|
lpwszIOSystemKey,
|
|||
|
0L, //Reserved
|
|||
|
NULL,
|
|||
|
0L, // no special options
|
|||
|
KEY_WRITE | KEY_READ, // desired access
|
|||
|
NULL, // default security
|
|||
|
&hIOSystemKey,
|
|||
|
&dwDisposition);
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
if ((Status == ERROR_ALREADY_EXISTS) &&
|
|||
|
(dwDisposition == REG_OPENED_EXISTING_KEY)) {
|
|||
|
// then this key is already in the registry so this is OK
|
|||
|
Status = ERROR_SUCCESS;
|
|||
|
}
|
|||
|
else {
|
|||
|
Dp_wprintf(GetFormatResource(DP_UNABLE_READ_REGISTRY));
|
|||
|
goto DoChangeCommandCleanup;
|
|||
|
}
|
|||
|
}
|
|||
|
if ( (Status == ERROR_SUCCESS) && (dwDisposition == REG_OPENED_EXISTING_KEY)) {
|
|||
|
DWORD dwSize;
|
|||
|
dwSize = sizeof(DWORD);
|
|||
|
|
|||
|
Status = RegQueryValueEx (
|
|||
|
hIOSystemKey,
|
|||
|
LargeIrps,
|
|||
|
0L,
|
|||
|
NULL,
|
|||
|
(LPBYTE)&dwIrpValue,
|
|||
|
&dwSize);
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "Registry LargeIrpStack=%d\n", dwIrpValue);
|
|||
|
#endif
|
|||
|
nIrpStackReg = dwIrpValue;
|
|||
|
bIrpStackReg = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
EnableFlag = GetEnableFlag(hDiskKey, hVolumeKey);
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "DoChangeCommand: EnableFlag is %x\n", EnableFlag);
|
|||
|
#endif
|
|||
|
|
|||
|
bModified = FALSE;
|
|||
|
|
|||
|
nIncrement = 0;
|
|||
|
if ( (EnableRequest & ENABLE_DISKDRIVE) &&
|
|||
|
!(EnableFlag & ENABLE_DISKDRIVE) ) {
|
|||
|
// Turn on filter for disk drives
|
|||
|
if (AddToFilter(hDiskKey) == ERROR_SUCCESS) {
|
|||
|
bModified = TRUE;
|
|||
|
nIncrement++;
|
|||
|
}
|
|||
|
}
|
|||
|
if ( (EnableRequest & ENABLE_VOLUME) &&
|
|||
|
!(EnableFlag & ENABLE_VOLUME) ) {
|
|||
|
// Turn on filter for volumes
|
|||
|
if (AddToFilter(hVolumeKey) == ERROR_SUCCESS) {
|
|||
|
bModified = TRUE;
|
|||
|
nIncrement++;
|
|||
|
}
|
|||
|
}
|
|||
|
if ( (DisableRequest & ENABLE_DISKDRIVE) &&
|
|||
|
(EnableFlag & ENABLE_DISKDRIVE) ) {
|
|||
|
// Turn off filter for disk drives
|
|||
|
if (RemoveFromFilter(hDiskKey) == ERROR_SUCCESS) {
|
|||
|
bModified = TRUE;
|
|||
|
nIncrement--;
|
|||
|
}
|
|||
|
}
|
|||
|
if ( (DisableRequest & ENABLE_VOLUME) &&
|
|||
|
(EnableFlag & ENABLE_VOLUME) ) {
|
|||
|
// Turn off filter for volumes
|
|||
|
if (RemoveFromFilter(hVolumeKey) == ERROR_SUCCESS) {
|
|||
|
bModified = TRUE;
|
|||
|
nIncrement--;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
nIrpStack = 0;
|
|||
|
EndFlag = GetEnableFlag(hDiskKey, hVolumeKey);
|
|||
|
|
|||
|
if (bModified) { // we have modified the registry
|
|||
|
|
|||
|
|
|||
|
dwValue = (EndFlag == 0) ? SERVICE_DISABLED : SERVICE_BOOT_START;
|
|||
|
Status = RegSetValueEx(
|
|||
|
hDiskPerfKey,
|
|||
|
StartKey,
|
|||
|
0L,
|
|||
|
REG_DWORD,
|
|||
|
(LPBYTE)&dwValue,
|
|||
|
sizeof(dwValue));
|
|||
|
//
|
|||
|
// First update service registry entries
|
|||
|
//
|
|||
|
|
|||
|
if (DisableRequest != 0) {
|
|||
|
nIrpStack = nIrpStackReg + nIncrement;
|
|||
|
if (EndFlag == 0) {
|
|||
|
//
|
|||
|
// Turn off service completely
|
|||
|
//
|
|||
|
// Set Irp stack size to original value or default
|
|||
|
if (nIrpStack < IRP_STACK_NODISKPERF)
|
|||
|
nIrpStack = IRP_STACK_NODISKPERF;
|
|||
|
}
|
|||
|
else { // else, there is only one stack left
|
|||
|
if (nIrpStack < IRP_STACK_NODISKPERF+1)
|
|||
|
nIrpStack = IRP_STACK_NODISKPERF+1;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (EnableRequest != 0) {
|
|||
|
nIrpStack = nIrpStackReg + nIncrement;
|
|||
|
//
|
|||
|
// Set proper Irp stack size
|
|||
|
//
|
|||
|
if (EndFlag == (ENABLE_DISKDRIVE | ENABLE_VOLUME)) {
|
|||
|
if (nIrpStack < IRP_STACK_NODISKPERF+2) // a value is set
|
|||
|
nIrpStack = IRP_STACK_NODISKPERF+2;
|
|||
|
}
|
|||
|
else { // at least one is enabled
|
|||
|
if (nIrpStack < IRP_STACK_NODISKPERF+1)
|
|||
|
nIrpStack = IRP_STACK_NODISKPERF+1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
//
|
|||
|
// No action taken. Should tell the user the state.
|
|||
|
//
|
|||
|
PrintStatus(TRUE, EndFlag, cMachineName);
|
|||
|
Dp_wprintf(GetFormatResource(DP_NOCHANGE));
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "New LargeIrp is %d\n", nIrpStack);
|
|||
|
#endif
|
|||
|
if (hIOSystemKey != NULL && Status == ERROR_SUCCESS) {
|
|||
|
if (bModified) {
|
|||
|
Status = RegSetValueEx (
|
|||
|
hIOSystemKey,
|
|||
|
LargeIrps,
|
|||
|
0L,
|
|||
|
REG_DWORD,
|
|||
|
(LPBYTE)&nIrpStack,
|
|||
|
sizeof(DWORD));
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
PrintStatus(FALSE, EndFlag, cMachineName);
|
|||
|
}
|
|||
|
else {
|
|||
|
Dp_wprintf(GetFormatResource(DP_UNABLE_MODIFY_VALUE));
|
|||
|
}
|
|||
|
}
|
|||
|
RegCloseKey(hIOSystemKey);
|
|||
|
}
|
|||
|
|
|||
|
DoChangeCommandCleanup:
|
|||
|
if (hDiskPerfKey != NULL) {
|
|||
|
RegCloseKey(hDiskPerfKey);
|
|||
|
}
|
|||
|
if (hDiskKey != NULL) {
|
|||
|
RegCloseKey(hDiskKey);
|
|||
|
}
|
|||
|
if (hVolumeKey != NULL) {
|
|||
|
RegCloseKey(hVolumeKey);
|
|||
|
}
|
|||
|
if (hRegistry != NULL) {
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
}
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
Dp_wprintf(GetFormatResource(DP_STATUS_FORMAT), Status);
|
|||
|
}
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
OpenRegKeys(
|
|||
|
IN LPCTSTR lpszMachine,
|
|||
|
OUT PHKEY hRegistry,
|
|||
|
OUT PHKEY hDiskKey,
|
|||
|
OUT PHKEY hVolumeKey,
|
|||
|
OUT PHKEY hServiceKey
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG status;
|
|||
|
|
|||
|
if (hRegistry == NULL)
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
|
|||
|
*hRegistry = NULL;
|
|||
|
status = RegConnectRegistry(
|
|||
|
lpszMachine,
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
hRegistry);
|
|||
|
if (status != ERROR_SUCCESS)
|
|||
|
return status;
|
|||
|
if (*hRegistry == NULL)
|
|||
|
return ERROR_INVALID_PARAMETER; // Avoid PREFIX error
|
|||
|
|
|||
|
if (hDiskKey) {
|
|||
|
*hDiskKey = NULL;
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
status = RegOpenKeyEx(
|
|||
|
*hRegistry,
|
|||
|
lpwszDiskDriveKey,
|
|||
|
(DWORD) 0,
|
|||
|
KEY_SET_VALUE | KEY_QUERY_VALUE,
|
|||
|
hDiskKey);
|
|||
|
}
|
|||
|
}
|
|||
|
if (hVolumeKey) {
|
|||
|
*hVolumeKey = NULL;
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
status = RegOpenKeyEx(
|
|||
|
*hRegistry,
|
|||
|
lpwszVolumeKey,
|
|||
|
(DWORD) 0,
|
|||
|
KEY_SET_VALUE | KEY_QUERY_VALUE,
|
|||
|
hVolumeKey);
|
|||
|
}
|
|||
|
}
|
|||
|
if (hServiceKey) {
|
|||
|
*hServiceKey = NULL;
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
status = RegOpenKeyEx(
|
|||
|
*hRegistry,
|
|||
|
lpwszDiskPerfKey,
|
|||
|
(DWORD) 0,
|
|||
|
KEY_SET_VALUE | KEY_QUERY_VALUE,
|
|||
|
hServiceKey);
|
|||
|
}
|
|||
|
}
|
|||
|
if ( (status != ERROR_SUCCESS) && (hDiskKey != NULL) ) {
|
|||
|
if (*hDiskKey != NULL)
|
|||
|
RegCloseKey(*hDiskKey);
|
|||
|
*hDiskKey = NULL;
|
|||
|
}
|
|||
|
if ( (status != ERROR_SUCCESS) && (hVolumeKey != NULL) ) {
|
|||
|
if (*hVolumeKey != NULL)
|
|||
|
RegCloseKey(*hVolumeKey);
|
|||
|
*hVolumeKey = NULL;
|
|||
|
}
|
|||
|
if ( (status != ERROR_SUCCESS) && (hServiceKey != NULL) ) {
|
|||
|
if (*hServiceKey != NULL)
|
|||
|
RegCloseKey(*hServiceKey);
|
|||
|
*hServiceKey = NULL;
|
|||
|
}
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
SetFilter(
|
|||
|
IN HKEY hKey,
|
|||
|
IN LPTSTR strFilterString,
|
|||
|
IN DWORD dwSize
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG status;
|
|||
|
LONG len;
|
|||
|
DWORD dwType = REG_MULTI_SZ;
|
|||
|
|
|||
|
if (hKey == NULL)
|
|||
|
return ERROR_BADKEY;
|
|||
|
|
|||
|
//
|
|||
|
// NOTE: Assumes that strFilterString is always MAX_PATH, NULL padded
|
|||
|
//
|
|||
|
len = dwSize / sizeof(TCHAR);
|
|||
|
if (len < 2) {
|
|||
|
dwSize = 2 * sizeof(TCHAR);
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "SetFilter: Length %d dwSize %d\n", len, dwSize);
|
|||
|
#endif
|
|||
|
}
|
|||
|
else { // ensures 2 null character always
|
|||
|
if (strFilterString[len-1] != 0) { // no trailing null
|
|||
|
len += 2;
|
|||
|
strFilterString[len] = 0;
|
|||
|
strFilterString[len+1] = 0;
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "SetFilter: New length(+2) %d\n", len);
|
|||
|
#endif
|
|||
|
}
|
|||
|
else if (strFilterString[len-2] != 0) { // only one trailing null
|
|||
|
len += 1;
|
|||
|
strFilterString[len+1] = 0;
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "SetFilter: New length(+1) %d\n", len);
|
|||
|
#endif
|
|||
|
}
|
|||
|
dwSize = len * sizeof(TCHAR);
|
|||
|
}
|
|||
|
if (len <= 2) {
|
|||
|
status = RegDeleteValue(hKey, REGSTR_VAL_UPPERFILTERS);
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "Delete status = %d\n", status);
|
|||
|
#endif
|
|||
|
return status;
|
|||
|
}
|
|||
|
status = RegSetValueEx(
|
|||
|
hKey,
|
|||
|
REGSTR_VAL_UPPERFILTERS,
|
|||
|
(DWORD) 0,
|
|||
|
dwType,
|
|||
|
(BYTE*)strFilterString,
|
|||
|
dwSize);
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
_ftprintf(stderr, _T("SetFilter: Cannot query key %s status=%d\n"),
|
|||
|
REGSTR_VAL_UPPERFILTERS, status);
|
|||
|
}
|
|||
|
else {
|
|||
|
fprintf(stderr, "SetFilter: ");
|
|||
|
DbgPrintMultiSz(strFilterString, dwSize);
|
|||
|
fprintf(stderr, "\n");
|
|||
|
}
|
|||
|
#endif
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
GetFilter(
|
|||
|
IN HKEY hKey,
|
|||
|
OUT LPTSTR strFilterString,
|
|||
|
IN DWORD dwSize
|
|||
|
)
|
|||
|
// Returns size of strFilterString
|
|||
|
{
|
|||
|
ULONG status;
|
|||
|
|
|||
|
if (hKey == NULL)
|
|||
|
return ERROR_BADKEY;
|
|||
|
|
|||
|
status = RegQueryValueEx(
|
|||
|
hKey,
|
|||
|
REGSTR_VAL_UPPERFILTERS,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
(BYTE*)strFilterString,
|
|||
|
&dwSize);
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
#if DBG
|
|||
|
_ftprintf(stderr, _T("GetFilter: Cannot query key %s status=%d\n"),
|
|||
|
REGSTR_VAL_UPPERFILTERS, status);
|
|||
|
#endif
|
|||
|
return 0;
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
else {
|
|||
|
fprintf(stderr, "GetFilter: ");
|
|||
|
DbgPrintMultiSz(strFilterString, dwSize);
|
|||
|
fprintf(stderr, "\n");
|
|||
|
}
|
|||
|
#endif
|
|||
|
return dwSize;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
CheckFilter(TCHAR *Buffer)
|
|||
|
{
|
|||
|
TCHAR *string = Buffer;
|
|||
|
ULONG stringLength, diskperfLen, result;
|
|||
|
|
|||
|
if (string == NULL)
|
|||
|
return 0;
|
|||
|
stringLength = _tcslen(string);
|
|||
|
|
|||
|
diskperfLen = _tcslen(DISKPERF_SERVICE_NAME);
|
|||
|
|
|||
|
result = FALSE;
|
|||
|
while(stringLength != 0) {
|
|||
|
|
|||
|
if ((diskperfLen == stringLength) &&
|
|||
|
(_tcsicmp(string, DISKPERF_SERVICE_NAME) == 0)) {
|
|||
|
#if DBG
|
|||
|
fprintf(stderr,
|
|||
|
"CheckFilter: string found at offset %d\n",
|
|||
|
(string - Buffer));
|
|||
|
#endif
|
|||
|
result = TRUE;
|
|||
|
break;
|
|||
|
} else {
|
|||
|
string += stringLength + 1;
|
|||
|
stringLength = _tcslen(string);
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
GetEnableFlag(
|
|||
|
IN HKEY hDiskKey,
|
|||
|
IN HKEY hVolumeKey
|
|||
|
)
|
|||
|
// Returns the flags indicating what is enabled
|
|||
|
{
|
|||
|
ULONG bFlag = 0;
|
|||
|
TCHAR strFilter[MAX_PATH+1] = {0};
|
|||
|
DWORD dwSize;
|
|||
|
ULONG status;
|
|||
|
|
|||
|
dwSize = sizeof(TCHAR) * (MAX_PATH+1);
|
|||
|
if (GetFilter(hDiskKey, strFilter, dwSize) > 0) {
|
|||
|
if (CheckFilter(strFilter))
|
|||
|
bFlag |= ENABLE_DISKDRIVE;
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
else
|
|||
|
fprintf(stderr, "GetEnableFlag: No filters for disk drive\n");
|
|||
|
#endif
|
|||
|
|
|||
|
dwSize = sizeof(TCHAR) * (MAX_PATH+1);
|
|||
|
if (GetFilter(hVolumeKey, strFilter, dwSize) > 0) {
|
|||
|
if (CheckFilter(strFilter))
|
|||
|
bFlag |= ENABLE_VOLUME;
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
else
|
|||
|
fprintf(stderr, "GetEnableFlag: No filters for volume\n");
|
|||
|
#endif
|
|||
|
return bFlag;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
AddToFilter(
|
|||
|
IN HKEY hKey
|
|||
|
)
|
|||
|
{
|
|||
|
TCHAR *string, buffer[MAX_PATH+1];
|
|||
|
ULONG dataLength;
|
|||
|
DWORD dwType, dwSize;
|
|||
|
|
|||
|
dwSize = sizeof(TCHAR) * MAX_PATH;
|
|||
|
RtlZeroMemory(buffer, dwSize + sizeof(TCHAR));
|
|||
|
string = buffer;
|
|||
|
|
|||
|
dataLength = GetFilter(hKey, buffer, dwSize);
|
|||
|
dwSize = dataLength;
|
|||
|
#if DBG
|
|||
|
if (dataLength > 0) {
|
|||
|
fprintf(stderr, "AddToFilter: Original string ");
|
|||
|
DbgPrintMultiSz(buffer, dataLength);
|
|||
|
fprintf(stderr, "\n");
|
|||
|
}
|
|||
|
else fprintf(stderr, "AddToFilter: Cannot get original string\n");
|
|||
|
#endif
|
|||
|
dataLength /= sizeof(TCHAR);
|
|||
|
if (dataLength != 0) {
|
|||
|
dataLength -= 1;
|
|||
|
}
|
|||
|
_tcscpy(&(string[dataLength]), DISKPERF_SERVICE_NAME);
|
|||
|
dwSize += (_tcslen(DISKPERF_SERVICE_NAME)+1) * sizeof(TCHAR);
|
|||
|
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "AddToFilter: New string ");
|
|||
|
DbgPrintMultiSz(buffer, dataLength + _tcslen(DISKPERF_SERVICE_NAME)+1);
|
|||
|
fprintf(stderr, "\n");
|
|||
|
#endif
|
|||
|
return SetFilter(hKey, buffer, dwSize);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
PrintStatus(
|
|||
|
IN BOOL bCurrent,
|
|||
|
IN ULONG EnableFlag,
|
|||
|
IN LPCTSTR cMachineName
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwValue;
|
|||
|
TCHAR OemDisplayStringBuffer[DISP_BUFF_LEN * 2];
|
|||
|
|
|||
|
dwValue = (EnableFlag == 0) ? SERVICE_DISABLED : SERVICE_BOOT_START;
|
|||
|
if ((EnableFlag & ENABLE_PERMANENT) | (EnableFlag & ENABLE_PERMANENT_IOCTL)) {
|
|||
|
_stprintf(OemDisplayStringBuffer,
|
|||
|
GetFormatResource(DP_PERMANENT_FORMAT),
|
|||
|
cMachineName);
|
|||
|
if (EnableFlag & ENABLE_PERMANENT_IOCTL) {
|
|||
|
Dp_wprintf(OemDisplayStringBuffer);
|
|||
|
_stprintf(OemDisplayStringBuffer,
|
|||
|
GetFormatResource(DP_PERMANENT_IOCTL),
|
|||
|
cMachineName);
|
|||
|
}
|
|||
|
else {
|
|||
|
Dp_wprintf(OemDisplayStringBuffer);
|
|||
|
_stprintf(OemDisplayStringBuffer,
|
|||
|
GetFormatResource(DP_PERMANENT_FORMAT1),
|
|||
|
cMachineName);
|
|||
|
Dp_wprintf(OemDisplayStringBuffer);
|
|||
|
_stprintf(OemDisplayStringBuffer,
|
|||
|
GetFormatResource(DP_PERMANENT_FORMAT2),
|
|||
|
cMachineName);
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( (EnableFlag == (ENABLE_DISKDRIVE | ENABLE_VOLUME)) ||
|
|||
|
(EnableFlag == 0) ) {
|
|||
|
_stprintf(OemDisplayStringBuffer,
|
|||
|
bCurrent ? GetFormatResource (DP_CURRENT_FORMAT1)
|
|||
|
: GetFormatResource (DP_NEW_DISKPERF_STATUS1),
|
|||
|
cMachineName,
|
|||
|
GetStringResource(REG_TO_DP_INDEX(dwValue)));
|
|||
|
}
|
|||
|
else {
|
|||
|
_stprintf (OemDisplayStringBuffer,
|
|||
|
bCurrent ? GetFormatResource (DP_CURRENT_FORMAT)
|
|||
|
: GetFormatResource (DP_NEW_DISKPERF_STATUS),
|
|||
|
(EnableFlag == ENABLE_DISKDRIVE) ?
|
|||
|
GetStringResource(DP_PHYSICAL) :
|
|||
|
GetStringResource(DP_LOGICAL),
|
|||
|
cMachineName,
|
|||
|
GetStringResource(REG_TO_DP_INDEX(dwValue)));
|
|||
|
}
|
|||
|
Dp_wprintf(OemDisplayStringBuffer);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RemoveFromFilter(
|
|||
|
IN HKEY hKey
|
|||
|
)
|
|||
|
{
|
|||
|
TCHAR *string, buffer[MAX_PATH+1];
|
|||
|
ULONG dataLength, stringLength, diskperfLen, found;
|
|||
|
ULONG removeSize;
|
|||
|
|
|||
|
dataLength = sizeof(TCHAR) * (MAX_PATH+1);
|
|||
|
RtlZeroMemory(buffer, sizeof(TCHAR) * MAX_PATH);
|
|||
|
dataLength = GetFilter(hKey, buffer, dataLength);
|
|||
|
if (dataLength == 0)
|
|||
|
return 0;
|
|||
|
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "RemoveFromFilter: Original string ");
|
|||
|
DbgPrintMultiSz(buffer, dataLength);
|
|||
|
fprintf(stderr, "'\n");
|
|||
|
#endif
|
|||
|
|
|||
|
string = (TCHAR *) buffer;
|
|||
|
if(dataLength != 0) {
|
|||
|
dataLength -= sizeof(TCHAR);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// now, find DiskPerf from the entry to remove it
|
|||
|
//
|
|||
|
stringLength = _tcslen(string);
|
|||
|
|
|||
|
diskperfLen = _tcslen(DISKPERF_SERVICE_NAME); // includes NULL
|
|||
|
removeSize = (diskperfLen+1) * sizeof(TCHAR);
|
|||
|
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "RemoveFromFilter: diskperfLen=%d removeSize=%d\n",
|
|||
|
diskperfLen, removeSize);
|
|||
|
#endif
|
|||
|
found = FALSE;
|
|||
|
while(stringLength != 0 && !found) {
|
|||
|
|
|||
|
#if DBG
|
|||
|
fprintf(stderr,
|
|||
|
"RemoveFromFilter: Loop stringLength=%d\n", stringLength);
|
|||
|
#endif
|
|||
|
if (diskperfLen == stringLength) {
|
|||
|
if(_tcsicmp(string, DISKPERF_SERVICE_NAME) == 0) {
|
|||
|
//
|
|||
|
// found it, so we will remove it right now
|
|||
|
//
|
|||
|
if (dataLength > removeSize) {
|
|||
|
RtlCopyMemory(
|
|||
|
string,
|
|||
|
string+stringLength+1,
|
|||
|
dataLength - removeSize);
|
|||
|
RtlZeroMemory(
|
|||
|
buffer + dataLength - removeSize,
|
|||
|
removeSize);
|
|||
|
}
|
|||
|
else {
|
|||
|
RtlZeroMemory( buffer, removeSize);
|
|||
|
}
|
|||
|
found = TRUE;
|
|||
|
}
|
|||
|
} else { // else, try the next entry
|
|||
|
string += stringLength + 1;
|
|||
|
stringLength = _tcslen(string);
|
|||
|
}
|
|||
|
}
|
|||
|
dataLength = dataLength + sizeof(TCHAR) - removeSize;
|
|||
|
buffer[dataLength] = 0;
|
|||
|
/* if (dataLength == sizeof(TCHAR)) {
|
|||
|
dataLength += sizeof(TCHAR);
|
|||
|
buffer[dataLength] = 0;
|
|||
|
} */
|
|||
|
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "RemoveFromFilter: New string ");
|
|||
|
DbgPrintMultiSz(buffer, dataLength);
|
|||
|
fprintf(stderr, "\n");
|
|||
|
#endif
|
|||
|
return SetFilter(hKey, buffer, dataLength);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/***
|
|||
|
* Dp_wprintf(format) - print formatted data
|
|||
|
*
|
|||
|
* Prints Unicode formatted string to console window using WriteConsoleW.
|
|||
|
* Note: This Dp_wprintf() is used to workaround the problem in c-runtime
|
|||
|
* which looks up LC_CTYPE even for Unicode string.
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
int __cdecl
|
|||
|
Dp_wprintf(
|
|||
|
const wchar_t *format,
|
|||
|
...
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
DWORD cchWChar;
|
|||
|
|
|||
|
va_list args;
|
|||
|
va_start( args, format );
|
|||
|
|
|||
|
cchWChar = Dp_vfwprintf(stdout, format, args);
|
|||
|
|
|||
|
va_end(args);
|
|||
|
|
|||
|
return cchWChar;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/***
|
|||
|
* Dp_fwprintf(stream, format) - print formatted data
|
|||
|
*
|
|||
|
* Prints Unicode formatted string to console window using WriteConsoleW.
|
|||
|
* Note: This Dp_fwprintf() is used to workaround the problem in c-runtime
|
|||
|
* which looks up LC_CTYPE even for Unicode string.
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
int __cdecl
|
|||
|
Dp_fwprintf(
|
|||
|
FILE *str,
|
|||
|
const wchar_t *format,
|
|||
|
...
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
DWORD cchWChar;
|
|||
|
|
|||
|
va_list args;
|
|||
|
va_start( args, format );
|
|||
|
|
|||
|
cchWChar = Dp_vfwprintf(str, format, args);
|
|||
|
|
|||
|
va_end(args);
|
|||
|
|
|||
|
return cchWChar;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int __cdecl
|
|||
|
Dp_vfwprintf(
|
|||
|
FILE *str,
|
|||
|
const wchar_t *format,
|
|||
|
va_list argptr
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
HANDLE hOut;
|
|||
|
|
|||
|
if (str == stderr) {
|
|||
|
hOut = GetStdHandle(STD_ERROR_HANDLE);
|
|||
|
}
|
|||
|
else {
|
|||
|
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|||
|
}
|
|||
|
|
|||
|
if ((GetFileType(hOut) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR) {
|
|||
|
DWORD cchWChar;
|
|||
|
WCHAR szBufferMessage[1024];
|
|||
|
|
|||
|
vswprintf( szBufferMessage, format, argptr );
|
|||
|
cchWChar = wcslen(szBufferMessage);
|
|||
|
WriteConsoleW(hOut, szBufferMessage, cchWChar, &cchWChar, NULL);
|
|||
|
return cchWChar;
|
|||
|
}
|
|||
|
|
|||
|
return vfwprintf(str, format, argptr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#if DBG
|
|||
|
void
|
|||
|
DbgPrintMultiSz(
|
|||
|
TCHAR *String,
|
|||
|
ULONG Size
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG len;
|
|||
|
|
|||
|
#if DBG
|
|||
|
fprintf(stderr, "%d ", Size);
|
|||
|
#endif
|
|||
|
len = _tcslen(String);
|
|||
|
while (len > 0) {
|
|||
|
_ftprintf(stderr, _T("'%s' "), String);
|
|||
|
String += len+1;
|
|||
|
len = _tcslen(String);
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
SplitCommandLine(
|
|||
|
LPTSTR CommandLine,
|
|||
|
LPTSTR* pArgv
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
LPTSTR arg;
|
|||
|
int i = 0;
|
|||
|
arg = _tcstok( CommandLine, _T(" \t"));
|
|||
|
while( arg != NULL ){
|
|||
|
_tcscpy(pArgv[i++], arg);
|
|||
|
arg = _tcstok(NULL, _T(" \t"));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
__cdecl main(
|
|||
|
int argc,
|
|||
|
char **argv
|
|||
|
)
|
|||
|
{
|
|||
|
LPTSTR *targv,*commandLine;
|
|||
|
ULONG Status = ERROR_SUCCESS;
|
|||
|
int i;
|
|||
|
|
|||
|
setlocale(LC_ALL, ".OCP");
|
|||
|
|
|||
|
MySetThreadUILanguage(0);
|
|||
|
|
|||
|
commandLine = (LPTSTR*)malloc( argc * sizeof(LPTSTR) );
|
|||
|
if (!commandLine)
|
|||
|
exit(1);
|
|||
|
for(i=0;i<argc;i++){
|
|||
|
commandLine[i] = (LPTSTR)malloc( (strlen(argv[i])+1) * sizeof(LPTSTR));
|
|||
|
if (!commandLine[i])
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
SplitCommandLine( GetCommandLine(), commandLine );
|
|||
|
targv = commandLine;
|
|||
|
|
|||
|
hMod = (HINSTANCE)GetModuleHandle(NULL); // get instance ID of this module;
|
|||
|
|
|||
|
// check for command arguments
|
|||
|
|
|||
|
if (argc == CMD_SHOW_LOCAL_STATUS) {
|
|||
|
Status = DisplayStatus(NULL);
|
|||
|
// if (Status == ERROR_SUCCESS) {
|
|||
|
// DisplayChangeCmd();
|
|||
|
// }
|
|||
|
} else if (argc >= CMD_DO_COMMAND) {
|
|||
|
if (ArgIsSystem(targv[1])) {
|
|||
|
Status = DisplayStatus (targv[1]);
|
|||
|
// if (Status != ERROR_SUCCESS) {
|
|||
|
// DisplayChangeCmd();
|
|||
|
// }
|
|||
|
} else { // do change command
|
|||
|
if (argc == LOCAL_CHANGE) {
|
|||
|
DoChangeCommand (targv[1], NULL);
|
|||
|
} else if (argc == REMOTE_CHANGE) {
|
|||
|
DoChangeCommand(targv[1], targv[2]);
|
|||
|
} else {
|
|||
|
DisplayChangeCmd();
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
DisplayCmdHelp();
|
|||
|
}
|
|||
|
Dp_wprintf(_T("\n"));
|
|||
|
|
|||
|
for(i=0;i<argc;i++){
|
|||
|
free(commandLine[i]);
|
|||
|
commandLine[i] = NULL;
|
|||
|
}
|
|||
|
free(commandLine);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
IsBeyondW2K(
|
|||
|
IN LPCTSTR lpszMachine,
|
|||
|
OUT PDWORD EnableCounter
|
|||
|
)
|
|||
|
{
|
|||
|
OSVERSIONINFO OsVersion;
|
|||
|
HKEY hRegistry, hKey;
|
|||
|
TCHAR szBuildNumber[32];
|
|||
|
TCHAR szVersion[32];
|
|||
|
DWORD dwBuildNumber, dwMajor, status, dwSize;
|
|||
|
BOOL bRet = FALSE;
|
|||
|
|
|||
|
*EnableCounter = 0;
|
|||
|
if (lpszMachine != NULL) {
|
|||
|
if (*lpszMachine != 0) {
|
|||
|
status = RegConnectRegistry(
|
|||
|
lpszMachine,
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
&hRegistry);
|
|||
|
if (status != ERROR_SUCCESS)
|
|||
|
return FALSE;
|
|||
|
status = RegOpenKeyEx(
|
|||
|
hRegistry,
|
|||
|
lpwszOsVersionKey,
|
|||
|
(DWORD) 0,
|
|||
|
KEY_QUERY_VALUE,
|
|||
|
&hKey);
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
dwSize = sizeof(TCHAR) * 32;
|
|||
|
status = RegQueryValueEx(
|
|||
|
hKey,
|
|||
|
lpwszBuildNumber,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
(BYTE*)szBuildNumber,
|
|||
|
&dwSize);
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
RegCloseKey(hKey);
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
status = RegQueryValueEx(
|
|||
|
hKey,
|
|||
|
lpwszOsVersion,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
(BYTE*)szVersion,
|
|||
|
&dwSize);
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
RegCloseKey(hKey);
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
RegCloseKey(hKey);
|
|||
|
status = RegOpenKeyEx(
|
|||
|
hRegistry,
|
|||
|
lpwszPartmgrKey,
|
|||
|
(DWORD) 0,
|
|||
|
KEY_QUERY_VALUE,
|
|||
|
&hKey);
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
*EnableCounter = 0;
|
|||
|
status = RegQueryValueEx(
|
|||
|
hKey,
|
|||
|
lpwszEnableCounterValue,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
(BYTE*) EnableCounter,
|
|||
|
&dwSize);
|
|||
|
if ((status != ERROR_SUCCESS) || (dwSize != sizeof(DWORD))) {
|
|||
|
*EnableCounter = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
dwBuildNumber = _ttoi(szBuildNumber);
|
|||
|
dwMajor = _ttoi(szVersion);
|
|||
|
if ((dwMajor >= 5) && (dwBuildNumber > 2195)) {
|
|||
|
bRet = TRUE;
|
|||
|
status = RegOpenKeyEx(
|
|||
|
hRegistry,
|
|||
|
lpwszPartmgrKey,
|
|||
|
(DWORD) 0,
|
|||
|
KEY_QUERY_VALUE,
|
|||
|
&hKey);
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
status = RegQueryValueEx(
|
|||
|
hKey,
|
|||
|
lpwszEnableCounterValue,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
(BYTE*) EnableCounter,
|
|||
|
&dwSize);
|
|||
|
if ((status != ERROR_SUCCESS) || (dwSize != sizeof(DWORD))) {
|
|||
|
*EnableCounter = 0;
|
|||
|
}
|
|||
|
RegCloseKey(hKey);
|
|||
|
}
|
|||
|
}
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
}
|
|||
|
}
|
|||
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|||
|
if (GetVersionEx(&OsVersion)) {
|
|||
|
if ((OsVersion.dwMajorVersion >= 5) &&
|
|||
|
(OsVersion.dwMinorVersion > 0) &&
|
|||
|
(OsVersion.dwBuildNumber > 2195))
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
EnableForIoctl(
|
|||
|
IN LPWSTR lpszMachineName
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
HKEY hRegistry, hKey;
|
|||
|
DWORD dwValue = 1;
|
|||
|
|
|||
|
hRegistry = NULL;
|
|||
|
|
|||
|
status = RegConnectRegistry(
|
|||
|
lpszMachineName,
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
&hRegistry);
|
|||
|
if (status != ERROR_SUCCESS)
|
|||
|
return status;
|
|||
|
if (hRegistry == NULL)
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
|
|||
|
hKey = NULL;
|
|||
|
status = RegOpenKeyEx(
|
|||
|
hRegistry,
|
|||
|
lpwszPartmgrKey,
|
|||
|
(DWORD) 0,
|
|||
|
KEY_SET_VALUE | KEY_QUERY_VALUE,
|
|||
|
&hKey);
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
return status;
|
|||
|
}
|
|||
|
status = RegSetValueEx(
|
|||
|
hKey,
|
|||
|
lpwszEnableCounterValue,
|
|||
|
0L,
|
|||
|
REG_DWORD,
|
|||
|
(LPBYTE)&dwValue,
|
|||
|
sizeof(dwValue));
|
|||
|
RegCloseKey(hKey);
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
DisableForIoctl(
|
|||
|
IN LPWSTR lpszMachineName,
|
|||
|
IN ULONG Request
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG nDisk, i;
|
|||
|
SYSTEM_DEVICE_INFORMATION DeviceInfo;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
UNICODE_STRING UnicodeName;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
IO_STATUS_BLOCK IoStatus;
|
|||
|
|
|||
|
WCHAR devname[256];
|
|||
|
PWCHAR s;
|
|||
|
|
|||
|
HANDLE PartitionHandle, MountMgrHandle, VolumeHandle;
|
|||
|
DWORD ReturnedBytes;
|
|||
|
|
|||
|
DWORD MountError;
|
|||
|
HKEY hRegistry, hKey;
|
|||
|
|
|||
|
status = RegConnectRegistry(
|
|||
|
lpszMachineName,
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
&hRegistry);
|
|||
|
if (status != ERROR_SUCCESS)
|
|||
|
return status;
|
|||
|
if (hRegistry == NULL)
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
|
|||
|
status = RegOpenKeyEx(
|
|||
|
hRegistry,
|
|||
|
lpwszPartmgrKey,
|
|||
|
(DWORD) 0,
|
|||
|
KEY_SET_VALUE | KEY_QUERY_VALUE,
|
|||
|
&hKey);
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
return status;
|
|||
|
}
|
|||
|
RegDeleteValue(hKey, lpwszEnableCounterValue);
|
|||
|
RegCloseKey(hKey);
|
|||
|
RegCloseKey(hRegistry);
|
|||
|
|
|||
|
if (!(Request & ENABLE_DISKDRIVE)) goto DisableVolume;
|
|||
|
status = NtQuerySystemInformation(SystemDeviceInformation, &DeviceInfo, sizeof(DeviceInfo), NULL);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
nDisk = DeviceInfo.NumberOfDisks;
|
|||
|
// for each physical disk
|
|||
|
for (i = 0; i < nDisk; i++) {
|
|||
|
|
|||
|
swprintf(devname, L"\\Device\\Harddisk%d\\Partition0", i);
|
|||
|
|
|||
|
RtlInitUnicodeString(&UnicodeName, devname);
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&UnicodeName,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
// opening a partition handle for physical drives
|
|||
|
status = NtOpenFile(
|
|||
|
&PartitionHandle,
|
|||
|
FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
|||
|
&ObjectAttributes,
|
|||
|
&IoStatus,
|
|||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
|
|||
|
);
|
|||
|
|
|||
|
if ( !NT_SUCCESS(status) ) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
// sending IOCTL over to Partition Handle
|
|||
|
if (!DeviceIoControl(PartitionHandle,
|
|||
|
IOCTL_DISK_PERFORMANCE_OFF,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&ReturnedBytes,
|
|||
|
NULL
|
|||
|
)) {
|
|||
|
#if DBG
|
|||
|
printf("IOCTL failed for %ws\n", devname);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
NtClose(PartitionHandle);
|
|||
|
}
|
|||
|
|
|||
|
DisableVolume:
|
|||
|
if (!(Request | ENABLE_VOLUME)) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
MountMgrHandle = FindFirstVolumeW(devname, sizeof(devname));
|
|||
|
if (MountMgrHandle == NULL) {
|
|||
|
#if DBG
|
|||
|
printf("Cannot find first volume\n");
|
|||
|
#endif
|
|||
|
return 0;
|
|||
|
}
|
|||
|
s = (PWCHAR) &devname[wcslen(devname)-1];
|
|||
|
if (*s == L'\\') {
|
|||
|
*s = UNICODE_NULL;
|
|||
|
}
|
|||
|
|
|||
|
VolumeHandle = CreateFile(devname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
|
|||
|
if (VolumeHandle != INVALID_HANDLE_VALUE) {
|
|||
|
#if DBG
|
|||
|
printf("Opened with success\n");
|
|||
|
#endif
|
|||
|
// sending IOCTL over to a volume handle
|
|||
|
if (!DeviceIoControl(VolumeHandle,
|
|||
|
IOCTL_DISK_PERFORMANCE_OFF,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&ReturnedBytes,
|
|||
|
NULL
|
|||
|
)) {
|
|||
|
#if DBG
|
|||
|
printf("IOCTL failed for %ws\n", devname);
|
|||
|
#endif
|
|||
|
}
|
|||
|
CloseHandle(VolumeHandle);
|
|||
|
}
|
|||
|
|
|||
|
while (FindNextVolumeW(MountMgrHandle, devname, sizeof(devname))) {
|
|||
|
s = (PWCHAR) &devname[wcslen(devname)-1];
|
|||
|
if (*s == L'\\') {
|
|||
|
*s = UNICODE_NULL;
|
|||
|
}
|
|||
|
VolumeHandle = CreateFile(devname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE);
|
|||
|
if (VolumeHandle != INVALID_HANDLE_VALUE) {
|
|||
|
#if DBG
|
|||
|
printf("Opened with success\n");
|
|||
|
#endif
|
|||
|
if (!DeviceIoControl(VolumeHandle,
|
|||
|
IOCTL_DISK_PERFORMANCE_OFF,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&ReturnedBytes,
|
|||
|
NULL
|
|||
|
)) {
|
|||
|
#if DBG
|
|||
|
printf("IOCTL failed for %ws\n", devname);
|
|||
|
#endif
|
|||
|
}
|
|||
|
CloseHandle(VolumeHandle);
|
|||
|
}
|
|||
|
}
|
|||
|
FindVolumeClose(MountMgrHandle);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
//
|
|||
|
// MySetThreadUILanguage
|
|||
|
//
|
|||
|
// This routine sets the thread UI language based on the console codepage.
|
|||
|
//
|
|||
|
// 9-29-00 WeiWu Created.
|
|||
|
// Copied from Base\Win32\Winnls so that it works in W2K as well
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
LANGID WINAPI MySetThreadUILanguage(
|
|||
|
WORD wReserved)
|
|||
|
{
|
|||
|
//
|
|||
|
// Cache system locale and CP info
|
|||
|
//
|
|||
|
static LCID s_lidSystem = 0;
|
|||
|
static UINT s_uiSysCp = 0;
|
|||
|
static UINT s_uiSysOEMCp = 0;
|
|||
|
|
|||
|
ULONG uiUserUICp;
|
|||
|
ULONG uiUserUIOEMCp;
|
|||
|
WCHAR szData[16];
|
|||
|
UNICODE_STRING ucStr;
|
|||
|
|
|||
|
LANGID lidUserUI = GetUserDefaultUILanguage();
|
|||
|
LCID lcidThreadOld = GetThreadLocale();
|
|||
|
|
|||
|
//
|
|||
|
// Set default thread locale to EN-US
|
|||
|
//
|
|||
|
// This allow us to fall back to English UI to avoid trashed characters
|
|||
|
// when console doesn't meet the criteria of rendering native UI.
|
|||
|
//
|
|||
|
LCID lcidThread = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
|
|||
|
UINT uiConsoleCp = GetConsoleOutputCP();
|
|||
|
|
|||
|
//
|
|||
|
// Make sure nobody uses it yet
|
|||
|
//
|
|||
|
ASSERT(wReserved == 0);
|
|||
|
|
|||
|
//
|
|||
|
// Get cached system locale and CP info.
|
|||
|
//
|
|||
|
if (!s_uiSysCp)
|
|||
|
{
|
|||
|
LCID lcidSystem = GetSystemDefaultLCID();
|
|||
|
|
|||
|
if (lcidSystem)
|
|||
|
{
|
|||
|
//
|
|||
|
// Get ANSI CP
|
|||
|
//
|
|||
|
GetLocaleInfoW(lcidSystem, LOCALE_IDEFAULTANSICODEPAGE, szData, sizeof(szData)/sizeof(WCHAR));
|
|||
|
RtlInitUnicodeString(&ucStr, szData);
|
|||
|
RtlUnicodeStringToInteger(&ucStr, 10, &uiUserUICp);
|
|||
|
|
|||
|
//
|
|||
|
// Get OEM CP
|
|||
|
//
|
|||
|
GetLocaleInfoW(lcidSystem, LOCALE_IDEFAULTCODEPAGE, szData, sizeof(szData)/sizeof(WCHAR));
|
|||
|
RtlInitUnicodeString(&ucStr, szData);
|
|||
|
RtlUnicodeStringToInteger(&ucStr, 10, &s_uiSysOEMCp);
|
|||
|
|
|||
|
//
|
|||
|
// Cache system primary langauge
|
|||
|
//
|
|||
|
s_lidSystem = PRIMARYLANGID(LANGIDFROMLCID(lcidSystem));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Don't cache user UI language and CP info, UI language can be changed without system reboot.
|
|||
|
//
|
|||
|
if (lidUserUI)
|
|||
|
{
|
|||
|
GetLocaleInfoW(MAKELCID(lidUserUI,SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, szData, sizeof(szData)/sizeof(WCHAR));
|
|||
|
RtlInitUnicodeString(&ucStr, szData);
|
|||
|
RtlUnicodeStringToInteger(&ucStr, 10, &uiUserUICp);
|
|||
|
|
|||
|
GetLocaleInfoW(MAKELCID(lidUserUI,SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, szData, sizeof(szData)/sizeof(WCHAR));
|
|||
|
RtlInitUnicodeString(&ucStr, szData);
|
|||
|
RtlUnicodeStringToInteger(&ucStr, 10, &uiUserUIOEMCp);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Complex scripts cannot be rendered in the console, so we
|
|||
|
// force the English (US) resource.
|
|||
|
//
|
|||
|
if (uiConsoleCp &&
|
|||
|
s_lidSystem != LANG_ARABIC &&
|
|||
|
s_lidSystem != LANG_HEBREW &&
|
|||
|
s_lidSystem != LANG_VIETNAMESE &&
|
|||
|
s_lidSystem != LANG_THAI)
|
|||
|
{
|
|||
|
//
|
|||
|
// Use UI language for console only when console CP, system CP and UI language CP match.
|
|||
|
//
|
|||
|
if ((uiConsoleCp == s_uiSysCp || uiConsoleCp == s_uiSysOEMCp) &&
|
|||
|
(uiConsoleCp == uiUserUICp || uiConsoleCp == uiUserUIOEMCp))
|
|||
|
{
|
|||
|
lcidThread = MAKELCID(lidUserUI, SORT_DEFAULT);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the thread locale if it's different from the currently set
|
|||
|
// thread locale.
|
|||
|
//
|
|||
|
if ((lcidThread != lcidThreadOld) && (!SetThreadLocale(lcidThread)))
|
|||
|
{
|
|||
|
lcidThread = lcidThreadOld;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Return the thread locale that was set.
|
|||
|
//
|
|||
|
return (LANGIDFROMLCID(lcidThread));
|
|||
|
}
|
|||
|
|