fixed refreshing the advanced properties on device changes Modified: trunk/reactos/lib/devmgr/advprop.c _____
Modified: trunk/reactos/lib/devmgr/advprop.c --- trunk/reactos/lib/devmgr/advprop.c 2005-12-01 20:12:00 UTC (rev 19804) +++ trunk/reactos/lib/devmgr/advprop.c 2005-12-01 20:31:49 UTC (rev 19805) @@ -30,6 +30,8 @@
#define NDEBUG #include <debug.h>
+#define DPN_DEVICEUPDATE (WM_USER + 0x1000) + typedef INT_PTR (WINAPI *PPROPERTYSHEETW)(LPCPROPSHEETHEADERW); typedef HPROPSHEETPAGE (WINAPI *PCREATEPROPERTYSHEETPAGEW)(LPCPROPSHEETPAGEW); typedef BOOL (WINAPI *PDESTROYPROPERTYSHEETPAGE)(HPROPSHEETPAGE); @@ -43,12 +45,27 @@
typedef struct _DEVADVPROP_INFO { + HWND hWndGeneralPage; + HWND hWndParent; + WNDPROC ParentOldWndProc; + HDEVINFO DeviceInfoSet; - PSP_DEVINFO_DATA DeviceInfoData; + SP_DEVINFO_DATA DeviceInfoData; + HANDLE hMachine; + LPCWSTR lpMachineName; + HINSTANCE hComCtl32; - HANDLE hMachine; - BOOL CanDisable; - BOOL DeviceEnabled; + + DWORD PropertySheetType; + DWORD nDevPropSheets; + HPROPSHEETPAGE *DevPropSheets; + + BOOL FreeDevPropSheets : 1; + BOOL CanDisable : 1; + BOOL DeviceEnabled : 1; + BOOL DeviceUsageChanged : 1; + BOOL CreatedDevInfoSet : 1; + WCHAR szDevName[255]; WCHAR szTemp[255]; WCHAR szDeviceID[1]; @@ -155,63 +172,193 @@ ApplyGeneralSettings(IN HWND hwndDlg, IN PDEVADVPROP_INFO dap) { - DEVENABLEACTION SelectedUsageAction; + if (dap->DeviceUsageChanged) + { + DEVENABLEACTION SelectedUsageAction;
- SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg, - IDC_DEVUSAGE)); - if (SelectedUsageAction != DEA_UNKNOWN) - { - switch (SelectedUsageAction) + SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg, + IDC_DEVUSAGE)); + if (SelectedUsageAction != DEA_UNKNOWN) { - case DEA_ENABLE: - if (!dap->DeviceEnabled) - { - /* FIXME - enable device */ - } - break; + switch (SelectedUsageAction) + { + case DEA_ENABLE: + if (!dap->DeviceEnabled) + { + /* FIXME - enable device */ + } + break;
- case DEA_DISABLE: - if (dap->DeviceEnabled) - { - /* FIXME - disable device */ - } - break; + case DEA_DISABLE: + if (dap->DeviceEnabled) + { + /* FIXME - disable device */ + } + break;
- default: - break; + default: + break; + } } + }
- /* disable the apply button */ - PropSheet_UnChanged(GetParent(hwndDlg), - hwndDlg); - } + /* disable the apply button */ + PropSheet_UnChanged(GetParent(hwndDlg), + hwndDlg); + dap->DeviceUsageChanged = FALSE; }
static VOID UpdateDevInfo(IN HWND hwndDlg, IN PDEVADVPROP_INFO dap, - IN BOOL ReOpenDevice) + IN BOOL ReOpen) { HICON hIcon; HWND hDevUsage; + HWND hPropSheetDlg; + BOOL bFlag; + DWORD i;
- if (ReOpenDevice) + hPropSheetDlg = GetParent(hwndDlg); + + if (ReOpen) { - /* note, we ignore the fact that SetupDiOpenDeviceInfo could fail here, - in case of failure we're still going to query information from it even - though those calls are going to fail. But they return readable strings - even in that case. */ - SetupDiOpenDeviceInfo(dap->DeviceInfoSet, - dap->szDeviceID, - hwndDlg, - 0, - dap->DeviceInfoData); + PROPSHEETHEADER psh; + HDEVINFO hOldDevInfo; + + /* switch to the General page */ + PropSheet_SetCurSelByID(hPropSheetDlg, + IDD_DEVICEGENERAL); + + /* remove and destroy the existing device property sheet pages */ + for (i = 0; + i != dap->nDevPropSheets; + i++) + { + PropSheet_RemovePage(hPropSheetDlg, + -1, + dap->DevPropSheets[i]); + } + + if (dap->FreeDevPropSheets) + { + /* don't free the array if it's the one allocated in + DisplayDeviceAdvancedProperties */ + HeapFree(GetProcessHeap(), + 0, + dap->DevPropSheets); + + dap->FreeDevPropSheets = FALSE; + } + + dap->DevPropSheets = NULL; + dap->nDevPropSheets = 0; + + /* create a new device info set and re-open the device */ + hOldDevInfo = dap->DeviceInfoSet; + dap->DeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL, + hwndDlg, + dap->lpMachineName, + NULL); + if (dap->DeviceInfoSet != INVALID_HANDLE_VALUE) + { + if (SetupDiOpenDeviceInfo(dap->DeviceInfoSet, + dap->szDeviceID, + hwndDlg, + 0, + &dap->DeviceInfoData)) + { + if (dap->CreatedDevInfoSet) + { + SetupDiDestroyDeviceInfoList(hOldDevInfo); + } + + dap->CreatedDevInfoSet = TRUE; + } + else + { + SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet); + dap->DeviceInfoSet = INVALID_HANDLE_VALUE; + dap->CreatedDevInfoSet = FALSE; + } + } + else + { + /* oops, something went wrong, restore the old device info set */ + dap->DeviceInfoSet = hOldDevInfo; + + if (dap->DeviceInfoSet != INVALID_HANDLE_VALUE) + { + SetupDiOpenDeviceInfo(dap->DeviceInfoSet, + dap->szDeviceID, + hwndDlg, + 0, + &dap->DeviceInfoData); + } + } + + /* find out how many new device property sheets to add. + fake a PROPSHEETHEADER structure, we don't plan to + call PropertySheet again!*/ + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = 0; + psh.nPages = 0; + + if (!SetupDiGetClassDevPropertySheets(dap->DeviceInfoSet, + &dap->DeviceInfoData, + &psh, + 0, + &dap->nDevPropSheets, + dap->PropertySheetType) && + dap->nDevPropSheets != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + dap->DevPropSheets = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dap->nDevPropSheets * sizeof(HPROPSHEETPAGE)); + if (dap->DevPropSheets != NULL) + { + psh.phpage = dap->DevPropSheets; + + /* query the new property sheet pages to add */ + if (SetupDiGetClassDevPropertySheets(dap->DeviceInfoSet, + &dap->DeviceInfoData, + &psh, + dap->nDevPropSheets, + NULL, + dap->PropertySheetType)) + { + /* add the property sheets */ + + for (i = 0; + i != dap->nDevPropSheets; + i++) + { + PropSheet_AddPage(hPropSheetDlg, + dap->DevPropSheets[i]); + } + + dap->FreeDevPropSheets = TRUE; + } + else + { + /* cleanup, we were unable to get the device property sheets */ + HeapFree(GetProcessHeap(), + 0, + dap->DevPropSheets); + + dap->nDevPropSheets = 0; + dap->DevPropSheets = NULL; + } + } + else + dap->nDevPropSheets = 0; + } }
/* get the device name */ if (GetDeviceDescriptionString(dap->DeviceInfoSet, - dap->DeviceInfoData, + &dap->DeviceInfoData, dap->szDevName, sizeof(dap->szDevName) / sizeof(dap->szDevName[0]))) { @@ -221,7 +368,7 @@ }
/* set the device image */ - if (SetupDiLoadClassIcon(&dap->DeviceInfoData->ClassGuid, + if (SetupDiLoadClassIcon(&dap->DeviceInfoData.ClassGuid, &hIcon, NULL)) { @@ -242,7 +389,7 @@ dap->szDevName);
/* set the device type edit control text */ - if (GetDeviceTypeString(dap->DeviceInfoData, + if (GetDeviceTypeString(&dap->DeviceInfoData, dap->szTemp, sizeof(dap->szTemp) / sizeof(dap->szTemp[0]))) { @@ -253,7 +400,7 @@
/* set the device manufacturer edit control text */ if (GetDeviceManufacturerString(dap->DeviceInfoSet, - dap->DeviceInfoData, + &dap->DeviceInfoData, dap->szTemp, sizeof(dap->szTemp) / sizeof(dap->szTemp[0]))) { @@ -263,7 +410,7 @@ }
/* set the device location edit control text */ - if (GetDeviceLocationString(dap->DeviceInfoData->DevInst, + if (GetDeviceLocationString(dap->DeviceInfoData.DevInst, dap->szTemp, sizeof(dap->szTemp) / sizeof(dap->szTemp[0]))) { @@ -273,7 +420,7 @@ }
/* set the device status edit control text */ - if (GetDeviceStatusString(dap->DeviceInfoData->DevInst, + if (GetDeviceStatusString(dap->DeviceInfoData.DevInst, dap->hMachine, dap->szTemp, sizeof(dap->szTemp) / sizeof(dap->szTemp[0]))) @@ -287,18 +434,24 @@ hDevUsage = GetDlgItem(hwndDlg, IDC_DEVUSAGE);
- if (!CanDisableDevice(dap->DeviceInfoData->DevInst, - dap->hMachine, - &dap->CanDisable)) + dap->CanDisable = FALSE; + dap->DeviceEnabled = FALSE; + + if (dap->DeviceInfoSet != INVALID_HANDLE_VALUE) { - dap->CanDisable = FALSE; - } + if (CanDisableDevice(dap->DeviceInfoData.DevInst, + dap->hMachine, + &bFlag)) + { + dap->CanDisable = bFlag; + }
- if (!IsDeviceEnabled(dap->DeviceInfoData->DevInst, - dap->hMachine, - &dap->DeviceEnabled)) - { - dap->DeviceEnabled = FALSE; + if (IsDeviceEnabled(dap->DeviceInfoData.DevInst, + dap->hMachine, + &bFlag)) + { + dap->DeviceEnabled = bFlag; + } }
/* enable/disable the device usage controls */ @@ -321,11 +474,55 @@ }
/* finally, disable the apply button */ - PropSheet_UnChanged(GetParent(hwndDlg), + PropSheet_UnChanged(hPropSheetDlg, hwndDlg); + dap->DeviceUsageChanged = FALSE; }
+static LRESULT +CALLBACK +DlgParentSubWndProc(IN HWND hwnd, + IN UINT uMsg, + IN WPARAM wParam, + IN LPARAM lParam) +{ + PDEVADVPROP_INFO dap; + + dap = (PDEVADVPROP_INFO)GetProp(hwnd, + L"DevMgrDevChangeSub"); + if (dap != NULL) + { + if (uMsg == WM_DEVICECHANGE && !IsWindowVisible(dap->hWndGeneralPage)) + { + SendMessage(dap->hWndGeneralPage, + WM_DEVICECHANGE, + wParam, + lParam); + } + + /* pass the message the the old window proc */ + return CallWindowProc(dap->ParentOldWndProc, + hwnd, + uMsg, + wParam, + lParam); + } + else + { + /* this is not a good idea if the subclassed window was an ansi + window, but we failed finding out the previous window proc + so we can't use CallWindowProc. This should rarely - if ever - + happen. */ + + return DefWindowProc(hwnd, + uMsg, + wParam, + lParam); + } +} + + static INT_PTR CALLBACK AdvPropGeneralDlgProc(IN HWND hwndDlg, @@ -353,6 +550,7 @@ { PropSheet_Changed(GetParent(hwndDlg), hwndDlg); + dap->DeviceUsageChanged = TRUE; } break; } @@ -378,10 +576,34 @@ dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam; if (dap != NULL) { + HWND hWndParent; + + dap->hWndGeneralPage = hwndDlg; + SetWindowLongPtr(hwndDlg, DWL_USER, (DWORD_PTR)dap);
+ /* subclass the parent window to always receive + WM_DEVICECHANGE messages */ + hWndParent = GetParent(hwndDlg); + if (hWndParent != NULL) + { + /* subclass the parent window. This is not safe + if the parent window belongs to another thread! */ + dap->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent, + GWLP_WNDPROC, + (LONG_PTR)DlgParentSubWndProc); + + if (dap->ParentOldWndProc != NULL && + SetProp(hWndParent, + L"DevMgrDevChangeSub", + (HANDLE)dap)) + { + dap->hWndParent = hWndParent; + } + } + UpdateDevInfo(hwndDlg, dap, FALSE); @@ -403,6 +625,14 @@ { HICON hDevIcon;
+ /* restore the old window proc of the subclassed parent window */ + if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL) + { + SetWindowLongPtr(dap->hWndParent, + GWLP_WNDPROC, + (LONG_PTR)dap->ParentOldWndProc); + } + /* destroy the device icon */ hDevIcon = (HICON)SendDlgItemMessage(hwndDlg, IDC_DEVICON, @@ -437,7 +667,6 @@ PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW; PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage; PDEVADVPROP_INFO DevAdvPropInfo; - DWORD PropertySheetType; HANDLE hMachine = NULL; DWORD DevIdSize = 0; INT_PTR Ret = -1; @@ -469,7 +698,7 @@ 0, &DevIdSize)) { - DPRINT1("SetupDiGetDeviceInterfaceDetail unexpectedly returned TRUE!\n"); + DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n"); return -1; }
@@ -496,7 +725,7 @@ /* create the internal structure associated with the "General", "Driver", ... pages */ DevAdvPropInfo = HeapAlloc(GetProcessHeap(), - 0, + HEAP_ZERO_MEMORY, FIELD_OFFSET(DEVADVPROP_INFO, szDeviceID) + (DevIdSize * sizeof(WCHAR))); @@ -517,29 +746,36 @@ goto Cleanup; } } + else + { + /* copy the device instance id supplied by the caller */ + wcscpy(DevAdvPropInfo->szDeviceID, + lpDeviceID); + }
DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet; - DevAdvPropInfo->DeviceInfoData = DeviceInfoData; - DevAdvPropInfo->hComCtl32 = hComCtl32; + DevAdvPropInfo->DeviceInfoData = *DeviceInfoData; DevAdvPropInfo->hMachine = hMachine; + DevAdvPropInfo->lpMachineName = lpMachineName; DevAdvPropInfo->szDevName[0] = L'\0'; + DevAdvPropInfo->hComCtl32 = hComCtl32;
psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW; psh.hwndParent = hWndParent; psh.pszCaption = DevAdvPropInfo->szDevName;
- PropertySheetType = lpMachineName != NULL ? - DIGCDP_FLAG_REMOTE_ADVANCED : - DIGCDP_FLAG_ADVANCED; + DevAdvPropInfo->PropertySheetType = lpMachineName != NULL ? + DIGCDP_FLAG_REMOTE_ADVANCED : + DIGCDP_FLAG_ADVANCED;
/* find out how many property sheets we need */ if (SetupDiGetClassDevPropertySheets(DeviceInfoSet, - DeviceInfoData, + &DevAdvPropInfo->DeviceInfoData, &psh, 0, &nPropSheets, - PropertySheetType) && + DevAdvPropInfo->PropertySheetType) && nPropSheets != 0) { DPRINT1("SetupDiGetClassDevPropertySheets unexpectedly returned TRUE!\n"); @@ -572,15 +808,19 @@ psh.nPages++; }
+ DevAdvPropInfo->nDevPropSheets = nPropSheets; + if (nPropSheets != 0) { + DevAdvPropInfo->DevPropSheets = psh.phpage + psh.nPages; + /* create the device property sheets */ if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet, - DeviceInfoData, + &DevAdvPropInfo->DeviceInfoData, &psh, nPropSheets + psh.nPages, NULL, - PropertySheetType)) + DevAdvPropInfo->PropertySheetType)) { goto Cleanup; } @@ -600,25 +840,49 @@
Cleanup: /* in case of failure the property sheets must be destroyed */ - for (i = 0; - i < psh.nPages; - i++) + if (psh.phpage != NULL) { - if (psh.phpage[i] != NULL) + for (i = 0; + i < psh.nPages; + i++) { - pDestroyPropertySheetPage(psh.phpage[i]); + if (psh.phpage[i] != NULL) + { + pDestroyPropertySheetPage(psh.phpage[i]); + } } } }
- HeapFree(GetProcessHeap(), - 0, - psh.phpage); + if (DevAdvPropInfo != NULL) + { + if (DevAdvPropInfo->FreeDevPropSheets) + { + /* don't free the array if it's the one allocated in + DisplayDeviceAdvancedProperties */ + HeapFree(GetProcessHeap(), + 0, + DevAdvPropInfo->DevPropSheets); + }
- HeapFree(GetProcessHeap(), - 0, - DevAdvPropInfo); + if (DevAdvPropInfo->CreatedDevInfoSet) + { + /* close the device info set in case a new one was created */ + SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet); + }
+ HeapFree(GetProcessHeap(), + 0, + DevAdvPropInfo); + } + + if (psh.phpage != NULL) + { + HeapFree(GetProcessHeap(), + 0, + psh.phpage); + } + if (hMachine != NULL) { CM_Disconnect_Machine(hMachine); @@ -665,19 +929,10 @@ hComCtl32 = LoadAndInitComctl32(); if (hComCtl32 != NULL) { - if (lpMachineName != NULL) - { - hDevInfo = SetupDiCreateDeviceInfoListEx(NULL, - hWndParent, - lpMachineName, - NULL); - } - else - { - hDevInfo = SetupDiCreateDeviceInfoList(NULL, - hWndParent); - } - + hDevInfo = SetupDiCreateDeviceInfoListEx(NULL, + hWndParent, + lpMachineName, + NULL); if (hDevInfo != INVALID_HANDLE_VALUE) { DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);