|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation
//
// File: finish.c
//
//--------------------------------------------------------------------------
#include "hdwwiz.h"
#include <help.h>
typedef BOOL (*SRSETRESTOREPOINT)( PRESTOREPOINTINFO pRestorePtSpec, PSTATEMGRSTATUS pSMgrStatus );
BOOL DeviceHasResources( DEVINST DeviceInst ) { CONFIGRET ConfigRet; ULONG lcType = NUM_LOG_CONF;
while (lcType--) { ConfigRet = CM_Get_First_Log_Conf_Ex(NULL, DeviceInst, lcType, NULL); if (ConfigRet == CR_SUCCESS) { return TRUE; } }
return FALSE; }
DWORD HdwRemoveDevice( PHARDWAREWIZ HardwareWiz ) { SP_REMOVEDEVICE_PARAMS RemoveDeviceParams; LONG Error = ERROR_SUCCESS;
RemoveDeviceParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); RemoveDeviceParams.ClassInstallHeader.InstallFunction = DIF_REMOVE; RemoveDeviceParams.Scope = DI_REMOVEDEVICE_GLOBAL; RemoveDeviceParams.HwProfile = 0;
if (!SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, (PSP_CLASSINSTALL_HEADER)&RemoveDeviceParams, sizeof(RemoveDeviceParams) ) || !SetupDiCallClassInstaller(DIF_REMOVE, HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData )) { Error = GetLastError(); }
//
// Clear the class install parameters.
//
SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, NULL, 0 );
return Error; }
BOOL GetClassGuidForInf( PTSTR InfFileName, LPGUID ClassGuid ) { TCHAR ClassName[MAX_CLASS_NAME_LEN]; DWORD NumGuids;
if (!SetupDiGetINFClass(InfFileName, ClassGuid, ClassName, SIZECHARS(ClassName), NULL)) { return FALSE; }
if (IsEqualGUID(ClassGuid, &GUID_NULL)) { //
// Then we need to retrieve the GUID associated with the INF's class name.
// (If this class name isn't installed (i.e., has no corresponding GUID),
// of if it matches with multiple GUIDs, then we abort.
//
if (!SetupDiClassGuidsFromName(ClassName, ClassGuid, 1, &NumGuids) || !NumGuids) { return FALSE; } }
return TRUE; }
LONG ClassInstallerInstalls( HWND hwndParent, PHARDWAREWIZ HardwareWiz, HDEVINFO hDeviceInfo, PSP_DEVINFO_DATA DeviceInfoData, BOOL InstallFilesOnly ) { DWORD Err = ERROR_SUCCESS; HSPFILEQ FileQueue = INVALID_HANDLE_VALUE; PVOID MessageHandlerContext = NULL; SP_DEVINSTALL_PARAMS DeviceInstallParams; DWORD ScanResult = 0; RESTOREPOINTINFO RestorePointInfo; STATEMGRSTATUS SMgrStatus; int FileQueueNeedsReboot = 0;
//
// verify with class installer, and class-specific coinstallers
// that the driver is not blacklisted. For DIF_ALLOW_INSTALL we
// accept ERROR_SUCCESS or ERROR_DI_DO_DEFAULT as good return codes.
//
if (!SetupDiCallClassInstaller(DIF_ALLOW_INSTALL, hDeviceInfo, DeviceInfoData ) && (GetLastError() != ERROR_DI_DO_DEFAULT)) {
Err = GetLastError(); goto clean0; }
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (!SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams )) {
Err = GetLastError(); goto clean0; }
FileQueue = SetupOpenFileQueue();
if (FileQueue == INVALID_HANDLE_VALUE) { Err = ERROR_NOT_ENOUGH_MEMORY; goto clean0; }
DeviceInstallParams.Flags |= DI_NOVCP; DeviceInstallParams.FileQueue = FileQueue;
SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams );
//
// Set the SPQ_FLAG_ABORT_IF_UNSIGNED value on the file queue. With this
// flag set setupapi will bail out of the copy if it encounters an unsigned
// file. At that point we will set a system restore point and then
// do the copy. This way the user can back out of an unsigned driver
// install using system restore.
//
// Note that system restore is currently not supported on 64-bit so don't
// bother setting the SPQ_FLAG_ABORT_IF_UNSIGNED.
//
#ifndef _WIN64
SetupSetFileQueueFlags(FileQueue, SPQ_FLAG_ABORT_IF_UNSIGNED, SPQ_FLAG_ABORT_IF_UNSIGNED ); #endif
//
// Install the files first in one shot.
// This allows new coinstallers to run during the install.
//
if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, hDeviceInfo, DeviceInfoData )) {
Err = GetLastError(); goto clean0; }
//
// Since we created our own FileQueue then we need to
// scan and possibly commit the queue and prune copies as needed.
//
if (!SetupScanFileQueue(FileQueue, SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE, hwndParent, NULL, NULL, &ScanResult )) {
//
// If the API failed then set the ScanResult to 0 (failure).
//
ScanResult = 0; }
//
// If the ScanResult is 1 then that means that all of the files are present
// and that there are no rename or delete operations are left in the copy
// queue. This means we can skip the file queue commit.
//
// If the ScanResult is 0 then there are file copy operations that are needed.
// If the ScanResult is 2 then there are delete, rename or backup operations
// that are needed.
//
if (ScanResult != 1) { MessageHandlerContext = SetupInitDefaultQueueCallbackEx( hwndParent, (DeviceInstallParams.Flags & DI_QUIETINSTALL) ? INVALID_HANDLE_VALUE : NULL, 0, 0, NULL );
if (MessageHandlerContext) { //
// Commit the file queue.
//
if (!SetupCommitFileQueue(hwndParent, FileQueue, SetupDefaultQueueCallback, MessageHandlerContext )) {
Err = GetLastError();
if (Err == ERROR_SET_SYSTEM_RESTORE_POINT) { SetupTermDefaultQueueCallback(MessageHandlerContext);
MessageHandlerContext = SetupInitDefaultQueueCallbackEx( hwndParent, (DeviceInstallParams.Flags & DI_QUIETINSTALL) ? INVALID_HANDLE_VALUE : NULL, 0, 0, NULL );
if (MessageHandlerContext) { HMODULE hSrClientDll = NULL; SRSETRESTOREPOINT pfnSrSetRestorePoint = NULL;
if ((hSrClientDll = LoadLibrary(TEXT("srclient.dll"))) != NULL) { if ((pfnSrSetRestorePoint = (SRSETRESTOREPOINT)GetProcAddress(hSrClientDll, "SRSetRestorePointW" )) != NULL) { //
// Set the system restore point.
//
RestorePointInfo.dwEventType = BEGIN_SYSTEM_CHANGE; RestorePointInfo.dwRestorePtType = DEVICE_DRIVER_INSTALL; RestorePointInfo.llSequenceNumber = 0; if (!LoadString(hHdwWiz, IDS_NEW_SETRESTOREPOINT, (LPWSTR)RestorePointInfo.szDescription, SIZECHARS(RestorePointInfo.szDescription) )) { RestorePointInfo.szDescription[0] = TEXT('\0'); } pfnSrSetRestorePoint(&RestorePointInfo, &SMgrStatus); }
FreeLibrary(hSrClientDll); }
//
// Clear the SPQ_FLAG_ABORT_IF_UNSIGNED flag so the file
// queue will be commited the next time.
//
SetupSetFileQueueFlags(FileQueue, SPQ_FLAG_ABORT_IF_UNSIGNED, 0 );
//
// Now that we have set the restore point and cleared the
// SPQ_FLAG_ABORT_IF_UNSIGNED flag from the file queue we
// can commit the queue again.
//
if (!SetupCommitFileQueue(hwndParent, FileQueue, SetupDefaultQueueCallback, MessageHandlerContext )) { Err = GetLastError(); goto clean0; } else { //
// We were successful in commiting the file queue, so check
// to see whether a reboot is required as a result of committing
// the queue (i.e. because files were in use, or the INF requested
// a reboot).
//
FileQueueNeedsReboot = SetupPromptReboot(FileQueue, NULL, TRUE); } } } else { goto clean0; } } else { //
// We were successful in commiting the file queue, so check
// to see whether a reboot is required as a result of committing
// the queue (i.e. because files were in use, or the INF requested
// a reboot).
//
FileQueueNeedsReboot = SetupPromptReboot(FileQueue, NULL, TRUE); } } }
//
// If we were only copiny files then we are done!
//
if (InstallFilesOnly) { Err = ERROR_SUCCESS; goto clean0; }
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParams(hDeviceInfo, DeviceInfoData, &DeviceInstallParams )) { DWORD FileQueueFlags; //
// If we didn't copy any files when commiting the file queue then the
// SPQ_FLAG_FILES_MODIFIED flag will NOT be set. In this case set
// the DI_FLAGSEX_RESTART_DEVICE_ONLY flag so that we only stop/start
// this single device. By default setupapi will stop/start this device
// as well as any other device that was using the same driver/filter
// that this device is using.
//
if (SetupGetFileQueueFlags(FileQueue, &FileQueueFlags) && !(FileQueueFlags & SPQ_FLAG_FILES_MODIFIED)) { DeviceInstallParams.FlagsEx |= DI_FLAGSEX_RESTART_DEVICE_ONLY; }
//
// Set the DI_NOFILECOPY flag since we already copied the files during
// the DIF_INSTALLDEVICEFILES, so we don't need to copy them again during
// the DIF_INSTALLDEVICE.
//
DeviceInstallParams.Flags |= DI_NOFILECOPY; SetupDiSetDeviceInstallParams(hDeviceInfo, DeviceInfoData, &DeviceInstallParams ); }
//
// Register any device-specific co-installers for this device,
//
if (!SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS, hDeviceInfo, DeviceInfoData )) {
Err = GetLastError(); goto clean0; }
//
// install any INF/class installer-specified interfaces.
// and then finally the real "InstallDevice"!
//
if (!SetupDiCallClassInstaller(DIF_INSTALLINTERFACES, hDeviceInfo, DeviceInfoData ) || !SetupDiCallClassInstaller(DIF_INSTALLDEVICE, hDeviceInfo, DeviceInfoData )) {
Err = GetLastError(); goto clean0; }
Err = ERROR_SUCCESS;
clean0:
if (MessageHandlerContext) { SetupTermDefaultQueueCallback(MessageHandlerContext); }
//
// If the file queue said that a reboot was needed then set the
// DI_NEEDRESTART flag.
//
if (FileQueueNeedsReboot) { DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams )) {
DeviceInstallParams.Flags |= DI_NEEDRESTART;
SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams ); } }
if (FileQueue != INVALID_HANDLE_VALUE) { //
// If we have a valid file queue handle and there was an error during
// the device install then we want to delete any new INFs that were
// copied into the INF directory. We do this under the assumption that
// since there was an error during the install these INFs must be bad.
//
if (Err != ERROR_SUCCESS) { SetupUninstallNewlyCopiedInfs(FileQueue, 0, NULL ); }
//
// Clear out our file queue from the device install params. We need
// to do this or else SetupCloseFileQueue will fail because it will
// still have a ref count.
//
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams )) {
DeviceInstallParams.Flags &= ~DI_NOVCP; DeviceInstallParams.FileQueue = INVALID_HANDLE_VALUE;
SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams ); }
SetupCloseFileQueue(FileQueue); }
return Err; }
//
// invokable only from finish page!
//
DWORD InstallDev( HWND hwndParent, PHARDWAREWIZ HardwareWiz ) { SP_DRVINFO_DATA DriverInfoData; SP_DRVINFO_DETAIL_DATA DriverInfoDetailData; SP_DEVINSTALL_PARAMS DeviceInstallParams; TCHAR ClassGuidString[MAX_GUID_STRING_LEN]; GUID ClassGuidInf; LPGUID ClassGuid; int ClassGuidNum; DWORD Error = ERROR_SUCCESS; BOOL IgnoreRebootFlags = FALSE; TCHAR Buffer[MAX_PATH]; ULONG DevNodeStatus = 0, Problem = 0;
if (!HardwareWiz->ClassGuidSelected) { HardwareWiz->ClassGuidSelected = (LPGUID)&GUID_NULL; }
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA); if (SetupDiGetSelectedDriver(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DriverInfoData )) { //
// Get details on this driver node, so that we can examine the INF that this
// node came from.
//
DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); if (!SetupDiGetDriverInfoDetail(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DriverInfoData, &DriverInfoDetailData, sizeof(DriverInfoDetailData), NULL )) { Error = GetLastError(); if (Error != ERROR_INSUFFICIENT_BUFFER) { goto clean0; } }
//
// Verif that the class is installed, if its not then
// attempt to install it.
//
HdwBuildClassInfoList(HardwareWiz, 0 );
//
// fetch classguid from inf, (It may be different than what we already
// have in class guid selected).
//
if (!GetClassGuidForInf(DriverInfoDetailData.InfFileName, &ClassGuidInf)) { ClassGuidInf = *HardwareWiz->ClassGuidSelected; }
if (IsEqualGUID(&ClassGuidInf, &GUID_NULL)) {
ClassGuidInf = GUID_DEVCLASS_UNKNOWN; }
//
// if the ClassGuidInf wasn't found then this class hasn't been installed yet.
// -install the class installer now.
//
ClassGuid = HardwareWiz->ClassGuidList; ClassGuidNum = HardwareWiz->ClassGuidNum; while (ClassGuidNum--) { if (IsEqualGUID(ClassGuid, &ClassGuidInf)) { break; }
ClassGuid++; }
if (ClassGuidNum < 0 && !SetupDiInstallClass(hwndParent, DriverInfoDetailData.InfFileName, 0, NULL )) { Error = GetLastError(); goto clean0; }
//
// Now make sure that the class of this device is the same as the class
// of the selected driver node.
//
if (!IsEqualGUID(&ClassGuidInf, HardwareWiz->ClassGuidSelected)) { pSetupStringFromGuid(&ClassGuidInf, ClassGuidString, SIZECHARS(ClassGuidString) );
SetupDiSetDeviceRegistryProperty(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, SPDRP_CLASSGUID, (PBYTE)ClassGuidString, sizeof(ClassGuidString) ); } }
//
// No selected driver, and no associated class--use "Unknown" class.
//
else {
//
// If the devnode is currently running 'raw', then remember this
// fact so that we don't require a reboot later (NULL driver installation
// isn't going to change anything).
//
if (CM_Get_DevNode_Status(&DevNodeStatus, &Problem, HardwareWiz->DeviceInfoData.DevInst, 0) == CR_SUCCESS) { if (!SetupDiGetDeviceRegistryProperty(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, SPDRP_SERVICE, NULL, // regdatatype
(PVOID)Buffer, sizeof(Buffer), NULL )) { *Buffer = TEXT('\0'); }
if ((DevNodeStatus & DN_STARTED) && (*Buffer == TEXT('\0'))) { IgnoreRebootFlags = TRUE; } }
if (IsEqualGUID(HardwareWiz->ClassGuidSelected, &GUID_NULL)) {
pSetupStringFromGuid(&GUID_DEVCLASS_UNKNOWN, ClassGuidString, SIZECHARS(ClassGuidString) );
SetupDiSetDeviceRegistryProperty(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, SPDRP_CLASSGUID, (PBYTE)ClassGuidString, sizeof(ClassGuidString) ); } }
//
// since this is a legacy install, set the manually installed bit if the
// driver that was selected was not a CopyFilesOnly (PnP) driver.
//
if (!HardwareWiz->CopyFilesOnly) { ULONG Len; CONFIGRET ConfigRet; ULONG ConfigFlag;
Len = sizeof(ConfigFlag); ConfigRet = CM_Get_DevNode_Registry_Property_Ex(HardwareWiz->DeviceInfoData.DevInst, CM_DRP_CONFIGFLAGS, NULL, (PVOID)&ConfigFlag, &Len, 0, NULL ); if (ConfigRet != CR_SUCCESS) { ConfigFlag = 0; }
ConfigFlag |= CONFIGFLAG_MANUAL_INSTALL; CM_Set_DevNode_Registry_Property_Ex(HardwareWiz->DeviceInfoData.DevInst, CM_DRP_CONFIGFLAGS, (PVOID)&ConfigFlag, sizeof(ConfigFlag), 0, NULL ); }
Error = ClassInstallerInstalls(hwndParent, HardwareWiz, HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, HardwareWiz->CopyFilesOnly );
if (Error != ERROR_SUCCESS) { //
// we Have an install error, including a user cancel.
// Install the null driver.
//
if (SetupDiSetSelectedDriver(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, NULL )) {
if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams )) { DeviceInstallParams.FlagsEx |= DI_FLAGSEX_SETFAILEDINSTALL; SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams ); }
SetupDiInstallDevice(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData); }
goto clean0; }
//
// Fetch the latest DeviceInstallParams for the restart bits.
//
if (!IgnoreRebootFlags) { DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DeviceInstallParams )) { if (DeviceInstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) { HardwareWiz->Reboot |= DI_NEEDREBOOT; } } }
clean0:
return Error; }
BOOL CALLBACK AddPropSheetPageProc( IN HPROPSHEETPAGE hpage, IN LPARAM lParam ) { *((HPROPSHEETPAGE *)lParam) = hpage; return TRUE; }
void DisplayResource( PHARDWAREWIZ HardwareWiz, HWND hWndParent, BOOL NeedsForcedConfig ) { HINSTANCE hLib; PROPSHEETHEADER psh; HPROPSHEETPAGE hpsPages[1]; SP_PROPSHEETPAGE_REQUEST PropPageRequest; LPFNADDPROPSHEETPAGES ExtensionPropSheetPage = NULL; SP_DEVINSTALL_PARAMS DevInstallParams;
//
// Now get the resource selection page from setupapi.dll
//
hLib = GetModuleHandle(TEXT("setupapi.dll")); if (hLib) { ExtensionPropSheetPage = (LPFNADDPROPSHEETPAGES)GetProcAddress(hLib, "ExtensionPropSheetPageProc"); }
if (!ExtensionPropSheetPage) { return; }
PropPageRequest.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST); PropPageRequest.PageRequested = SPPSR_SELECT_DEVICE_RESOURCES; PropPageRequest.DeviceInfoSet = HardwareWiz->hDeviceInfo; PropPageRequest.DeviceInfoData = &HardwareWiz->DeviceInfoData;
if (!ExtensionPropSheetPage(&PropPageRequest, AddPropSheetPageProc, (LONG_PTR)hpsPages )) { // warning ?
return; }
//
// create the property sheet
//
psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW; psh.hwndParent = hWndParent; psh.hInstance = hHdwWiz; psh.pszIcon = NULL;
psh.pszCaption = (LPTSTR)IDS_ADDNEWDEVICE;
psh.nPages = 1; psh.phpage = hpsPages; psh.nStartPage = 0; psh.pfnCallback = NULL;
//
// Clear the Propchange pending bit in the DeviceInstall params.
//
DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DevInstallParams )) { DevInstallParams.FlagsEx &= ~DI_FLAGSEX_PROPCHANGE_PENDING; SetupDiSetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DevInstallParams ); }
//
// Set the CONFIGFLAG_NEEDS_FORCED_CONFIG if this device needs a forced config.
//
if (NeedsForcedConfig) {
DWORD ConfigFlags = 0; ULONG ulSize = sizeof(ConfigFlags);
if (CM_Get_DevInst_Registry_Property(HardwareWiz->DeviceInfoData.DevInst, CM_DRP_CONFIGFLAGS, NULL, (LPBYTE)&ConfigFlags, &ulSize, 0) != CR_SUCCESS) { ConfigFlags = 0; }
ConfigFlags |= CONFIGFLAG_NEEDS_FORCED_CONFIG;
CM_Set_DevInst_Registry_Property(HardwareWiz->DeviceInfoData.DevInst, CM_DRP_CONFIGFLAGS, (LPBYTE)&ConfigFlags, sizeof(ConfigFlags), 0 ); }
if (PropertySheet(&psh) == -1) { DestroyPropertySheetPage(hpsPages[0]); }
//
// If a PropChange occurred invoke the DIF_PROPERTYCHANGE
//
if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DevInstallParams )) { if (DevInstallParams.FlagsEx & DI_FLAGSEX_PROPCHANGE_PENDING) { SP_PROPCHANGE_PARAMS PropChangeParams;
PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; PropChangeParams.Scope = DICS_FLAG_GLOBAL; PropChangeParams.HwProfile = 0;
if (SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, (PSP_CLASSINSTALL_HEADER)&PropChangeParams, sizeof(PropChangeParams) )) { SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData ); }
//
// Clear the class install parameters.
//
SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, NULL, 0 ); } }
//
// See if we need to reboot
//
if (SetupDiGetDeviceInstallParams(HardwareWiz->hDeviceInfo, &HardwareWiz->DeviceInfoData, &DevInstallParams )) { if (DevInstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)) { HardwareWiz->Reboot |= DI_NEEDREBOOT; } }
//
// Clear the CONFIGFLAG_NEEDS_FORCED_CONFIG if this device needs a forced config.
//
if (NeedsForcedConfig) {
DWORD ConfigFlags = 0; ULONG ulSize = sizeof(ConfigFlags);
if (CM_Get_DevInst_Registry_Property(HardwareWiz->DeviceInfoData.DevInst, CM_DRP_CONFIGFLAGS, NULL, (LPBYTE)&ConfigFlags, &ulSize, 0) == CR_SUCCESS) {
ConfigFlags &= ~CONFIGFLAG_NEEDS_FORCED_CONFIG;
CM_Set_DevInst_Registry_Property(HardwareWiz->DeviceInfoData.DevInst, CM_DRP_CONFIGFLAGS, (LPBYTE)&ConfigFlags, sizeof(ConfigFlags), 0 ); } }
return; }
INT_PTR CALLBACK HdwInstallDevDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam ) { HWND hwndParentDlg = GetParent(hDlg); PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER); HICON hicon;
UNREFERENCED_PARAMETER(wParam);
switch (wMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam; HardwareWiz = (PHARDWAREWIZ)lppsp->lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
break; }
case WM_DESTROY: hicon = (HICON)SendDlgItemMessage(hDlg,IDC_CLASSICON,STM_GETICON,0,0); if (hicon) { DestroyIcon(hicon); } break;
case WUM_DOINSTALL:
// do the Install
HardwareWiz->LastError = InstallDev(hDlg, HardwareWiz); HardwareWiz->InstallPending = FALSE; HardwareWiz->CurrCursor = NULL; PropSheet_PressButton(hwndParentDlg, PSBTN_NEXT); break;
case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_SETACTIVE: { HardwareWiz->PrevPage = IDD_ADDDEVICE_INSTALLDEV;
//
// This is an intermediary status page, no buttons needed.
// Set the device description
// Set the class Icon
//
PropSheet_SetWizButtons(hwndParentDlg, 0); EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), FALSE);
SetDriverDescription(hDlg, IDC_HDW_DESCRIPTION, HardwareWiz);
if (SetupDiLoadClassIcon(HardwareWiz->ClassGuidSelected, &hicon, NULL)) { hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L); if (hicon) { DestroyIcon(hicon); } }
HardwareWiz->CurrCursor = HardwareWiz->IdcWait; SetCursor(HardwareWiz->CurrCursor);
//
// Post ourselves a msg, to do the actual install, this allows this
// page to show itself while the install is actually occuring.
//
HardwareWiz->InstallPending = TRUE;
PostMessage(hDlg, WUM_DOINSTALL, 0, 0);
break; }
case PSN_WIZNEXT:
//
// Add the FinishInstall Page and jump to it if the installation succeded.
//
if (HardwareWiz->LastError == ERROR_SUCCESS) {
HardwareWiz->WizExtFinishInstall.hPropSheet = CreateWizExtPage(IDD_WIZARDEXT_FINISHINSTALL, WizExtFinishInstallDlgProc, HardwareWiz );
if (HardwareWiz->WizExtFinishInstall.hPropSheet) { PropSheet_AddPage(hwndParentDlg, HardwareWiz->WizExtFinishInstall.hPropSheet); }
SetDlgMsgResult(hDlg, wMsg, IDD_WIZARDEXT_FINISHINSTALL);
//
// There was an error during the installation so just jump to our finish page.
//
} else {
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_FINISH); } break; } break;
case WM_SETCURSOR: if (HardwareWiz->CurrCursor) { SetCursor(HardwareWiz->CurrCursor); break; }
// fall thru to return(FALSE);
default: return(FALSE); }
return(TRUE); }
void ShowInstallSummary( HWND hDlg, PHARDWAREWIZ HardwareWiz ) { LONG Error; ULONG Problem, DevNodeStatus; BOOL HasResources; HWND hwndParentDlg = GetParent(hDlg); PTCHAR ErrorMsg, ProblemText; TCHAR TextBuffer[MAX_PATH*4];
Problem = 0; *TextBuffer = TEXT('\0');
Error = HardwareWiz->LastError;
//
// Installation was canceled
//
if (Error == ERROR_CANCELLED) { PropSheet_PressButton(hwndParentDlg, PSBTN_CANCEL); return; }
//
// Installation failed
//
if (Error != ERROR_SUCCESS) { HardwareWiz->Installed = FALSE; LoadText(TextBuffer, SIZECHARS(TextBuffer), IDS_HDW_ERRORFIN1, IDS_HDW_ERRORFIN1);
//
// Add on a description of the error to the end of the text buffer.
// NOTE: if the description of the error does not fit in our huge text
// buffer then it also won't fit in the dialog, however we should display
// as much as we can to the user. The full error will be logged in
// setupapi.log so PSS can still figure out what happened.
//
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, HRESULT_FROM_SETUPAPI(Error), 0, (LPTSTR)&ErrorMsg, 0, NULL)) {
StringCchCat(TextBuffer, SIZECHARS(TextBuffer), TEXT("\n\n")); StringCchCat(TextBuffer, SIZECHARS(TextBuffer), ErrorMsg); LocalFree(ErrorMsg); }
SetDlgItemText(hDlg, IDC_HDW_TEXT, TextBuffer); }
//
// No errors installing the drivers for this device
//
else { //
// Check to see if the device itself has any problems
//
Error = CM_Get_DevNode_Status(&DevNodeStatus, &Problem, HardwareWiz->DeviceInfoData.DevInst, 0 ); if (Error != CR_SUCCESS) {
//
// For some reason, we couldn't retrieve the devnode's status.
// Default status and problem values to zero.
//
DevNodeStatus = Problem = 0; }
//
// make sure the reboot flags\Problem are set correctly
//
if (HardwareWiz->CopyFilesOnly || HardwareWiz->Reboot || Problem == CM_PROB_NEED_RESTART) { if (Problem != CM_PROB_PARTIAL_LOG_CONF) { Problem = CM_PROB_NEED_RESTART; }
HardwareWiz->Reboot |= DI_NEEDREBOOT; }
HardwareWiz->Installed = TRUE; HasResources = DeviceHasResources(HardwareWiz->DeviceInfoData.DevInst);
//
// The device has a problem
//
if ((Error != CR_SUCCESS) || Problem) { if (Problem == CM_PROB_NEED_RESTART) { if (HasResources && !HardwareWiz->CopyFilesOnly) { LoadText(TextBuffer, SIZECHARS(TextBuffer), IDS_HDW_NORMAL_LEGACY_FINISH1, IDS_HDW_NORMAL_LEGACY_FINISH1); } else { LoadText(TextBuffer, SIZECHARS(TextBuffer), IDS_HDW_NORMALFINISH1, IDS_HDW_NORMALFINISH1); }
LoadText(TextBuffer, SIZECHARS(TextBuffer), IDS_NEEDREBOOT, IDS_NEEDREBOOT); }
else { LoadText(TextBuffer, SIZECHARS(TextBuffer), IDS_INSTALL_PROBLEM, IDS_INSTALL_PROBLEM);
//
// If the device has a problem then get the problem text from
// device manager. It the TextBuffer is too small then the
// user will just see a truncated error message, so it is
// OK if StringCchCat fails.
//
if (Problem) { ProblemText = DeviceProblemText(HardwareWiz->DeviceInfoData.DevInst, 0, Problem );
if (ProblemText) { StringCchCat(TextBuffer, SIZECHARS(TextBuffer), TEXT("\n\n")); StringCchCat(TextBuffer, SIZECHARS(TextBuffer), ProblemText); LocalFree(ProblemText); } } }
//
// Show the resource button if the device has resources and it has a problem
//
if (HasResources || (Problem && !(HardwareWiz->Reboot && (DevNodeStatus & DN_STARTED))) || (Problem == CM_PROB_PARTIAL_LOG_CONF)) { ShowWindow(GetDlgItem(hDlg, IDC_HDW_DISPLAYRESOURCE), SW_SHOW); } }
//
// Installation was sucessful and the device does not have any problems
//
else { LoadText(TextBuffer, SIZECHARS(TextBuffer), IDS_HDW_NORMALFINISH1, IDS_HDW_NORMALFINISH1); }
SetDlgItemText(hDlg, IDC_HDW_TEXT, TextBuffer); } }
INT_PTR CALLBACK HdwAddDeviceFinishDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam ) { HICON hicon; PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
UNREFERENCED_PARAMETER(wParam);
switch (wMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam; HardwareWiz = (PHARDWAREWIZ)lppsp->lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz); SetWindowFont(GetDlgItem(hDlg, IDC_HDWNAME), HardwareWiz->hfontTextBigBold, TRUE);
break; }
case WM_DESTROY: hicon = (HICON)SendDlgItemMessage(hDlg,IDC_CLASSICON,STM_GETICON,0,0); if (hicon) { DestroyIcon(hicon); } break;
case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_SETACTIVE: //
// No back button since install is already done.
// set the device description
// Hide Resources button until we know if resources exist or not.
// Set the class Icon
//
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
SetDriverDescription(hDlg, IDC_HDW_DESCRIPTION, HardwareWiz);
ShowWindow(GetDlgItem(hDlg, IDC_HDW_DISPLAYRESOURCE), SW_HIDE);
//
// Set the class Icon
//
if (SetupDiLoadClassIcon(&HardwareWiz->DeviceInfoData.ClassGuid, &hicon, NULL)) {
hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L); if (hicon) {
DestroyIcon(hicon); } }
ShowInstallSummary(hDlg, HardwareWiz); break;
case PSN_RESET: //
// Cancel the install
//
if (HardwareWiz->Registered) { HardwareWiz->Installed = FALSE; } break;
case PSN_WIZFINISH: //
// Pnp Device install only consists of copying files
// when the system does the real install, it will create
// the proper devnode, so remove our temporary devnode.
//
if (HardwareWiz->CopyFilesOnly && HardwareWiz->Registered) { HardwareWiz->Installed = FALSE; break; } break;
case NM_RETURN: case NM_CLICK: DisplayResource(HardwareWiz, GetParent(hDlg), FALSE); break;
} break;
default: return(FALSE); }
return(TRUE); }
INT_PTR CALLBACK WizExtFinishInstallDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam ) { HWND hwndParentDlg = GetParent(hDlg); PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER); int PrevPageId;
UNREFERENCED_PARAMETER(wParam);
switch (wMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam; HardwareWiz = (PHARDWAREWIZ)lppsp->lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz); break; }
case WM_DESTROY: break;
case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_SETACTIVE:
PrevPageId = HardwareWiz->PrevPage; HardwareWiz->PrevPage = IDD_WIZARDEXT_FINISHINSTALL;
if (PrevPageId == IDD_ADDDEVICE_INSTALLDEV) { //
// Moving forward on first page
//
//
// Add ClassWizard Extension pages for FinishInstall
//
AddClassWizExtPages(hwndParentDlg, HardwareWiz, &HardwareWiz->WizExtFinishInstall.DeviceWizardData, DIF_NEWDEVICEWIZARD_FINISHINSTALL );
//
// Add the end page, which is FinishInstall end
//
HardwareWiz->WizExtFinishInstall.hPropSheetEnd = CreateWizExtPage(IDD_WIZARDEXT_FINISHINSTALL_END, WizExtFinishInstallEndDlgProc, HardwareWiz );
if (HardwareWiz->WizExtFinishInstall.hPropSheetEnd) { PropSheet_AddPage(hwndParentDlg, HardwareWiz->WizExtFinishInstall.hPropSheetEnd); } }
//
// We can't go backwards, so always go forward
//
SetDlgMsgResult(hDlg, wMsg, -1); break;
case PSN_WIZNEXT: SetDlgMsgResult(hDlg, wMsg, 0); break; } break;
default: return(FALSE); }
return(TRUE); }
INT_PTR CALLBACK WizExtFinishInstallEndDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam ) { PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER); int PrevPageId;
UNREFERENCED_PARAMETER(wParam);
switch (wMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam; HardwareWiz = (PHARDWAREWIZ)lppsp->lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz); break; }
case WM_DESTROY: break;
case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_SETACTIVE:
PrevPageId = HardwareWiz->PrevPage; HardwareWiz->PrevPage = IDD_WIZARDEXT_FINISHINSTALL_END;
//
// We can't go backwards, so always go forward
//
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_FINISH); break;
case PSN_WIZBACK: case PSN_WIZNEXT: SetDlgMsgResult(hDlg, wMsg, 0); break; } break;
default: return(FALSE); }
return(TRUE); }
|