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
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;
|
|
}
|
|
|