/*++ 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 #include // // 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; iNumDependentServices; 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; ihSCManager, 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; }