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

1296 lines
40 KiB

/*++
Copyright (c) Microsoft Corporation
Module Name :
diskprop.c
Abstract :
Implementation of the Disk Class Installer and its Policies Tab
Revision History :
--*/
#include "propp.h"
#include "diskprop.h"
#include "volprop.h"
BOOL
IsUserAdmin(VOID)
/*++
Routine Description:
This routine returns TRUE if the caller's process is a
member of the Administrators local group.
Caller is NOT expected to be impersonating anyone and IS
expected to be able to open their own process and process
token.
Arguments:
None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group.
--*/
{
HANDLE Token;
DWORD BytesRequired;
PTOKEN_GROUPS Groups;
BOOL b;
DWORD i;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
//
// Open the process token.
//
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&Token)) {
return(FALSE);
}
b = FALSE;
Groups = NULL;
//
// Get group information.
//
if(!GetTokenInformation(Token,TokenGroups,NULL,0,&BytesRequired)
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
&& (Groups = (PTOKEN_GROUPS)LocalAlloc(LMEM_FIXED,BytesRequired))
&& GetTokenInformation(Token,TokenGroups,Groups,BytesRequired,&BytesRequired)) {
b = AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsGroup
);
if(b) {
//
// See if the user has the administrator group.
//
b = FALSE;
for(i=0; i<Groups->GroupCount; i++) {
if(EqualSid(Groups->Groups[i].Sid,AdministratorsGroup)) {
b = TRUE;
break;
}
}
FreeSid(AdministratorsGroup);
}
}
//
// Clean up and return.
//
if(Groups) {
LocalFree(Groups);
}
CloseHandle(Token);
return(b);
}
BOOL CALLBACK
VolumePropPageProvider(PSP_PROPSHEETPAGE_REQUEST Request, LPFNADDPROPSHEETPAGE AddPageRoutine, LPARAM AddPageContext)
{
//
// Since there is nothing to be displayed simply fail this call
//
return FALSE;
}
VOID
AttemptToSuppressDiskInstallReboot(IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData)
/*++
Routine Description:
Because disks are listed as "critical devices" (i.e., they're in the
critical device database), they get bootstrapped by PnP during boot. Thus,
by the time we're installing a disk in user-mode, it's most likely already
on-line (unless the disk has some problem). Unfortunately, if the disk is
the boot device, we won't be able to dynamically affect the changes (if
any) to tear the stack down and bring it back up with any new settings,
drivers, etc. This causes problems for OEM Preinstall scenarios where the
target machines have different disks than the source machine used to create
the preinstall image. If we simply perform our default behavior, then
the user's experience would be to unbox their brand new machine, boot for
the first time and go through OOBE, and then be greeted upon login with a
reboot prompt!
To fix this, we've defined a private [DDInstall] section INF flag (specific
to INFs of class "DiskDrive") that indicates we can forego the reboot if
certain criteria are met. Those criteria are:
1. No files were modified as a result of this device's installation
(determined by checking the devinfo element's
DI_FLAGSEX_RESTART_DEVICE_ONLY flag, which the device installer uses to
track whether such file modifications have occurred).
2. The INF used to install this device is signed.
3. The INF driver node has a DiskCiPrivateData = <int> entry in its
[DDInstall] section that has bit 2 (0x4) set. Note that this setting
is intentionally obfuscated because we don't want third parties trying
to use this, as they won't understand the ramifications or
requirements, and will more than likely get this wrong (trading an
annoying but harmless reboot requirement into a much more severe
stability issue).
This routine makes the above checks, and if it is found that the reboot can
be suppressed, it clears the DI_NEEDRESTART and DI_NEEDREBOOT flags from
the devinfo element's device install parameters.
Arguments:
DeviceInfoSet - Supplies the device information set.
DeviceInfoData - Supplies the device information element that has just
been successfully installed (via SetupDiInstallDevice).
Return Value:
None.
--*/
{
SP_DEVINSTALL_PARAMS DeviceInstallParams;
PSP_DRVINFO_DATA DriverInfoData = NULL;
PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData = NULL;
PSP_INF_SIGNER_INFO InfSignerInfo = NULL;
HINF hInf;
TCHAR InfSectionWithExt[255]; // max section name length is 255 chars
INFCONTEXT InfContext;
INT Flags;
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if(!SetupDiGetDeviceInstallParams(DeviceInfoSet,
DeviceInfoData,
&DeviceInstallParams)) {
//
// Couldn't retrieve the device install params--this should never
// happen.
//
goto clean0;
}
if(!(DeviceInstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))) {
//
// The device doesn't require a reboot (must not be the boot device!)
//
goto clean0;
}
if(!(DeviceInstallParams.FlagsEx & DI_FLAGSEX_RESTART_DEVICE_ONLY)) {
//
// Since this flag isn't set, this indicates that the device installer
// modified one or more files as part of this device's installation.
// Thus, it isn't safe for us to suppress the reboot request.
//
goto clean0;
}
//
// OK, we have a device that needs a reboot, and no files were modified
// during its installation. Now check the INF to see if it's signed.
// (Note: the SP_DRVINFO_DATA, SP_DRVINFO_DETAIL_DATA, and
// SP_INF_SIGNER_INFO structures are rather large, so we allocate them
// instead of using lots of stack space.)
//
DriverInfoData = LocalAlloc(0, sizeof(SP_DRVINFO_DATA));
if(DriverInfoData) {
DriverInfoData->cbSize = sizeof(SP_DRVINFO_DATA);
} else {
goto clean0;
}
if(!SetupDiGetSelectedDriver(DeviceInfoSet,
DeviceInfoData,
DriverInfoData)) {
//
// We must be installing the NULL driver (which is unlikely)...
//
goto clean0;
}
DriverInfoDetailData = LocalAlloc(0, sizeof(SP_DRVINFO_DETAIL_DATA));
if(DriverInfoDetailData) {
DriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
} else {
goto clean0;
}
if(!SetupDiGetDriverInfoDetail(DeviceInfoSet,
DeviceInfoData,
DriverInfoData,
DriverInfoDetailData,
sizeof(SP_DRVINFO_DETAIL_DATA),
NULL)
&& (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
//
// Failed to retrieve driver info details--should never happen.
//
goto clean0;
}
InfSignerInfo = LocalAlloc(0, sizeof(SP_INF_SIGNER_INFO));
if(InfSignerInfo) {
InfSignerInfo->cbSize = sizeof(SP_INF_SIGNER_INFO);
} else {
goto clean0;
}
if(!SetupVerifyInfFile(DriverInfoDetailData->InfFileName,
NULL,
InfSignerInfo)) {
//
// INF isn't signed--we wouldn't trust its "no reboot required" flag,
// even if it had one.
//
goto clean0;
}
//
// INF is signed--let's open it up and see if it specifes the "no reboot
// required" flag in it's (decorated) DDInstall section...
//
hInf = SetupOpenInfFile(DriverInfoDetailData->InfFileName,
NULL,
INF_STYLE_WIN4,
NULL
);
if(hInf == INVALID_HANDLE_VALUE) {
//
// Failed to open the INF. This is incredibly odd, since we just got
// through validating the INF's digital signature...
//
goto clean0;
}
if(!SetupDiGetActualSectionToInstall(hInf,
DriverInfoDetailData->SectionName,
InfSectionWithExt,
sizeof(InfSectionWithExt) / sizeof(TCHAR),
NULL,
NULL)
|| !SetupFindFirstLine(hInf,
InfSectionWithExt,
TEXT("DiskCiPrivateData"),
&InfContext)
|| !SetupGetIntField(&InfContext, 1, &Flags)) {
Flags = 0;
}
SetupCloseInfFile(hInf);
if(Flags & DISKCIPRIVATEDATA_NO_REBOOT_REQUIRED) {
//
// This signed INF is vouching for the fact that no reboot is
// required for full functionality of this disk. Thus, we'll
// clear the DI_NEEDRESTART and DI_NEEDREBOOT flags, so that
// the user won't be prompted to reboot. Note that during the
// default handling routine (SetupDiInstallDevice), a non-fatal
// problem was set on the devnode indicating that a reboot is
// needed. This will not result in a yellow-bang in DevMgr,
// but you would see text in the device status field indicating
// a reboot is needed if you go into the General tab of the
// device's property sheet.
//
CLEAR_FLAG(DeviceInstallParams.Flags, DI_NEEDRESTART);
CLEAR_FLAG(DeviceInstallParams.Flags, DI_NEEDREBOOT);
SetupDiSetDeviceInstallParams(DeviceInfoSet,
DeviceInfoData,
&DeviceInstallParams
);
}
clean0:
if(DriverInfoData) {
LocalFree(DriverInfoData);
}
if(DriverInfoDetailData) {
LocalFree(DriverInfoDetailData);
}
if(InfSignerInfo) {
LocalFree(InfSignerInfo);
}
}
DWORD
DiskClassInstaller(IN DI_FUNCTION InstallFunction, IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
/*++
Routine Description:
This routine is the class installer function for disk drive.
Arguments:
InstallFunction - Supplies the install function.
DeviceInfoSet - Supplies the device info set.
DeviceInfoData - Supplies the device info data.
Return Value:
If this function successfully completed the requested action, the return
value is NO_ERROR.
If the default behavior is to be performed for the requested action, the
return value is ERROR_DI_DO_DEFAULT.
If an error occurred while attempting to perform the requested action, a
Win32 error code is returned.
--*/
{
switch (InstallFunction)
{
case DIF_INSTALLDEVICE:
{
//
// Let the default action occur to get the device installed.
//
if (!SetupDiInstallDevice(DeviceInfoSet, DeviceInfoData))
{
//
// Failed to install the device--just return the error reported
//
return GetLastError();
}
//
// Default device install action succeeded, now check for reboot
// requirement and suppress it, if possible.
//
AttemptToSuppressDiskInstallReboot(DeviceInfoSet, DeviceInfoData);
//
// Regardless of whether we successfully suppressed the reboot, we
// still report success, because the install went fine.
//
return NO_ERROR;
}
case DIF_ADDPROPERTYPAGE_ADVANCED:
case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
{
SP_ADDPROPERTYPAGE_DATA AddPropertyPageData = { 0 };
//
// These property sheets are not for the entire class
//
if (DeviceInfoData == NULL)
{
break;
}
AddPropertyPageData.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
if (SetupDiGetClassInstallParams(DeviceInfoSet,
DeviceInfoData,
(PSP_CLASSINSTALL_HEADER)&AddPropertyPageData,
sizeof(SP_ADDPROPERTYPAGE_DATA),
NULL))
{
//
// Ensure that the maximum number of dynamic pages has not yet been met
//
if (AddPropertyPageData.NumDynamicPages >= MAX_INSTALLWIZARD_DYNAPAGES)
{
return NO_ERROR;
}
if (InstallFunction == DIF_ADDPROPERTYPAGE_ADVANCED)
{
//
// Create the Disk Policies Tab
//
PDISK_PAGE_DATA pData = HeapAlloc(GetProcessHeap(), 0, sizeof(DISK_PAGE_DATA));
if (pData)
{
HPROPSHEETPAGE hPage = NULL;
PROPSHEETPAGE page = { 0 };
pData->DeviceInfoSet = DeviceInfoSet;
pData->DeviceInfoData = DeviceInfoData;
page.dwSize = sizeof(PROPSHEETPAGE);
page.dwFlags = PSP_USECALLBACK;
page.hInstance = ModuleInstance;
page.pszTemplate = MAKEINTRESOURCE(ID_DISK_PROPPAGE);
page.pfnDlgProc = DiskDialogProc;
page.pfnCallback = DiskDialogCallback;
page.lParam = (LPARAM) pData;
hPage = CreatePropertySheetPage(&page);
if (hPage)
{
AddPropertyPageData.DynamicPages[AddPropertyPageData.NumDynamicPages++] = hPage;
}
else
{
HeapFree(GetProcessHeap(), 0, pData);
}
}
}
//
// The Volumes Tab is limited to Administrators
//
if (IsUserAdmin() && AddPropertyPageData.NumDynamicPages < MAX_INSTALLWIZARD_DYNAPAGES)
{
//
// Create the Volumes Tab
//
PVOLUME_PAGE_DATA pData = HeapAlloc(GetProcessHeap(), 0, sizeof(VOLUME_PAGE_DATA));
if (pData)
{
HPROPSHEETPAGE hPage = NULL;
PROPSHEETPAGE page = { 0 };
pData->DeviceInfoSet = DeviceInfoSet;
pData->DeviceInfoData = DeviceInfoData;
page.dwSize = sizeof(PROPSHEETPAGE);
page.dwFlags = PSP_USECALLBACK;
page.hInstance = ModuleInstance;
page.pszTemplate = MAKEINTRESOURCE(ID_VOLUME_PROPPAGE);
page.pfnDlgProc = VolumeDialogProc;
page.pfnCallback = VolumeDialogCallback;
page.lParam = (LPARAM) pData;
hPage = CreatePropertySheetPage(&page);
if (hPage)
{
//
// Look to see if we were launched by Disk Management
//
HMODULE LdmModule = NULL;
pData->bInvokedByDiskmgr = FALSE;
LdmModule = GetModuleHandle(TEXT("dmdskmgr"));
if (LdmModule)
{
IS_REQUEST_PENDING pfnIsRequestPending = (IS_REQUEST_PENDING) GetProcAddress(LdmModule, "IsRequestPending");
if (pfnIsRequestPending)
{
if ((*pfnIsRequestPending)())
{
pData->bInvokedByDiskmgr = TRUE;
}
}
}
AddPropertyPageData.DynamicPages[AddPropertyPageData.NumDynamicPages++] = hPage;
}
else
{
HeapFree(GetProcessHeap(), 0, pData);
}
}
}
SetupDiSetClassInstallParams(DeviceInfoSet,
DeviceInfoData,
(PSP_CLASSINSTALL_HEADER)&AddPropertyPageData,
sizeof(SP_ADDPROPERTYPAGE_DATA));
}
return NO_ERROR;
}
}
return ERROR_DI_DO_DEFAULT;
}
HANDLE
GetHandleForDisk(LPTSTR DeviceName)
{
HANDLE h = INVALID_HANDLE_VALUE;
int i = 0;
BOOL success = FALSE;
TCHAR buf[MAX_PATH] = { 0 };
TCHAR fakeDeviceName[MAX_PATH] = { 0 };
h = CreateFile(DeviceName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (h != INVALID_HANDLE_VALUE)
return h;
while (!success && i < 10) {
_sntprintf(buf, sizeof(buf) / sizeof(buf[0]) - 1, _T("DISK_FAKE_DEVICE_%d_"), i++);
success = DefineDosDevice(DDD_RAW_TARGET_PATH,
buf,
DeviceName);
if (success) {
_sntprintf(fakeDeviceName, sizeof(fakeDeviceName) / sizeof(fakeDeviceName[0]) - 1, _T("\\\\.\\%s"), buf);
h = CreateFile(fakeDeviceName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
DefineDosDevice(DDD_REMOVE_DEFINITION,
buf,
NULL);
}
}
return h;
}
UINT
GetCachingPolicy(PDISK_PAGE_DATA data)
{
HANDLE hDisk;
DISK_CACHE_INFORMATION cacheInfo;
TCHAR buf[MAX_PATH] = { 0 };
DWORD len;
if (!SetupDiGetDeviceRegistryProperty(data->DeviceInfoSet,
data->DeviceInfoData,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
NULL,
(PBYTE)buf,
sizeof(buf) - sizeof(TCHAR),
NULL))
{
return GetLastError();
}
if (INVALID_HANDLE_VALUE == (hDisk = GetHandleForDisk(buf))) {
return ERROR_INVALID_HANDLE;
}
//
// Get cache info - IOCTL_DISK_GET_CACHE_INFORMATION
//
if (!DeviceIoControl(hDisk,
IOCTL_DISK_GET_CACHE_INFORMATION,
NULL,
0,
&cacheInfo,
sizeof(DISK_CACHE_INFORMATION),
&len,
NULL)) {
CloseHandle(hDisk);
return GetLastError();
}
data->OrigWriteCacheSetting = cacheInfo.WriteCacheEnabled;
data->CurrWriteCacheSetting = cacheInfo.WriteCacheEnabled;
//
// Get the cache setting - IOCTL_DISK_GET_CACHE_SETTING
//
if (!DeviceIoControl(hDisk,
IOCTL_DISK_GET_CACHE_SETTING,
NULL,
0,
&data->CacheSetting,
sizeof(DISK_CACHE_SETTING),
&len,
NULL)) {
CloseHandle(hDisk);
return GetLastError();
}
data->CurrentIsPowerProtected = data->CacheSetting.IsPowerProtected;
CloseHandle(hDisk);
return ERROR_SUCCESS;
}
VOID
UpdateCachingPolicy(HWND HWnd, PDISK_PAGE_DATA data)
{
if (data->IsCachingPolicy)
{
if (data->CurrentRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL)
{
//
// This policy requires that no caching be done at any
// level. Uncheck and gray out the write cache setting
//
CheckDlgButton(HWnd, IDC_DISK_POLICY_WRITE_CACHE, 0);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_WRITE_CACHE), FALSE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_WRITE_CACHE_MESG), FALSE);
data->CurrWriteCacheSetting = FALSE;
}
else
{
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_WRITE_CACHE), TRUE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_WRITE_CACHE_MESG), TRUE);
}
if (data->CurrWriteCacheSetting == FALSE)
{
//
// The power-protected mode option does not apply if
// caching is off. Uncheck and gray out this setting
//
CheckDlgButton(HWnd, IDC_DISK_POLICY_PP_CACHE, 0);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_PP_CACHE), FALSE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_PP_CACHE_MESG), FALSE);
data->CurrentIsPowerProtected = FALSE;
}
else
{
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_PP_CACHE), TRUE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_PP_CACHE_MESG), TRUE);
}
}
else
{
//
// The caching policy cannot be modified
//
}
}
UINT
SetCachingPolicy(PDISK_PAGE_DATA data)
{
HANDLE hDisk;
DISK_CACHE_INFORMATION cacheInfo;
TCHAR buf[MAX_PATH] = { 0 };
DWORD len;
if (!SetupDiGetDeviceRegistryProperty(data->DeviceInfoSet,
data->DeviceInfoData,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
NULL,
(PBYTE)buf,
sizeof(buf) - sizeof(TCHAR),
NULL))
{
return GetLastError();
}
if (INVALID_HANDLE_VALUE == (hDisk = GetHandleForDisk(buf))) {
return ERROR_INVALID_HANDLE;
}
data->CacheSetting.IsPowerProtected = (BOOLEAN)data->CurrentIsPowerProtected;
//
// Set the cache setting - IOCTL_DISK_SET_CACHE_SETTING
//
if (!DeviceIoControl(hDisk,
IOCTL_DISK_SET_CACHE_SETTING,
&data->CacheSetting,
sizeof(DISK_CACHE_SETTING),
NULL,
0,
&len,
NULL)) {
CloseHandle(hDisk);
return GetLastError();
}
//
// Get cache info - IOCTL_DISK_GET_CACHE_INFORMATION
//
if (!DeviceIoControl(hDisk,
IOCTL_DISK_GET_CACHE_INFORMATION,
NULL,
0,
&cacheInfo,
sizeof(DISK_CACHE_INFORMATION),
&len,
NULL)) {
CloseHandle(hDisk);
return GetLastError();
}
cacheInfo.WriteCacheEnabled = (BOOLEAN)data->CurrWriteCacheSetting;
//
// Set cache info - IOCTL_DISK_SET_CACHE_INFORMATION
//
if (!DeviceIoControl(hDisk,
IOCTL_DISK_SET_CACHE_INFORMATION,
&cacheInfo,
sizeof(DISK_CACHE_INFORMATION),
NULL,
0,
&len,
NULL)) {
CloseHandle(hDisk);
return GetLastError();
}
data->OrigWriteCacheSetting = data->CurrWriteCacheSetting;
CloseHandle(hDisk);
return ERROR_SUCCESS;
}
UINT
GetRemovalPolicy(PDISK_PAGE_DATA data)
{
HANDLE hDisk;
TCHAR buf[MAX_PATH] = { 0 };
DWORD len;
if (!SetupDiGetDeviceRegistryProperty(data->DeviceInfoSet,
data->DeviceInfoData,
SPDRP_REMOVAL_POLICY,
NULL,
(PBYTE)&data->DefaultRemovalPolicy,
sizeof(DWORD),
NULL))
{
return GetLastError();
}
if (!SetupDiGetDeviceRegistryProperty(data->DeviceInfoSet,
data->DeviceInfoData,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
NULL,
(PBYTE)buf,
sizeof(buf) - sizeof(TCHAR),
NULL))
{
return GetLastError();
}
if (INVALID_HANDLE_VALUE == (hDisk = GetHandleForDisk(buf))) {
return ERROR_INVALID_HANDLE;
}
//
// Get hotplug info - IOCTL_STORAGE_GET_HOTPLUG_INFO
//
if (!DeviceIoControl(hDisk,
IOCTL_STORAGE_GET_HOTPLUG_INFO,
NULL,
0,
&data->HotplugInfo,
sizeof(STORAGE_HOTPLUG_INFO),
&len,
NULL)) {
CloseHandle(hDisk);
return GetLastError();
}
data->CurrentRemovalPolicy = (data->HotplugInfo.DeviceHotplug) ? CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL : CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL;
CloseHandle(hDisk);
return ERROR_SUCCESS;
}
DWORD WINAPI
UtilpRestartDeviceWr(PDISK_PAGE_DATA data)
{
UtilpRestartDevice(data->DeviceInfoSet, data->DeviceInfoData);
return ERROR_SUCCESS;
}
VOID
UtilpRestartDeviceEx(HWND HWnd, PDISK_PAGE_DATA data)
{
HANDLE hThread = NULL;
MSG msg;
//
// Temporary workaround to prevent the user from
// making any more changes and giving the effect
// that something is happening
//
EnableWindow(GetDlgItem(GetParent(HWnd), IDOK), FALSE);
EnableWindow(GetDlgItem(GetParent(HWnd), IDCANCEL), FALSE);
data->IsBusy = TRUE;
//
// Call this utility on a seperate thread
//
hThread = CreateThread(NULL, 0, UtilpRestartDeviceWr, (LPVOID)data, 0, NULL);
if (hThread)
{
while (1)
{
if (MsgWaitForMultipleObjects(1, &hThread, FALSE, INFINITE, QS_ALLINPUT) != (WAIT_OBJECT_0 + 1))
{
break;
}
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (!PropSheet_IsDialogMessage(HWnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
CloseHandle(hThread);
}
data->IsBusy = FALSE;
EnableWindow(GetDlgItem(GetParent(HWnd), IDOK), TRUE);
EnableWindow(GetDlgItem(GetParent(HWnd), IDCANCEL), TRUE);
}
UINT
SetRemovalPolicy(HWND HWnd, PDISK_PAGE_DATA data)
{
HANDLE hDisk;
TCHAR buf[MAX_PATH] = { 0 };
DWORD len;
if (!SetupDiGetDeviceRegistryProperty(data->DeviceInfoSet,
data->DeviceInfoData,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
NULL,
(PBYTE)buf,
sizeof(buf) - sizeof(TCHAR),
NULL))
{
return GetLastError();
}
if (INVALID_HANDLE_VALUE == (hDisk = GetHandleForDisk(buf))) {
return ERROR_INVALID_HANDLE;
}
data->HotplugInfo.DeviceHotplug = (data->CurrentRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL) ? TRUE : FALSE;
//
// Set hotplug info - IOCTL_STORAGE_SET_HOTPLUG_INFO
//
if (!DeviceIoControl(hDisk,
IOCTL_STORAGE_SET_HOTPLUG_INFO,
&data->HotplugInfo,
sizeof(STORAGE_HOTPLUG_INFO),
NULL,
0,
&len,
NULL)) {
CloseHandle(hDisk);
return GetLastError();
}
CloseHandle(hDisk);
UtilpRestartDeviceEx(HWnd, data);
return ERROR_SUCCESS;
}
BOOL
DiskOnInitDialog(HWND HWnd, HWND HWndFocus, LPARAM LParam)
{
LPPROPSHEETPAGE page = (LPPROPSHEETPAGE) LParam;
PDISK_PAGE_DATA diskData = (PDISK_PAGE_DATA) page->lParam;
UINT status;
//
// Initially assume that the device does not have a surprise removal policy
//
CheckRadioButton(HWnd, IDC_DISK_POLICY_SURPRISE, IDC_DISK_POLICY_ORDERLY, IDC_DISK_POLICY_ORDERLY);
diskData->IsBusy = FALSE;
//
// Obtain the Caching Policy
//
status = GetCachingPolicy(diskData);
if (status == ERROR_SUCCESS)
{
diskData->IsCachingPolicy = TRUE;
CheckDlgButton(HWnd, IDC_DISK_POLICY_WRITE_CACHE, diskData->OrigWriteCacheSetting);
//
// Determine the most appropriate message to display under this setting
//
if (diskData->CacheSetting.State != DiskCacheNormal)
{
TCHAR szMesg[MAX_PATH] = { 0 };
//
// The write caching option on this device should either be
// disabled (to protect data integrity) or cannot be modified
//
if (diskData->CacheSetting.State == DiskCacheWriteThroughNotSupported)
{
LoadString(ModuleInstance, IDS_DISK_POLICY_WRITE_CACHE_MSG1, szMesg, MAX_PATH);
}
else if (diskData->CacheSetting.State == DiskCacheModifyUnsuccessful)
{
LoadString(ModuleInstance, IDS_DISK_POLICY_WRITE_CACHE_MSG2, szMesg, MAX_PATH);
}
SetDlgItemText(HWnd, IDC_DISK_POLICY_WRITE_CACHE_MESG, szMesg);
}
//
// The power-protected mode option does not apply if
// caching is off. Uncheck and gray out this setting
//
if (diskData->OrigWriteCacheSetting == FALSE)
{
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_PP_CACHE), FALSE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_PP_CACHE_MESG), FALSE);
diskData->CurrentIsPowerProtected = FALSE;
}
CheckDlgButton(HWnd, IDC_DISK_POLICY_PP_CACHE, diskData->CurrentIsPowerProtected);
}
else
{
//
// Either we could not open a handle to the device
// or this device does not support write caching
//
diskData->IsCachingPolicy = FALSE;
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_WRITE_CACHE), SW_HIDE);
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_WRITE_CACHE_MESG), SW_HIDE);
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_PP_CACHE), SW_HIDE);
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_PP_CACHE_MESG), SW_HIDE);
}
//
// Obtain the Removal Policy
//
status = GetRemovalPolicy(diskData);
if (status == ERROR_SUCCESS)
{
//
// Check to see if the drive is removable
//
if ((diskData->DefaultRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL) ||
(diskData->DefaultRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL))
{
if (diskData->CurrentRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL)
{
CheckRadioButton(HWnd, IDC_DISK_POLICY_SURPRISE, IDC_DISK_POLICY_ORDERLY, IDC_DISK_POLICY_SURPRISE);
UpdateCachingPolicy(HWnd, diskData);
}
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_DEFAULT), SW_SHOW);
}
else
{
//
// The removal policy on fixed disks cannot be modified
//
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_SURPRISE), FALSE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_SURPRISE_MESG), FALSE);
//
// Replace the SysLink with static text
//
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_ORDERLY_MESG), SW_HIDE);
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_ORDERLY_MSGD), SW_SHOW);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_ORDERLY), FALSE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_ORDERLY_MSGD), FALSE);
}
}
else
{
//
// We could not obtain a removal policy
//
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_SURPRISE), FALSE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_SURPRISE_MESG), FALSE);
//
// Replace the SysLink with static text
//
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_ORDERLY_MESG), SW_HIDE);
ShowWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_ORDERLY_MSGD), SW_SHOW);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_ORDERLY), FALSE);
EnableWindow(GetDlgItem(HWnd, IDC_DISK_POLICY_ORDERLY_MSGD), FALSE);
}
SetWindowLongPtr(HWnd, DWLP_USER, (LONG_PTR) diskData);
return TRUE;
}
VOID
DiskOnCommand(HWND HWnd, INT id, HWND HWndCtl, UINT codeNotify)
{
PDISK_PAGE_DATA diskData = (PDISK_PAGE_DATA) GetWindowLongPtr(HWnd, DWLP_USER);
switch (id)
{
case IDC_DISK_POLICY_SURPRISE:
{
diskData->CurrentRemovalPolicy = CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL;
UpdateCachingPolicy(HWnd, diskData);
PropSheet_Changed(GetParent(HWnd), HWnd);
break;
}
case IDC_DISK_POLICY_ORDERLY:
{
diskData->CurrentRemovalPolicy = CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL;
UpdateCachingPolicy(HWnd, diskData);
PropSheet_Changed(GetParent(HWnd), HWnd);
break;
}
case IDC_DISK_POLICY_WRITE_CACHE:
{
diskData->CurrWriteCacheSetting = !diskData->CurrWriteCacheSetting;
UpdateCachingPolicy(HWnd, diskData);
PropSheet_Changed(GetParent(HWnd), HWnd);
break;
}
case IDC_DISK_POLICY_PP_CACHE:
{
diskData->CurrentIsPowerProtected = !diskData->CurrentIsPowerProtected;
PropSheet_Changed(GetParent(HWnd), HWnd);
break;
}
case IDC_DISK_POLICY_DEFAULT:
{
if (diskData->CurrentRemovalPolicy != diskData->DefaultRemovalPolicy)
{
diskData->CurrentRemovalPolicy = diskData->DefaultRemovalPolicy;
if (diskData->CurrentRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL)
{
CheckRadioButton(HWnd, IDC_DISK_POLICY_SURPRISE, IDC_DISK_POLICY_ORDERLY, IDC_DISK_POLICY_ORDERLY);
}
else
{
CheckRadioButton(HWnd, IDC_DISK_POLICY_SURPRISE, IDC_DISK_POLICY_ORDERLY, IDC_DISK_POLICY_SURPRISE);
}
UpdateCachingPolicy(HWnd, diskData);
PropSheet_Changed(GetParent(HWnd), HWnd);
}
break;
}
}
}
LRESULT
DiskOnNotify(HWND HWnd, INT HWndFocus, LPNMHDR lpNMHdr)
{
PDISK_PAGE_DATA diskData = (PDISK_PAGE_DATA) GetWindowLongPtr(HWnd, DWLP_USER);
switch (lpNMHdr->code)
{
case PSN_APPLY:
{
if (diskData->IsCachingPolicy)
{
if ((diskData->CurrWriteCacheSetting != diskData->OrigWriteCacheSetting) ||
(diskData->CacheSetting.IsPowerProtected != diskData->CurrentIsPowerProtected))
{
SetCachingPolicy(diskData);
}
}
if (((diskData->CurrentRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL) && (diskData->HotplugInfo.DeviceHotplug == TRUE)) ||
((diskData->CurrentRemovalPolicy == CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL) && (diskData->HotplugInfo.DeviceHotplug == FALSE)))
{
SetRemovalPolicy(HWnd, diskData);
}
break;
}
case NM_RETURN:
case NM_CLICK:
{
TCHAR szPath[MAX_PATH] = { 0 };
LoadString(ModuleInstance, IDS_DISK_POLICY_HOTPLUG, szPath, MAX_PATH);
ShellExecute(NULL, _T("open"), _T("RUNDLL32.EXE"), szPath, NULL, SW_SHOWNORMAL);
break;
}
}
return 0;
}
VOID
DiskContextMenu(HWND HwndControl, WORD Xpos, WORD Ypos)
{
WinHelp(HwndControl, _T("devmgr.hlp"), HELP_CONTEXTMENU, (ULONG_PTR) DiskHelpIDs);
}
VOID
DiskHelp(HWND ParentHwnd, LPHELPINFO HelpInfo)
{
if (HelpInfo->iContextType == HELPINFO_WINDOW)
{
WinHelp((HWND) HelpInfo->hItemHandle, _T("devmgr.hlp"), HELP_WM_HELP, (ULONG_PTR) DiskHelpIDs);
}
}
INT_PTR
DiskDialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
HANDLE_MSG(hWnd, WM_INITDIALOG, DiskOnInitDialog);
HANDLE_MSG(hWnd, WM_COMMAND, DiskOnCommand);
HANDLE_MSG(hWnd, WM_NOTIFY, DiskOnNotify);
case WM_SETCURSOR:
{
//
// Temporary workaround to prevent the user from
// making any more changes and giving the effect
// that something is happening
//
PDISK_PAGE_DATA diskData = (PDISK_PAGE_DATA) GetWindowLongPtr(hWnd, DWLP_USER);
if (diskData->IsBusy)
{
SetCursor(LoadCursor(NULL, IDC_WAIT));
SetWindowLongPtr(hWnd, DWLP_MSGRESULT, TRUE);
return TRUE;
}
break;
}
case WM_CONTEXTMENU:
DiskContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
break;
case WM_HELP:
DiskHelp(hWnd, (LPHELPINFO)lParam);
break;
}
return FALSE;
}
BOOL
DiskDialogCallback(HWND HWnd, UINT Message, LPPROPSHEETPAGE Page)
{
switch (Message)
{
case PSPCB_CREATE:
{
break;
}
case PSPCB_RELEASE:
{
PDISK_PAGE_DATA pData = (PDISK_PAGE_DATA) Page->lParam;
HeapFree(GetProcessHeap(), 0, pData);
break;
}
}
return TRUE;
}