//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation // // File: finish.c // //-------------------------------------------------------------------------- #include "hdwwiz.h" #include 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); }