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.
 
 
 
 
 
 

1856 lines
53 KiB

/*++
Copyright (c) Microsoft Corporation
Module Name:
clasprop.c
Abstract:
Routines for the following 'built-in' class property page providers:
LegacyDriver
Author:
Lonny McMichael 15-May-1997
--*/
#include "setupp.h"
#pragma hdrstop
#include <help.h>
#include <strsafe.h>
//
// Help Ids for legacy driver property page
//
#define idh_devmgr_driver_hidden_servicename 2480
#define idh_devmgr_driver_hidden_displayname 2481
#define idh_devmgr_driver_hidden_status 2482
#define idh_devmgr_driver_hidden_startbut 2483
#define idh_devmgr_driver_hidden_stopbut 2484
#define idh_devmgr_driver_hidden_startup 2485
#define idh_devmgr_devdrv_details 400400
#define idh_devmgr_driver_copyright 106130
#define idh_devmgr_driver_driver_files 106100
#define idh_devmgr_driver_provider 106110
#define idh_devmgr_driver_file_version 106120
const DWORD LegacyDriver_HelpIDs[]=
{
IDC_STATIC_SERVICE_NAME, idh_devmgr_driver_hidden_servicename,
IDC_EDIT_SERVICE_NAME, idh_devmgr_driver_hidden_servicename,
IDC_STATIC_DISPLAY_NAME, idh_devmgr_driver_hidden_displayname,
IDC_EDIT_DISPLAY_NAME, idh_devmgr_driver_hidden_displayname,
IDC_STATIC_CURRENT_STATUS_STATIC, idh_devmgr_driver_hidden_status,
IDC_STATIC_CURRENT_STATUS, idh_devmgr_driver_hidden_status,
IDC_BUTTON_START, idh_devmgr_driver_hidden_startbut,
IDC_BUTTON_STOP, idh_devmgr_driver_hidden_stopbut,
IDC_COMBO_STARTUP_TYPE, idh_devmgr_driver_hidden_startup,
IDC_LEGACY_DETAILS, idh_devmgr_devdrv_details,
IDC_PROP_LEGACY_ICON, NO_HELP,
IDC_PROP_LEGACY_DESC, NO_HELP,
IDC_GROUP_CURRENT_STATUS, NO_HELP,
IDC_GROUP_STARTUP_TYPE, NO_HELP,
0, 0
};
const DWORD DriverFiles_HelpIDs[]=
{
IDC_DRIVERFILES_ICON, NO_HELP,
IDC_DRIVERFILES_DESC, NO_HELP,
IDC_DRIVERFILES_FILES, NO_HELP,
IDC_DRIVERFILES_FILELIST, idh_devmgr_driver_driver_files,
IDC_DRIVERFILES_TITLE_PROVIDER, idh_devmgr_driver_provider,
IDC_DRIVERFILES_PROVIDER, idh_devmgr_driver_provider,
IDC_DRIVERFILES_TITLE_COPYRIGHT,idh_devmgr_driver_copyright,
IDC_DRIVERFILES_COPYRIGHT, idh_devmgr_driver_copyright,
IDC_DRIVERFILES_TITLE_VERSION, idh_devmgr_driver_file_version,
IDC_DRIVERFILES_VERSION, idh_devmgr_driver_file_version,
0, 0
};
#define SERVICE_BUFFER_SIZE 4096
#define MAX_SECONDS_UNTIL_TIMEOUT 30
#define SERVICE_WAIT_TIME 500
#define WAIT_TIME_SLOT 1
#define TRIES_COUNT 5
#define START_LEGACY_DEVICE 0
#define STOP_LEGACY_DEVICE 1
//
// The only reason we have the DiskPropPageProvider and TapePropPageProvider
// APIs are so that the classes can get their icon out of syssetup.dll.
//
BOOL
DiskPropPageProvider(
IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest,
IN LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc,
IN LPARAM lParam
)
{
//
// No property pages to add for now
//
UNREFERENCED_PARAMETER(PropPageRequest);
UNREFERENCED_PARAMETER(lpfnAddPropSheetPageProc);
UNREFERENCED_PARAMETER(lParam);
return TRUE;
}
BOOL
TapePropPageProvider(
IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest,
IN LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc,
IN LPARAM lParam
)
{
//
// No property pages to add for now
//
UNREFERENCED_PARAMETER(PropPageRequest);
UNREFERENCED_PARAMETER(lpfnAddPropSheetPageProc);
UNREFERENCED_PARAMETER(lParam);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
// Driver Files popup dialog
//
///////////////////////////////////////////////////////////////////////////////
typedef struct _DRIVERFILES_INFO {
HDEVINFO DeviceInfoSet;
PSP_DEVINFO_DATA DeviceInfoData;
} DRIVERFILES_INFO, * PDRIVERFILES_INFO;
const TCHAR* tszStringFileInfo = TEXT("StringFileInfo\\%04X%04X\\");
const TCHAR* tszFileVersion = TEXT("FileVersion");
const TCHAR* tszLegalCopyright = TEXT("LegalCopyright");
const TCHAR* tszCompanyName = TEXT("CompanyName");
const TCHAR* tszTranslation = TEXT("VarFileInfo\\Translation");
const TCHAR* tszStringFileInfoDefault = TEXT("StringFileInfo\\040904B0\\");
BOOL
GetVersionInfo(
IN PTSTR FullPathName,
OUT PTSTR Provider,
IN ULONG CchProviderSize,
OUT PTSTR Copyright,
IN ULONG CchCopyrightSize,
OUT PTSTR Version,
IN ULONG CchVersionSize
)
{
DWORD Size, dwHandle;
TCHAR str[MAX_PATH];
TCHAR strStringFileInfo[MAX_PATH];
PVOID pVerInfo;
Size = GetFileVersionInfoSize((LPTSTR)(LPCTSTR)FullPathName, &dwHandle);
if (!Size) {
return FALSE;
}
if ((pVerInfo = malloc(Size)) != NULL) {
if (GetFileVersionInfo((LPTSTR)(LPCTSTR)FullPathName, dwHandle, Size, pVerInfo)) {
//
// get VarFileInfo\Translation
//
PVOID pBuffer;
UINT Len;
if (!VerQueryValue(pVerInfo, (LPTSTR)tszTranslation, &pBuffer, &Len)) {
StringCchCopy(strStringFileInfo,
SIZECHARS(strStringFileInfo),
tszStringFileInfoDefault);
} else {
StringCchPrintf(strStringFileInfo,
SIZECHARS(strStringFileInfo),
tszStringFileInfo, *((WORD*)pBuffer), *(((WORD*)pBuffer) + 1));
}
if (SUCCEEDED(StringCchCopy(str, SIZECHARS(str), strStringFileInfo)) &&
SUCCEEDED(StringCchCat(str, SIZECHARS(str), tszFileVersion)) &&
VerQueryValue(pVerInfo, (LPTSTR)(LPCTSTR)str, &pBuffer, &Len)) {
StringCchCopy(Version, CchVersionSize, (LPTSTR)pBuffer);
if (SUCCEEDED(StringCchCopy(str, SIZECHARS(str), strStringFileInfo)) &&
SUCCEEDED(StringCchCat(str, SIZECHARS(str), tszLegalCopyright)) &&
VerQueryValue(pVerInfo, (LPTSTR)(LPCTSTR)str, &pBuffer, &Len)) {
StringCchCopy(Copyright, CchCopyrightSize, (LPTSTR)pBuffer);
if (SUCCEEDED(StringCchCopy(str, SIZECHARS(str), strStringFileInfo)) &&
SUCCEEDED(StringCchCat(str, SIZECHARS(str), tszCompanyName)) &&
VerQueryValue(pVerInfo, (LPTSTR)(LPCTSTR)str, &pBuffer, &Len)) {
StringCchCopy(Provider, CchProviderSize, (LPTSTR)pBuffer);
}
}
}
}
free(pVerInfo);
}
return TRUE;
}
BOOL
pDriverFilesGetServiceFilePath(
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
PTSTR ServiceFilePath,
ULONG CchServiceFileSize
)
{
BOOL bReturn = FALSE;
TCHAR ServiceName[MAX_PATH];
SC_HANDLE hSCManager = NULL;
SC_HANDLE hSCService = NULL;
LPQUERY_SERVICE_CONFIG lpqscBuf = NULL;
DWORD dwBytesNeeded, Size;
BOOL bComposePathNameFromServiceName = TRUE;
ServiceFilePath[0] = TEXT('\0');
if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
DeviceInfoData,
SPDRP_SERVICE,
NULL,
(PBYTE)ServiceName,
sizeof(ServiceName),
NULL)) {
try {
//
// Open the Service Control Manager
//
if ((hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ)) != NULL) {
//
// Try to open the service's handle
//
if ((hSCService = OpenService(hSCManager, ServiceName, GENERIC_READ)) != NULL) {
//
// Now, attempt to get the configuration
//
if ((!QueryServiceConfig(hSCService, NULL, 0, &dwBytesNeeded)) &&
(ERROR_INSUFFICIENT_BUFFER == GetLastError())) {
if ((lpqscBuf = (LPQUERY_SERVICE_CONFIG)malloc(dwBytesNeeded)) != NULL) {
if ((QueryServiceConfig(hSCService, lpqscBuf, dwBytesNeeded, &Size)) &&
(lpqscBuf->lpBinaryPathName[0] != TEXT('\0'))) {
if (GetFileAttributes(lpqscBuf->lpBinaryPathName) != 0xFFFFFFFF) {
bReturn = TRUE;
StringCchCopy(ServiceFilePath, CchServiceFileSize, lpqscBuf->lpBinaryPathName);
bComposePathNameFromServiceName = FALSE;
}
}
free(lpqscBuf);
}
}
CloseServiceHandle(hSCService);
}
CloseServiceHandle(hSCManager);
}
//
// If we could not get the path name from the service then we will attempt
// to find it ourselves
//
if (bComposePathNameFromServiceName) {
TCHAR FullPathName[MAX_PATH];
if (GetSystemDirectory(FullPathName, SIZECHARS(FullPathName)) &&
SUCCEEDED(StringCchCat(FullPathName, SIZECHARS(FullPathName), TEXT("\\drivers\\"))) &&
SUCCEEDED(StringCchCat(FullPathName, SIZECHARS(FullPathName), ServiceName)) &&
SUCCEEDED(StringCchCat(FullPathName, SIZECHARS(FullPathName), TEXT(".sys")))) {
if (GetFileAttributes(FullPathName) != 0xFFFFFFFF) {
bReturn = TRUE;
StringCchCopy(ServiceFilePath, CchServiceFileSize, FullPathName);
}
}
}
} except (EXCEPTION_EXECUTE_HANDLER) {
;
}
}
return(bReturn);
}
void
DriverFiles_ShowFileDetail(
HWND hDlg
)
{
TCHAR DriverFile[MAX_PATH];
TCHAR Provider[MAX_PATH];
TCHAR Copyright[MAX_PATH];
TCHAR Version[MAX_PATH];
DWORD_PTR Index;
if ((Index = SendMessage(GetDlgItem(hDlg, IDC_DRIVERFILES_FILELIST), LB_GETCURSEL, 0, 0)) != LB_ERR) {
SendMessage(GetDlgItem(hDlg, IDC_DRIVERFILES_FILELIST), LB_GETTEXT, Index, (LPARAM)DriverFile);
Provider[0] = TEXT('\0');
Copyright[0] = TEXT('\0');
Version[0] = TEXT('\0');
GetVersionInfo(DriverFile,
Provider,
SIZECHARS(Provider),
Copyright,
SIZECHARS(Copyright),
Version,
SIZECHARS(Version));
if (Provider[0] != TEXT('\0')) {
SetDlgItemText(hDlg, IDC_DRIVERFILES_PROVIDER, Provider);
}
if (Version[0] != TEXT('\0')) {
SetDlgItemText(hDlg, IDC_DRIVERFILES_VERSION, Version);
}
if (Copyright[0] != TEXT('\0')) {
SetDlgItemText(hDlg, IDC_DRIVERFILES_COPYRIGHT, Copyright);
}
}
}
BOOL
DriverFiles_OnInitDialog(
HWND hDlg,
HWND FocusHwnd,
LPARAM lParam
)
{
PDRIVERFILES_INFO dfi = (PDRIVERFILES_INFO) GetWindowLongPtr(hDlg, DWLP_USER);
HICON ClassIcon;
HICON OldIcon;
TCHAR DeviceDescription[MAX_DEVICE_ID_LEN];
TCHAR DriverName[MAX_PATH];
UNREFERENCED_PARAMETER(FocusHwnd);
dfi = (PDRIVERFILES_INFO)lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (ULONG_PTR)dfi);
//
// Draw the interface: first the icon
//
if (SetupDiLoadClassIcon(&dfi->DeviceInfoData->ClassGuid, &ClassIcon, NULL)) {
OldIcon = (HICON)SendDlgItemMessage(hDlg,
IDC_DRIVERFILES_ICON,
STM_SETICON,
(WPARAM)ClassIcon,
0);
if (OldIcon) {
DestroyIcon(OldIcon);
}
}
//
// Then the device name
//
if (SetupDiGetDeviceRegistryProperty(dfi->DeviceInfoSet,
dfi->DeviceInfoData,
SPDRP_DEVICEDESC,
NULL,
(PBYTE)DeviceDescription,
MAX_DEVICE_ID_LEN,
NULL)) {
SetDlgItemText(hDlg, IDC_DRIVERFILES_DESC, DeviceDescription);
}
if ((pDriverFilesGetServiceFilePath(dfi->DeviceInfoSet, dfi->DeviceInfoData, DriverName, SIZECHARS(DriverName))) &&
(DriverName[0] != TEXT('\0'))) {
SendMessage(GetDlgItem(hDlg, IDC_DRIVERFILES_FILELIST), LB_ADDSTRING, 0, (LPARAM)DriverName);
}
SendMessage(GetDlgItem(hDlg, IDC_DRIVERFILES_FILELIST), LB_SETCURSEL, 0, 0);
DriverFiles_ShowFileDetail(hDlg);
return TRUE;
}
BOOL
DriverFiles_OnContextMenu(
HWND HwndControl,
WORD Xpos,
WORD Ypos
)
{
UNREFERENCED_PARAMETER(Xpos);
UNREFERENCED_PARAMETER(Ypos);
WinHelp(HwndControl,
L"devmgr.hlp",
HELP_CONTEXTMENU,
(ULONG_PTR) DriverFiles_HelpIDs);
return FALSE;
}
void
DriverFiles_OnHelp(
HWND ParentHwnd,
LPHELPINFO HelpInfo
)
{
UNREFERENCED_PARAMETER(ParentHwnd);
if (HelpInfo->iContextType == HELPINFO_WINDOW) {
WinHelp((HWND) HelpInfo->hItemHandle,
L"devmgr.hlp",
HELP_WM_HELP,
(ULONG_PTR) DriverFiles_HelpIDs);
}
}
void
DriverFiles_OnCommand(
HWND hDlg,
int ControlId,
HWND ControlHwnd,
UINT NotifyCode
)
{
UNREFERENCED_PARAMETER(ControlHwnd);
UNREFERENCED_PARAMETER(NotifyCode);
switch (ControlId) {
case IDOK:
case IDCANCEL:
EndDialog(hDlg, 0);
break;
case IDC_DRIVERFILES_FILELIST:
if (ControlId == LBN_SELCHANGE) {
DriverFiles_ShowFileDetail(hDlg);
}
break;
}
}
INT_PTR
APIENTRY
DriverFiles_DlgProc(
IN HWND hDlg,
IN UINT uMessage,
IN WPARAM wParam,
IN LPARAM lParam
)
{
switch(uMessage) {
case WM_INITDIALOG:
return DriverFiles_OnInitDialog(hDlg, (HWND)wParam, lParam);
case WM_COMMAND:
DriverFiles_OnCommand(hDlg, (int) LOWORD(wParam), (HWND)lParam, (UINT)HIWORD(wParam));
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_CONTEXTMENU:
return DriverFiles_OnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
case WM_HELP:
DriverFiles_OnHelp(hDlg, (LPHELPINFO) lParam);
break;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
//
// Legacy Devices property page provider
//
///////////////////////////////////////////////////////////////////////////////
typedef struct _LEGACY_PAGE_INFO {
HDEVINFO DeviceInfoSet;
PSP_DEVINFO_DATA DeviceInfoData;
SC_HANDLE hSCManager; // Handle to the SC Manager
SC_HANDLE hService; // The handle to the service
DWORD dwStartType; // The start type
SERVICE_STATUS ServiceStatus; // Tells us if the service is started
TCHAR ServiceName[MAX_DEVICE_ID_LEN];
TCHAR DisplayName[MAX_PATH];
DWORD NumDependentServices;
LPENUM_SERVICE_STATUS pDependentServiceList;
} LEGACY_PAGE_INFO, * PLEGACY_PAGE_INFO;
BOOL
DependentServices_OnInitDialog(
HWND hDlg,
HWND FocusHwnd,
LPARAM lParam
)
{
PLEGACY_PAGE_INFO lpi;
HWND hWndListBox;
DWORD i;
HICON hicon = NULL;
UNREFERENCED_PARAMETER(FocusHwnd);
lpi = (PLEGACY_PAGE_INFO)lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (ULONG_PTR)lpi);
hicon = LoadIcon(NULL, IDI_WARNING);
if (hicon != NULL) {
SendDlgItemMessage(hDlg, IDC_ICON_WARN_SERVICES, STM_SETICON, (WPARAM)hicon, 0L);
DestroyIcon(hicon);
}
hWndListBox = GetDlgItem(hDlg, IDC_LIST_SERVICES);
for (i=0; i<lpi->NumDependentServices; i++) {
SendMessage(hWndListBox,
LB_ADDSTRING,
0,
(LPARAM) lpi->pDependentServiceList[i].lpDisplayName
);
}
return TRUE;
}
INT_PTR
APIENTRY
DependentServicesDlgProc(
IN HWND hDlg,
IN UINT uMessage,
IN WPARAM wParam,
IN LPARAM lParam
)
{
switch(uMessage) {
case WM_INITDIALOG:
return DependentServices_OnInitDialog(hDlg, (HWND)wParam, lParam);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
break;
}
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
}
return FALSE;
}
int
pLegacyDriverMapStateToName(
IN DWORD dwServiceState
)
{
switch(dwServiceState) {
case SERVICE_STOPPED:
return IDS_SVC_STATUS_STOPPED;
case SERVICE_STOP_PENDING:
return IDS_SVC_STATUS_STOPPING;
case SERVICE_RUNNING:
return IDS_SVC_STATUS_STARTED;
case SERVICE_START_PENDING:
return IDS_SVC_STATUS_STARTING;
case SERVICE_PAUSED:
return IDS_SVC_STATUS_PAUSED;
case SERVICE_PAUSE_PENDING:
return IDS_SVC_STATUS_PAUSING;
case SERVICE_CONTINUE_PENDING:
return IDS_SVC_STATUS_RESUMING;
default:
return IDS_SVC_STATUS_UNKNOWN;
}
}
VOID
pLegacyDriverInitializeStartButtons(
IN HWND hDlg,
IN LPSERVICE_STATUS ServiceStatus
)
{
//
// Decide how to paint the two start/stop buttons
//
TCHAR szStatus[MAX_PATH];
//
// Set the status text
//
if (LoadString(MyModuleHandle,
pLegacyDriverMapStateToName(ServiceStatus->dwCurrentState),
szStatus,
MAX_PATH)) {
SetDlgItemText(hDlg, IDC_STATIC_CURRENT_STATUS, szStatus);
}
//
// Decide if the service is started or stopped
//
if ((ServiceStatus->dwCurrentState == SERVICE_STOPPED) ) {
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_START), TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_STOP), FALSE);
} else {
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_STOP), TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_START), FALSE);
}
//
// If the service doesn't accept stops, grey the stop
// button
//
if (!(ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_STOP)) {
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_STOP), FALSE);
}
return;
}
VOID
pLegacyDriverSetPropertyPageState(
IN HWND hDlg,
IN PLEGACY_PAGE_INFO lpi,
IN BOOL ReadOnly
)
{
DWORD_PTR Index;
DWORD_PTR ServiceStartType;
TCHAR szStatus[MAX_PATH];
if (ReadOnly) {
//
// Disable everything
//
EnableWindow(GetDlgItem(hDlg, IDC_COMBO_STARTUP_TYPE), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_START), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_STOP), FALSE);
//
// Set the status text
//
if (LoadString(MyModuleHandle,
pLegacyDriverMapStateToName(lpi->ServiceStatus.dwCurrentState),
szStatus,
MAX_PATH)) {
SetDlgItemText(hDlg, IDC_STATIC_CURRENT_STATUS, szStatus);
}
} else {
Index = 0;
while ((ServiceStartType = SendMessage(GetDlgItem(hDlg, IDC_COMBO_STARTUP_TYPE),
CB_GETITEMDATA, Index, 0)) != CB_ERR) {
if (ServiceStartType == lpi->dwStartType) {
SendMessage(GetDlgItem(hDlg, IDC_COMBO_STARTUP_TYPE), CB_SETCURSEL, Index, 0);
break;
}
Index++;
}
SendMessage(GetDlgItem(hDlg, IDC_COMBO_STARTUP_TYPE), CB_GETCURSEL, 0, 0);
//
// If the start type is SERVICE_DISABLED then gray out both the start
// and stop buttons.
//
if (lpi->dwStartType == SERVICE_DISABLED) {
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_START), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_STOP), FALSE);
//
// Set the status text
//
if (LoadString(MyModuleHandle,
pLegacyDriverMapStateToName(lpi->ServiceStatus.dwCurrentState),
szStatus,
MAX_PATH)) {
SetDlgItemText(hDlg, IDC_STATIC_CURRENT_STATUS, szStatus);
}
} else {
pLegacyDriverInitializeStartButtons(hDlg, &lpi->ServiceStatus);
}
}
return;
}
BOOL
pLegacyDriverCheckServiceStatus(
IN SC_HANDLE hService,
IN OUT LPSERVICE_STATUS ServiceStatus,
IN USHORT ControlType
)
{
DWORD dwIntendedState;
DWORD dwCummulateTimeSpent = 0;
if ((ControlType != START_LEGACY_DEVICE) &&
(ControlType != STOP_LEGACY_DEVICE)) {
return TRUE;
}
if (ControlType == START_LEGACY_DEVICE) {
dwIntendedState = SERVICE_RUNNING;
} else {
dwIntendedState = SERVICE_STOPPED;
}
if (!QueryServiceStatus(hService, ServiceStatus)) {
return FALSE;
}
while (ServiceStatus->dwCurrentState != dwIntendedState) {
//
// Wait for the specified interval
//
Sleep(SERVICE_WAIT_TIME);
//
// Check the status again
//
if (!QueryServiceStatus(hService, ServiceStatus)) {
return FALSE;
}
//
// OK, add a (generous) timeout here
//
dwCummulateTimeSpent += SERVICE_WAIT_TIME;
if (dwCummulateTimeSpent > 1000 * MAX_SECONDS_UNTIL_TIMEOUT) {
SetLastError(ERROR_SERVICE_REQUEST_TIMEOUT);
return FALSE;
}
}
//
// If we are here we can return only TRUE
//
return TRUE;
}
VOID
pLegacyDriverDisplayErrorMsgBox(
IN HWND hWnd,
IN LPTSTR ServiceName,
IN int ResId,
IN DWORD ErrorCode
)
{
TCHAR TextBuffer[MAX_PATH * 4];
PTCHAR ErrorMsg;
if (LoadString(MyModuleHandle, ResId, TextBuffer, SIZECHARS(TextBuffer))) {
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
ErrorCode,
0,
(LPTSTR)&ErrorMsg,
0,
NULL
)) {
StringCchCat(TextBuffer, SIZECHARS(TextBuffer), ErrorMsg);
MessageBox(hWnd, TextBuffer, ServiceName, MB_OK);
LocalFree(ErrorMsg);
}
}
}
VOID
pLegacyDriverOnStart(
IN HWND hDlg
)
{
PLEGACY_PAGE_INFO lpi;
HCURSOR hOldCursor;
//
// Retrieve the device data structure first
//
lpi = (PLEGACY_PAGE_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
try {
if (!StartService(lpi->hService,
0,
NULL)) {
pLegacyDriverDisplayErrorMsgBox(hDlg,
lpi->DisplayName,
IDS_SVC_START_ERROR,
GetLastError()
);
goto clean0;
}
pLegacyDriverCheckServiceStatus(lpi->hService,
&lpi->ServiceStatus,
START_LEGACY_DEVICE
);
clean0:
//
// Repaint the status part
//
pLegacyDriverSetPropertyPageState(hDlg, lpi, FALSE);
}except (EXCEPTION_EXECUTE_HANDLER) {
lpi = lpi;
}
SetCursor(hOldCursor);
return;
}
VOID
pLegacyDriverOnStop(
IN HWND hDlg
)
{
BOOL bStopServices = TRUE;
DWORD Err;
PLEGACY_PAGE_INFO lpi;
HCURSOR hOldCursor;
DWORD cbBytesNeeded;
DWORD dwServicesReturned = 0;
DWORD i;
TCHAR DisplayName[MAX_PATH];
SC_HANDLE hService;
SERVICE_STATUS ServiceStatus;
LPENUM_SERVICE_STATUS pDependentServiceList = NULL;
//
// Retrieve the device data structure first
//
lpi = (PLEGACY_PAGE_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
MYASSERT (lpi);
if (!lpi) {
return;
}
hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
try {
//
// Find out if this device has any dependent services, and if so then
// how many bytes are needed to enumerate the dependent services.
//
EnumDependentServices(lpi->hService,
SERVICE_ACTIVE,
NULL,
0,
&cbBytesNeeded,
&dwServicesReturned
);
if (cbBytesNeeded > 0) {
pDependentServiceList = (LPENUM_SERVICE_STATUS)malloc(cbBytesNeeded);
if (pDependentServiceList) {
EnumDependentServices(lpi->hService,
SERVICE_ACTIVE,
pDependentServiceList,
cbBytesNeeded,
&cbBytesNeeded,
&dwServicesReturned
);
if (dwServicesReturned > 0) {
//
// Ask the user if they want to stop these dependet services.
//
lpi->NumDependentServices = dwServicesReturned;
lpi->pDependentServiceList = pDependentServiceList;
if (DialogBoxParam(MyModuleHandle,
MAKEINTRESOURCE(IDD_SERVICE_STOP_DEPENDENCIES),
hDlg,
DependentServicesDlgProc,
(LPARAM)lpi
) == IDCANCEL) {
bStopServices = FALSE;
}
}
}
}
//
// Stop this service and all the dependent services if the user did
// not cancel out of the dialog box.
//
if (bStopServices) {
Err = ERROR_SUCCESS;
SetCursor(LoadCursor(NULL, IDC_WAIT));
//
// First stop all of the dependent services if their are any.
//
if (pDependentServiceList && (dwServicesReturned > 0)) {
for (i=0; i<dwServicesReturned; i++) {
hService = OpenService(lpi->hSCManager,
pDependentServiceList[i].lpServiceName,
GENERIC_READ | SERVICE_STOP
);
if (hService == NULL) {
//
// Just bail out if we encountered an error. The reason
// is that if one of the services cannot be stopped
// then we won't be able to stop the selected service.
//
Err = GetLastError();
StringCchCopy(DisplayName, SIZECHARS(DisplayName), pDependentServiceList[i].lpServiceName);
break;
}
if (!ControlService(hService,
SERVICE_CONTROL_STOP,
&ServiceStatus
)) {
Err = GetLastError();
StringCchCopy(DisplayName, SIZECHARS(DisplayName), pDependentServiceList[i].lpServiceName);
CloseServiceHandle(hService);
break;
}
//
// Wait for the service to actually stop.
//
if (!pLegacyDriverCheckServiceStatus(hService,
&ServiceStatus,
STOP_LEGACY_DEVICE
)) {
Err = GetLastError();
StringCchCopy(DisplayName, SIZECHARS(DisplayName), pDependentServiceList[i].lpServiceName);
CloseServiceHandle(hService);
break;
}
CloseServiceHandle(hService);
}
}
//
// Only attempt to stop the selected service if all of the dependent
// services were stoped.
//
if (Err == ERROR_SUCCESS) {
//
// Tell the service to stop.
//
if (!ControlService(lpi->hService,
SERVICE_CONTROL_STOP,
&lpi->ServiceStatus)) {
Err = GetLastError();
StringCchCopy(DisplayName, SIZECHARS(DisplayName), lpi->DisplayName);
} else {
//
// Wait for the service to stop.
//
if (!pLegacyDriverCheckServiceStatus(lpi->hService,
&lpi->ServiceStatus,
STOP_LEGACY_DEVICE
)) {
Err = GetLastError();
StringCchCopy(DisplayName, SIZECHARS(DisplayName), lpi->DisplayName);
}
}
}
if (Err != ERROR_SUCCESS) {
pLegacyDriverDisplayErrorMsgBox(hDlg,
DisplayName,
IDS_SVC_STOP_ERROR,
Err
);
}
//
// Repaint the status part
//
pLegacyDriverSetPropertyPageState(hDlg, lpi, FALSE);
}
}except (EXCEPTION_EXECUTE_HANDLER) {
pDependentServiceList = pDependentServiceList;
}
if (pDependentServiceList) {
free(pDependentServiceList);
}
SetCursor(hOldCursor);
return;
}
PLEGACY_PAGE_INFO
LegacyDriver_CreatePageInfo(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData)
{
PLEGACY_PAGE_INFO lpi = (PLEGACY_PAGE_INFO) MyMalloc(sizeof(LEGACY_PAGE_INFO));
if (!lpi) {
return NULL;
}
lpi->DeviceInfoSet = DeviceInfoSet;
lpi->DeviceInfoData = DeviceInfoData;
return lpi;
}
VOID
LegacyDriver_OnApply(
IN HWND hDlg,
IN DWORD StartType
)
{
PLEGACY_PAGE_INFO lpi;
SC_LOCK sclLock = NULL;
USHORT uCount = 0;
LPQUERY_SERVICE_CONFIG lpqscBuf = NULL;
LPQUERY_SERVICE_CONFIG lpqscTmp = NULL;
DWORD dwBytesNeeded;
//
// Retrieve the device data structure first
//
lpi = (PLEGACY_PAGE_INFO)GetWindowLongPtr(hDlg, DWLP_USER);
try {
//
// Decide if we need to make any changes
//
if ((StartType == lpi->dwStartType) &&
(StartType != SERVICE_DEMAND_START)) {
goto clean0;
}
//
// I guess we need to make some changes here and there...
// Get the database lock first.
//
do {
sclLock = LockServiceDatabase(lpi->hSCManager);
if (sclLock == NULL) {
//
// If there is another error then the database locked by
// another process, bail out
//
if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED) {
goto clean0;
} else {
//
// (Busy) wait and try again
//
Sleep (1000 * WAIT_TIME_SLOT);
uCount++;
}
}
} while ((uCount < TRIES_COUNT) && (sclLock == NULL));
if (sclLock == NULL) {
//
// Bail out now, we waited enough
//
goto clean0;
}
//
// I have the lock. Hurry and query, then change the config
//
//
// Now, attempt to get the configuration
//
if ((lpqscBuf = (LPQUERY_SERVICE_CONFIG)malloc(SERVICE_BUFFER_SIZE)) == NULL) {
//
// We're out of here
//
goto clean0;
}
if (!QueryServiceConfig(lpi->hService,
lpqscBuf,
SERVICE_BUFFER_SIZE,
&dwBytesNeeded
)) {
//
// Try again with a new buffer
//
if ((lpqscTmp = realloc(lpqscBuf, dwBytesNeeded)) != NULL) {
//
// Make sure the realloc doesn't leak...
//
lpqscBuf = lpqscTmp;
}
else {
//
// We're out of here
//
goto clean0;
}
if (!QueryServiceConfig(lpi->hService,
lpqscBuf,
SERVICE_BUFFER_SIZE,
&dwBytesNeeded
)) {
goto clean0;
}
}
//
// Change tye service type (we needed the service name, too,
// that's why we're querying it first)
//
if (ChangeServiceConfig(lpi->hService,
SERVICE_NO_CHANGE,
StartType,
SERVICE_NO_CHANGE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL)) {
//
// We succesfully changed the status.
// Reflect in our page display
//
lpi->dwStartType = StartType;
}
//
// Unlock the database
//
if (sclLock) {
UnlockServiceDatabase(sclLock);
sclLock = NULL;
}
//
// We want to see something different on apply, so repaint
// the whole stuff
//
pLegacyDriverSetPropertyPageState(hDlg,
lpi,
FALSE); // if we managed to apply some changes
// we are not read-only
clean0:
if (sclLock) {
UnlockServiceDatabase(sclLock);
sclLock = NULL;
}
if (lpqscBuf) {
free(lpqscBuf);
}
} except (EXCEPTION_EXECUTE_HANDLER) {
lpi = lpi;
}
return;
}
BOOL
LegacyDriver_OnInitDialog(
HWND hDlg,
HWND FocusHwnd,
LPARAM lParam
)
{
PLEGACY_PAGE_INFO lpi = (PLEGACY_PAGE_INFO) GetWindowLongPtr(hDlg, DWLP_USER);
BOOL ReadOnly = FALSE;
HICON ClassIcon;
HICON OldIcon;
TCHAR DeviceDescription[MAX_DEVICE_ID_LEN];
TCHAR DriverName[MAX_PATH];
TCHAR StartupType[MAX_PATH];
DWORD dwBytesNeeded;
LPQUERY_SERVICE_CONFIG lpqscBuf = NULL;
LPQUERY_SERVICE_CONFIG lpqscTmp = NULL;
DWORD_PTR index;
HWND hCombo;
UNREFERENCED_PARAMETER(FocusHwnd);
lpi = (PLEGACY_PAGE_INFO) ((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (ULONG_PTR)lpi);
//
// First, open the Service Control Manager
//
lpi->hSCManager = OpenSCManager(NULL,
NULL,
GENERIC_WRITE | GENERIC_READ | GENERIC_EXECUTE);
if (!lpi->hSCManager && (GetLastError() == ERROR_ACCESS_DENIED)) {
//
// This is not fatal, attempt to open the database only
// for read
//
ReadOnly = FALSE;
lpi->hSCManager = OpenSCManager(NULL,
NULL,
GENERIC_READ);
if (!lpi->hSCManager) {
//
// This is fatal
//
lpi->hSCManager = NULL;
}
}
//
// Now, get the service name
//
if (!SetupDiGetDeviceRegistryProperty(lpi->DeviceInfoSet,
lpi->DeviceInfoData,
SPDRP_SERVICE,
NULL,
(PBYTE)lpi->ServiceName,
sizeof(lpi->ServiceName),
NULL)
) {
LoadString(MyModuleHandle, IDS_UNKNOWN, lpi->ServiceName, SIZECHARS(lpi->ServiceName));
ReadOnly = TRUE;
goto clean0;
}
//
// Now we have a service name, try to open its handle
//
if (!ReadOnly) {
lpi->hService = OpenService(lpi->hSCManager,
lpi->ServiceName,
GENERIC_WRITE | GENERIC_READ |
GENERIC_EXECUTE);
if (!lpi->hService) {
//
// OK, let them try again
//
ReadOnly = TRUE;
}
}
if (ReadOnly) {
lpi->hService = OpenService(lpi->hSCManager,
lpi->ServiceName,
GENERIC_READ);
if (!lpi->hService) {
//
// Sorry, this is fatal
//
ReadOnly = TRUE;
goto clean0;
}
}
//
// Now, attempt to get the configuration
//
lpqscBuf = (LPQUERY_SERVICE_CONFIG)malloc(SERVICE_BUFFER_SIZE);
if (!lpqscBuf) {
ReadOnly = TRUE;
goto clean0;
}
if (!QueryServiceConfig(lpi->hService,
lpqscBuf,
SERVICE_BUFFER_SIZE,
&dwBytesNeeded
)) {
//
// Try again with a new buffer
//
if ((lpqscTmp = realloc(lpqscBuf, dwBytesNeeded)) != NULL) {
//
// Make sure the realloc didn't leak...
//
lpqscBuf = lpqscTmp;
}
else {
//
// We're out of here
//
ReadOnly = TRUE;
goto clean0;
}
if (!QueryServiceConfig(lpi->hService,
lpqscBuf,
SERVICE_BUFFER_SIZE,
&dwBytesNeeded
)) {
ReadOnly = TRUE;
goto clean0;
}
}
//
// We have the buffer now, get the start type from it
//
lpi->dwStartType = lpqscBuf->dwStartType;
if (!ControlService(lpi->hService,
SERVICE_CONTROL_INTERROGATE,
&lpi->ServiceStatus)) {
DWORD Err = GetLastError();
//
// If ControlService failed with one of the following errors then it is OK
// and the ServiceStatus was still filled in.
//
if ((Err != NO_ERROR) &&
(Err != ERROR_SERVICE_NOT_ACTIVE)) {
//
// Bail out,
//
ReadOnly = TRUE;
goto clean0;
}
}
//
// Add the startup types to the combo box
//
hCombo = GetDlgItem(hDlg, IDC_COMBO_STARTUP_TYPE);
LoadString(MyModuleHandle, IDS_SERVICE_STARTUP_AUTOMATIC, StartupType, SIZECHARS(StartupType));
index = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)StartupType);
SendMessage(hCombo, CB_SETITEMDATA, index, (LPARAM)SERVICE_AUTO_START);
LoadString(MyModuleHandle, IDS_SERVICE_STARTUP_BOOT, StartupType, SIZECHARS(StartupType));
index = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)StartupType);
SendMessage(hCombo, CB_SETITEMDATA, index, (LPARAM)SERVICE_BOOT_START);
LoadString(MyModuleHandle, IDS_SERVICE_STARTUP_DEMAND, StartupType, SIZECHARS(StartupType));
index = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)StartupType);
SendMessage(hCombo, CB_SETITEMDATA, index, (LPARAM)SERVICE_DEMAND_START);
LoadString(MyModuleHandle, IDS_SERVICE_STARTUP_SYSTEM, StartupType, SIZECHARS(StartupType));
index = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)StartupType);
SendMessage(hCombo, CB_SETITEMDATA, index, (LPARAM)SERVICE_SYSTEM_START);
LoadString(MyModuleHandle, IDS_SERVICE_STARTUP_DISABLED, StartupType, SIZECHARS(StartupType));
index = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)StartupType);
SendMessage(hCombo, CB_SETITEMDATA, index, (LPARAM)SERVICE_DISABLED);
clean0:
//
// Now draw the interface: first the icon
//
if (SetupDiLoadClassIcon(&lpi->DeviceInfoData->ClassGuid, &ClassIcon, NULL)) {
OldIcon = (HICON)SendDlgItemMessage(hDlg,
IDC_PROP_LEGACY_ICON,
STM_SETICON,
(WPARAM)ClassIcon,
0);
if (OldIcon) {
DestroyIcon(OldIcon);
}
}
//
// Then the device name
//
if (SetupDiGetDeviceRegistryProperty(lpi->DeviceInfoSet,
lpi->DeviceInfoData,
SPDRP_DEVICEDESC,
NULL,
(PBYTE)DeviceDescription,
MAX_DEVICE_ID_LEN,
NULL)) {
SetDlgItemText(hDlg, IDC_PROP_LEGACY_DESC, DeviceDescription);
}
SetDlgItemText(hDlg, IDC_EDIT_SERVICE_NAME, lpi->ServiceName);
if (lpqscBuf && lpqscBuf->lpDisplayName) {
SetDlgItemText(hDlg, IDC_EDIT_DISPLAY_NAME, lpqscBuf->lpDisplayName);
StringCchCopy(lpi->DisplayName, SIZECHARS(lpi->DisplayName), lpqscBuf->lpDisplayName);
} else {
TCHAR Unknown[MAX_PATH];
LoadString(MyModuleHandle, IDS_UNKNOWN, Unknown, SIZECHARS(Unknown));
SetDlgItemText(hDlg, IDC_EDIT_DISPLAY_NAME, Unknown);
StringCchCopy(lpi->DisplayName, SIZECHARS(lpi->DisplayName), Unknown);
}
pLegacyDriverSetPropertyPageState(hDlg, lpi, ReadOnly);
//
// Show/Gray the details button
//
EnableWindow(GetDlgItem(hDlg, IDC_LEGACY_DETAILS),
(pDriverFilesGetServiceFilePath(lpi->DeviceInfoSet, lpi->DeviceInfoData, DriverName, SIZECHARS(DriverName))));
if (lpqscBuf) {
free(lpqscBuf);
}
return TRUE;
}
void
LegacyDriver_OnCommand(
HWND hDlg,
int ControlId,
HWND ControlHwnd,
UINT NotifyCode
)
{
PLEGACY_PAGE_INFO lpi = (PLEGACY_PAGE_INFO) GetWindowLongPtr(hDlg, DWLP_USER);
UNREFERENCED_PARAMETER(ControlHwnd);
if (NotifyCode == CBN_SELCHANGE) {
PropSheet_Changed(GetParent(hDlg), hDlg);
}
else {
switch (ControlId) {
case IDC_BUTTON_START:
pLegacyDriverOnStart(hDlg);
break;
case IDC_BUTTON_STOP:
pLegacyDriverOnStop(hDlg);
break;
case IDC_LEGACY_DETAILS:
{
DRIVERFILES_INFO dfi;
ZeroMemory(&dfi, sizeof(DRIVERFILES_INFO));
dfi.DeviceInfoSet = lpi->DeviceInfoSet;
dfi.DeviceInfoData = lpi->DeviceInfoData;
DialogBoxParam(MyModuleHandle, MAKEINTRESOURCE(IDD_DRIVERFILES),
hDlg, DriverFiles_DlgProc, (LPARAM)&dfi);
}
break;
default:
break;
}
}
}
BOOL
LegacyDriver_OnNotify(
HWND hDlg,
LPNMHDR NmHdr
)
{
DWORD StartType;
DWORD_PTR Index;
switch (NmHdr->code) {
//
// The user is about to change an up down control
//
case UDN_DELTAPOS:
PropSheet_Changed(GetParent(hDlg), hDlg);
return FALSE;
//
// Sent when the user clicks on Apply OR OK !!
//
case PSN_APPLY:
if (CB_ERR != (Index = SendMessage(GetDlgItem(hDlg, IDC_COMBO_STARTUP_TYPE),
CB_GETCURSEL, 0, 0))) {
StartType = (DWORD)SendMessage(GetDlgItem(hDlg, IDC_COMBO_STARTUP_TYPE), CB_GETITEMDATA, Index, 0);
LegacyDriver_OnApply(hDlg, StartType);
}
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;
default:
return FALSE;
}
}
BOOL
LegacyDriver_OnContextMenu(
HWND HwndControl,
WORD Xpos,
WORD Ypos
)
{
UNREFERENCED_PARAMETER(Xpos);
UNREFERENCED_PARAMETER(Ypos);
WinHelp(HwndControl,
L"devmgr.hlp",
HELP_CONTEXTMENU,
(ULONG_PTR) LegacyDriver_HelpIDs);
return FALSE;
}
void
LegacyDriver_OnHelp(
HWND ParentHwnd,
LPHELPINFO HelpInfo
)
{
UNREFERENCED_PARAMETER(ParentHwnd);
if (HelpInfo->iContextType == HELPINFO_WINDOW) {
WinHelp((HWND) HelpInfo->hItemHandle,
L"devmgr.hlp",
HELP_WM_HELP,
(ULONG_PTR) LegacyDriver_HelpIDs);
}
}
INT_PTR
APIENTRY
LegacyDriver_DlgProc(
IN HWND hDlg,
IN UINT uMessage,
IN WPARAM wParam,
IN LPARAM lParam
)
{
HICON hicon;
switch(uMessage) {
case WM_COMMAND:
LegacyDriver_OnCommand(hDlg, (int) LOWORD(wParam), (HWND)lParam, (UINT)HIWORD(wParam));
break;
case WM_INITDIALOG:
return LegacyDriver_OnInitDialog(hDlg, (HWND)wParam, lParam);
case WM_NOTIFY:
return LegacyDriver_OnNotify(hDlg, (NMHDR *)lParam);
case WM_CONTEXTMENU:
return LegacyDriver_OnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
case WM_HELP:
LegacyDriver_OnHelp(hDlg, (LPHELPINFO) lParam);
break;
case WM_DESTROY:
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_PROP_LEGACY_ICON, STM_GETICON, 0, 0);
if (hicon) {
DestroyIcon(hicon);
}
}
return FALSE;
}
void
LegacyDriver_DestroyPageInfo(
PLEGACY_PAGE_INFO lpi
)
{
try {
//
// Close the service handle
//
if (lpi->hService) {
CloseServiceHandle(lpi->hService);
}
//
// Close the service manager handle
//
if (lpi->hSCManager) {
CloseServiceHandle(lpi->hSCManager);
}
} except (EXCEPTION_EXECUTE_HANDLER) {
//
// Access a variable, so that the compiler will respect our statement
// order w.r.t. assignment.
//
lpi = lpi;
}
MyFree(lpi);
}
UINT CALLBACK
LegacyDriver_PropPageCallback(
HWND Hwnd,
UINT Message,
LPPROPSHEETPAGE PropSheetPage
)
{
PLEGACY_PAGE_INFO lpi;
UNREFERENCED_PARAMETER(Hwnd);
switch (Message) {
case PSPCB_CREATE:
return TRUE; // return TRUE to continue with creation of page
case PSPCB_RELEASE:
lpi = (PLEGACY_PAGE_INFO) PropSheetPage->lParam;
LegacyDriver_DestroyPageInfo(lpi);
return 0; // return value ignored
default:
break;
}
return TRUE;
}
HPROPSHEETPAGE
LegacyDriver_CreatePropertyPage(
PROPSHEETPAGE * PropSheetPage,
PLEGACY_PAGE_INFO lpi
)
{
//
// Add the Port Settings property page
//
PropSheetPage->dwSize = sizeof(PROPSHEETPAGE);
PropSheetPage->dwFlags = PSP_USECALLBACK;
PropSheetPage->dwFlags = PSP_DEFAULT;
PropSheetPage->hInstance = MyModuleHandle;
PropSheetPage->pszTemplate = MAKEINTRESOURCE(IDD_PROP_LEGACY_SERVICE);
//
// following points to the dlg window proc
//
PropSheetPage->pfnDlgProc = LegacyDriver_DlgProc;
PropSheetPage->lParam = (LPARAM)lpi;
//
// Following points to the control callback of the dlg window proc.
// The callback gets called before creation/after destruction of the page
//
PropSheetPage->pfnCallback = LegacyDriver_PropPageCallback;
//
// Allocate the actual page
//
return CreatePropertySheetPage(PropSheetPage);
}
BOOL
LegacyDriverPropPageProvider(
LPVOID Info,
LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc,
LPARAM lParam
)
{
SP_DEVINSTALL_PARAMS DevInstallParams;
PSP_PROPSHEETPAGE_REQUEST PropPageRequest;
PROPSHEETPAGE psp;
HPROPSHEETPAGE hpsp;
PLEGACY_PAGE_INFO lpi;
PropPageRequest = (PSP_PROPSHEETPAGE_REQUEST) Info;
if (PropPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES) {
lpi = LegacyDriver_CreatePageInfo(PropPageRequest->DeviceInfoSet, PropPageRequest->DeviceInfoData);
if (!lpi) {
return FALSE;
}
hpsp = LegacyDriver_CreatePropertyPage(&psp, lpi);
if (!hpsp) {
return FALSE;
}
if (!lpfnAddPropSheetPageProc(hpsp, lParam)) {
DestroyPropertySheetPage(hpsp);
return FALSE;
}
//
// Tell device manager that we will display our own Driver tab for legacy device
//
ZeroMemory(&DevInstallParams, sizeof(DevInstallParams));
DevInstallParams.cbSize = sizeof(DevInstallParams);
SetupDiGetDeviceInstallParams(lpi->DeviceInfoSet, lpi->DeviceInfoData, &DevInstallParams);
DevInstallParams.Flags |= DI_DRIVERPAGE_ADDED;
SetupDiSetDeviceInstallParams(lpi->DeviceInfoSet, lpi->DeviceInfoData, &DevInstallParams);
}
return TRUE;
}