I know this *_new thing is a bit overused, but there are a lot of changes coming to devmgr and rather than take it out of the build for a few days, it's easier to do it this way
svn path=/trunk/; revision=68369
--- /dev/null
+
+spec2def(devmgr.dll devmgr.spec ADD_IMPORTLIB)
+
+list(APPEND SOURCE
+ advprop.c
+ devprblm.c
+ hwpage.c
+ hwresource.c
+ misc.c
+ stubs.c
+ precomp.h
+ ${CMAKE_CURRENT_BINARY_DIR}/devmgr_stubs.c)
+
+add_library(devmgr SHARED
+ ${SOURCE}
+ devmgr.rc
+ ${CMAKE_CURRENT_BINARY_DIR}/devmgr.def)
+
+set_module_type(devmgr win32dll UNICODE)
+target_link_libraries(devmgr uuid wine)
+add_importlibs(devmgr setupapi advapi32 newdev user32 version msvcrt kernel32 ntdll)
+add_pch(devmgr precomp.h SOURCE)
+add_cd_file(TARGET devmgr DESTINATION reactos/system32 FOR all)
--- /dev/null
+/*
+ * ReactOS Device Manager Applet
+ * Copyright (C) 2004 - 2005 ReactOS Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+/*
+ *
+ * PROJECT: ReactOS devmgr.dll
+ * FILE: lib/devmgr/advprop.c
+ * PURPOSE: ReactOS Device Manager
+ * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
+ * Ged Murphy <gedmurphy@reactos.org>
+ * UPDATE HISTORY:
+ * 04-04-2004 Created
+ */
+
+#include "precomp.h"
+
+#include <winver.h>
+
+
+static UINT WINAPI
+EnumDeviceDriverFilesCallback(IN PVOID Context,
+ IN UINT Notification,
+ IN UINT_PTR Param1,
+ IN UINT_PTR Param2)
+{
+ LVITEM li;
+ PENUMDRIVERFILES_CONTEXT EnumDriverFilesContext = (PENUMDRIVERFILES_CONTEXT)Context;
+
+ li.mask = LVIF_TEXT | LVIF_STATE;
+ li.iItem = EnumDriverFilesContext->nCount++;
+ li.iSubItem = 0;
+ li.state = (li.iItem == 0 ? LVIS_SELECTED : 0);
+ li.stateMask = LVIS_SELECTED;
+ li.pszText = (LPWSTR)Param1;
+ (void)ListView_InsertItem(EnumDriverFilesContext->hDriversListView,
+ &li);
+ return NO_ERROR;
+}
+
+
+static VOID
+UpdateDriverDetailsDlg(IN HWND hwndDlg,
+ IN HWND hDriversListView,
+ IN PDEVADVPROP_INFO dap)
+{
+ HDEVINFO DeviceInfoSet;
+ PSP_DEVINFO_DATA DeviceInfoData;
+ SP_DRVINFO_DATA DriverInfoData;
+ ENUMDRIVERFILES_CONTEXT EnumDriverFilesContext;
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ /* set the device image */
+ SendDlgItemMessage(hwndDlg,
+ IDC_DEVICON,
+ STM_SETICON,
+ (WPARAM)dap->hDevIcon,
+ 0);
+
+ /* set the device name edit control text */
+ SetDlgItemText(hwndDlg,
+ IDC_DEVNAME,
+ dap->szDevName);
+
+ /* fill the driver files list view */
+ EnumDriverFilesContext.hDriversListView = hDriversListView;
+ EnumDriverFilesContext.nCount = 0;
+
+ (void)ListView_DeleteAllItems(EnumDriverFilesContext.hDriversListView);
+ DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
+ if (FindCurrentDriver(DeviceInfoSet,
+ DeviceInfoData,
+ &DriverInfoData) &&
+ SetupDiSetSelectedDriver(DeviceInfoSet,
+ DeviceInfoData,
+ &DriverInfoData))
+ {
+ HSPFILEQ queueHandle;
+
+ queueHandle = SetupOpenFileQueue();
+ if (queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE)
+ {
+ SP_DEVINSTALL_PARAMS DeviceInstallParams = {0};
+ DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+ if (SetupDiGetDeviceInstallParams(DeviceInfoSet,
+ DeviceInfoData,
+ &DeviceInstallParams))
+ {
+ DeviceInstallParams.FileQueue = queueHandle;
+ DeviceInstallParams.Flags |= DI_NOVCP;
+
+ if (SetupDiSetDeviceInstallParams(DeviceInfoSet,
+ DeviceInfoData,
+ &DeviceInstallParams) &&
+ SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
+ DeviceInfoSet,
+ DeviceInfoData))
+ {
+ DWORD scanResult;
+ RECT rcClient;
+ LVCOLUMN lvc;
+
+ /* enumerate the driver files */
+ SetupScanFileQueue(queueHandle,
+ SPQ_SCAN_USE_CALLBACK,
+ NULL,
+ EnumDeviceDriverFilesCallback,
+ &EnumDriverFilesContext,
+ &scanResult);
+
+ /* update the list view column width */
+ GetClientRect(hDriversListView,
+ &rcClient);
+ lvc.mask = LVCF_WIDTH;
+ lvc.cx = rcClient.right;
+ (void)ListView_SetColumn(hDriversListView,
+ 0,
+ &lvc);
+
+ /* highlight the first item from list */
+ if (ListView_GetSelectedCount(hDriversListView) != 0)
+ {
+ ListView_SetItemState(hDriversListView,
+ 0,
+ LVIS_FOCUSED | LVIS_SELECTED,
+ LVIS_FOCUSED | LVIS_SELECTED);
+ }
+ }
+ }
+
+ SetupCloseFileQueue(queueHandle);
+ }
+ }
+}
+
+
+static VOID
+UpdateDriverVersionInfoDetails(IN HWND hwndDlg,
+ IN LPCWSTR lpszDriverPath)
+{
+ DWORD dwHandle;
+ DWORD dwVerInfoSize;
+ LPVOID lpData = NULL;
+ LPVOID lpInfo;
+ UINT uInfoLen;
+ DWORD dwLangId;
+ WCHAR szLangInfo[255];
+ WCHAR szLangPath[MAX_PATH];
+ LPWSTR lpCompanyName = NULL;
+ LPWSTR lpFileVersion = NULL;
+ LPWSTR lpLegalCopyright = NULL;
+ LPWSTR lpDigitalSigner = NULL;
+ UINT uBufLen;
+ WCHAR szNotAvailable[255];
+
+ /* extract version info from selected file */
+ dwVerInfoSize = GetFileVersionInfoSize(lpszDriverPath,
+ &dwHandle);
+ if (!dwVerInfoSize)
+ goto done;
+
+ lpData = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwVerInfoSize);
+ if (!lpData)
+ goto done;
+
+ if (!GetFileVersionInfo(lpszDriverPath,
+ dwHandle,
+ dwVerInfoSize,
+ lpData))
+ goto done;
+
+ if (!VerQueryValue(lpData,
+ L"\\VarFileInfo\\Translation",
+ &lpInfo,
+ &uInfoLen))
+ goto done;
+
+ dwLangId = *(LPDWORD)lpInfo;
+ swprintf(szLangInfo, L"\\StringFileInfo\\%04x%04x\\",
+ LOWORD(dwLangId), HIWORD(dwLangId));
+
+ /* read CompanyName */
+ wcscpy(szLangPath, szLangInfo);
+ wcscat(szLangPath, L"CompanyName");
+
+ VerQueryValue(lpData,
+ szLangPath,
+ (void **)&lpCompanyName,
+ (PUINT)&uBufLen);
+
+ /* read FileVersion */
+ wcscpy(szLangPath, szLangInfo);
+ wcscat(szLangPath, L"FileVersion");
+
+ VerQueryValue(lpData,
+ szLangPath,
+ (void **)&lpFileVersion,
+ (PUINT)&uBufLen);
+
+ /* read LegalTrademarks */
+ wcscpy(szLangPath, szLangInfo);
+ wcscat(szLangPath, L"LegalCopyright");
+
+ VerQueryValue(lpData,
+ szLangPath,
+ (void **)&lpLegalCopyright,
+ (PUINT)&uBufLen);
+
+ /* TODO: read digital signer info */
+
+done:
+ if (!LoadString(hDllInstance,
+ IDS_NOTAVAILABLE,
+ szNotAvailable,
+ sizeof(szNotAvailable) / sizeof(WCHAR)))
+ {
+ wcscpy(szNotAvailable, L"n/a");
+ }
+
+ /* update labels */
+ if (!lpCompanyName)
+ lpCompanyName = szNotAvailable;
+ SetDlgItemText(hwndDlg,
+ IDC_FILEPROVIDER,
+ lpCompanyName);
+
+ if (!lpFileVersion)
+ lpFileVersion = szNotAvailable;
+ SetDlgItemText(hwndDlg,
+ IDC_FILEVERSION,
+ lpFileVersion);
+
+ if (!lpLegalCopyright)
+ lpLegalCopyright = szNotAvailable;
+ SetDlgItemText(hwndDlg,
+ IDC_FILECOPYRIGHT,
+ lpLegalCopyright);
+
+ if (!lpDigitalSigner)
+ lpDigitalSigner = szNotAvailable;
+ SetDlgItemText(hwndDlg,
+ IDC_DIGITALSIGNER,
+ lpDigitalSigner);
+
+ /* release version info */
+ if (lpData)
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpData);
+}
+
+
+static INT_PTR
+CALLBACK
+DriverDetailsDlgProc(IN HWND hwndDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam)
+{
+ PDEVADVPROP_INFO dap;
+ INT_PTR Ret = FALSE;
+
+ dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
+ DWL_USER);
+
+ if (dap != NULL || uMsg == WM_INITDIALOG)
+ {
+ switch (uMsg)
+ {
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ case IDCANCEL:
+ {
+ EndDialog(hwndDlg,
+ IDOK);
+ break;
+ }
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ EndDialog(hwndDlg,
+ IDCANCEL);
+ break;
+ }
+
+ case WM_INITDIALOG:
+ {
+ LV_COLUMN lvc;
+ HWND hDriversListView;
+ WCHAR szBuffer[260];
+
+ dap = (PDEVADVPROP_INFO)lParam;
+ if (dap != NULL)
+ {
+ SetWindowLongPtr(hwndDlg,
+ DWL_USER,
+ (DWORD_PTR)dap);
+
+ hDriversListView = GetDlgItem(hwndDlg,
+ IDC_DRIVERFILES);
+
+ /* add a column to the list view control */
+ lvc.mask = LVCF_FMT | LVCF_WIDTH;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.cx = 0;
+ (void)ListView_InsertColumn(hDriversListView,
+ 0,
+ &lvc);
+
+ UpdateDriverDetailsDlg(hwndDlg,
+ hDriversListView,
+ dap);
+
+ if (ListView_GetItemCount(hDriversListView) == 0)
+ {
+ if(LoadStringW(hDllInstance, IDS_NODRIVERS, szBuffer, _countof(szBuffer)))
+ MessageBoxW(hwndDlg, szBuffer, dap->szDevName, MB_OK);
+ EndDialog(hwndDlg, IDCANCEL);
+ }
+ }
+
+ Ret = TRUE;
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmhdr = (LPNMHDR)lParam;
+
+ switch (pnmhdr->code)
+ {
+ case LVN_ITEMCHANGED:
+ {
+ LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
+ HWND hDriversListView = GetDlgItem(hwndDlg,
+ IDC_DRIVERFILES);
+
+ if (ListView_GetSelectedCount(hDriversListView) == 0)
+ {
+ /* nothing is selected - empty the labels */
+ SetDlgItemText(hwndDlg,
+ IDC_FILEPROVIDER,
+ NULL);
+ SetDlgItemText(hwndDlg,
+ IDC_FILEVERSION,
+ NULL);
+ SetDlgItemText(hwndDlg,
+ IDC_FILECOPYRIGHT,
+ NULL);
+ SetDlgItemText(hwndDlg,
+ IDC_DIGITALSIGNER,
+ NULL);
+ }
+ else if (pnmv->uNewState != 0)
+ {
+ /* extract version info and update the labels */
+ WCHAR szDriverPath[MAX_PATH];
+
+ ListView_GetItemText(hDriversListView,
+ pnmv->iItem,
+ pnmv->iSubItem,
+ szDriverPath,
+ MAX_PATH);
+
+ UpdateDriverVersionInfoDetails(hwndDlg,
+ szDriverPath);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ return Ret;
+}
+
+
+static
+VOID
+UpdateDriver(
+ IN HWND hwndDlg,
+ IN PDEVADVPROP_INFO dap)
+{
+ TOKEN_PRIVILEGES Privileges;
+ HANDLE hToken;
+ DWORD dwReboot;
+ BOOL NeedReboot = FALSE;
+
+ // Better use InstallDevInst:
+ // BOOL
+ // WINAPI
+ // InstallDevInst(
+ // HWND hWnd,
+ // LPWSTR wszDeviceId,
+ // BOOL bUpdate,
+ // DWORD *dwReboot);
+ // See: http://comp.os.ms-windows.programmer.win32.narkive.com/J8FTd4KK/signature-of-undocumented-installdevinstex
+
+ if (!InstallDevInst(hwndDlg, dap->szDeviceID, TRUE, &dwReboot))
+ return;
+
+ if (NeedReboot == FALSE)
+ return;
+
+ //FIXME: load text from resource file
+ if (MessageBoxW(hwndDlg, L"Reboot now?", L"Reboot required", MB_YESNO | MB_ICONQUESTION) != IDYES)
+ return;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
+ {
+ ERR("OpenProcessToken failed\n");
+ return;
+ }
+
+ /* Get the LUID for the Shutdown privilege */
+ if (!LookupPrivilegeValueW(NULL, SE_SHUTDOWN_NAME, &Privileges.Privileges[0].Luid))
+ {
+ ERR("LookupPrivilegeValue failed\n");
+ CloseHandle(hToken);
+ return;
+ }
+
+ /* Assign the Shutdown privilege to our process */
+ Privileges.PrivilegeCount = 1;
+ Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (!AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL))
+ {
+ ERR("AdjustTokenPrivileges failed\n");
+ CloseHandle(hToken);
+ return;
+ }
+
+ /* Finally shut down the system */
+ if (!ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED))
+ {
+ ERR("ExitWindowsEx failed\n");
+ CloseHandle(hToken);
+ }
+}
+
+
+static VOID
+UpdateDriverDlg(IN HWND hwndDlg,
+ IN PDEVADVPROP_INFO dap)
+{
+ HDEVINFO DeviceInfoSet;
+ PSP_DEVINFO_DATA DeviceInfoData;
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ /* set the device image */
+ SendDlgItemMessage(hwndDlg,
+ IDC_DEVICON,
+ STM_SETICON,
+ (WPARAM)dap->hDevIcon,
+ 0);
+
+ /* set the device name edit control text */
+ SetDlgItemText(hwndDlg,
+ IDC_DEVNAME,
+ dap->szDevName);
+
+ /* query the driver provider */
+ if (GetDriverProviderString(DeviceInfoSet,
+ DeviceInfoData,
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ SetDlgItemText(hwndDlg,
+ IDC_DRVPROVIDER,
+ dap->szTemp);
+ }
+
+ /* query the driver date */
+ if (GetDriverDateString(DeviceInfoSet,
+ DeviceInfoData,
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ SetDlgItemText(hwndDlg,
+ IDC_DRVDATE,
+ dap->szTemp);
+ }
+
+ /* query the driver version */
+ if (GetDriverVersionString(DeviceInfoSet,
+ DeviceInfoData,
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ SetDlgItemText(hwndDlg,
+ IDC_DRVVERSION,
+ dap->szTemp);
+ }
+}
+
+
+static INT_PTR
+CALLBACK
+AdvProcDriverDlgProc(IN HWND hwndDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam)
+{
+ PDEVADVPROP_INFO dap;
+ INT_PTR Ret = FALSE;
+
+ dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
+ DWL_USER);
+
+ if (dap != NULL || uMsg == WM_INITDIALOG)
+ {
+ switch (uMsg)
+ {
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_DRIVERDETAILS:
+ DialogBoxParam(hDllInstance,
+ MAKEINTRESOURCE(IDD_DRIVERDETAILS),
+ hwndDlg,
+ DriverDetailsDlgProc,
+ (ULONG_PTR)dap);
+ break;
+
+ case IDC_UPDATEDRIVER:
+ UpdateDriver(hwndDlg, dap);
+ break;
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ NMHDR *hdr = (NMHDR*)lParam;
+ switch (hdr->code)
+ {
+ case PSN_APPLY:
+ break;
+ }
+ break;
+ }
+
+ case WM_INITDIALOG:
+ {
+ dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
+ if (dap != NULL)
+ {
+ SetWindowLongPtr(hwndDlg,
+ DWL_USER,
+ (DWORD_PTR)dap);
+
+ UpdateDriverDlg(hwndDlg,
+ dap);
+ }
+ Ret = TRUE;
+ break;
+ }
+ }
+ }
+
+ return Ret;
+}
+
+
+static VOID
+SetListViewText(HWND hwnd,
+ INT iItem,
+ LPWSTR lpText)
+{
+ LVITEM li;
+
+ li.mask = LVIF_TEXT | LVIF_STATE;
+ li.iItem = iItem;
+ li.iSubItem = 0;
+ li.state = 0; //(li.iItem == 0 ? LVIS_SELECTED : 0);
+ li.stateMask = LVIS_SELECTED;
+ li.pszText = lpText;
+ (void)ListView_InsertItem(hwnd,
+ &li);
+}
+
+
+static VOID
+UpdateDetailsDlg(IN HWND hwndDlg,
+ IN PDEVADVPROP_INFO dap)
+{
+ HWND hwndComboBox;
+ HWND hwndListView;
+ LV_COLUMN lvc;
+ RECT rcClient;
+
+ UINT i;
+ UINT Properties[] =
+ {
+ IDS_PROP_DEVICEID,
+ IDS_PROP_HARDWAREIDS,
+ IDS_PROP_COMPATIBLEIDS,
+ IDS_PROP_MATCHINGDEVICEID,
+ IDS_PROP_SERVICE,
+ IDS_PROP_ENUMERATOR,
+ IDS_PROP_CAPABILITIES,
+ IDS_PROP_DEVNODEFLAGS,
+ IDS_PROP_CONFIGFLAGS,
+ IDS_PROP_CSCONFIGFLAGS,
+ IDS_PROP_EJECTIONRELATIONS,
+ IDS_PROP_REMOVALRELATIONS,
+ IDS_PROP_BUSRELATIONS,
+ IDS_PROP_DEVUPPERFILTERS,
+ IDS_PROP_DEVLOWERFILTERS,
+ IDS_PROP_CLASSUPPERFILTERS,
+ IDS_PROP_CLASSLOWERFILTERS,
+ IDS_PROP_CLASSINSTALLER,
+ IDS_PROP_CLASSCOINSTALLER,
+ IDS_PROP_DEVICECOINSTALLER,
+ IDS_PROP_FIRMWAREREVISION,
+ IDS_PROP_CURRENTPOWERSTATE,
+ IDS_PROP_POWERCAPABILITIES,
+ IDS_PROP_POWERSTATEMAPPINGS
+ };
+
+
+ /* set the device image */
+ SendDlgItemMessage(hwndDlg,
+ IDC_DEVICON,
+ STM_SETICON,
+ (WPARAM)dap->hDevIcon,
+ 0);
+
+ /* set the device name edit control text */
+ SetDlgItemText(hwndDlg,
+ IDC_DEVNAME,
+ dap->szDevName);
+
+
+ hwndComboBox = GetDlgItem(hwndDlg,
+ IDC_DETAILSPROPNAME);
+
+ hwndListView = GetDlgItem(hwndDlg,
+ IDC_DETAILSPROPVALUE);
+
+ for (i = 0; i != sizeof(Properties) / sizeof(Properties[0]); i++)
+ {
+ /* fill in the device usage combo box */
+ if (LoadString(hDllInstance,
+ Properties[i],
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ SendMessage(hwndComboBox,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM)dap->szTemp);
+ }
+ }
+
+
+ GetClientRect(hwndListView,
+ &rcClient);
+
+ /* add a column to the list view control */
+ lvc.mask = LVCF_FMT | LVCF_WIDTH;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.cx = rcClient.right;
+ (void)ListView_InsertColumn(hwndListView,
+ 0,
+ &lvc);
+
+ SendMessage(hwndComboBox,
+ CB_SETCURSEL,
+ 0,
+ 0);
+
+ SetListViewText(hwndListView, 0, dap->szDeviceID);
+
+ SetFocus(hwndComboBox);
+}
+
+
+static VOID
+DisplayDevicePropertyText(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView,
+ IN DWORD dwProperty)
+{
+ HDEVINFO DeviceInfoSet;
+ PSP_DEVINFO_DATA DeviceInfoData;
+ DWORD dwType;
+ DWORD dwSize;
+ DWORD dwValue;
+ LPBYTE lpBuffer;
+ LPWSTR lpStr;
+ INT len;
+ INT index;
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ dwSize = 0;
+ SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
+ DeviceInfoData,
+ dwProperty,
+ &dwType,
+ NULL,
+ 0,
+ &dwSize);
+ if (dwSize == 0)
+ {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND)
+ {
+ swprintf(dap->szTemp, L"Error: Getting the size failed! (Error: %ld)", GetLastError());
+ SetListViewText(hwndListView, 0, dap->szTemp);
+ }
+ return;
+ }
+
+ if (dwType == REG_SZ)
+ dwSize += sizeof(WCHAR);
+
+ lpBuffer = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwSize);
+ if (lpBuffer == NULL)
+ {
+ SetListViewText(hwndListView, 0, L"Error: Allocating the buffer failed!");
+ return;
+ }
+
+ if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
+ DeviceInfoData,
+ dwProperty,
+ &dwType,
+ lpBuffer,
+ dwSize,
+ &dwSize))
+ {
+ if (dwType == REG_SZ)
+ {
+ SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
+ }
+ else if (dwType == REG_MULTI_SZ)
+ {
+ lpStr = (LPWSTR)lpBuffer;
+ index = 0;
+ while (*lpStr != 0)
+ {
+ len = wcslen(lpStr) + 1;
+
+ SetListViewText(hwndListView, index, lpStr);
+
+ lpStr += len;
+ index++;
+ }
+ }
+ else if (dwType == REG_DWORD)
+ {
+ dwValue = *(DWORD *) lpBuffer;
+
+ switch (dwProperty)
+ {
+ case SPDRP_CAPABILITIES:
+ index = 0;
+ if (dwValue & CM_DEVCAP_LOCKSUPPORTED)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_LOCKSUPPORTED");
+ if (dwValue & CM_DEVCAP_EJECTSUPPORTED)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_EJECTSUPPORTED");
+ if (dwValue & CM_DEVCAP_REMOVABLE)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_REMOVABLE");
+ if (dwValue & CM_DEVCAP_DOCKDEVICE)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_DOCKDEVICE");
+ if (dwValue & CM_DEVCAP_UNIQUEID)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_UNIQUEID");
+ if (dwValue & CM_DEVCAP_SILENTINSTALL)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_SILENTINSTALL");
+ if (dwValue & CM_DEVCAP_RAWDEVICEOK)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_RAWDEVICEOK");
+ if (dwValue & CM_DEVCAP_SURPRISEREMOVALOK)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_SURPRISEREMOVALOK");
+ if (dwValue & CM_DEVCAP_HARDWAREDISABLED)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_HARDWAREDISABLED");
+ if (dwValue & CM_DEVCAP_NONDYNAMIC)
+ SetListViewText(hwndListView, index++, L"CM_DEVCAP_NONDYNAMIC");
+ break;
+
+ case SPDRP_CONFIGFLAGS:
+ index = 0;
+ if (dwValue & CONFIGFLAG_DISABLED)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_DISABLED");
+ if (dwValue & CONFIGFLAG_REMOVED)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_REMOVED");
+ if (dwValue & CONFIGFLAG_MANUAL_INSTALL)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_MANUAL_INSTALL");
+ if (dwValue & CONFIGFLAG_IGNORE_BOOT_LC)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_IGNORE_BOOT_LC");
+ if (dwValue & CONFIGFLAG_NET_BOOT)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_NET_BOOT");
+ if (dwValue & CONFIGFLAG_REINSTALL)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_REINSTALL");
+ if (dwValue & CONFIGFLAG_FAILEDINSTALL)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_FAILEDINSTALL");
+ if (dwValue & CONFIGFLAG_CANTSTOPACHILD)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_CANTSTOPACHILD");
+ if (dwValue & CONFIGFLAG_OKREMOVEROM)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_OKREMOVEROM");
+ if (dwValue & CONFIGFLAG_NOREMOVEEXIT)
+ SetListViewText(hwndListView, index++, L"CONFIGFLAG_NOREMOVEEXIT");
+ break;
+
+ default:
+ swprintf(dap->szTemp, L"0x%08lx", dwValue);
+ SetListViewText(hwndListView, 0, dap->szTemp);
+ break;
+ }
+ }
+ else
+ {
+ SetListViewText(hwndListView, 0, L"Error: Unsupported value type!");
+
+ }
+ }
+ else
+ {
+ SetListViewText(hwndListView, 0, L"Error: Retrieving the value failed!");
+ }
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpBuffer);
+}
+
+static VOID
+DisplayDevNodeFlags(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView)
+{
+ DWORD dwStatus = 0;
+ DWORD dwProblem = 0;
+ INT index;
+
+ CM_Get_DevNode_Status_Ex(&dwStatus,
+ &dwProblem,
+ dap->DeviceInfoData.DevInst,
+ 0,
+ dap->hMachine);
+
+ index = 0;
+ if (dwStatus & DN_ROOT_ENUMERATED)
+ SetListViewText(hwndListView, index++, L"DN_ROOT_ENUMERATED");
+ if (dwStatus & DN_DRIVER_LOADED)
+ SetListViewText(hwndListView, index++, L"DN_DRIVER_LOADED");
+ if (dwStatus & DN_ENUM_LOADED)
+ SetListViewText(hwndListView, index++, L"DN_ENUM_LOADED");
+ if (dwStatus & DN_STARTED)
+ SetListViewText(hwndListView, index++, L"DN_STARTED");
+ if (dwStatus & DN_MANUAL)
+ SetListViewText(hwndListView, index++, L"DN_MANUAL");
+ if (dwStatus & DN_NEED_TO_ENUM)
+ SetListViewText(hwndListView, index++, L"DN_NEED_TO_ENUM");
+ if (dwStatus & DN_DRIVER_BLOCKED)
+ SetListViewText(hwndListView, index++, L"DN_DRIVER_BLOCKED");
+ if (dwStatus & DN_HARDWARE_ENUM)
+ SetListViewText(hwndListView, index++, L"DN_HARDWARE_ENUM");
+ if (dwStatus & DN_NEED_RESTART)
+ SetListViewText(hwndListView, index++, L"DN_NEED_RESTART");
+ if (dwStatus & DN_CHILD_WITH_INVALID_ID)
+ SetListViewText(hwndListView, index++, L"DN_CHILD_WITH_INVALID_ID");
+ if (dwStatus & DN_HAS_PROBLEM)
+ SetListViewText(hwndListView, index++, L"DN_HAS_PROBLEM");
+ if (dwStatus & DN_FILTERED)
+ SetListViewText(hwndListView, index++, L"DN_FILTERED");
+ if (dwStatus & DN_LEGACY_DRIVER)
+ SetListViewText(hwndListView, index++, L"DN_LEGACY_DRIVER");
+ if (dwStatus & DN_DISABLEABLE)
+ SetListViewText(hwndListView, index++, L"DN_DISABLEABLE");
+ if (dwStatus & DN_REMOVABLE)
+ SetListViewText(hwndListView, index++, L"DN_REMOVABLE");
+ if (dwStatus & DN_PRIVATE_PROBLEM)
+ SetListViewText(hwndListView, index++, L"DN_PRIVATE_PROBLEM");
+ if (dwStatus & DN_MF_PARENT)
+ SetListViewText(hwndListView, index++, L"DN_MF_PARENT");
+ if (dwStatus & DN_MF_CHILD)
+ SetListViewText(hwndListView, index++, L"DN_MF_CHILD");
+ if (dwStatus & DN_WILL_BE_REMOVED)
+ SetListViewText(hwndListView, index++, L"DN_WILL_BE_REMOVED");
+
+ if (dwStatus & DN_NOT_FIRST_TIMEE)
+ SetListViewText(hwndListView, index++, L"DN_NOT_FIRST_TIMEE");
+ if (dwStatus & DN_STOP_FREE_RES)
+ SetListViewText(hwndListView, index++, L"DN_STOP_FREE_RES");
+ if (dwStatus & DN_REBAL_CANDIDATE)
+ SetListViewText(hwndListView, index++, L"DN_REBAL_CANDIDATE");
+ if (dwStatus & DN_BAD_PARTIAL)
+ SetListViewText(hwndListView, index++, L"DN_BAD_PARTIAL");
+ if (dwStatus & DN_NT_ENUMERATOR)
+ SetListViewText(hwndListView, index++, L"DN_NT_ENUMERATOR");
+ if (dwStatus & DN_NT_DRIVER)
+ SetListViewText(hwndListView, index++, L"DN_NT_DRIVER");
+
+ if (dwStatus & DN_NEEDS_LOCKING)
+ SetListViewText(hwndListView, index++, L"DN_NEEDS_LOCKING");
+ if (dwStatus & DN_ARM_WAKEUP)
+ SetListViewText(hwndListView, index++, L"DN_ARM_WAKEUP");
+ if (dwStatus & DN_APM_ENUMERATOR)
+ SetListViewText(hwndListView, index++, L"DN_APM_ENUMERATOR");
+ if (dwStatus & DN_APM_DRIVER)
+ SetListViewText(hwndListView, index++, L"DN_APM_DRIVER");
+ if (dwStatus & DN_SILENT_INSTALL)
+ SetListViewText(hwndListView, index++, L"DN_SILENT_INSTALL");
+ if (dwStatus & DN_NO_SHOW_IN_DM)
+ SetListViewText(hwndListView, index++, L"DN_NO_SHOW_IN_DM");
+ if (dwStatus & DN_BOOT_LOG_PROB)
+ SetListViewText(hwndListView, index++, L"DN_BOOT_LOG_PROB");
+
+// swprintf(dap->szTemp, L"0x%08x", dwStatus);
+// SetListViewText(hwndListView, 0, dap->szTemp);
+}
+
+
+static VOID
+DisplayDevNodeEnumerator(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView)
+{
+ PSP_DEVINFO_DATA DeviceInfoData;
+
+ DWORD dwType = 0;
+ WCHAR szBuffer[256];
+ DWORD dwSize = 256 * sizeof(WCHAR);
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ CM_Get_DevNode_Registry_Property_ExW(DeviceInfoData->DevInst,
+ CM_DRP_ENUMERATOR_NAME,
+ &dwType,
+ &szBuffer,
+ &dwSize,
+ 0,
+ dap->hMachine);
+
+ SetListViewText(hwndListView, 0, szBuffer);
+}
+
+
+static VOID
+DisplayCsFlags(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView)
+{
+ DWORD dwValue = 0;
+ INT index;
+
+ CM_Get_HW_Prof_Flags_Ex(dap->szDevName,
+ 0, /* current hardware profile */
+ &dwValue,
+ 0,
+ dap->hMachine);
+
+ index = 0;
+ if (dwValue & CSCONFIGFLAG_DISABLED)
+ SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DISABLED");
+
+ if (dwValue & CSCONFIGFLAG_DO_NOT_CREATE)
+ SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_CREATE");
+
+ if (dwValue & CSCONFIGFLAG_DO_NOT_START)
+ SetListViewText(hwndListView, index++, L"CSCONFIGFLAG_DO_NOT_START");
+}
+
+
+static VOID
+DisplayMatchingDeviceId(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView)
+{
+ HDEVINFO DeviceInfoSet;
+ PSP_DEVINFO_DATA DeviceInfoData;
+ WCHAR szBuffer[256];
+ HKEY hKey;
+ DWORD dwSize;
+ DWORD dwType;
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
+ DeviceInfoData,
+ DICS_FLAG_GLOBAL,
+ 0,
+ DIREG_DRV,
+ KEY_QUERY_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ dwSize = 256 * sizeof(WCHAR);
+ if (RegQueryValueEx(hKey,
+ L"MatchingDeviceId",
+ NULL,
+ &dwType,
+ (LPBYTE)szBuffer,
+ &dwSize) == ERROR_SUCCESS)
+ {
+ SetListViewText(hwndListView, 0, szBuffer);
+ }
+
+ RegCloseKey(hKey);
+ }
+}
+
+
+static VOID
+DisplayClassCoinstallers(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView)
+{
+ HDEVINFO DeviceInfoSet;
+ PSP_DEVINFO_DATA DeviceInfoData;
+ WCHAR szClassGuid[45];
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ DWORD dwSize;
+ DWORD dwType;
+ LPBYTE lpBuffer = NULL;
+ LPWSTR lpStr;
+ INT index;
+ INT len;
+ LONG lError;
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ dwSize = 45 * sizeof(WCHAR);
+ if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
+ DeviceInfoData,
+ SPDRP_CLASSGUID,
+ &dwType,
+ (LPBYTE)szClassGuid,
+ dwSize,
+ &dwSize))
+ return;
+
+ lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
+ 0,
+ GENERIC_READ,
+ &hKey);
+ if (lError != ERROR_SUCCESS)
+ return;
+
+ dwSize = 0;
+ lError = RegQueryValueEx(hKey,
+ szClassGuid,
+ NULL,
+ &dwType,
+ NULL,
+ &dwSize);
+ if (lError != ERROR_SUCCESS)
+ goto done;
+
+ if (dwSize == 0)
+ goto done;
+
+ lpBuffer = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwSize);
+
+ RegQueryValueEx(hKey,
+ szClassGuid,
+ NULL,
+ &dwType,
+ lpBuffer,
+ &dwSize);
+
+ lpStr = (LPWSTR)lpBuffer;
+ index = 0;
+ while (*lpStr != 0)
+ {
+ len = wcslen(lpStr) + 1;
+
+ SetListViewText(hwndListView, index, lpStr);
+
+ lpStr += len;
+ index++;
+ }
+
+done:
+ if (lpBuffer != NULL)
+ HeapFree(GetProcessHeap(), 0, lpBuffer);
+
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+}
+
+
+static VOID
+DisplayDeviceCoinstallers(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView)
+{
+ HDEVINFO DeviceInfoSet;
+ PSP_DEVINFO_DATA DeviceInfoData;
+ HKEY hKey;
+ DWORD dwSize;
+ DWORD dwType;
+ LPBYTE lpBuffer;
+ LPWSTR lpStr;
+ INT index;
+ INT len;
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
+ DeviceInfoData,
+ DICS_FLAG_GLOBAL,
+ 0,
+ DIREG_DRV,
+ KEY_QUERY_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ dwSize = 0;
+ if (RegQueryValueEx(hKey,
+ L"CoInstallers32",
+ NULL,
+ &dwType,
+ NULL,
+ &dwSize) == ERROR_SUCCESS &&
+ dwSize > 0)
+ {
+
+ lpBuffer = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwSize);
+
+ RegQueryValueEx(hKey,
+ L"CoInstallers32",
+ NULL,
+ &dwType,
+ lpBuffer,
+ &dwSize);
+
+ lpStr = (LPWSTR)lpBuffer;
+ index = 0;
+ while (*lpStr != 0)
+ {
+ len = wcslen(lpStr) + 1;
+
+ SetListViewText(hwndListView, index, lpStr);
+
+ lpStr += len;
+ index++;
+ }
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpBuffer);
+ }
+
+ RegCloseKey(hKey);
+ }
+}
+
+
+static VOID
+DisplayClassProperties(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView,
+ IN LPWSTR lpProperty)
+{
+ HDEVINFO DeviceInfoSet;
+ PSP_DEVINFO_DATA DeviceInfoData;
+ WCHAR szClassGuid[45];
+ DWORD dwSize;
+ DWORD dwType;
+ HKEY hKey;
+ GUID ClassGuid;
+ LPBYTE lpBuffer;
+ LPWSTR lpStr;
+ INT index = 0;
+ INT len;
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ dwSize = 45 * sizeof(WCHAR);
+ if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
+ DeviceInfoData,
+ SPDRP_CLASSGUID,
+ &dwType,
+ (LPBYTE)szClassGuid,
+ dwSize,
+ &dwSize))
+ return;
+
+ pSetupGuidFromString(szClassGuid,
+ &ClassGuid);
+
+ hKey = SetupDiOpenClassRegKey(&ClassGuid,
+ KEY_QUERY_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ dwSize = 0;
+ if (RegQueryValueEx(hKey,
+ lpProperty,
+ NULL,
+ &dwType,
+ NULL,
+ &dwSize) == ERROR_SUCCESS &&
+ dwSize > 0)
+ {
+ lpBuffer = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwSize);
+
+ RegQueryValueEx(hKey,
+ lpProperty,
+ NULL,
+ &dwType,
+ lpBuffer,
+ &dwSize);
+
+ if (dwType == REG_SZ)
+ {
+ SetListViewText(hwndListView, 0, (LPWSTR)lpBuffer);
+ }
+ else if (dwType == REG_MULTI_SZ)
+ {
+ lpStr = (LPWSTR)lpBuffer;
+ index = 0;
+ while (*lpStr != 0)
+ {
+ len = wcslen(lpStr) + 1;
+
+ SetListViewText(hwndListView, index, lpStr);
+
+ lpStr += len;
+ index++;
+ }
+ }
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpBuffer);
+ }
+
+ RegCloseKey(hKey);
+ }
+}
+
+
+static VOID
+DisplayDeviceRelations(
+ IN PDEVADVPROP_INFO dap,
+ IN HWND hwndListView,
+ IN ULONG ulFlags)
+{
+ ULONG ulLength = 0;
+ LPWSTR pszBuffer = NULL, pszStr;
+ INT index = 0, len;
+
+ CONFIGRET ret;
+
+ ret = CM_Get_Device_ID_List_Size_ExW(&ulLength,
+ dap->szDeviceID,
+ ulFlags,
+ NULL);
+ if (ret != CR_SUCCESS)
+ return;
+
+ pszBuffer = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ ulLength);
+ if (pszBuffer == NULL)
+ return;
+
+ ret = CM_Get_Device_ID_List_ExW(dap->szDeviceID,
+ pszBuffer,
+ ulLength,
+ ulFlags,
+ NULL);
+ if (ret != CR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, pszBuffer);
+ return;
+ }
+
+ pszStr = pszBuffer;
+ index = 0;
+ while (*pszStr != 0)
+ {
+ len = wcslen(pszStr) + 1;
+
+ SetListViewText(hwndListView, index, pszStr);
+
+ pszStr += len;
+ index++;
+ }
+
+ HeapFree(GetProcessHeap(), 0, pszBuffer);
+}
+
+
+static VOID
+DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
+ IN HWND hwndComboBox,
+ IN HWND hwndListView)
+{
+ INT Index;
+
+ Index = (INT)SendMessage(hwndComboBox,
+ CB_GETCURSEL,
+ 0,
+ 0);
+ if (Index == CB_ERR)
+ return;
+
+ (void)ListView_DeleteAllItems(hwndListView);
+
+ switch (Index)
+ {
+ case 0:
+ SetListViewText(hwndListView, 0, dap->szDeviceID);
+ break;
+
+ case 1: /* Hardware ID */
+ DisplayDevicePropertyText(dap,
+ hwndListView,
+ SPDRP_HARDWAREID);
+ break;
+
+ case 2: /* Compatible IDs */
+ DisplayDevicePropertyText(dap,
+ hwndListView,
+ SPDRP_COMPATIBLEIDS);
+ break;
+
+ case 3: /* Matching ID */
+ DisplayMatchingDeviceId(dap,
+ hwndListView);
+ break;
+
+ case 4: /* Service */
+ DisplayDevicePropertyText(dap,
+ hwndListView,
+ SPDRP_SERVICE);
+ break;
+
+ case 5: /* Enumerator */
+ DisplayDevNodeEnumerator(dap,
+ hwndListView);
+ break;
+
+ case 6: /* Capabilities */
+ DisplayDevicePropertyText(dap,
+ hwndListView,
+ SPDRP_CAPABILITIES);
+ break;
+
+ case 7: /* Devnode Flags */
+ DisplayDevNodeFlags(dap,
+ hwndListView);
+ break;
+
+ case 8: /* Config Flags */
+ DisplayDevicePropertyText(dap,
+ hwndListView,
+ SPDRP_CONFIGFLAGS);
+ break;
+
+ case 9: /* CSConfig Flags */
+ DisplayCsFlags(dap,
+ hwndListView);
+ break;
+
+ case 10: /* Ejection relation */
+ DisplayDeviceRelations(dap,
+ hwndListView,
+ CM_GETIDLIST_FILTER_EJECTRELATIONS);
+ break;
+
+ case 11: /* Removal relations */
+ DisplayDeviceRelations(dap,
+ hwndListView,
+ CM_GETIDLIST_FILTER_REMOVALRELATIONS);
+ break;
+
+ case 12: /* Bus relation */
+ DisplayDeviceRelations(dap,
+ hwndListView,
+ CM_GETIDLIST_FILTER_BUSRELATIONS);
+ break;
+
+ case 13: /* Device Upper Filters */
+ DisplayDevicePropertyText(dap,
+ hwndListView,
+ SPDRP_UPPERFILTERS);
+ break;
+
+ case 14: /* Device Lower Filters */
+ DisplayDevicePropertyText(dap,
+ hwndListView,
+ SPDRP_LOWERFILTERS);
+ break;
+
+ case 15: /* Class Upper Filters */
+ DisplayClassProperties(dap,
+ hwndListView,
+ L"UpperFilters");
+ break;
+
+ case 16: /* Class Lower Filters */
+ DisplayClassProperties(dap,
+ hwndListView,
+ L"LowerFilters");
+ break;
+
+ case 17: /* Class Installer */
+ DisplayClassProperties(dap,
+ hwndListView,
+ L"Installer32");
+ break;
+
+ case 18: /* Class Coinstaller */
+ DisplayClassCoinstallers(dap,
+ hwndListView);
+ break;
+
+ case 19: /* Device Coinstaller */
+ DisplayDeviceCoinstallers(dap,
+ hwndListView);
+ break;
+
+#if 0
+ case 20: /* Firmware Revision */
+ break;
+
+ case 21: /* Current Power State */
+ break;
+
+ case 20: /* Power Capabilities */
+ break;
+
+ case 21: /* Power State Mappings */
+ break;
+#endif
+
+ default:
+ SetListViewText(hwndListView, 0, L"<Not implemented yet>");
+ break;
+ }
+}
+
+
+static INT_PTR
+CALLBACK
+AdvProcDetailsDlgProc(IN HWND hwndDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam)
+{
+ PDEVADVPROP_INFO dap;
+ INT_PTR Ret = FALSE;
+
+ dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
+ DWL_USER);
+
+ if (dap != NULL || uMsg == WM_INITDIALOG)
+ {
+ switch (uMsg)
+ {
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_DETAILSPROPNAME:
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ DisplayDeviceProperties(dap,
+ GetDlgItem(hwndDlg, IDC_DETAILSPROPNAME),
+ GetDlgItem(hwndDlg, IDC_DETAILSPROPVALUE));
+ }
+ break;
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ NMHDR *hdr = (NMHDR*)lParam;
+ switch (hdr->code)
+ {
+ case PSN_APPLY:
+ break;
+ }
+ break;
+ }
+
+ case WM_INITDIALOG:
+ {
+ dap = (PDEVADVPROP_INFO)((LPPROPSHEETPAGE)lParam)->lParam;
+ if (dap != NULL)
+ {
+ SetWindowLongPtr(hwndDlg,
+ DWL_USER,
+ (DWORD_PTR)dap);
+
+ UpdateDetailsDlg(hwndDlg,
+ dap);
+ }
+ Ret = TRUE;
+ break;
+ }
+ }
+ }
+
+ return Ret;
+}
+
+
+static VOID
+InitDevUsageActions(IN HWND hwndDlg,
+ IN HWND hComboBox,
+ IN PDEVADVPROP_INFO dap)
+{
+ INT Index;
+ UINT i;
+ UINT Actions[] =
+ {
+ IDS_ENABLEDEVICE,
+ IDS_DISABLEDEVICE,
+ };
+
+ for (i = 0;
+ i != sizeof(Actions) / sizeof(Actions[0]);
+ i++)
+ {
+ /* fill in the device usage combo box */
+ if (LoadString(hDllInstance,
+ Actions[i],
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ Index = (INT)SendMessage(hComboBox,
+ CB_ADDSTRING,
+ 0,
+ (LPARAM)dap->szTemp);
+ if (Index != CB_ERR)
+ {
+ SendMessage(hComboBox,
+ CB_SETITEMDATA,
+ (WPARAM)Index,
+ (LPARAM)Actions[i]);
+
+ switch (Actions[i])
+ {
+ case IDS_ENABLEDEVICE:
+ if (dap->DeviceStarted)
+ {
+ SendMessage(hComboBox,
+ CB_SETCURSEL,
+ (WPARAM)Index,
+ 0);
+ }
+ break;
+
+ case IDS_DISABLEDEVICE:
+ if (!dap->DeviceStarted)
+ {
+ SendMessage(hComboBox,
+ CB_SETCURSEL,
+ (WPARAM)Index,
+ 0);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+static UINT
+GetSelectedUsageAction(IN HWND hComboBox)
+{
+ INT Index;
+ UINT Ret = 0;
+
+ Index = (INT)SendMessage(hComboBox,
+ CB_GETCURSEL,
+ 0,
+ 0);
+ if (Index != CB_ERR)
+ {
+ INT iRet = (INT) SendMessage(hComboBox,
+ CB_GETITEMDATA,
+ (WPARAM)Index,
+ 0);
+ if (iRet != CB_ERR)
+ {
+ Ret = (UINT)iRet;
+ }
+ }
+
+ return Ret;
+}
+
+
+static BOOL
+ApplyGeneralSettings(IN HWND hwndDlg,
+ IN PDEVADVPROP_INFO dap)
+{
+ BOOL Ret = FALSE;
+
+ if (dap->DeviceUsageChanged && dap->IsAdmin && dap->CanDisable)
+ {
+ UINT SelectedUsageAction;
+ BOOL NeedReboot = FALSE;
+
+ SelectedUsageAction = GetSelectedUsageAction(GetDlgItem(hwndDlg,
+ IDC_DEVUSAGE));
+ switch (SelectedUsageAction)
+ {
+ case IDS_ENABLEDEVICE:
+ if (!dap->DeviceStarted)
+ {
+ Ret = EnableDevice(dap->DeviceInfoSet,
+ &dap->DeviceInfoData,
+ TRUE,
+ 0,
+ &NeedReboot);
+ }
+ break;
+
+ case IDS_DISABLEDEVICE:
+ if (dap->DeviceStarted)
+ {
+ Ret = EnableDevice(dap->DeviceInfoSet,
+ &dap->DeviceInfoData,
+ FALSE,
+ 0,
+ &NeedReboot);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (Ret)
+ {
+ if (NeedReboot)
+ {
+ /* make PropertySheet() return PSM_REBOOTSYSTEM */
+ PropSheet_RebootSystem(hwndDlg);
+ }
+ }
+ else
+ {
+ /* FIXME - display an error message */
+ FIXME("Failed to enable/disable device! LastError: %d\n",
+ GetLastError());
+ }
+ }
+ else
+ Ret = !dap->DeviceUsageChanged;
+
+ /* disable the apply button */
+ PropSheet_UnChanged(GetParent(hwndDlg),
+ hwndDlg);
+ dap->DeviceUsageChanged = FALSE;
+ return Ret;
+}
+
+
+static VOID
+UpdateDevInfo(IN HWND hwndDlg,
+ IN PDEVADVPROP_INFO dap,
+ IN BOOL ReOpen)
+{
+ HWND hDevUsage, hPropSheetDlg, hDevProbBtn;
+ CONFIGRET cr;
+ ULONG Status, ProblemNumber;
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ UINT TroubleShootStrId = IDS_TROUBLESHOOTDEV;
+ BOOL bFlag, bDevActionAvailable = TRUE;
+ BOOL bDrvInstalled = FALSE;
+ DWORD iPage;
+ HDEVINFO DeviceInfoSet = NULL;
+ PSP_DEVINFO_DATA DeviceInfoData = NULL;
+ PROPSHEETHEADER psh;
+ DWORD nDriverPages = 0;
+ BOOL RecalcPages = FALSE;
+
+ TRACE("UpdateDevInfo()\n");
+
+ hPropSheetDlg = GetParent(hwndDlg);
+
+ if (dap->PageInitialized)
+ {
+ /* switch to the General page */
+ PropSheet_SetCurSelByID(hPropSheetDlg,
+ IDD_DEVICEGENERAL);
+
+ /* remove and destroy the existing device property sheet pages */
+ if (dap->DevPropSheets != NULL)
+ {
+ for (iPage = 0;
+ iPage != dap->nDevPropSheets;
+ iPage++)
+ {
+ if (dap->DevPropSheets[iPage] != NULL)
+ {
+ PropSheet_RemovePage(hPropSheetDlg,
+ (WPARAM) -1,
+ dap->DevPropSheets[iPage]);
+ RecalcPages = TRUE;
+ }
+ }
+ }
+ }
+
+ iPage = 0;
+
+ 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;
+
+ if (ReOpen)
+ {
+ /* create a new device info set and re-open the device */
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ SetupDiDestroyDeviceInfoList(dap->CurrentDeviceInfoSet);
+ }
+
+ dap->ParentDevInst = 0;
+ dap->CurrentDeviceInfoSet = SetupDiCreateDeviceInfoListEx(NULL,
+ hwndDlg,
+ dap->lpMachineName,
+ NULL);
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ if (SetupDiOpenDeviceInfo(dap->CurrentDeviceInfoSet,
+ dap->szDeviceID,
+ hwndDlg,
+ 0,
+ &dap->CurrentDeviceInfoData))
+ {
+ if (dap->CloseDevInst)
+ {
+ SetupDiDestroyDeviceInfoList(dap->DeviceInfoSet);
+ }
+
+ dap->CloseDevInst = TRUE;
+ dap->DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ dap->DeviceInfoData = dap->CurrentDeviceInfoData;
+ dap->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
+ }
+ else
+ goto GetParentNode;
+ }
+ else
+ {
+GetParentNode:
+ /* get the parent node from the initial devinst */
+ CM_Get_Parent_Ex(&dap->ParentDevInst,
+ dap->DeviceInfoData.DevInst,
+ 0,
+ dap->hMachine);
+ }
+
+ if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ DeviceInfoSet = dap->CurrentDeviceInfoSet;
+ DeviceInfoData = &dap->CurrentDeviceInfoData;
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+ }
+ else
+ {
+ DeviceInfoSet = dap->DeviceInfoSet;
+ DeviceInfoData = &dap->DeviceInfoData;
+ }
+
+ dap->HasDriverPage = FALSE;
+ dap->HasResourcePage = FALSE;
+ dap->HasPowerPage = FALSE;
+ if (IsDriverInstalled(DeviceInfoData->DevInst,
+ dap->hMachine,
+ &bDrvInstalled) &&
+ bDrvInstalled)
+ {
+ if (SetupDiCallClassInstaller((dap->ShowRemotePages ?
+ DIF_ADDREMOTEPROPERTYPAGE_ADVANCED :
+ DIF_ADDPROPERTYPAGE_ADVANCED),
+ DeviceInfoSet,
+ DeviceInfoData))
+ {
+ /* get install params */
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
+ DeviceInfoData,
+ &InstallParams))
+ {
+ /* zero the flags */
+ InstallParams.Flags = 0;
+ }
+
+ dap->HasDriverPage = !(InstallParams.Flags & DI_DRIVERPAGE_ADDED);
+ dap->HasResourcePage = !(InstallParams.Flags & DI_RESOURCEPAGE_ADDED);
+ dap->HasPowerPage = !(InstallParams.Flags & DI_FLAGSEX_POWERPAGE_ADDED);
+ }
+ }
+
+ /* get the device icon */
+ if (dap->hDevIcon != NULL)
+ {
+ DestroyIcon(dap->hDevIcon);
+ dap->hDevIcon = NULL;
+ }
+ if (!SetupDiLoadClassIcon(&DeviceInfoData->ClassGuid,
+ &dap->hDevIcon,
+ NULL))
+ {
+ dap->hDevIcon = NULL;
+ }
+
+ /* get the device name */
+ if (GetDeviceDescriptionString(DeviceInfoSet,
+ DeviceInfoData,
+ dap->szDevName,
+ sizeof(dap->szDevName) / sizeof(dap->szDevName[0])))
+ {
+ PropSheet_SetTitle(hPropSheetDlg,
+ PSH_PROPTITLE,
+ dap->szDevName);
+ }
+
+ /* set the device image */
+ SendDlgItemMessage(hwndDlg,
+ IDC_DEVICON,
+ STM_SETICON,
+ (WPARAM)dap->hDevIcon,
+ 0);
+
+ /* set the device name edit control text */
+ SetDlgItemText(hwndDlg,
+ IDC_DEVNAME,
+ dap->szDevName);
+
+ /* set the device type edit control text */
+ if (GetDeviceTypeString(DeviceInfoData,
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ SetDlgItemText(hwndDlg,
+ IDC_DEVTYPE,
+ dap->szTemp);
+ }
+
+ /* set the device manufacturer edit control text */
+ if (GetDeviceManufacturerString(DeviceInfoSet,
+ DeviceInfoData,
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ SetDlgItemText(hwndDlg,
+ IDC_DEVMANUFACTURER,
+ dap->szTemp);
+ }
+
+ /* set the device location edit control text */
+ if (GetDeviceLocationString(DeviceInfoSet,
+ DeviceInfoData,
+ dap->ParentDevInst,
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ SetDlgItemText(hwndDlg,
+ IDC_DEVLOCATION,
+ dap->szTemp);
+ }
+
+ /* set the device status edit control text */
+ if (GetDeviceStatusString(DeviceInfoData->DevInst,
+ dap->hMachine,
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])))
+ {
+ SetDlgItemText(hwndDlg,
+ IDC_DEVSTATUS,
+ dap->szTemp);
+ }
+
+ /* set the device troubleshoot button text and disable it if necessary */
+ hDevProbBtn = GetDlgItem(hwndDlg,
+ IDC_DEVPROBLEM);
+ cr = CM_Get_DevNode_Status_Ex(&Status,
+ &ProblemNumber,
+ DeviceInfoData->DevInst,
+ 0,
+ dap->hMachine);
+ if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
+ {
+ switch (ProblemNumber)
+ {
+ case CM_PROB_DEVLOADER_FAILED:
+ {
+ /* FIXME - only if it's not a root bus devloader,
+ disable the button otherwise */
+ TroubleShootStrId = IDS_UPDATEDRV;
+ break;
+ }
+
+ case CM_PROB_OUT_OF_MEMORY:
+ case CM_PROB_ENTRY_IS_WRONG_TYPE:
+ case CM_PROB_LACKED_ARBITRATOR:
+ case CM_PROB_FAILED_START:
+ case CM_PROB_LIAR:
+ case CM_PROB_UNKNOWN_RESOURCE:
+ {
+ TroubleShootStrId = IDS_UPDATEDRV;
+ break;
+ }
+
+ case CM_PROB_BOOT_CONFIG_CONFLICT:
+ case CM_PROB_NORMAL_CONFLICT:
+ case CM_PROB_REENUMERATION:
+ {
+ /* FIXME - Troubleshoot conflict */
+ break;
+ }
+
+ case CM_PROB_FAILED_FILTER:
+ case CM_PROB_REINSTALL:
+ case CM_PROB_FAILED_INSTALL:
+ {
+ TroubleShootStrId = IDS_REINSTALLDRV;
+ break;
+ }
+
+ case CM_PROB_DEVLOADER_NOT_FOUND:
+ {
+ /* FIXME - 4 cases:
+ 1) if it's a missing system devloader:
+ - disable the button (Reinstall Driver)
+ 2) if it's not a system devloader but still missing:
+ - Reinstall Driver
+ 3) if it's not a system devloader but the file can be found:
+ - Update Driver
+ 4) if it's a missing or empty software key
+ - Update Driver
+ */
+ break;
+ }
+
+ case CM_PROB_INVALID_DATA:
+ case CM_PROB_PARTIAL_LOG_CONF:
+ case CM_PROB_NO_VALID_LOG_CONF:
+ case CM_PROB_HARDWARE_DISABLED:
+ case CM_PROB_CANT_SHARE_IRQ:
+ case CM_PROB_TRANSLATION_FAILED:
+ case CM_PROB_SYSTEM_SHUTDOWN:
+ case CM_PROB_PHANTOM:
+ bDevActionAvailable = FALSE;
+ break;
+
+ case CM_PROB_NOT_VERIFIED:
+ case CM_PROB_DEVICE_NOT_THERE:
+ /* FIXME - search hardware */
+ break;
+
+ case CM_PROB_NEED_RESTART:
+ case CM_PROB_WILL_BE_REMOVED:
+ case CM_PROB_MOVED:
+ case CM_PROB_TOO_EARLY:
+ case CM_PROB_DISABLED_SERVICE:
+ TroubleShootStrId = IDS_REBOOT;
+ break;
+
+ case CM_PROB_REGISTRY:
+ /* FIXME - check registry? */
+ break;
+
+ case CM_PROB_DISABLED:
+ /* if device was disabled by the user: */
+ TroubleShootStrId = IDS_ENABLEDEV;
+ /* FIXME - otherwise disable button because the device was
+ disabled by the system*/
+ break;
+
+ case CM_PROB_DEVLOADER_NOT_READY:
+ /* FIXME - if it's a graphics adapter:
+ - if it's a a secondary adapter and the main adapter
+ couldn't be found
+ - disable button
+ - else
+ - Properties
+ - else
+ - Update driver
+ */
+ break;
+
+ case CM_PROB_FAILED_ADD:
+ TroubleShootStrId = IDS_PROPERTIES;
+ break;
+ }
+ }
+
+ if (LoadString(hDllInstance,
+ TroubleShootStrId,
+ dap->szTemp,
+ sizeof(dap->szTemp) / sizeof(dap->szTemp[0])) != 0)
+ {
+ SetWindowText(hDevProbBtn,
+ dap->szTemp);
+ }
+ EnableWindow(hDevProbBtn,
+ dap->IsAdmin && bDevActionAvailable);
+
+ /* check if the device can be enabled/disabled */
+ hDevUsage = GetDlgItem(hwndDlg,
+ IDC_DEVUSAGE);
+
+ dap->CanDisable = FALSE;
+ dap->DeviceStarted = FALSE;
+
+ if (CanDisableDevice(DeviceInfoData->DevInst,
+ dap->hMachine,
+ &bFlag))
+ {
+ dap->CanDisable = bFlag;
+ }
+
+ if (IsDeviceStarted(DeviceInfoData->DevInst,
+ dap->hMachine,
+ &bFlag))
+ {
+ dap->DeviceStarted = bFlag;
+ }
+
+ /* enable/disable the device usage controls */
+ EnableWindow(GetDlgItem(hwndDlg,
+ IDC_DEVUSAGELABEL),
+ dap->CanDisable && dap->IsAdmin);
+ EnableWindow(hDevUsage,
+ dap->CanDisable && dap->IsAdmin);
+
+ /* clear the combobox */
+ SendMessage(hDevUsage,
+ CB_RESETCONTENT,
+ 0,
+ 0);
+ if (dap->CanDisable)
+ {
+ InitDevUsageActions(hwndDlg,
+ hDevUsage,
+ dap);
+ }
+
+ /* 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;
+
+ /* get the number of device property sheets for the device */
+ if (!SetupDiGetClassDevPropertySheets(DeviceInfoSet,
+ DeviceInfoData,
+ &psh,
+ 0,
+ &nDriverPages,
+ dap->PropertySheetType) &&
+ nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+TRACE("Count %d additional pages!\n", nDriverPages);
+ dap->nDevPropSheets += nDriverPages;
+ }
+ else
+ {
+ nDriverPages = 0;
+ }
+
+ /* include the driver page */
+ if (dap->HasDriverPage)
+ dap->nDevPropSheets++;
+
+ /* include the details page */
+ if (dap->Extended)
+ dap->nDevPropSheets++;
+
+ if (dap->HasResourcePage)
+ dap->nDevPropSheets++;
+
+ /* add the device property sheets */
+ if (dap->nDevPropSheets != 0)
+ {
+TRACE("Show %d pages!\n", dap->nDevPropSheets);
+ dap->DevPropSheets = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
+ if (dap->DevPropSheets != NULL)
+ {
+ if (nDriverPages != 0)
+ {
+ psh.phpage = dap->DevPropSheets;
+
+ /* query the device property sheet pages to add */
+ if (SetupDiGetClassDevPropertySheets(DeviceInfoSet,
+ DeviceInfoData,
+ &psh,
+ dap->nDevPropSheets,
+ NULL,
+ dap->PropertySheetType))
+ {
+ /* add the property sheets */
+ for (iPage = 0;
+ iPage < nDriverPages;
+ iPage++)
+ {
+TRACE("Add page %d\n", iPage);
+TRACE("Sheet %p\n", dap->DevPropSheets[iPage]);
+
+ if (PropSheet_AddPage(hPropSheetDlg,
+ dap->DevPropSheets[iPage]))
+ {
+ RecalcPages = TRUE;
+ }
+ else
+ {
+TRACE("PropSheet_AddPage() failed\n");
+ }
+ }
+
+ dap->FreeDevPropSheets = TRUE;
+ }
+ else
+ {
+TRACE("SetupDiGetClassDevPropertySheets() failed\n");
+ /* cleanup, we were unable to get the device property sheets */
+ iPage = nDriverPages;
+ dap->nDevPropSheets -= nDriverPages;
+ nDriverPages = 0;
+ }
+ }
+ else
+ iPage = 0;
+
+ /* add the driver page if necessary */
+ if (dap->HasDriverPage)
+ {
+ PROPSHEETPAGE pspDriver = {0};
+ pspDriver.dwSize = sizeof(PROPSHEETPAGE);
+ pspDriver.dwFlags = PSP_DEFAULT;
+ pspDriver.hInstance = hDllInstance;
+ pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDRIVER);
+ pspDriver.pfnDlgProc = AdvProcDriverDlgProc;
+ pspDriver.lParam = (LPARAM)dap;
+ dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
+ if (dap->DevPropSheets[iPage] != NULL)
+ {
+ if (PropSheet_AddPage(hPropSheetDlg,
+ dap->DevPropSheets[iPage]))
+ {
+ iPage++;
+ RecalcPages = TRUE;
+ }
+ else
+ {
+ dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
+ dap->DevPropSheets[iPage] = NULL;
+ }
+ }
+ }
+
+ if (dap->Extended)
+ {
+ /* Add the details page */
+ PROPSHEETPAGE pspDetails = {0};
+ pspDetails.dwSize = sizeof(PROPSHEETPAGE);
+ pspDetails.dwFlags = PSP_DEFAULT;
+ pspDetails.hInstance = hDllInstance;
+ pspDetails.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEDETAILS);
+ pspDetails.pfnDlgProc = AdvProcDetailsDlgProc;
+ pspDetails.lParam = (LPARAM)dap;
+ dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDetails);
+ if (dap->DevPropSheets[iPage] != NULL)
+ {
+ if (PropSheet_AddPage(hPropSheetDlg,
+ dap->DevPropSheets[iPage]))
+ {
+ iPage++;
+ RecalcPages = TRUE;
+ }
+ else
+ {
+ dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
+ dap->DevPropSheets[iPage] = NULL;
+ }
+ }
+ }
+
+ if (dap->HasResourcePage)
+ {
+ PROPSHEETPAGE pspDriver = {0};
+ pspDriver.dwSize = sizeof(PROPSHEETPAGE);
+ pspDriver.dwFlags = PSP_DEFAULT;
+ pspDriver.hInstance = hDllInstance;
+ pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICERESOURCES);
+ pspDriver.pfnDlgProc = ResourcesProcDriverDlgProc;
+ pspDriver.lParam = (LPARAM)dap;
+ dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
+ if (dap->DevPropSheets[iPage] != NULL)
+ {
+ if (PropSheet_AddPage(hPropSheetDlg,
+ dap->DevPropSheets[iPage]))
+ {
+ iPage++;
+ RecalcPages = TRUE;
+ }
+ else
+ {
+ dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
+ dap->DevPropSheets[iPage] = NULL;
+ }
+ }
+ }
+ /* FIXME: Add the power page */
+ }
+ else
+ dap->nDevPropSheets = 0;
+ }
+
+ if (RecalcPages)
+ {
+ PropSheet_RecalcPageSizes(hPropSheetDlg);
+ }
+
+ /* finally, disable the apply button */
+ 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,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam)
+{
+ PDEVADVPROP_INFO dap;
+ INT_PTR Ret = FALSE;
+
+ dap = (PDEVADVPROP_INFO)GetWindowLongPtr(hwndDlg,
+ DWL_USER);
+
+ if (dap != NULL || uMsg == WM_INITDIALOG)
+ {
+ switch (uMsg)
+ {
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_DEVUSAGE:
+ {
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ PropSheet_Changed(GetParent(hwndDlg),
+ hwndDlg);
+ dap->DeviceUsageChanged = TRUE;
+ }
+ break;
+ }
+
+ case IDC_DEVPROBLEM:
+ {
+ if (dap->IsAdmin)
+ {
+ /* display the device problem wizard */
+ ShowDeviceProblemWizard(hwndDlg,
+ dap->DeviceInfoSet,
+ &dap->DeviceInfoData,
+ dap->hMachine);
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ NMHDR *hdr = (NMHDR*)lParam;
+ switch (hdr->code)
+ {
+ case PSN_APPLY:
+ ApplyGeneralSettings(hwndDlg,
+ dap);
+ break;
+ }
+ break;
+ }
+
+ case WM_INITDIALOG:
+ {
+ 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;
+ }
+ }
+
+ /* do not call UpdateDevInfo directly in here because it modifies
+ the pages of the property sheet! */
+ PostMessage(hwndDlg,
+ PM_INITIALIZE,
+ 0,
+ 0);
+ }
+ Ret = TRUE;
+ break;
+ }
+
+ case WM_DEVICECHANGE:
+ {
+ /* FIXME - don't call UpdateDevInfo for all events */
+ UpdateDevInfo(hwndDlg,
+ dap,
+ TRUE);
+ Ret = TRUE;
+ break;
+ }
+
+ case PM_INITIALIZE:
+ {
+ UpdateDevInfo(hwndDlg,
+ dap,
+ FALSE);
+ dap->PageInitialized = TRUE;
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ /* restore the old window proc of the subclassed parent window */
+ if (dap->hWndParent != NULL && dap->ParentOldWndProc != NULL)
+ {
+ if (SetWindowLongPtr(dap->hWndParent,
+ GWLP_WNDPROC,
+ (LONG_PTR)dap->ParentOldWndProc) == (LONG_PTR)DlgParentSubWndProc)
+ {
+ RemoveProp(dap->hWndParent,
+ L"DevMgrDevChangeSub");
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ return Ret;
+}
+
+
+INT_PTR
+DisplayDeviceAdvancedProperties(IN HWND hWndParent,
+ IN LPCWSTR lpDeviceID OPTIONAL,
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN HINSTANCE hComCtl32,
+ IN LPCWSTR lpMachineName,
+ IN DWORD dwFlags)
+{
+ PROPSHEETHEADER psh = {0};
+ PROPSHEETPAGE pspGeneral = {0};
+ PPROPERTYSHEETW pPropertySheetW;
+ PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
+ PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
+ PDEVADVPROP_INFO DevAdvPropInfo;
+ HMACHINE hMachine = NULL;
+ DWORD DevIdSize = 0;
+ INT_PTR Ret = -1;
+
+ /* we don't want to statically link against comctl32, so find the
+ functions we need dynamically */
+ pPropertySheetW =
+ (PPROPERTYSHEETW)GetProcAddress(hComCtl32,
+ "PropertySheetW");
+ pCreatePropertySheetPageW =
+ (PCREATEPROPERTYSHEETPAGEW)GetProcAddress(hComCtl32,
+ "CreatePropertySheetPageW");
+ pDestroyPropertySheetPage =
+ (PDESTROYPROPERTYSHEETPAGE)GetProcAddress(hComCtl32,
+ "DestroyPropertySheetPage");
+ if (pPropertySheetW == NULL ||
+ pCreatePropertySheetPageW == NULL ||
+ pDestroyPropertySheetPage == NULL)
+ {
+ return -1;
+ }
+
+ if (lpDeviceID == NULL)
+ {
+ /* find out how much size is needed for the device id */
+ if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
+ DeviceInfoData,
+ NULL,
+ 0,
+ &DevIdSize))
+ {
+ ERR("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
+ return -1;
+ }
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ DevIdSize = (DWORD)wcslen(lpDeviceID) + 1;
+ }
+
+ if (lpMachineName != NULL && lpMachineName[0] != L'\0')
+ {
+ CONFIGRET cr = CM_Connect_Machine(lpMachineName,
+ &hMachine);
+ if (cr != CR_SUCCESS)
+ {
+ return -1;
+ }
+ }
+
+ /* create the internal structure associated with the "General",
+ "Driver", ... pages */
+ DevAdvPropInfo = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ FIELD_OFFSET(DEVADVPROP_INFO,
+ szDeviceID) +
+ (DevIdSize * sizeof(WCHAR)));
+ if (DevAdvPropInfo == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto Cleanup;
+ }
+
+ if (lpDeviceID == NULL)
+ {
+ /* read the device instance id */
+ if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
+ DeviceInfoData,
+ DevAdvPropInfo->szDeviceID,
+ DevIdSize,
+ NULL))
+ {
+ goto Cleanup;
+ }
+ }
+ else
+ {
+ /* copy the device instance id supplied by the caller */
+ wcscpy(DevAdvPropInfo->szDeviceID,
+ lpDeviceID);
+ }
+
+ DevAdvPropInfo->DeviceInfoSet = DeviceInfoSet;
+ DevAdvPropInfo->DeviceInfoData = *DeviceInfoData;
+ DevAdvPropInfo->CurrentDeviceInfoSet = INVALID_HANDLE_VALUE;
+ DevAdvPropInfo->CurrentDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+
+ DevAdvPropInfo->ShowRemotePages = (lpMachineName != NULL && lpMachineName[0] != L'\0');
+ DevAdvPropInfo->hMachine = hMachine;
+ DevAdvPropInfo->lpMachineName = lpMachineName;
+ DevAdvPropInfo->szDevName[0] = L'\0';
+ DevAdvPropInfo->hComCtl32 = hComCtl32;
+ DevAdvPropInfo->pCreatePropertySheetPageW = pCreatePropertySheetPageW;
+ DevAdvPropInfo->pDestroyPropertySheetPage = pDestroyPropertySheetPage;
+
+ DevAdvPropInfo->IsAdmin = IsUserAdmin();
+ DevAdvPropInfo->DoDefaultDevAction = ((dwFlags & DPF_DEVICE_STATUS_ACTION) != 0);
+ DevAdvPropInfo->Extended = ((dwFlags & DPF_EXTENDED) != 0);
+
+ psh.dwSize = sizeof(PROPSHEETHEADER);
+ psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
+ psh.hwndParent = hWndParent;
+ psh.pszCaption = DevAdvPropInfo->szDevName;
+
+ DevAdvPropInfo->PropertySheetType = DevAdvPropInfo->ShowRemotePages ?
+ DIGCDP_FLAG_REMOTE_ADVANCED :
+ DIGCDP_FLAG_ADVANCED;
+
+ psh.phpage = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ 1 * sizeof(HPROPSHEETPAGE));
+ if (psh.phpage == NULL)
+ {
+ goto Cleanup;
+ }
+
+ /* add the "General" property sheet */
+ pspGeneral.dwSize = sizeof(PROPSHEETPAGE);
+ pspGeneral.dwFlags = PSP_DEFAULT;
+ pspGeneral.hInstance = hDllInstance;
+ pspGeneral.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICEGENERAL);
+ pspGeneral.pfnDlgProc = AdvPropGeneralDlgProc;
+ pspGeneral.lParam = (LPARAM)DevAdvPropInfo;
+ psh.phpage[psh.nPages] = pCreatePropertySheetPageW(&pspGeneral);
+ if (psh.phpage[psh.nPages] != NULL)
+ {
+ psh.nPages++;
+ }
+
+ DevAdvPropInfo->nDevPropSheets = psh.nPages;
+
+ if (psh.nPages != 0)
+ {
+ Ret = pPropertySheetW(&psh);
+
+ /* NOTE: no need to destroy the property sheets anymore! */
+ }
+ else
+ {
+ UINT i;
+
+Cleanup:
+ /* in case of failure the property sheets must be destroyed */
+ if (psh.phpage != NULL)
+ {
+ for (i = 0;
+ i < psh.nPages;
+ i++)
+ {
+ if (psh.phpage[i] != NULL)
+ {
+ pDestroyPropertySheetPage(psh.phpage[i]);
+ }
+ }
+ }
+ }
+
+ if (DevAdvPropInfo != NULL)
+ {
+ if (DevAdvPropInfo->FreeDevPropSheets)
+ {
+ /* don't free the array if it's the one allocated in
+ DisplayDeviceAdvancedProperties */
+ HeapFree(GetProcessHeap(),
+ 0,
+ DevAdvPropInfo->DevPropSheets);
+ }
+
+ if (DevAdvPropInfo->CloseDevInst)
+ {
+ /* close the device info set in case a new one was created */
+ SetupDiDestroyDeviceInfoList(DevAdvPropInfo->DeviceInfoSet);
+ }
+
+ if (DevAdvPropInfo->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+ {
+ SetupDiDestroyDeviceInfoList(DevAdvPropInfo->CurrentDeviceInfoSet);
+ }
+
+ if (DevAdvPropInfo->hDevIcon != NULL)
+ {
+ DestroyIcon(DevAdvPropInfo->hDevIcon);
+ }
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ DevAdvPropInfo);
+ }
+
+ if (psh.phpage != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ psh.phpage);
+ }
+
+ if (hMachine != NULL)
+ {
+ CM_Disconnect_Machine(hMachine);
+ }
+
+ return Ret;
+}
+
+
+static BOOL
+GetDeviceAndComputerName(LPWSTR lpString,
+ WCHAR szDeviceID[],
+ WCHAR szMachineName[])
+{
+ BOOL ret = FALSE;
+
+ szDeviceID[0] = L'\0';
+ szMachineName[0] = L'\0';
+
+ while (*lpString != L'\0')
+ {
+ if (*lpString == L'/')
+ {
+ lpString++;
+ if(!_wcsnicmp(lpString, L"DeviceID", 8))
+ {
+ lpString += 9;
+ if (*lpString != L'\0')
+ {
+ int i = 0;
+ while ((*lpString != L' ') &&
+ (*lpString != L'\0') &&
+ (i <= MAX_DEVICE_ID_LEN))
+ {
+ szDeviceID[i++] = *lpString++;
+ }
+ szDeviceID[i] = L'\0';
+ ret = TRUE;
+ }
+ }
+ else if (!_wcsnicmp(lpString, L"MachineName", 11))
+ {
+ lpString += 12;
+ if (*lpString != L'\0')
+ {
+ int i = 0;
+ while ((*lpString != L' ') &&
+ (*lpString != L'\0') &&
+ (i <= MAX_COMPUTERNAME_LENGTH))
+ {
+ szMachineName[i++] = *lpString++;
+ }
+ szMachineName[i] = L'\0';
+ }
+ }
+ /* knock the pointer back one and let the next
+ * pointer deal with incrementing, otherwise we
+ * go past the end of the string */
+ lpString--;
+ }
+ lpString++;
+ }
+
+ return ret;
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DeviceAdvancedPropertiesW
+ *
+ * DESCRIPTION
+ * Invokes the device properties dialog, this version may add some property pages
+ * for some devices
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * lpMachineName: Machine Name, NULL is the local machine
+ * lpDeviceID: Specifies the device whose properties are to be shown
+ *
+ * RETURN VALUE
+ * Always returns -1, a call to GetLastError returns 0 if successful
+ *
+ * @implemented
+ */
+INT_PTR
+WINAPI
+DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL,
+ IN LPCWSTR lpMachineName OPTIONAL,
+ IN LPCWSTR lpDeviceID)
+{
+ HDEVINFO hDevInfo;
+ SP_DEVINFO_DATA DevInfoData;
+ HINSTANCE hComCtl32;
+ INT_PTR Ret = -1;
+
+ if (lpDeviceID == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* dynamically load comctl32 */
+ hComCtl32 = LoadAndInitComctl32();
+ if (hComCtl32 != NULL)
+ {
+ hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
+ hWndParent,
+ lpMachineName,
+ NULL);
+ if (hDevInfo != INVALID_HANDLE_VALUE)
+ {
+ DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ if (SetupDiOpenDeviceInfo(hDevInfo,
+ lpDeviceID,
+ hWndParent,
+ 0,
+ &DevInfoData))
+ {
+ Ret = DisplayDeviceAdvancedProperties(hWndParent,
+ lpDeviceID,
+ hDevInfo,
+ &DevInfoData,
+ hComCtl32,
+ lpMachineName,
+ 0);
+ }
+
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+ }
+
+ FreeLibrary(hComCtl32);
+ }
+
+ return Ret;
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DeviceAdvancedPropertiesA
+ *
+ * DESCRIPTION
+ * Invokes the device properties dialog, this version may add some property pages
+ * for some devices
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * lpMachineName: Machine Name, NULL is the local machine
+ * lpDeviceID: Specifies the device whose properties are to be shown
+ *
+ * RETURN VALUE
+ * Always returns -1, a call to GetLastError returns 0 if successful
+ *
+ * @implemented
+ */
+INT_PTR
+WINAPI
+DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL,
+ IN LPCSTR lpMachineName OPTIONAL,
+ IN LPCSTR lpDeviceID)
+{
+ LPWSTR lpMachineNameW = NULL;
+ LPWSTR lpDeviceIDW = NULL;
+ INT_PTR Ret = -1;
+
+ if (lpMachineName != NULL)
+ {
+ if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
+ CP_ACP)))
+ {
+ goto Cleanup;
+ }
+ }
+ if (lpDeviceID != NULL)
+ {
+ if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
+ CP_ACP)))
+ {
+ goto Cleanup;
+ }
+ }
+
+ Ret = DeviceAdvancedPropertiesW(hWndParent,
+ lpMachineNameW,
+ lpDeviceIDW);
+
+Cleanup:
+ if (lpMachineNameW != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpMachineNameW);
+ }
+ if (lpDeviceIDW != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpDeviceIDW);
+ }
+
+ return Ret;
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DevicePropertiesExA
+ *
+ * DESCRIPTION
+ * Invokes the extended device properties dialog
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * lpMachineName: Machine Name, NULL is the local machine
+ * lpDeviceID: Specifies the device whose properties are to be shown, optional if
+ * bShowDevMgr is nonzero
+ * dwFlags: This parameter can be a combination of the following flags:
+ * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
+ * the default device status action button
+ * to be clicked (Troubleshoot, Enable
+ * Device, etc)
+ * bShowDevMgr: If non-zero it displays the device manager instead of
+ * the advanced device property dialog
+ *
+ * RETURN VALUE
+ * 1: if bShowDevMgr is non-zero and no error occured
+ * -1: a call to GetLastError returns 0 if successful
+ *
+ * @implemented
+ */
+INT_PTR
+WINAPI
+DevicePropertiesExA(IN HWND hWndParent OPTIONAL,
+ IN LPCSTR lpMachineName OPTIONAL,
+ IN LPCSTR lpDeviceID OPTIONAL,
+ IN DWORD dwFlags OPTIONAL,
+ IN BOOL bShowDevMgr)
+{
+ LPWSTR lpMachineNameW = NULL;
+ LPWSTR lpDeviceIDW = NULL;
+ INT_PTR Ret = -1;
+
+ if (lpMachineName != NULL)
+ {
+ if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
+ CP_ACP)))
+ {
+ goto Cleanup;
+ }
+ }
+ if (lpDeviceID != NULL)
+ {
+ if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
+ CP_ACP)))
+ {
+ goto Cleanup;
+ }
+ }
+
+ Ret = DevicePropertiesExW(hWndParent,
+ lpMachineNameW,
+ lpDeviceIDW,
+ dwFlags,
+ bShowDevMgr);
+
+Cleanup:
+ if (lpMachineNameW != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpMachineNameW);
+ }
+ if (lpDeviceIDW != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpDeviceIDW);
+ }
+
+ return Ret;
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DevicePropertiesExW
+ *
+ * DESCRIPTION
+ * Invokes the extended device properties dialog
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * lpMachineName: Machine Name, NULL is the local machine
+ * lpDeviceID: Specifies the device whose properties are to be shown, optional if
+ * bShowDevMgr is nonzero
+ * dwFlags: This parameter can be a combination of the following flags:
+ * * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
+ * the default device status action button
+ * to be clicked (Troubleshoot, Enable
+ * Device, etc)
+ * bShowDevMgr: If non-zero it displays the device manager instead of
+ * the advanced device property dialog
+ *
+ * RETURN VALUE
+ * 1: if bShowDevMgr is non-zero and no error occured
+ * -1: a call to GetLastError returns 0 if successful
+ *
+ * @implemented
+ */
+INT_PTR
+WINAPI
+DevicePropertiesExW(IN HWND hWndParent OPTIONAL,
+ IN LPCWSTR lpMachineName OPTIONAL,
+ IN LPCWSTR lpDeviceID OPTIONAL,
+ IN DWORD dwFlags OPTIONAL,
+ IN BOOL bShowDevMgr)
+{
+ INT_PTR Ret = -1;
+
+ if (dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION))
+ {
+ FIXME("DevPropertiesExW: Invalid flags: 0x%x\n",
+ dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION));
+ SetLastError(ERROR_INVALID_FLAGS);
+ return -1;
+ }
+
+ if (bShowDevMgr)
+ {
+ FIXME("DevPropertiesExW doesn't support bShowDevMgr!\n");
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ }
+ else
+ {
+ HDEVINFO hDevInfo;
+ SP_DEVINFO_DATA DevInfoData;
+ HINSTANCE hComCtl32;
+
+ if (lpDeviceID == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ /* dynamically load comctl32 */
+ hComCtl32 = LoadAndInitComctl32();
+ if (hComCtl32 != NULL)
+ {
+ hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
+ hWndParent,
+ lpMachineName,
+ NULL);
+ if (hDevInfo != INVALID_HANDLE_VALUE)
+ {
+ DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ if (SetupDiOpenDeviceInfo(hDevInfo,
+ lpDeviceID,
+ hWndParent,
+ 0,
+ &DevInfoData))
+ {
+ Ret = DisplayDeviceAdvancedProperties(hWndParent,
+ lpDeviceID,
+ hDevInfo,
+ &DevInfoData,
+ hComCtl32,
+ lpMachineName,
+ dwFlags);
+ }
+
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+ }
+
+ FreeLibrary(hComCtl32);
+ }
+ }
+
+ return Ret;
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DevicePropertiesA
+ *
+ * DESCRIPTION
+ * Invokes the device properties dialog directly
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * lpMachineName: Machine Name, NULL is the local machine
+ * lpDeviceID: Specifies the device whose properties are to be shown
+ * bShowDevMgr: If non-zero it displays the device manager instead of
+ * the device property dialog
+ *
+ * RETURN VALUE
+ * >=0: if no errors occured
+ * -1: if errors occured
+ *
+ * REVISIONS
+ *
+ * @implemented
+ */
+int
+WINAPI
+DevicePropertiesA(HWND hWndParent,
+ LPCSTR lpMachineName,
+ LPCSTR lpDeviceID,
+ BOOL bShowDevMgr)
+{
+ return DevicePropertiesExA(hWndParent,
+ lpMachineName,
+ lpDeviceID,
+ DPF_EXTENDED,
+ bShowDevMgr);
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DevicePropertiesW
+ *
+ * DESCRIPTION
+ * Invokes the device properties dialog directly
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * lpMachineName: Machine Name, NULL is the local machine
+ * lpDeviceID: Specifies the device whose properties are to be shown
+ * bShowDevMgr: If non-zero it displays the device manager instead of
+ * the device property dialog
+ *
+ * RETURN VALUE
+ * >=0: if no errors occured
+ * -1: if errors occured
+ *
+ * REVISIONS
+ *
+ * @implemented
+ */
+int
+WINAPI
+DevicePropertiesW(HWND hWndParent,
+ LPCWSTR lpMachineName,
+ LPCWSTR lpDeviceID,
+ BOOL bShowDevMgr)
+{
+ return DevicePropertiesExW(hWndParent,
+ lpMachineName,
+ lpDeviceID,
+ DPF_EXTENDED,
+ bShowDevMgr);
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DeviceProperties_RunDLLA
+ *
+ * DESCRIPTION
+ * Invokes the device properties dialog
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * hInst: Handle to the application instance
+ * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
+ * also see NOTEs
+ * nCmdShow: Specifies how the window should be shown
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ *
+ * NOTE
+ * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
+ * (/MachineName is optional). This function only parses this string and eventually
+ * calls DeviceProperties().
+ *
+ * @implemented
+ */
+VOID
+WINAPI
+DeviceProperties_RunDLLA(HWND hWndParent,
+ HINSTANCE hInst,
+ LPCSTR lpDeviceCmd,
+ int nCmdShow)
+{
+ LPWSTR lpDeviceCmdW = NULL;
+
+ if (lpDeviceCmd != NULL)
+ {
+ if ((lpDeviceCmdW = ConvertMultiByteToUnicode(lpDeviceCmd,
+ CP_ACP)))
+ {
+ DeviceProperties_RunDLLW(hWndParent,
+ hInst,
+ lpDeviceCmdW,
+ nCmdShow);
+ }
+ }
+
+ if (lpDeviceCmdW != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpDeviceCmdW);
+ }
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DeviceProperties_RunDLLW
+ *
+ * DESCRIPTION
+ * Invokes the device properties dialog
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * hInst: Handle to the application instance
+ * lpDeviceCmd: A command that includes the DeviceID of the properties to be shown,
+ * also see NOTEs
+ * nCmdShow: Specifies how the window should be shown
+ *
+ * RETURN VALUE
+ *
+ * REVISIONS
+ *
+ * NOTE
+ * - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH"
+ * (/MachineName is optional). This function only parses this string and eventually
+ * calls DeviceProperties().
+ *
+ * @implemented
+ */
+VOID
+WINAPI
+DeviceProperties_RunDLLW(HWND hWndParent,
+ HINSTANCE hInst,
+ LPCWSTR lpDeviceCmd,
+ int nCmdShow)
+{
+ WCHAR szDeviceID[MAX_DEVICE_ID_LEN+1];
+ WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+1];
+ LPWSTR lpString = (LPWSTR)lpDeviceCmd;
+
+ if (!GetDeviceAndComputerName(lpString,
+ szDeviceID,
+ szMachineName))
+ {
+ ERR("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID, szMachineName);
+ return;
+ }
+
+ DevicePropertiesW(hWndParent,
+ szMachineName,
+ szDeviceID,
+ FALSE);
+}
--- /dev/null
+/*
+* PROJECT: ReactOS Device Manager
+* LICENSE: GPL - See COPYING in the top level directory
+* FILE: dll/win32/devmgr/devmgr/ClassNode.cpp
+* PURPOSE: Class object for
+* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
+*
+*/
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "ClassNode.h"
+
+
+CClassNode::CClassNode(
+ _In_ LPGUID ClassGuid,
+ _In_ PSP_CLASSIMAGELIST_DATA ImageListData
+ ) :
+ CNode(ClassNode, ImageListData)
+{
+ CopyMemory(&m_ClassGuid, ClassGuid, sizeof(GUID));
+}
+
+
+CClassNode::~CClassNode()
+{
+}
+
+
+bool
+CClassNode::SetupNode()
+{
+ DWORD RequiredSize, Type, Size;
+ DWORD Success;
+ HKEY hKey;
+
+ // Open the registry key for this class
+ hKey = SetupDiOpenClassRegKeyExW(&m_ClassGuid,
+ MAXIMUM_ALLOWED,
+ DIOCR_INSTALLER,
+ NULL,
+ 0);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ Size = DISPLAY_NAME_LEN;
+ Type = REG_SZ;
+
+ // Lookup the class description (win7+)
+ Success = RegQueryValueExW(hKey,
+ L"ClassDesc",
+ NULL,
+ &Type,
+ (LPBYTE)m_DisplayName,
+ &Size);
+ if (Success == ERROR_SUCCESS)
+ {
+ // Check if the string starts with an @
+ if (m_DisplayName[0] == L'@')
+ {
+ // The description is located in a module resource
+ Success = ConvertResourceDescriptorToString(m_DisplayName, DISPLAY_NAME_LEN);
+ }
+ }
+ else if (Success == ERROR_FILE_NOT_FOUND)
+ {
+ // WinXP stores the description in the default value
+ Success = RegQueryValueExW(hKey,
+ NULL,
+ NULL,
+ &Type,
+ (LPBYTE)m_DisplayName,
+ &Size);
+ }
+
+ // Close the registry key
+ RegCloseKey(hKey);
+ }
+ else
+ {
+ Success = GetLastError();
+ }
+
+ // Check if we failed to get the class description
+ if (Success != ERROR_SUCCESS)
+ {
+ // Use the class name as the description
+ RequiredSize = DISPLAY_NAME_LEN;
+ (VOID)SetupDiClassNameFromGuidW(&m_ClassGuid,
+ m_DisplayName,
+ RequiredSize,
+ &RequiredSize);
+ }
+
+ // Get the image index for this class
+ (VOID)SetupDiGetClassImageIndex(m_ImageListData,
+ &m_ClassGuid,
+ &m_ClassImage);
+
+ return true;
+}
+
+
+DWORD
+CClassNode::ConvertResourceDescriptorToString(
+ _Inout_z_ LPWSTR ResourceDescriptor,
+ _In_ DWORD ResourceDescriptorSize
+ )
+{
+ WCHAR ModulePath[MAX_PATH];
+ WCHAR ResString[256];
+ INT ResourceId;
+ HMODULE hModule;
+ LPWSTR ptr;
+ DWORD Size;
+ DWORD dwError;
+
+
+ // First check for a semi colon */
+ ptr = wcschr(ResourceDescriptor, L';');
+ if (ptr)
+ {
+ // This must be an inf based descriptor, the desc is after the semi colon
+ StringCbCopyW(ResourceDescriptor, ResourceDescriptorSize, ++ptr);
+ dwError = ERROR_SUCCESS;
+ }
+ else
+ {
+ // This must be a dll resource based descriptor. Find the comma
+ ptr = wcschr(ResourceDescriptor, L',');
+ if (ptr == NULL) return ERROR_INVALID_DATA;
+
+ // Terminate the string where the comma was
+ *ptr = UNICODE_NULL;
+
+ // Expand any environment strings
+ Size = ExpandEnvironmentStringsW(&ResourceDescriptor[1], ModulePath, MAX_PATH);
+ if (Size > MAX_PATH) return ERROR_BUFFER_OVERFLOW;
+ if (Size == 0) return GetLastError();
+
+ // Put the comma back and move past it
+ *ptr = L',';
+ ptr++;
+
+ // Load the dll
+ hModule = LoadLibraryExW(ModulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
+ if (hModule == NULL) return GetLastError();
+
+ // Convert the resource id to a number
+ ResourceId = _wtoi(ptr);
+
+ // If the number is negative, make it positive
+ if (ResourceId < 0) ResourceId = -ResourceId;
+
+ // Load the string from the dll
+ if (LoadStringW(hModule, ResourceId, ResString, 256))
+ {
+ StringCbCopyW(ResourceDescriptor, ResourceDescriptorSize, ResString);
+ dwError = ERROR_SUCCESS;
+ }
+ else
+ {
+ dwError = GetLastError();
+ }
+
+ // Free the library
+ FreeLibrary(hModule);
+ }
+
+ return dwError;
+}
--- /dev/null
+#pragma once
+#include "Node.h"
+
+class CClassNode : public CNode
+{
+public:
+
+ CClassNode(
+ _In_ LPGUID ClassGuid,
+ _In_ PSP_CLASSIMAGELIST_DATA ImageListData
+ );
+
+ ~CClassNode();
+
+ virtual bool SetupNode();
+
+private:
+
+ DWORD ConvertResourceDescriptorToString(
+ _Inout_z_ LPWSTR ResourceDescriptor,
+ _In_ DWORD ResourceDescriptorSize
+ );
+};
+
--- /dev/null
+/*
+* PROJECT: ReactOS Device Manager
+* LICENSE: GPL - See COPYING in the top level directory
+* FILE: dll/win32/devmgr/devmgr/ClassNode.cpp
+* PURPOSE: Class object for
+* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
+*
+*/
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "DeviceNode.h"
+
+
+CDeviceNode::CDeviceNode(
+ _In_opt_ DEVINST Device,
+ _In_ PSP_CLASSIMAGELIST_DATA ImageListData
+ ) :
+ CNode(DeviceNode, ImageListData),
+ m_DevInst(Device),
+ m_hDevInfo(NULL),
+ m_Status(0),
+ m_ProblemNumber(0),
+ m_OverlayImage(0)
+{
+ ZeroMemory(&m_DevinfoData, sizeof(SP_DEVINFO_DATA));
+}
+
+CDeviceNode::~CDeviceNode()
+{
+ Cleanup();
+}
+
+bool
+CDeviceNode::SetupNode()
+{
+ WCHAR ClassGuidString[MAX_GUID_STRING_LEN];
+ ULONG ulLength;
+ CONFIGRET cr;
+
+ // Get the length of the device id string
+ cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0);
+ if (cr == CR_SUCCESS)
+ {
+ // We alloc heap here because this will be stored in the lParam of the TV
+ m_DeviceId = new WCHAR[ulLength + 1];
+
+ // Now get the actual device id
+ cr = CM_Get_Device_IDW(m_DevInst,
+ m_DeviceId,
+ ulLength + 1,
+ 0);
+ if (cr != CR_SUCCESS)
+ {
+ delete[] m_DeviceId;
+ m_DeviceId = NULL;
+ }
+
+ }
+
+ // Make sure we got the string
+ if (m_DeviceId == NULL)
+ return false;
+
+ // Build up a handle a and devinfodata struct
+ m_hDevInfo = SetupDiCreateDeviceInfoListExW(NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (m_hDevInfo != INVALID_HANDLE_VALUE)
+ {
+ m_DevinfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ SetupDiOpenDeviceInfoW(m_hDevInfo,
+ m_DeviceId,
+ NULL,
+ 0,
+ &m_DevinfoData);
+ }
+
+
+ // Set the overlay if the device has a problem
+ if (HasProblem())
+ {
+ m_OverlayImage = 1;
+ }
+
+ // The disabled overlay takes precidence over the problem overlay
+ if (IsDisabled())
+ {
+ m_OverlayImage = 2;
+ }
+
+
+ // Get the class guid for this device
+ ulLength = MAX_GUID_STRING_LEN * sizeof(WCHAR);
+ cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
+ CM_DRP_CLASSGUID,
+ NULL,
+ ClassGuidString,
+ &ulLength,
+ 0);
+ if (cr == CR_SUCCESS)
+ {
+ // Convert the string to a proper guid
+ CLSIDFromString(ClassGuidString, &m_ClassGuid);
+ }
+ else
+ {
+ // It's a device with no driver
+ m_ClassGuid = GUID_DEVCLASS_UNKNOWN;
+ }
+
+
+ // Get the image for the class this device is in
+ SetupDiGetClassImageIndex(m_ImageListData,
+ &m_ClassGuid,
+ &m_ClassImage);
+
+ // Get the description for the device
+ ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
+ cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
+ CM_DRP_FRIENDLYNAME,
+ NULL,
+ m_DisplayName,
+ &ulLength,
+ 0);
+ if (cr != CR_SUCCESS)
+ {
+ ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
+ cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
+ CM_DRP_DEVICEDESC,
+ NULL,
+ m_DisplayName,
+ &ulLength,
+ 0);
+
+ }
+
+ // Cleanup if something failed
+ if (cr != CR_SUCCESS)
+ {
+ Cleanup();
+ return false;
+ }
+
+ return true;
+}
+
+bool
+CDeviceNode::HasProblem()
+{
+ CONFIGRET cr;
+ cr = CM_Get_DevNode_Status_Ex(&m_Status,
+ &m_ProblemNumber,
+ m_DevInst,
+ 0,
+ NULL);
+ if (cr == CR_SUCCESS)
+ {
+ return ((m_Status & (DN_HAS_PROBLEM | DN_PRIVATE_PROBLEM)) != 0);
+ }
+
+ return false;
+}
+
+bool
+CDeviceNode::IsHidden()
+{
+ CONFIGRET cr;
+ cr = CM_Get_DevNode_Status_Ex(&m_Status,
+ &m_ProblemNumber,
+ m_DevInst,
+ 0,
+ NULL);
+ if (cr == CR_SUCCESS)
+ {
+ return ((m_Status & DN_NO_SHOW_IN_DM) != 0);
+ }
+
+ return false;
+}
+
+bool
+CDeviceNode::CanDisable()
+{
+ CONFIGRET cr;
+ cr = CM_Get_DevNode_Status_Ex(&m_Status,
+ &m_ProblemNumber,
+ m_DevInst,
+ 0,
+ NULL);
+ if (cr == CR_SUCCESS)
+ {
+ return ((m_Status & DN_DISABLEABLE) != 0);
+ }
+
+ return false;
+}
+
+bool
+CDeviceNode::IsDisabled()
+{
+ CONFIGRET cr;
+ cr = CM_Get_DevNode_Status_Ex(&m_Status,
+ &m_ProblemNumber,
+ m_DevInst,
+ 0,
+ NULL);
+ if (cr == CR_SUCCESS)
+ {
+ return ((m_ProblemNumber & (CM_PROB_DISABLED | CM_PROB_HARDWARE_DISABLED)) != 0);
+ }
+
+ return false;
+}
+
+bool
+CDeviceNode::IsStarted()
+{
+ CONFIGRET cr;
+ cr = CM_Get_DevNode_Status_Ex(&m_Status,
+ &m_ProblemNumber,
+ m_DevInst,
+ 0,
+ NULL);
+ if (cr == CR_SUCCESS)
+ {
+ return ((m_Status & DN_STARTED) != 0);
+ }
+
+ return false;
+}
+
+bool
+CDeviceNode::IsInstalled()
+{
+ CONFIGRET cr;
+ cr = CM_Get_DevNode_Status_Ex(&m_Status,
+ &m_ProblemNumber,
+ m_DevInst,
+ 0,
+ NULL);
+ if (cr == CR_SUCCESS)
+ {
+ return ((m_Status & DN_HAS_PROBLEM) != 0 ||
+ (m_Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0);
+ }
+
+ return false;
+}
+
+bool
+CDeviceNode::CanUninstall()
+{
+ CONFIGRET cr;
+ cr = CM_Get_DevNode_Status_Ex(&m_Status,
+ &m_ProblemNumber,
+ m_DevInst,
+ 0,
+ NULL);
+ if (cr == CR_SUCCESS)
+ {
+ if ((m_Status & DN_ROOT_ENUMERATED) != 0 &&
+ (m_Status & DN_DISABLEABLE) == 0)
+ return false;
+ }
+
+ return true;
+}
+
+bool
+CDeviceNode::EnableDevice(
+ _In_ bool Enable,
+ _Out_ bool &NeedsReboot
+ )
+{
+ bool Canceled = false;
+
+ SetFlags(DI_NODI_DEFAULTACTION, 0);
+
+ SP_PROPCHANGE_PARAMS pcp;
+ pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
+ pcp.StateChange = (Enable ? DICS_ENABLE : DICS_DISABLE);
+ pcp.HwProfile = 0;
+
+
+ // check both scopes to make sure we can make the change
+ for (int i = 0; i < 2; i++)
+ {
+ // Check globally first, then check config specific
+ pcp.Scope = (i == 0) ? DICS_FLAG_GLOBAL : DICS_FLAG_CONFIGSPECIFIC;
+
+ if (SetupDiSetClassInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &pcp.ClassInstallHeader,
+ sizeof(SP_PROPCHANGE_PARAMS)))
+ {
+ SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
+ m_hDevInfo,
+ &m_DevinfoData);
+ }
+
+ if (GetLastError() == ERROR_CANCELLED)
+ {
+ Canceled = true;
+ break;
+ }
+ }
+
+ if (Canceled == false)
+ {
+ pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
+ if (SetupDiSetClassInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &pcp.ClassInstallHeader,
+ sizeof(SP_PROPCHANGE_PARAMS)))
+ {
+ SetupDiChangeState(m_hDevInfo, &m_DevinfoData);
+ }
+
+ if (Enable)
+ {
+ // config specific enabling first, then global enabling.
+ // The global appears to be the one that starts the device
+ pcp.Scope = DICS_FLAG_GLOBAL;
+ if (SetupDiSetClassInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &pcp.ClassInstallHeader,
+ sizeof(SP_PROPCHANGE_PARAMS)))
+ {
+ SetupDiChangeState(m_hDevInfo, &m_DevinfoData);
+ }
+ }
+
+ SetFlags(DI_PROPERTIES_CHANGE, 0);
+
+ NeedsReboot = ((GetFlags() & (DI_NEEDRESTART | DI_NEEDREBOOT)) != 0);
+ }
+
+ RemoveFlags(DI_NODI_DEFAULTACTION, 0);
+
+ return true;
+}
+
+bool
+CDeviceNode::UninstallDevice()
+{
+
+ if (CanUninstall() == false)
+ return false;
+
+ SP_REMOVEDEVICE_PARAMS RemoveDevParams;
+ RemoveDevParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
+ RemoveDevParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
+ RemoveDevParams.Scope = DI_REMOVEDEVICE_GLOBAL;
+ RemoveDevParams.HwProfile = 0;
+
+ //
+ // We probably need to walk all the siblings of this
+ // device and ask if they're happy with the uninstall
+ //
+
+
+ // Remove it
+ SetupDiSetClassInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &RemoveDevParams.ClassInstallHeader,
+ sizeof(SP_REMOVEDEVICE_PARAMS));
+ SetupDiCallClassInstaller(DIF_REMOVE, m_hDevInfo, &m_DevinfoData);
+
+ // Clear the install params
+ SetupDiSetClassInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ NULL,
+ 0);
+
+ return true;
+
+}
+
+/* PRIVATE METHODS ******************************************************/
+
+void
+CDeviceNode::Cleanup()
+{
+ if (m_DeviceId)
+ {
+ delete[] m_DeviceId;
+ m_DeviceId = NULL;
+ }
+ if (m_hDevInfo)
+ {
+ SetupDiDestroyDeviceInfoList(m_hDevInfo);
+ m_hDevInfo = NULL;
+ }
+}
+
+DWORD
+CDeviceNode::GetFlags(
+ )
+{
+ SP_DEVINSTALL_PARAMS DevInstallParams;
+ DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+ if (SetupDiGetDeviceInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &DevInstallParams))
+ {
+ return DevInstallParams.Flags;
+ }
+ return 0;
+}
+
+bool
+CDeviceNode::SetFlags(
+ _In_ DWORD Flags,
+ _In_ DWORD FlagsEx
+ )
+{
+ SP_DEVINSTALL_PARAMS DevInstallParams;
+ DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+ if (SetupDiGetDeviceInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &DevInstallParams))
+ {
+ DevInstallParams.Flags |= Flags;
+ DevInstallParams.FlagsEx |= FlagsEx;
+ return (SetupDiSetDeviceInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &DevInstallParams) != 0);
+ }
+ return false;
+}
+
+bool
+CDeviceNode::RemoveFlags(
+ _In_ DWORD Flags,
+ _In_ DWORD FlagsEx
+ )
+{
+ SP_DEVINSTALL_PARAMS DevInstallParams;
+ DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+ if (SetupDiGetDeviceInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &DevInstallParams))
+ {
+ DevInstallParams.Flags &= ~Flags;
+ DevInstallParams.FlagsEx &= ~FlagsEx;
+ return (SetupDiSetDeviceInstallParamsW(m_hDevInfo,
+ &m_DevinfoData,
+ &DevInstallParams) != 0);
+ }
+ return false;
+}
+
+
--- /dev/null
+#pragma once
+#include "Node.h"
+
+class CDeviceNode : public CNode
+{
+private:
+ SP_DEVINFO_DATA m_DevinfoData;
+ HDEVINFO m_hDevInfo;
+ DEVINST m_DevInst;
+ ULONG m_Status;
+ ULONG m_ProblemNumber;
+ int m_OverlayImage;
+
+public:
+ CDeviceNode(
+ _In_opt_ DEVINST Device,
+ _In_ PSP_CLASSIMAGELIST_DATA ImageListData
+ );
+
+ ~CDeviceNode();
+
+ virtual bool SetupNode();
+
+ DEVINST GetDeviceInst() { return m_DevInst; }
+ int GetOverlayImage() { return m_OverlayImage; }
+
+ bool HasProblem();
+ bool IsHidden();
+ bool CanDisable();
+ virtual bool IsDisabled();
+ bool IsStarted();
+ bool IsInstalled();
+ bool CanUninstall();
+ virtual bool CanUpdate() { return true; } // unimplemented
+
+ bool EnableDevice(
+ _In_ bool Enable,
+ _Out_ bool &NeedsReboot
+ );
+
+ bool UninstallDevice(
+ );
+
+private:
+ void Cleanup(
+ );
+
+ bool SetFlags(
+ _In_ DWORD Flags,
+ _In_ DWORD FlagsEx
+ );
+
+ bool RemoveFlags(
+ _In_ DWORD Flags,
+ _In_ DWORD FlagsEx
+ );
+
+ DWORD GetFlags(
+ );
+};
+
--- /dev/null
+/*
+ * PROJECT: ReactOS Device Manager
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: dll/win32/devmgr/devmgr/DeviceView.cpp
+ * PURPOSE: Implements the tree view which contains the devices
+ * COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
+ */
+
+
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "DeviceView.h"
+
+
+// DATA ********************************************/
+
+#define CLASS_NAME_LEN 256
+#define CLASS_DESC_LEN 256
+#define ROOT_NAME_SIZE MAX_COMPUTERNAME_LENGTH + 1
+
+extern "C" {
+INT_PTR
+WINAPI
+DevicePropertiesExW(
+ IN HWND hWndParent OPTIONAL,
+ IN LPCWSTR lpMachineName OPTIONAL,
+ IN LPCWSTR lpDeviceID OPTIONAL,
+ IN DWORD dwFlags OPTIONAL,
+ IN BOOL bShowDevMgr
+);
+}
+typedef INT_PTR(WINAPI *pDevicePropertiesExW)(HWND,LPCWSTR,LPCWSTR,DWORD,BOOL);
+
+struct RefreshThreadData
+{
+ CDeviceView *This;
+ BOOL ScanForChanges;
+ BOOL UpdateView;
+ LPWSTR DeviceId;
+};
+
+
+// PUBLIC METHODS ************************************/
+
+CDeviceView::CDeviceView(
+ HWND hMainWnd
+ ) :
+ m_hMainWnd(hMainWnd),
+ m_hTreeView(NULL),
+ m_hPropertyDialog(NULL),
+ m_hMenu(NULL),
+ m_ViewType(DevicesByType),
+ m_ShowHidden(FALSE),
+ m_RootNode(NULL)
+{
+ ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
+}
+
+CDeviceView::~CDeviceView(void)
+{
+}
+
+bool
+CDeviceView::Initialize()
+{
+ // Get the device image list
+ m_ImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
+ BOOL bSuccess = SetupDiGetClassImageList(&m_ImageListData);
+ if (bSuccess == FALSE) return false;
+
+ // Create the main treeview
+ m_hTreeView = CreateWindowExW(WS_EX_CLIENTEDGE,
+ WC_TREEVIEW,
+ NULL,
+ WS_CHILD | WS_VISIBLE | WS_BORDER | TVS_HASLINES |
+ TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_LINESATROOT,
+ 0, 0, 0, 0,
+ m_hMainWnd,
+ (HMENU)IDC_TREEVIEW,
+ g_hInstance,
+ NULL);
+ if (m_hTreeView)
+ {
+ // Set the image list against the treeview
+ (void)TreeView_SetImageList(m_hTreeView,
+ m_ImageListData.ImageList,
+ TVSIL_NORMAL);
+
+ // Give the treeview arrows instead of +/- boxes (on Win7)
+ SetWindowTheme(m_hTreeView, L"explorer", NULL);
+ }
+
+
+
+ return !!(m_hTreeView);
+}
+
+bool
+CDeviceView::Uninitialize()
+{
+ EmptyDeviceView();
+
+ if (m_ImageListData.ImageList != NULL)
+ {
+ SetupDiDestroyClassImageList(&m_ImageListData);
+ ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
+ }
+
+ return true;
+}
+
+LRESULT
+CDeviceView::OnSize(
+ _In_ int x,
+ _In_ int y,
+ _In_ int cx,
+ _In_ int cy
+ )
+{
+ // Resize the treeview
+ SetWindowPos(m_hTreeView,
+ NULL,
+ x,
+ y,
+ cx,
+ cy,
+ SWP_NOZORDER);
+
+ return 0;
+}
+
+LRESULT
+CDeviceView::OnRightClick(
+ _In_ LPNMHDR NmHdr
+ )
+{
+ HTREEITEM hItem = TreeView_GetNextItem(NmHdr->hwndFrom, 0, TVGN_DROPHILITE);
+ if (hItem)
+ {
+ TreeView_SelectItem(NmHdr->hwndFrom, hItem);
+ }
+
+ return 0;
+}
+
+LRESULT
+CDeviceView::OnContextMenu(
+ _In_ LPARAM lParam
+ )
+{
+ HTREEITEM hSelected = TreeView_GetSelection(m_hTreeView);
+
+ RECT rc;
+ if (TreeView_GetItemRect(m_hTreeView,
+ hSelected,
+ &rc,
+ TRUE))
+ {
+ POINT pt;
+ if (GetCursorPos(&pt) &&
+ ScreenToClient(m_hTreeView, &pt) &&
+ PtInRect(&rc, pt))
+ {
+ CNode *Node = GetSelectedNode();
+ if (Node)
+ {
+ // Create the context menu
+ HMENU hContextMenu = CreatePopupMenu();
+
+ // Add the actions for this node
+ BuildActionMenuForNode(hContextMenu, Node, false);
+
+ INT xPos = GET_X_LPARAM(lParam);
+ INT yPos = GET_Y_LPARAM(lParam);
+
+ // Display the menu
+ TrackPopupMenuEx(hContextMenu,
+ TPM_RIGHTBUTTON,
+ xPos,
+ yPos,
+ m_hMainWnd,
+ NULL);
+
+ DestroyMenu(hContextMenu);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+void
+CDeviceView::Refresh(
+ _In_ ViewType Type,
+ _In_ bool ScanForChanges,
+ _In_ bool UpdateView,
+ _In_opt_ LPWSTR DeviceId
+ )
+{
+ // Enum devices on a seperate thread to keep the gui responsive
+
+ m_ViewType = Type;
+
+ RefreshThreadData *ThreadData;
+ ThreadData = new RefreshThreadData();
+ ThreadData->This = this;
+ ThreadData->ScanForChanges = ScanForChanges;
+ ThreadData->UpdateView = UpdateView;
+ ThreadData->DeviceId = NULL;
+
+ if (DeviceId)
+ {
+ // Node gets deleted on refresh so we copy it to another block
+ size_t Length = wcslen(DeviceId) + 1;
+ ThreadData->DeviceId = new WCHAR[Length];
+ StringCbCopyW(ThreadData->DeviceId, Length, DeviceId);
+ }
+
+
+ HANDLE hThread;
+ hThread = (HANDLE)_beginthreadex(NULL,
+ 0,
+ &RefreshThread,
+ ThreadData,
+ 0,
+ NULL);
+
+ if (hThread) CloseHandle(hThread);
+}
+
+LRESULT
+CDeviceView::OnAction(
+ _In_ UINT Action
+)
+{
+ switch (Action)
+ {
+ case IDC_PROPERTIES:
+ {
+ DisplayPropertySheet();
+ break;
+ }
+
+ case IDC_SCAN_HARDWARE:
+ {
+ Refresh(GetCurrentView(),
+ true,
+ true,
+ NULL);
+ break;
+ }
+
+ case IDC_ENABLE_DRV:
+ {
+ bool NeedsReboot;
+ if (EnableSelectedDevice(true, NeedsReboot) &&
+ NeedsReboot)
+ {
+ MessageBox(m_hMainWnd, L"Rebooting", L"Enable", MB_OK);
+ }
+ break;
+ }
+
+ case IDC_DISABLE_DRV:
+ {
+ bool NeedsReboot;
+ EnableSelectedDevice(false, NeedsReboot);
+ break;
+ }
+
+ case IDC_UPDATE_DRV:
+ {
+ MessageBox(m_hMainWnd, L"Not yet implemented", L"Update Driver", MB_OK);
+ break;
+ }
+
+ case IDC_UNINSTALL_DRV:
+ {
+ UninstallSelectedDevice();
+ break;
+ }
+
+ case IDC_ADD_HARDWARE:
+ {
+ MessageBox(m_hMainWnd, L"Not yet implemented", L"Add Hardware", MB_OK);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void
+CDeviceView::DisplayPropertySheet()
+{
+ //
+ // In ReactOS we can link to DevicePropertiesEx but
+ // not in windows as it's not part of the SDK
+
+#ifndef __REACTOS__
+ HMODULE hModule = LoadLibraryW(L"devmgr.dll");
+ if (hModule == NULL) return;
+
+ pDevicePropertiesExW DevicePropertiesExW;
+ DevicePropertiesExW = (pDevicePropertiesExW)GetProcAddress(hModule,
+ "DevicePropertiesExW");
+ if (DevicePropertiesExW == NULL)
+ {
+ FreeLibrary(hModule);
+ return;
+ }
+#endif
+
+ CNode *Node = GetSelectedNode();
+ if (Node && Node->HasProperties())
+ {
+ DevicePropertiesExW(m_hTreeView,
+ NULL,
+ Node->GetDeviceId(),
+ 1,//DPF_EXTENDED,
+ FALSE);
+ }
+
+#ifndef __REACTOS__
+ FreeLibrary(hModule);
+#endif
+}
+
+void
+CDeviceView::SetFocus()
+{
+}
+
+bool
+CDeviceView::CreateActionMenu(
+ _In_ HMENU OwnerMenu,
+ _In_ bool MainMenu
+ )
+{
+ CNode *Node = GetSelectedNode();
+ if (Node)
+ {
+ BuildActionMenuForNode(OwnerMenu, Node, MainMenu);
+ return true;
+ }
+
+ return false;
+}
+
+CNode*
+CDeviceView::GetSelectedNode()
+{
+ TV_ITEM TvItem;
+ TvItem.hItem = TreeView_GetSelection(m_hTreeView);
+ return GetNode(&TvItem);
+}
+
+
+
+// PRIVATE METHODS *******************************************/
+
+bool
+CDeviceView::AddRootDevice()
+{
+ m_hTreeRoot = InsertIntoTreeView(NULL, m_RootNode);
+ return (m_hTreeRoot != NULL);
+}
+
+bool
+CDeviceView::GetNextClass(
+ _In_ ULONG ClassIndex,
+ _Out_ LPGUID ClassGuid,
+ _Out_ HDEVINFO *hDevInfo
+ )
+{
+ CONFIGRET cr;
+
+ // Get the next class in the list
+ cr = CM_Enumerate_Classes(ClassIndex,
+ ClassGuid,
+ 0);
+ if (cr != CR_SUCCESS) return false;
+
+ // Check if this is the unknown class
+ if (IsEqualGUID(*ClassGuid, GUID_DEVCLASS_UNKNOWN))
+ {
+ // Get device info for all devices
+ *hDevInfo = SetupDiGetClassDevsW(NULL,
+ NULL,
+ NULL,
+ DIGCF_ALLCLASSES);
+ }
+ else
+ {
+ // We only want the devices for this class
+ *hDevInfo = SetupDiGetClassDevsW(ClassGuid,
+ NULL,
+ NULL,
+ DIGCF_PRESENT);
+ }
+
+ return (hDevInfo != INVALID_HANDLE_VALUE);
+}
+
+unsigned int __stdcall CDeviceView::RefreshThread(void *Param)
+{
+ RefreshThreadData *ThreadData = (RefreshThreadData *)Param;
+ CDeviceView *This = ThreadData->This;
+
+
+ // Empty the treeview
+ This->EmptyDeviceView();
+ This->m_hTreeRoot = NULL;
+
+ // Refresh the devices only if requested. This means
+ // switching views uses the cache and remains fast
+ if (ThreadData->ScanForChanges)
+ {
+ This->RefreshDeviceList();
+ }
+
+ // display the type of view the user wants
+ switch (This->m_ViewType)
+ {
+ case DevicesByType:
+ (void)This->ListDevicesByType();
+ break;
+
+ case DevicesByConnection:
+ (VOID)This->ListDevicesByConnection();
+ break;
+
+ case ResourcesByType:
+ break;
+
+ case ResourcesByConnection:
+ break;
+ }
+
+
+ This->SelectNode(ThreadData->DeviceId);
+
+ if (ThreadData->DeviceId)
+ delete[] ThreadData->DeviceId;
+ delete ThreadData;
+
+ return 0;
+}
+
+
+bool
+CDeviceView::ListDevicesByType()
+{
+ CClassNode *ClassNode;
+ CDeviceNode *DeviceNode;
+ HDEVINFO hDevInfo;
+ HTREEITEM hTreeItem = NULL;
+ GUID ClassGuid;
+ INT ClassIndex;
+ BOOL bClassSuccess, bSuccess;
+
+ // Start by adding the root node to the tree
+ bSuccess = AddRootDevice();
+ if (bSuccess == false) return false;
+
+ ClassIndex = 0;
+ do
+ {
+ // Loop through all the device classes
+ bClassSuccess = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
+ if (bClassSuccess)
+ {
+ bool bClassUnknown = false;
+ bool AddedParent = false;
+ INT DeviceIndex = 0;
+ bool MoreItems = false;
+
+ // Get the cached class node
+ ClassNode = GetClassNode(&ClassGuid);
+ if (ClassNode == NULL)
+ {
+ ATLASSERT(FALSE);
+ ClassIndex++;
+ continue;
+ }
+
+ // Set a flag is this is the (special case) unknown class
+ if (IsEqualGUID(ClassGuid, GUID_DEVCLASS_UNKNOWN))
+ bClassUnknown = true;
+
+ do
+ {
+ // Get a handle to all the devices in this class
+ SP_DEVINFO_DATA DeviceInfoData;
+ ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
+ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ bSuccess = SetupDiEnumDeviceInfo(hDevInfo,
+ DeviceIndex,
+ &DeviceInfoData);
+ if (bSuccess == FALSE && GetLastError() == ERROR_NO_MORE_ITEMS)
+ MoreItems = false;
+
+ if (bSuccess)
+ {
+ MoreItems = true;
+
+ // The unknown class handle contains all devices on the system,
+ // and we're just looking for the ones with a null GUID
+ if (bClassUnknown)
+ {
+ if (IsEqualGUID(DeviceInfoData.ClassGuid, GUID_NULL) == FALSE)
+ {
+ // This is a known device, we aren't interested in it
+ DeviceIndex++;
+ continue;
+ }
+ }
+
+ // Get the cached device node
+ DeviceNode = GetDeviceNode(DeviceInfoData.DevInst);
+ if (DeviceNode == NULL)
+ {
+ ATLASSERT(bClassUnknown == true);
+ DeviceIndex++;
+ continue;
+ }
+
+ // Check if this is a hidden device
+ if (DeviceNode->IsHidden())
+ {
+ // Ignore this device if we aren't displaying hidden devices
+ if (m_ShowHidden == FALSE)
+ {
+ DeviceIndex++;
+ continue;
+ }
+ }
+
+ // We have a device, we need to add the parent if it hasn't yet been added
+ if (AddedParent == false)
+ {
+ // Insert the new class under the root item
+ hTreeItem = InsertIntoTreeView(m_hTreeRoot,
+ ClassNode);
+ AddedParent = true;
+ }
+
+ // Add the device under the class item node
+ (void)InsertIntoTreeView(hTreeItem, DeviceNode);
+
+ // Expand the class if it has a problem device
+ if (DeviceNode->HasProblem())
+ {
+ (void)TreeView_Expand(m_hTreeView,
+ hTreeItem,
+ TVE_EXPAND);
+ }
+ }
+
+ DeviceIndex++;
+
+ } while (MoreItems);
+
+ // If this class has devices, sort them alphabetically
+ if (AddedParent == true)
+ {
+ (void)TreeView_SortChildren(m_hTreeView,
+ hTreeItem,
+ 0);
+ }
+ }
+
+ ClassIndex++;
+
+ } while (bClassSuccess);
+
+ // Sort the classes alphabetically
+ (void)TreeView_SortChildren(m_hTreeView,
+ m_hTreeRoot,
+ 0);
+
+ // Expand the root item
+ (void)TreeView_Expand(m_hTreeView,
+ m_hTreeRoot,
+ TVE_EXPAND);
+
+ // Pre-select the root item
+ (VOID)TreeView_SelectItem(m_hTreeView,
+ m_hTreeRoot);
+
+ return 0;
+}
+
+bool
+CDeviceView::ListDevicesByConnection()
+{
+ bool bSuccess;
+
+ // Start by adding the root node to the tree
+ bSuccess = AddRootDevice();
+ if (bSuccess == false) return false;
+
+ // Walk the device tree and add all the devices
+ (void)RecurseChildDevices(m_RootNode->GetDeviceInst(), m_hTreeRoot);
+
+ // Expand the root item
+ (void)TreeView_Expand(m_hTreeView,
+ m_hTreeRoot,
+ TVE_EXPAND);
+
+ return true;
+}
+
+bool
+CDeviceView::RecurseChildDevices(
+ _In_ DEVINST ParentDevice,
+ _In_ HTREEITEM hParentTreeItem
+ )
+{
+ HTREEITEM hDevItem = NULL;
+ DEVINST Device;
+ bool HasProblem = false;
+ bool bSuccess;
+
+ // Check if the parent has any child devices
+ if (GetChildDevice(ParentDevice, &Device) == FALSE)
+ return true;
+
+ // Get the cached device node
+ CDeviceNode *DeviceNode;
+ DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device));
+ if (DeviceNode == nullptr)
+ {
+ ATLASSERT(FALSE);
+ return false;
+ }
+
+ // Don't show hidden devices if not requested
+ if ((m_ShowHidden == TRUE) || (!(DeviceNode->IsHidden())))
+ {
+ // Add this device to the tree under its parent
+ hDevItem = InsertIntoTreeView(hParentTreeItem,
+ DeviceNode);
+ if (hDevItem)
+ {
+ // Check if this child has any children itself
+ if (!RecurseChildDevices(Device, hDevItem))
+ HasProblem = true;
+ }
+
+ if (DeviceNode->HasProblem())
+ {
+ HasProblem = true;
+ }
+ }
+
+
+ // Check for siblings
+ for (;;)
+ {
+ // Check if the parent device has anything at the same level
+ bSuccess = GetSiblingDevice(Device, &Device);
+ if (bSuccess == FALSE) break;
+
+ DeviceNode = dynamic_cast<CDeviceNode *>(GetDeviceNode(Device));
+ if (DeviceNode == nullptr)
+ {
+ ATLASSERT(FALSE);
+ }
+
+ // Don't show hidden devices if not requested
+ if ((m_ShowHidden == TRUE) || (!(DeviceNode->IsHidden())))
+ {
+ if (DeviceNode->HasProblem())
+ {
+ HasProblem = true;
+ }
+
+ // Add this device to the tree under its parent
+ hDevItem = InsertIntoTreeView(hParentTreeItem,
+ DeviceNode);
+ if (hDevItem)
+ {
+ // Check if this child has any children itself
+ if (!RecurseChildDevices(Device, hDevItem))
+ HasProblem = true;
+ }
+ }
+ }
+
+ (void)TreeView_SortChildren(m_hTreeView,
+ hParentTreeItem,
+ 0);
+
+ // Expand the class if it has a problem device
+ if (HasProblem == true)
+ {
+ (void)TreeView_Expand(m_hTreeView,
+ hParentTreeItem,
+ TVE_EXPAND);
+ }
+
+ // If there was a problem, expand the ancestors
+ if (HasProblem) return false;
+
+ return true;
+}
+
+bool
+CDeviceView::EnableSelectedDevice(
+ _In_ bool Enable,
+ _Out_ bool &NeedsReboot
+ )
+{
+ CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetSelectedNode());
+ if (Node == nullptr) return false;
+
+ if (Enable == false)
+ {
+ CAtlStringW str;
+ if (str.LoadStringW(g_hInstance, IDS_CONFIRM_DISABLE))
+ {
+ if (MessageBoxW(m_hMainWnd,
+ str,
+ Node->GetDisplayName(),
+ MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) != IDYES)
+ {
+ return false;
+ }
+ }
+ }
+
+ if (Node->EnableDevice(Enable, NeedsReboot))
+ {
+ Refresh(m_ViewType, true, true, Node->GetDeviceId());
+ return true;
+ }
+
+ return false;
+}
+
+bool
+CDeviceView::UninstallSelectedDevice(
+ )
+{
+ CDeviceNode *Node = dynamic_cast<CDeviceNode *>(GetSelectedNode());
+ if (Node == nullptr) return false;
+
+ return Node->UninstallDevice();
+}
+
+bool
+CDeviceView::GetChildDevice(
+ _In_ DEVINST ParentDevInst,
+ _Out_ PDEVINST DevInst
+)
+{
+ CONFIGRET cr;
+ cr = CM_Get_Child(DevInst,
+ ParentDevInst,
+ 0);
+ return (cr == CR_SUCCESS);
+}
+
+bool
+CDeviceView::GetSiblingDevice(
+ _In_ DEVINST PrevDevice,
+ _Out_ PDEVINST DevInst
+)
+{
+ CONFIGRET cr;
+ cr = CM_Get_Sibling(DevInst,
+ PrevDevice,
+ 0);
+ return (cr == CR_SUCCESS);
+}
+
+HTREEITEM
+CDeviceView::InsertIntoTreeView(
+ _In_opt_ HTREEITEM hParent,
+ _In_ CNode *Node
+ )
+{
+ LPWSTR lpLabel;
+ lpLabel = Node->GetDisplayName();
+
+ TV_ITEMW tvi;
+ TV_INSERTSTRUCT tvins;
+ ZeroMemory(&tvi, sizeof(tvi));
+ ZeroMemory(&tvins, sizeof(tvins));
+
+ tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.pszText = lpLabel;
+ tvi.cchTextMax = wcslen(lpLabel);
+ tvi.lParam = (LPARAM)Node;
+ tvi.iImage = Node->GetClassImage();
+ tvi.iSelectedImage = Node->GetClassImage();
+
+ // try to cast it to a device node. This will only suceed if it's the correct type
+ CDeviceNode *DeviceNode = dynamic_cast<CDeviceNode *>(Node);
+ if (DeviceNode && DeviceNode->GetOverlayImage())
+ {
+ tvi.mask |= TVIF_STATE;
+ tvi.stateMask = TVIS_OVERLAYMASK;
+ tvi.state = INDEXTOOVERLAYMASK(DeviceNode->GetOverlayImage());
+ }
+
+ tvins.item = tvi;
+ tvins.hParent = hParent;
+
+ return TreeView_InsertItem(m_hTreeView, &tvins);
+}
+
+void
+CDeviceView::BuildActionMenuForNode(
+ _In_ HMENU OwnerMenu,
+ _In_ CNode *Node,
+ _In_ bool MainMenu
+ )
+{
+ // Create a seperator structure
+ MENUITEMINFOW MenuSeperator = { 0 };
+ MenuSeperator.cbSize = sizeof(MENUITEMINFOW);
+ MenuSeperator.fType = MFT_SEPARATOR;
+
+ // Setup the
+ MENUITEMINFOW MenuItemInfo = { 0 };
+ MenuItemInfo.cbSize = sizeof(MENUITEMINFOW);
+ MenuItemInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA | MIIM_SUBMENU;
+ MenuItemInfo.fType = MFT_STRING;
+
+ CAtlStringW String;
+ int i = 0;
+
+ // Device nodes have extra data
+ if (Node->GetNodeType() == DeviceNode)
+ {
+ CDeviceNode *DeviceNode = dynamic_cast<CDeviceNode *>(Node);
+
+ if (DeviceNode->CanUpdate())
+ {
+ String.LoadStringW(g_hInstance, IDS_MENU_UPDATE);
+ MenuItemInfo.wID = IDC_UPDATE_DRV;
+ MenuItemInfo.dwTypeData = String.GetBuffer();
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
+ i++;
+ }
+
+ if (DeviceNode->IsDisabled())
+ {
+ String.LoadStringW(g_hInstance, IDS_MENU_ENABLE);
+ MenuItemInfo.wID = IDC_ENABLE_DRV;
+ MenuItemInfo.dwTypeData = String.GetBuffer();
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
+ i++;
+ }
+
+ if (DeviceNode->CanDisable() && !DeviceNode->IsDisabled())
+ {
+ String.LoadStringW(g_hInstance, IDS_MENU_DISABLE);
+ MenuItemInfo.wID = IDC_DISABLE_DRV;
+ MenuItemInfo.dwTypeData = String.GetBuffer();
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
+ i++;
+ }
+
+ if (DeviceNode->CanUninstall())
+ {
+ String.LoadStringW(g_hInstance, IDS_MENU_UNINSTALL);
+ MenuItemInfo.wID = IDC_UNINSTALL_DRV;
+ MenuItemInfo.dwTypeData = String.GetBuffer();
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
+ i++;
+ }
+
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuSeperator);
+ i++;
+ }
+
+ // All nodes have the scan option
+ String.LoadStringW(g_hInstance, IDS_MENU_SCAN);
+ MenuItemInfo.wID = IDC_SCAN_HARDWARE;
+ MenuItemInfo.dwTypeData = String.GetBuffer();
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
+ i++;
+
+ if ((Node->GetNodeType() == RootNode) || (MainMenu == true))
+ {
+ String.LoadStringW(g_hInstance, IDS_MENU_ADD);
+ MenuItemInfo.wID = IDC_ADD_HARDWARE;
+ MenuItemInfo.dwTypeData = String.GetBuffer();
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
+ i++;
+ }
+
+ if (Node->HasProperties())
+ {
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuSeperator);
+ i++;
+
+ String.LoadStringW(g_hInstance, IDS_MENU_PROPERTIES);
+ MenuItemInfo.wID = IDC_PROPERTIES;
+ MenuItemInfo.dwTypeData = String.GetBuffer();
+ InsertMenuItemW(OwnerMenu, i, TRUE, &MenuItemInfo);
+ i++;
+
+ SetMenuDefaultItem(OwnerMenu, IDC_PROPERTIES, FALSE);
+ }
+}
+
+HTREEITEM
+CDeviceView::RecurseFindDevice(
+ _In_ HTREEITEM hParentItem,
+ _In_ LPWSTR DeviceId
+ )
+{
+ HTREEITEM FoundItem;
+ HTREEITEM hItem;
+ TVITEMW tvItem;
+ CNode *Node;
+
+ // Check if this node has any children
+ hItem = TreeView_GetChild(m_hTreeView, hParentItem);
+ if (hItem == NULL) return NULL;
+
+ // The lParam contains the node pointer data
+ tvItem.hItem = hItem;
+ tvItem.mask = TVIF_PARAM;
+ if (TreeView_GetItem(m_hTreeView, &tvItem) &&
+ tvItem.lParam != NULL)
+ {
+ // check for a matching deviceid
+ Node = reinterpret_cast<CNode *>(tvItem.lParam);
+ if (Node->GetDeviceId() &&
+ (wcscmp(Node->GetDeviceId(), DeviceId) == 0))
+ {
+ return hItem;
+ }
+ }
+
+ // This node may have its own children
+ FoundItem = RecurseFindDevice(hItem, DeviceId);
+ if (FoundItem) return FoundItem;
+
+ // Loop all the siblings
+ for (;;)
+ {
+ // Get the next item at this level
+ hItem = TreeView_GetNextSibling(m_hTreeView, hItem);
+ if (hItem == NULL) break;
+
+ // The lParam contains the node pointer data
+ tvItem.hItem = hItem;
+ tvItem.mask = TVIF_PARAM;
+ if (TreeView_GetItem(m_hTreeView, &tvItem))
+ {
+ // check for a matching deviceid
+ Node = reinterpret_cast<CNode *>(tvItem.lParam);
+ if (Node->GetDeviceId() &&
+ wcscmp(Node->GetDeviceId(), DeviceId) == 0)
+ {
+ return hItem;
+ }
+ }
+
+ // This node may have its own children
+ FoundItem = RecurseFindDevice(hItem, DeviceId);
+ if (FoundItem) return FoundItem;
+ }
+
+ return hItem;
+}
+
+void
+CDeviceView::SelectNode(
+ _In_ LPWSTR DeviceId
+ )
+{
+ HTREEITEM hRoot, hItem;
+
+ // Check if there are any items in the tree
+ hRoot = TreeView_GetRoot(m_hTreeView);
+ if (hRoot == NULL) return;
+
+ // If we don't want to set select a node, just select root
+ if (DeviceId == NULL)
+ {
+ TreeView_SelectItem(m_hTreeView, hRoot);
+ return;
+ }
+
+ // Scan the tree looking for the node we want
+ hItem = RecurseFindDevice(hRoot, DeviceId);
+ if (hItem)
+ {
+ TreeView_SelectItem(m_hTreeView, hItem);
+ TreeView_Expand(m_hTreeView, hItem, TVM_EXPAND);
+ }
+ else
+ {
+ TreeView_SelectItem(m_hTreeView, hRoot);
+ }
+}
+
+
+void
+CDeviceView::EmptyDeviceView()
+{
+ (VOID)TreeView_DeleteAllItems(m_hTreeView);
+}
+
+
+CClassNode*
+CDeviceView::GetClassNode(
+ _In_ LPGUID ClassGuid
+ )
+{
+ POSITION Pos;
+ CClassNode *Node;
+
+ Pos = m_ClassNodeList.GetHeadPosition();
+
+ do
+ {
+ Node = m_ClassNodeList.GetNext(Pos);
+ if (IsEqualGUID(*Node->GetClassGuid(), *ClassGuid))
+ {
+ //ATLASSERT(Node->GetType() == NodeClass);
+ break;
+ }
+
+ Node = NULL;
+
+ } while (Pos != NULL);
+
+ return Node;
+}
+
+CDeviceNode*
+CDeviceView::GetDeviceNode(
+ _In_ DEVINST Device
+ )
+{
+ POSITION Pos;
+ CDeviceNode *Node;
+
+ Pos = m_DeviceNodeList.GetHeadPosition();
+
+ do
+ {
+ Node = m_DeviceNodeList.GetNext(Pos);
+ if (Node->GetDeviceInst() == Device)
+ {
+ //ATLASSERT(Node->GetType() == NodeDevice);
+ break;
+ }
+
+ Node = NULL;
+
+ } while (Pos != NULL);
+
+ return Node;
+}
+
+CNode* CDeviceView::GetNode(
+ _In_ LPTV_ITEMW TvItem
+ )
+{
+ TvItem->mask = TVIF_PARAM;
+ if (TreeView_GetItem(m_hTreeView, TvItem))
+ {
+ return (CNode *)TvItem->lParam;
+ }
+ return NULL;
+}
+
+void
+CDeviceView::EmptyLists()
+{
+ CNode *Node;
+
+ while (!m_ClassNodeList.IsEmpty())
+ {
+ Node = m_ClassNodeList.RemoveTail();
+ delete Node;
+ }
+
+ while (!m_DeviceNodeList.IsEmpty())
+ {
+ Node = m_DeviceNodeList.RemoveTail();
+ delete Node;
+ }
+}
+
+bool
+CDeviceView::RefreshDeviceList()
+{
+ GUID ClassGuid;
+ CClassNode *ClassNode;
+ CDeviceNode *DeviceNode;
+ HDEVINFO hDevInfo;
+ SP_DEVINFO_DATA DeviceInfoData;
+ DWORD i;
+ BOOL Success;
+
+ ULONG ClassIndex = 0;
+
+ EmptyLists();
+
+ if (m_RootNode) delete m_RootNode;
+ m_RootNode = new CRootNode(&m_ImageListData);
+ m_RootNode->SetupNode();
+ // Loop through all the classes
+ do
+ {
+ Success = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
+ if (Success)
+ {
+ // Create a new class node and add it to the list
+ ClassNode = new CClassNode(&ClassGuid, &m_ImageListData);
+ if (ClassNode->SetupNode())
+ {
+ m_ClassNodeList.AddTail(ClassNode);
+ }
+
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+ }
+ ClassIndex++;
+ } while (Success);
+
+
+ // Get all the devices on the local machine
+ hDevInfo = SetupDiGetClassDevsW(NULL,
+ 0,
+ 0,
+ DIGCF_PRESENT | DIGCF_ALLCLASSES);
+ if (hDevInfo == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ // loop though all the devices
+ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ for (i = 0;; i++)
+ {
+ // Get the devinst for this device
+ Success = SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData);
+ if (Success == FALSE) break;
+
+ // create a new device node and add it to the list
+ DeviceNode = new CDeviceNode(DeviceInfoData.DevInst, &m_ImageListData);
+ if (DeviceNode->SetupNode())
+ {
+ m_DeviceNodeList.AddTail(DeviceNode);
+ }
+ }
+
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+
+ return TRUE;
+}
\ No newline at end of file
--- /dev/null
+#pragma once
+#include "DeviceNode.h"
+#include "ClassNode.h"
+#include "RootNode.h"
+
+enum ViewType
+{
+ DevicesByType,
+ DevicesByConnection,
+ ResourcesByType,
+ ResourcesByConnection
+};
+
+
+class CDeviceView
+{
+ CRootNode *m_RootNode;
+ CAtlList<CClassNode *> m_ClassNodeList;
+ CAtlList<CDeviceNode *> m_DeviceNodeList;
+ SP_CLASSIMAGELIST_DATA m_ImageListData;
+ HWND m_hMainWnd;
+ HWND m_hTreeView;
+ HWND m_hPropertyDialog;
+ HMENU m_hMenu;
+ ViewType m_ViewType;
+ HTREEITEM m_hTreeRoot;
+ bool m_ShowHidden;
+
+public:
+ CDeviceView(
+ HWND hMainWnd
+ );
+
+ ~CDeviceView(void);
+
+ bool Initialize();
+ bool Uninitialize();
+
+ LRESULT OnSize(
+ _In_ int x,
+ _In_ int y,
+ _In_ int cx,
+ _In_ int cy
+ );
+
+ LRESULT OnRightClick(
+ _In_ LPNMHDR NmHdr
+ );
+
+ LRESULT OnContextMenu(
+ _In_ LPARAM lParam
+ );
+
+ LRESULT OnAction(
+ UINT Action
+ );
+
+ VOID Refresh(
+ _In_ ViewType Type,
+ _In_ bool ScanForChanges,
+ _In_ bool UpdateView,
+ _In_opt_ LPWSTR DeviceId
+ );
+
+ VOID DisplayPropertySheet();
+ VOID SetFocus();
+
+ VOID SetHiddenDevices(_In_ bool ShowHidden)
+ {
+ m_ShowHidden = ShowHidden;
+ }
+
+ ViewType GetCurrentView() { return m_ViewType; }
+
+ bool CreateActionMenu(
+ _In_ HMENU OwnerMenu,
+ _In_ bool MainMenu
+ );
+
+ CNode* GetSelectedNode(
+ );
+
+ bool SelDeviceIsStarted();
+ bool SelDeviceIsInstalled();
+
+private:
+ bool AddRootDevice();
+
+ bool RefreshDeviceList();
+
+ static unsigned int __stdcall RefreshThread(
+ void *Param
+ );
+
+ bool ListDevicesByConnection(
+ );
+ bool ListDevicesByType(
+ );
+
+ bool GetNextClass(
+ _In_ ULONG ClassIndex,
+ _Out_ LPGUID ClassGuid,
+ _Out_ HDEVINFO *hDevInfo
+ );
+
+ bool RecurseChildDevices(
+ _In_ DEVINST ParentDevice,
+ _In_ HTREEITEM hParentTreeItem
+ );
+
+ bool EnableSelectedDevice(
+ _In_ bool Enable,
+ _Out_ bool &NeedsReboot
+ );
+
+ bool UninstallSelectedDevice(
+ );
+
+ bool GetChildDevice(
+ _In_ DEVINST ParentDevInst,
+ _Out_ PDEVINST DevInst
+ );
+
+ bool GetSiblingDevice(
+ _In_ DEVINST PrevDevice,
+ _Out_ PDEVINST DevInst
+ );
+
+ HTREEITEM InsertIntoTreeView(
+ _In_opt_ HTREEITEM hParent,
+ _In_ CNode *Node
+ );
+
+ void BuildActionMenuForNode(
+ _In_ HMENU OwnerMenu,
+ _In_ CNode *Node,
+ _In_ bool MainMenu
+ );
+
+ HTREEITEM RecurseFindDevice(
+ _In_ HTREEITEM hParentItem,
+ _In_ LPWSTR DeviceId
+ );
+
+ void SelectNode(
+ _In_ LPWSTR DeviceId
+ );
+
+ void EmptyDeviceView(
+ );
+
+ CNode* GetNode(
+ _In_ LPTV_ITEMW TvItem
+ );
+
+ CClassNode* GetClassNode(
+ _In_ LPGUID ClassGuid
+ );
+ CDeviceNode* GetDeviceNode(
+ _In_ DEVINST Device
+ );
+ void EmptyLists(
+ );
+};
+
--- /dev/null
+/*
+ * PROJECT: ReactOS Device Manager
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: dll/win32/devmgr/devmgr/MainWindow.cpp
+ * PURPOSE: Implements the main container window for the device view
+ * COPYRIGHT: Copyright 2014 - 2015 Ged Murphy <gedmurphy@reactos.org>
+ */
+
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "MainWindow.h"
+
+
+/* DATA *****************************************************/
+
+#define BTN_PROPERTIES 0
+#define BTN_SCAN_HARDWARE 1
+#define BTN_ENABLE_DRV 2
+#define BTN_DISABLE_DRV 3
+#define BTN_UPDATE_DRV 4
+#define BTN_UNINSTALL_DRV 5
+
+
+// menu hints
+static const MENU_HINT MainMenuHintTable[] =
+{
+ // File Menu
+ { IDC_EXIT, IDS_HINT_EXIT },
+
+ // Action Menu
+ { IDC_PROPERTIES, IDS_HINT_PROPERTIES },
+ { IDC_SCAN_HARDWARE, IDS_HINT_SCAN },
+ { IDC_ENABLE_DRV, IDS_HINT_ENABLE },
+ { IDC_DISABLE_DRV, IDS_HINT_DISABLE },
+ { IDC_UPDATE_DRV, IDS_HINT_UPDATE },
+ { IDC_UNINSTALL_DRV, IDS_HINT_UNINSTALL },
+ { IDC_ADD_HARDWARE, IDS_HINT_ADD },
+
+
+ // View Menu
+ { IDC_DEVBYTYPE, IDS_HINT_DEV_BY_TYPE},
+ { IDC_DEVBYCONN, IDS_HINT_DEV_BY_CONN},
+ { IDC_RESBYTYPE, IDS_HINT_RES_BY_TYPE},
+ { IDC_RESBYCONN, IDS_HINT_RES_BY_TYPE},
+ { IDC_SHOWHIDDEN, IDS_HINT_SHOW_HIDDEN },
+
+ { IDC_ABOUT, IDS_HINT_ABOUT }
+
+};
+
+
+// system menu hints
+static const MENU_HINT SystemMenuHintTable[] =
+{
+ {SC_RESTORE, IDS_HINT_SYS_RESTORE},
+ {SC_MOVE, IDS_HINT_SYS_MOVE},
+ {SC_SIZE, IDS_HINT_SYS_SIZE},
+ {SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE},
+ {SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE},
+ {SC_CLOSE, IDS_HINT_SYS_CLOSE},
+};
+
+static TBBUTTON TbButtons[] =
+{
+ { BTN_PROPERTIES, IDC_PROPERTIES, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+ { BTN_SCAN_HARDWARE, IDC_SCAN_HARDWARE, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+ { 2, IDC_STATIC, TBSTATE_ENABLED, BTNS_SEP, 0, 0 },
+ { BTN_ENABLE_DRV, IDC_ENABLE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+ { BTN_DISABLE_DRV, IDC_DISABLE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+ { BTN_UPDATE_DRV, IDC_UPDATE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+ { BTN_UNINSTALL_DRV, IDC_UNINSTALL_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 }
+};
+
+
+/* PUBLIC METHODS **********************************************/
+
+CMainWindow::CMainWindow(void) :
+ m_ToolbarhImageList(NULL),
+ m_hMainWnd(NULL),
+ m_hStatusBar(NULL),
+ m_hToolBar(NULL),
+ m_CmdShow(0)
+{
+ m_szMainWndClass = L"DevMgmtWndClass";
+}
+
+CMainWindow::~CMainWindow(void)
+{
+ // Destroy any previous list
+ if (m_ToolbarhImageList) ImageList_Destroy(m_ToolbarhImageList);
+}
+
+bool
+CMainWindow::Initialize(LPCTSTR lpCaption,
+ int nCmdShow)
+{
+ CAtlStringW szCaption;
+ WNDCLASSEXW wc = {0};
+
+ // Store the show window value
+ m_CmdShow = nCmdShow;
+
+ // Setup the window class struct
+ wc.cbSize = sizeof(WNDCLASSEXW);
+ wc.lpfnWndProc = MainWndProc;
+ wc.hInstance = g_hInstance;
+ wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCEW(IDI_MAIN_ICON));
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+ wc.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
+ wc.lpszClassName = m_szMainWndClass;
+ wc.hIconSm = (HICON)LoadImage(g_hInstance,
+ MAKEINTRESOURCE(IDI_MAIN_ICON),
+ IMAGE_ICON,
+ 16,
+ 16,
+ LR_SHARED);
+
+ // Register the window
+ if (RegisterClassExW(&wc))
+ {
+ // Create the main window and store the object pointer
+ m_hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
+ m_szMainWndClass,
+ lpCaption,
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ 550,
+ 500,
+ NULL,
+ NULL,
+ g_hInstance,
+ this);
+ }
+
+ // Return creation result
+ return !!(m_hMainWnd);
+}
+
+void
+CMainWindow::Uninitialize()
+{
+ // Unregister the window class
+ UnregisterClassW(m_szMainWndClass, g_hInstance);
+}
+
+int
+CMainWindow::Run()
+{
+ MSG Msg;
+
+ // Pump the message queue
+ while (GetMessageW(&Msg, NULL, 0, 0 ) != 0)
+ {
+ TranslateMessage(&Msg);
+ DispatchMessageW(&Msg);
+ }
+
+ return 0;
+}
+
+
+/* PRIVATE METHODS **********************************************/
+
+bool
+CMainWindow::MainWndMenuHint(WORD CmdId,
+ const MENU_HINT *HintArray,
+ DWORD HintsCount,
+ UINT DefHintId)
+{
+ bool Found = false;
+ const MENU_HINT *LastHint;
+ UINT HintId = DefHintId;
+
+ LastHint = HintArray + HintsCount;
+ while (HintArray != LastHint)
+ {
+ if (HintArray->CmdId == CmdId)
+ {
+ HintId = HintArray->HintId;
+ Found = true;
+ break;
+ }
+ HintArray++;
+ }
+
+ StatusBarLoadString(m_hStatusBar,
+ SB_SIMPLEID,
+ g_hInstance,
+ HintId);
+
+ return Found;
+}
+
+void
+CMainWindow::UpdateStatusBar(
+ _In_ bool InMenuLoop
+ )
+{
+ SendMessageW(m_hStatusBar,
+ SB_SIMPLE,
+ (WPARAM)InMenuLoop,
+ 0);
+}
+
+bool
+CMainWindow::RefreshView(ViewType Type)
+{
+ UINT CheckId = 0;
+ BOOL bSuccess;
+
+ // Refreshed the cached view
+ m_DeviceView->Refresh(Type, FALSE, TRUE, NULL);
+
+ // Get the menu item id
+ switch (Type)
+ {
+ case DevicesByType: CheckId = IDC_DEVBYTYPE; break;
+ case DevicesByConnection: CheckId = IDC_DEVBYCONN; break;
+ case ResourcesByType: CheckId = IDC_RESBYTYPE; break;
+ case ResourcesByConnection: CheckId = IDC_RESBYCONN; break;
+ default: ATLASSERT(FALSE); break;
+ }
+
+ // Set the new check item
+ bSuccess = CheckMenuRadioItem(m_hMenu,
+ IDC_DEVBYTYPE,
+ IDC_RESBYCONN,
+ CheckId,
+ MF_BYCOMMAND);
+
+ return TRUE;
+}
+
+bool
+CMainWindow::CreateToolBar()
+{
+ TBADDBITMAP TbAddBitmap;
+ INT Index;
+
+ DWORD dwStyles = WS_CHILDWINDOW | TBSTYLE_FLAT | TBSTYLE_WRAPABLE | TBSTYLE_TOOLTIPS | CCS_NODIVIDER;
+ DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
+
+ // Create the toolbar window
+ m_hToolBar = CreateWindowExW(dwExStyles,
+ TOOLBARCLASSNAME,
+ NULL,
+ dwStyles,
+ 0, 0, 0, 0,
+ m_hMainWnd,
+ (HMENU)IDC_TOOLBAR,
+ g_hInstance,
+ NULL);
+ if (m_hToolBar == NULL) return FALSE;
+
+ // Don't show clipped buttons
+ SendMessageW(m_hToolBar,
+ TB_SETEXTENDEDSTYLE,
+ 0,
+ TBSTYLE_EX_HIDECLIPPEDBUTTONS);
+
+ SendMessageW(m_hToolBar, TB_SETBITMAPSIZE, 0, MAKELONG(16, 16));
+
+ // Set the struct size, the toobar needs this...
+ SendMessageW(m_hToolBar,
+ TB_BUTTONSTRUCTSIZE,
+ sizeof(TBBUTTON),
+ 0);
+
+ TbAddBitmap.hInst = g_hInstance;
+ TbAddBitmap.nID = IDB_TOOLBAR;
+ Index = SendMessageW(m_hToolBar, TB_ADDBITMAP, _countof(TbButtons), (LPARAM)&TbAddBitmap);
+
+ SendMessageW(m_hToolBar, TB_ADDBUTTONSW, _countof(TbButtons), (LPARAM)TbButtons);
+ SendMessageW(m_hToolBar, TB_AUTOSIZE, 0, 0);
+
+ if (TRUE)
+ {
+ ShowWindow(m_hToolBar, SW_SHOW);
+ }
+
+ return TRUE;
+}
+
+bool
+CMainWindow::CreateStatusBar()
+{
+ int StatWidths[] = {110, -1}; // widths of status bar
+ bool bRet = FALSE;
+
+ // Create the status bar
+ m_hStatusBar = CreateWindowExW(0,
+ STATUSCLASSNAME,
+ NULL,
+ WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
+ 0, 0, 0, 0,
+ m_hMainWnd,
+ (HMENU)IDC_STATUSBAR,
+ g_hInstance,
+ NULL);
+ if (m_hStatusBar)
+ {
+ // Set the width
+ bRet = (SendMessageW(m_hStatusBar,
+ SB_SETPARTS,
+ sizeof(StatWidths) / sizeof(int),
+ (LPARAM)StatWidths) != 0);
+ }
+
+ return bRet;
+}
+
+void CMainWindow::UpdateToolbar()
+{
+ WORD State;
+
+ CNode *Node = m_DeviceView->GetSelectedNode();
+
+ // properties button
+ if (Node->HasProperties())
+ {
+ State = TBSTATE_ENABLED;
+ }
+ else
+ {
+ State = TBSTATE_HIDDEN;
+ }
+ SendMessageW(m_hToolBar, TB_SETSTATE, IDC_PROPERTIES, MAKELPARAM(State, 0));
+ SendMessageW(m_hToolBar, TB_SETSTATE, IDC_UPDATE_DRV, MAKELPARAM(State, 0)); //hack
+ SendMessageW(m_hToolBar, TB_SETSTATE, IDC_UNINSTALL_DRV, MAKELPARAM(State, 0)); // hack
+
+
+
+ // enable driver button
+ if (Node->GetNodeType() == DeviceNode &&
+ dynamic_cast<CDeviceNode *>(Node)->IsDisabled())
+ {
+ State = TBSTATE_ENABLED;
+ }
+ else
+ {
+ State = TBSTATE_HIDDEN;
+ }
+ SendMessageW(m_hToolBar, TB_SETSTATE, IDC_ENABLE_DRV, MAKELPARAM(State, 0));
+
+ // disable driver button
+ if (Node->GetNodeType() == DeviceNode &&
+ dynamic_cast<CDeviceNode *>(Node)->CanDisable() &&
+ !dynamic_cast<CDeviceNode *>(Node)->IsDisabled())
+ {
+ State = TBSTATE_ENABLED;
+ }
+ else
+ {
+ State = TBSTATE_HIDDEN;
+ }
+ SendMessageW(m_hToolBar, TB_SETSTATE, IDC_DISABLE_DRV, MAKELPARAM(State, 0));
+
+
+
+
+
+}
+
+
+
+bool
+CMainWindow::StatusBarLoadString(IN HWND hStatusBar,
+ IN INT PartId,
+ IN HINSTANCE hInstance,
+ IN UINT uID)
+{
+ CAtlStringW szMessage;
+ bool bRet = false;
+
+ // Load the string
+ if (szMessage.LoadStringW(hInstance, uID))
+ {
+ // Show the string on the status bar
+ bRet = (SendMessageW(hStatusBar,
+ SB_SETTEXT,
+ (WPARAM)PartId,
+ (LPARAM)szMessage.GetBuffer()) != 0);
+ }
+
+ return bRet;
+}
+
+LRESULT
+CMainWindow::OnCreate(HWND hwnd)
+{
+ LRESULT RetCode;
+
+ RetCode = -1;
+ m_hMainWnd = hwnd;
+
+ // Store a handle to the main menu
+ m_hMenu = GetMenu(m_hMainWnd);
+
+ // Create the toolbar and statusbar
+ if (CreateToolBar() && CreateStatusBar())
+ {
+ // Create the device view object
+ m_DeviceView = new CDeviceView(m_hMainWnd);
+ if (m_DeviceView->Initialize())
+ {
+ // Do the initial scan
+ m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
+ true,
+ true,
+ NULL);
+
+ // Display the window according to the user request
+ ShowWindow(hwnd, m_CmdShow);
+ RetCode = 0;
+ }
+ }
+
+ return RetCode;
+}
+
+LRESULT
+CMainWindow::OnSize()
+{
+ RECT rcClient, rcTool, rcStatus;
+ INT lvHeight, iToolHeight, iStatusHeight;
+
+ // Autosize the toolbar
+ SendMessage(m_hToolBar, TB_AUTOSIZE, 0, 0);
+
+ // Get the toolbar rect and save the height
+ GetWindowRect(m_hToolBar, &rcTool);
+ iToolHeight = rcTool.bottom - rcTool.top;
+
+ // Resize the status bar
+ SendMessage(m_hStatusBar, WM_SIZE, 0, 0);
+
+ // Get the statusbar rect and save the height
+ GetWindowRect(m_hStatusBar, &rcStatus);
+ iStatusHeight = rcStatus.bottom - rcStatus.top;
+
+ // Get the full client rect
+ GetClientRect(m_hMainWnd, &rcClient);
+
+ // Calculate the remaining height for the treeview
+ lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
+
+ // Resize the device view
+ m_DeviceView->OnSize(0,
+ iToolHeight,
+ rcClient.right,
+ lvHeight);
+
+ return 0;
+}
+
+LRESULT
+CMainWindow::OnNotify(LPARAM lParam)
+{
+ LPNMHDR NmHdr = (LPNMHDR)lParam;
+ LRESULT Ret;
+
+ switch (NmHdr->code)
+ {
+ case TVN_SELCHANGED:
+ {
+ UpdateToolbar();
+ break;
+ }
+
+ case NM_DBLCLK:
+ {
+ m_DeviceView->DisplayPropertySheet();
+ break;
+ }
+
+ case NM_RCLICK:
+ {
+ Ret = m_DeviceView->OnRightClick(NmHdr);
+ break;
+ }
+
+ case NM_RETURN:
+ {
+ m_DeviceView->DisplayPropertySheet();
+ break;
+ }
+
+ case TTN_GETDISPINFO:
+ {
+ LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT)lParam;
+
+ UINT_PTR idButton = lpttt->hdr.idFrom;
+ switch (idButton)
+ {
+ case IDC_PROPERTIES:
+ lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_PROPERTIES);
+ break;
+ case IDC_SCAN_HARDWARE:
+ lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_SCAN);
+ break;
+ case IDC_ENABLE_DRV:
+ lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_ENABLE);
+ break;
+ case IDC_DISABLE_DRV:
+ lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_DISABLE);
+ break;
+ case IDC_UPDATE_DRV:
+ lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UPDATE);
+ break;
+ case IDC_UNINSTALL_DRV:
+ lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UNINSTALL);
+ break;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+LRESULT
+CMainWindow::OnContext(LPARAM lParam)
+{
+ return m_DeviceView->OnContextMenu(lParam);
+}
+
+LRESULT
+CMainWindow::OnCommand(WPARAM wParam,
+ LPARAM /*lParam*/)
+{
+ LRESULT RetCode = 0;
+ WORD Msg;
+
+ // Get the message
+ Msg = LOWORD(wParam);
+
+ switch (Msg)
+ {
+ case IDC_PROPERTIES:
+ case IDC_SCAN_HARDWARE:
+ case IDC_ENABLE_DRV:
+ case IDC_DISABLE_DRV:
+ case IDC_UPDATE_DRV:
+ case IDC_UNINSTALL_DRV:
+ case IDC_ADD_HARDWARE:
+ {
+ m_DeviceView->OnAction(Msg);
+ break;
+ }
+
+ case IDC_ACTIONMENU:
+ {
+ // Create a popup menu with all the actions for the selected node
+ HMENU hMenu = CreatePopupMenu();
+ m_DeviceView->CreateActionMenu(hMenu, true);
+
+ // Calculate where to put the menu
+ RECT rc;
+ GetMenuItemRect(m_hMainWnd, m_hMenu, 1, &rc);
+ LONG Height = rc.bottom - rc.top;
+
+ // Display the menu
+ TrackPopupMenuEx(hMenu,
+ TPM_RIGHTBUTTON,
+ rc.left,
+ rc.top + Height,
+ m_hMainWnd,
+ NULL);
+
+ DestroyMenu(hMenu);
+ break;
+ }
+
+ case IDC_DEVBYTYPE:
+ {
+ RefreshView(DevicesByType);
+ break;
+ }
+
+ case IDC_DEVBYCONN:
+ {
+ RefreshView(DevicesByConnection);
+ break;
+ }
+
+ case IDC_SHOWHIDDEN:
+ {
+ // Get the current state
+ UINT CurCheckState = GetMenuState(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND);
+ if (CurCheckState == MF_CHECKED)
+ {
+ m_DeviceView->SetHiddenDevices(false);
+ CheckMenuItem(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND | MF_UNCHECKED);
+ }
+ else if (CurCheckState == MF_UNCHECKED)
+ {
+ m_DeviceView->SetHiddenDevices(true);
+ CheckMenuItem(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND | MF_CHECKED);
+ }
+ // Refresh the device view
+ m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
+ false,
+ true,
+ NULL);
+ break;
+ }
+
+ case IDC_ABOUT:
+ {
+ // Apportion blame
+ MessageBoxW(m_hMainWnd,
+ L"ReactOS Device Manager\r\nCopyright Ged Murphy 2015",
+ L"About",
+ MB_OK | MB_APPLMODAL);
+
+ // Set focus back to the treeview
+ m_DeviceView->SetFocus();
+ break;
+ }
+
+ case IDC_EXIT:
+ {
+ // Post a close message to the window
+ PostMessageW(m_hMainWnd,
+ WM_CLOSE,
+ 0,
+ 0);
+ break;
+ }
+
+ default:
+ // We didn't handle it
+ RetCode = -1;
+ break;
+ }
+
+ return RetCode;
+}
+
+LRESULT
+CMainWindow::OnDestroy()
+{
+ // Uninitialize the device view
+ m_DeviceView->Uninitialize();
+
+ // Kill the object
+ delete m_DeviceView;
+ m_DeviceView = NULL;
+
+ // Clear the user data pointer
+ SetWindowLongPtr(m_hMainWnd, GWLP_USERDATA, 0);
+
+ // Break the message loop
+ PostQuitMessage(0);
+
+ return 0;
+}
+
+LRESULT CALLBACK
+CMainWindow::MainWndProc(HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ CMainWindow *This;
+ LRESULT RetCode = 0;
+
+ // Get the object pointer from window context
+ This = (CMainWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (This == NULL)
+ {
+ // Check that this isn't a create message
+ if (msg != WM_CREATE)
+ {
+ // Don't handle null info pointer
+ goto HandleDefaultMessage;
+ }
+ }
+
+ switch(msg)
+ {
+ case WM_CREATE:
+ {
+ // Get the object pointer from the create param
+ This = (CMainWindow *)((LPCREATESTRUCT)lParam)->lpCreateParams;
+
+ // Store the pointer in the window's global user data
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)This);
+
+ // Call the create handler
+ RetCode = This->OnCreate(hwnd);
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ RetCode = This->OnSize();
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ RetCode = This->OnNotify(lParam);
+ break;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ RetCode = This->OnContext(lParam);
+ break;
+ }
+
+ case WM_MENUSELECT:
+ {
+ if (This->m_hStatusBar != NULL)
+ {
+ if (!This->MainWndMenuHint(LOWORD(wParam),
+ MainMenuHintTable,
+ sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
+ IDS_HINT_BLANK))
+ {
+ This->MainWndMenuHint(LOWORD(wParam),
+ SystemMenuHintTable,
+ sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
+ IDS_HINT_BLANK);
+ }
+ }
+
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ // Handle the command message
+ RetCode = This->OnCommand(wParam, lParam);
+ if (RetCode == -1)
+ {
+ // Hand it off to the default message handler
+ goto HandleDefaultMessage;
+ }
+ break;
+ }
+
+ case WM_ENTERMENULOOP:
+ {
+ This->UpdateStatusBar(true);
+ break;
+ }
+
+ case WM_EXITMENULOOP:
+ {
+ This->UpdateStatusBar(false);
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ // Destroy the main window
+ DestroyWindow(hwnd);
+ break;
+ }
+
+
+ case WM_DESTROY:
+ {
+ // Call the destroy handler
+ RetCode = This->OnDestroy();
+ break;
+ }
+
+ default:
+ {
+HandleDefaultMessage:
+ RetCode = DefWindowProc(hwnd, msg, wParam, lParam);
+ break;
+ }
+ }
+
+ return RetCode;
+}
+
+
+//////// MOVE ME ////////////////
+
+HINSTANCE g_hInstance = NULL;
+HANDLE ProcessHeap = NULL;
+
+BOOL
+WINAPI
+DeviceManager_ExecuteW(HWND /*hWndParent*/,
+ HINSTANCE hInst,
+ LPCWSTR /*lpMachineName*/,
+ int nCmdShow)
+{
+ CMainWindow MainWindow;
+ INITCOMMONCONTROLSEX icex;
+ CAtlStringW szAppName;
+ int Ret = 1;
+
+ // Store the global values
+ g_hInstance = hInst;
+ ProcessHeap = GetProcessHeap();
+
+ // Initialize common controls
+ icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ icex.dwICC = ICC_BAR_CLASSES | ICC_COOL_CLASSES;
+ InitCommonControlsEx(&icex);
+
+ // Load the application name
+ if (szAppName.LoadStringW(g_hInstance, IDS_APPNAME))
+ {
+ // Initialize the main window
+ if (MainWindow.Initialize(szAppName, nCmdShow))
+ {
+ // Run the application
+ Ret = MainWindow.Run();
+
+ // Uninitialize the main window
+ MainWindow.Uninitialize();
+ }
+ }
+
+ return Ret;
+}
--- /dev/null
+#pragma once
+#include "DeviceView.h"
+
+typedef struct _MENU_HINT
+{
+ WORD CmdId;
+ UINT HintId;
+} MENU_HINT, *PMENU_HINT;
+
+class CMainWindow
+{
+ CAtlStringW m_szMainWndClass;
+ CDeviceView *m_DeviceView;
+ HWND m_hMainWnd;
+ HWND m_hStatusBar;
+ HWND m_hToolBar;
+ HIMAGELIST m_ToolbarhImageList;
+ HMENU m_hMenu;
+ HMENU m_hActionMenu;
+ int m_CmdShow;
+
+public:
+ CMainWindow(void);
+ ~CMainWindow(void);
+
+ bool Initialize(LPCTSTR lpCaption, int nCmdShow);
+ int Run();
+ void Uninitialize();
+
+private:
+ static LRESULT CALLBACK MainWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+ LRESULT OnCreate(HWND hwnd);
+ LRESULT OnDestroy();
+ LRESULT OnSize();
+ LRESULT OnNotify(LPARAM lParam);
+ LRESULT OnContext(LPARAM lParam);
+ LRESULT OnCommand(WPARAM wParam, LPARAM lParam);
+
+ bool CreateToolBar();
+ bool CreateStatusBar();
+
+ void UpdateToolbar(
+ );
+
+ bool StatusBarLoadString(
+ HWND hStatusBar,
+ INT PartId,
+ HINSTANCE hInstance,
+ UINT uID
+ );
+
+ void UpdateStatusBar(
+ _In_ bool InMenuLoop
+ );
+
+ bool MainWndMenuHint(
+ WORD CmdId,
+ const MENU_HINT *HintArray,
+ DWORD HintsCount,
+ UINT DefHintId
+ );
+
+ bool RefreshView(
+ ViewType Type
+ );
+};
+
--- /dev/null
+/*
+* PROJECT: ReactOS Device Manager
+* LICENSE: GPL - See COPYING in the top level directory
+* FILE: dll/win32/devmgr/devmgr/node.cpp
+* PURPOSE: Abstract base object for each node in the tree
+* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
+*
+*/
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "Node.h"
+
+
+/* PUBLIC METHODS *******************************************/
+
+CNode::CNode(_In_ NodeType Type,
+ _In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
+ m_NodeType(Type),
+ m_ImageListData(ImageListData),
+ m_DeviceId(NULL),
+ m_ClassImage(0)
+{
+ m_DisplayName[0] = UNICODE_NULL;
+ m_ClassGuid = GUID_NULL;
+}
+
+CNode::~CNode()
+{
+}
--- /dev/null
+#pragma once
+
+#define DISPLAY_NAME_LEN 256
+
+enum NodeType
+{
+ RootNode,
+ ClassNode,
+ DeviceNode
+};
+
+class CNode
+{
+protected:
+ PSP_CLASSIMAGELIST_DATA m_ImageListData;
+ LPWSTR m_DeviceId;
+ WCHAR m_DisplayName[DISPLAY_NAME_LEN];
+ GUID m_ClassGuid;
+ INT m_ClassImage;
+ NodeType m_NodeType;
+
+public:
+ CNode(
+ _In_ NodeType Type,
+ _In_ PSP_CLASSIMAGELIST_DATA ImageListData
+ );
+
+ ~CNode();
+
+ virtual bool SetupNode() = 0;
+
+ NodeType GetNodeType() { return m_NodeType; }
+ LPGUID GetClassGuid() { return &m_ClassGuid; }
+ LPWSTR GetDisplayName() { return m_DisplayName; }
+ INT GetClassImage() { return m_ClassImage; }
+ LPWSTR GetDeviceId() { return m_DeviceId; }
+ bool HasProperties() { return (m_DeviceId != NULL); }
+};
+
--- /dev/null
+#define IDC_STATIC -1
+
+#define IDS_APPNAME 10
+
+#define IDI_MAIN_ICON 20
+#define IDB_ROOT_IMAGE 21
+#define IDB_TOOLBAR 22
+
+/* windows */
+#define IDC_TREEVIEW 50
+#define IDC_TOOLBAR 51
+#define IDC_STATUSBAR 52
+#define IDR_MAINMENU 53
+#define IDR_POPUP 54
+
+/* Actions */
+#define IDC_PROPERTIES 100
+#define IDC_SCAN_HARDWARE 101
+#define IDC_ENABLE_DRV 102
+#define IDC_DISABLE_DRV 103
+#define IDC_UPDATE_DRV 104
+#define IDC_UNINSTALL_DRV 105
+#define IDC_ADD_HARDWARE 106
+
+/* Menu items */
+#define IDC_ACTIONMENU 150
+#define IDC_ABOUT 151
+#define IDC_EXIT 152
+
+
+/* view menu */
+#define IDC_DEVBYTYPE 200
+#define IDC_DEVBYCONN 201
+#define IDC_RESBYTYPE 202
+#define IDC_RESBYCONN 203
+#define IDC_SHOWHIDDEN 204
+
+
+/* tooltips */
+#define IDS_TOOLTIP_PROPERTIES 300
+#define IDS_TOOLTIP_SCAN 301
+#define IDS_TOOLTIP_ENABLE 302
+#define IDS_TOOLTIP_DISABLE 303
+#define IDS_TOOLTIP_UPDATE 304
+#define IDS_TOOLTIP_UNINSTALL 305
+
+/* General strings */
+#define IDS_CONFIRM_DISABLE 400
+
+/* Menu strings */
+#define IDS_MENU_UPDATE 500
+#define IDS_MENU_ENABLE 501
+#define IDS_MENU_DISABLE 502
+#define IDS_MENU_UNINSTALL 503
+#define IDS_MENU_SCAN 504
+#define IDS_MENU_ADD 505
+#define IDS_MENU_PROPERTIES 506
+
+
+/* menu hints */
+#define IDS_HINT_BLANK 1000
+#define IDS_HINT_PROPERTIES 1001
+#define IDS_HINT_SCAN 1002
+#define IDS_HINT_ENABLE 1003
+#define IDS_HINT_DISABLE 1004
+#define IDS_HINT_UPDATE 1005
+#define IDS_HINT_UNINSTALL 1006
+#define IDS_HINT_ADD 1007
+#define IDS_HINT_ABOUT 20008
+#define IDS_HINT_EXIT 20009
+
+#define IDS_HINT_DEV_BY_TYPE 20020
+#define IDS_HINT_DEV_BY_CONN 20021
+#define IDS_HINT_RES_BY_TYPE 20022
+#define IDS_HINT_RES_BY_CONN 20023
+#define IDS_HINT_SHOW_HIDDEN 20024
+
+/* system menu hints */
+#define IDS_HINT_SYS_RESTORE 21001
+#define IDS_HINT_SYS_MOVE 21002
+#define IDS_HINT_SYS_SIZE 21003
+#define IDS_HINT_SYS_MINIMIZE 21004
+#define IDS_HINT_SYS_MAXIMIZE 21005
+#define IDS_HINT_SYS_CLOSE 21006
--- /dev/null
+/*
+* PROJECT: ReactOS Device Manager
+* LICENSE: GPL - See COPYING in the top level directory
+* FILE: dll/win32/devmgr/devmgr/RootNode.cpp
+* PURPOSE: Root object for
+* COPYRIGHT: Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
+*
+*/
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "RootNode.h"
+
+
+CRootNode::CRootNode(_In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
+ CNode(RootNode, ImageListData)
+{
+}
+
+
+CRootNode::~CRootNode()
+{
+}
+
+
+bool
+CRootNode::SetupNode()
+{
+
+ // Load the bitmap we'll be using as the root image
+ HBITMAP hRootImage;
+ hRootImage = LoadBitmapW(g_hInstance,
+ MAKEINTRESOURCEW(IDB_ROOT_IMAGE));
+ if (hRootImage == NULL) return FALSE;
+
+ // Add this bitmap to the device image list. This is a bit hacky, but it's safe
+ m_ClassImage = ImageList_Add(m_ImageListData->ImageList,
+ hRootImage,
+ NULL);
+ DeleteObject(hRootImage);
+
+
+ // Get the root instance
+ CONFIGRET cr;
+ cr = CM_Locate_DevNodeW(&m_DevInst,
+ NULL,
+ CM_LOCATE_DEVNODE_NORMAL);
+ if (cr != CR_SUCCESS)
+ {
+ return false;
+ }
+
+ // The root name is the computer name
+ DWORD Size = DISPLAY_NAME_LEN;
+ if (GetComputerNameW(m_DisplayName, &Size))
+ _wcslwr(m_DisplayName);
+
+ return true;
+
+
+}
\ No newline at end of file
--- /dev/null
+#pragma once
+#include "Node.h"
+
+class CRootNode : public CNode
+{
+private:
+ DEVINST m_DevInst;
+
+public:
+ CRootNode(_In_ PSP_CLASSIMAGELIST_DATA ImageListData);
+ ~CRootNode();
+
+ virtual bool SetupNode();
+
+ DEVINST GetDeviceInst() { return m_DevInst; }
+};
+
--- /dev/null
+#pragma once
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#pragma once
+#include "resource.h"
+
+extern HINSTANCE g_hInstance;
+extern HANDLE ProcessHeap;
+
--- /dev/null
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+IDR_MAINMENU MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "E&xit", IDC_EXIT
+ END
+ MENUITEM "Action" IDC_ACTIONMENU
+ POPUP "View"
+ BEGIN
+ MENUITEM "Devices by type", IDC_DEVBYTYPE
+ MENUITEM "Devices by connection", IDC_DEVBYCONN
+ MENUITEM "Resources by type", IDC_RESBYTYPE, GRAYED
+ MENUITEM "Resources by connection", IDC_RESBYCONN, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "Show hidden devices", IDC_SHOWHIDDEN
+ END
+ POPUP "Help"
+ BEGIN
+ MENUITEM "About", IDC_ABOUT
+ END
+END
+
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_CONFIRM_DISABLE "Disabling this device will cause it to stop functioning.\r\nDo you really want to disable it?"
+END
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_MENU_UPDATE "Update driver software..."
+ IDS_MENU_ENABLE "Enable"
+ IDS_MENU_DISABLE "Disable"
+ IDS_MENU_UNINSTALL "Uninstall"
+ IDS_MENU_SCAN "Scan for hardware changes"
+ IDS_MENU_ADD "Add hardware"
+ IDS_MENU_PROPERTIES "Properties"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_TOOLTIP_PROPERTIES "Properties"
+ IDS_TOOLTIP_SCAN "Scan for hardware changes"
+ IDS_TOOLTIP_ENABLE "Enable"
+ IDS_TOOLTIP_DISABLE "Disable"
+ IDS_TOOLTIP_UPDATE "Update Driver Software"
+ IDS_TOOLTIP_UNINSTALL "Uninstall"
+END
+
+/* Hints */
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_APPNAME "ReactOS Device Manager"
+ IDS_HINT_BLANK " "
+ IDS_HINT_PROPERTIES " Open property dialog for the current selection."
+ IDS_HINT_SCAN " Scan for changed or new plug and play devices."
+ IDS_HINT_ENABLE " Enables the selected device."
+ IDS_HINT_DISABLE " Disables the selected device."
+ IDS_HINT_UPDATE " Launches the Update Driver Software wizard for the selected device."
+ IDS_HINT_UNINSTALL " Uninstalls the driver for the selected device."
+ IDS_HINT_ADD " Adds a legacy (non-Plug and Play) device to the computer."
+ IDS_HINT_ABOUT " About ReactOS Device Manager."
+ IDS_HINT_EXIT " Exits the program."
+
+ IDS_HINT_DEV_BY_TYPE " Displays devices by hardware type."
+ IDS_HINT_DEV_BY_CONN " Displays devices by connection."
+ IDS_HINT_RES_BY_TYPE " Displays resources by type."
+ IDS_HINT_RES_BY_CONN " Displays resources by connection type."
+ IDS_HINT_SHOW_HIDDEN " Displays legacy devices and devices that are no longer installed."
+
+ IDS_HINT_SYS_RESTORE " Restores this window to normal size."
+ IDS_HINT_SYS_MOVE " Moves this window."
+ IDS_HINT_SYS_SIZE " Resizes this window."
+ IDS_HINT_SYS_MINIMIZE " Collapses this window to an icon."
+ IDS_HINT_SYS_MAXIMIZE " Expands this window to fill this screen."
+ IDS_HINT_SYS_CLOSE " Closes this window."
+END
--- /dev/null
+/* TRANSLATOR: 2015 Erdem Ersoy (eersoy93) (erdemersoy@live.com) */
+
+LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
+
+IDR_MAINMENU MENU
+BEGIN
+ POPUP "&Kütük"
+ BEGIN
+ MENUITEM "&Çıkış", IDC_EXIT
+ END
+ POPUP "&Eylem"
+ BEGIN
+ MENUITEM "&Sürücü Yazılmını Şimdikileştir..." IDC_UPDATE_DRV
+ MENUITEM "&EtkinleÅŸtir" IDC_ENABLE_DRV
+ MENUITEM "E&dilginleÅŸtir" IDC_DISABLE_DRV
+ MENUITEM "&Kaldır" IDC_UNINSTALL_DRV
+ MENUITEM SEPARATOR
+ MENUITEM "D&onanım Değişiklikleri İçin Tara" IDC_SCAN_HARDWARE
+ MENUITEM "Do&nanım Ekle" IDC_ADD_HARDWARE, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "&Husûsiyetler", IDC_PROPERTIES
+ END
+ POPUP "&Görünüm"
+ BEGIN
+ MENUITEM "&Türe Göre Aygıtlar", IDC_DEVBYTYPE
+ MENUITEM "&Bağlantıya Göre Aygıtlar", IDC_DEVBYCONN
+ MENUITEM "T&üre Göre Kaynaklar", IDC_RESBYTYPE, GRAYED
+ MENUITEM "B&ağlantıya Göre Kaynaklar", IDC_RESBYCONN, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "&Gizli Aygıtları Göster", IDC_SHOWHIDDEN
+ END
+ POPUP "&Yardım"
+ BEGIN
+ MENUITEM "&Üzerine", IDC_ABOUT
+ END
+END
+
+IDR_POPUP MENU
+BEGIN
+ POPUP "popup"
+ BEGIN
+ MENUITEM "&Sürücü Yazılmını Şimdikileştir..." IDC_UPDATE_DRV
+ MENUITEM "&EtkinleÅŸtir" IDC_ENABLE_DRV
+ MENUITEM "E&dilginleÅŸtir" IDC_DISABLE_DRV
+ MENUITEM "&Kaldır" IDC_UNINSTALL_DRV
+ MENUITEM SEPARATOR
+ MENUITEM "D&onanım Değişiklikleri İçin Tara" IDC_SCAN_HARDWARE
+ MENUITEM "Do&nanım Ekle" IDC_ADD_HARDWARE, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "&Husûsiyetler", IDC_PROPERTIES
+ END
+END
+
+#define IDS_HINT_PROPERTIES 20001
+#define IDS_HINT_SCAN 20002
+#define IDS_HINT_ENABLE 20003
+#define IDS_HINT_DISABLE 20004
+#define IDS_HINT_UPDATE 20005
+#define IDS_HINT_UNINSTALL 20006
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_TOOLTIP_PROPERTIES "Husûsiyetler"
+ IDS_TOOLTIP_SCAN "Donanım Değişiklikleri İçin Tara"
+ IDS_TOOLTIP_ENABLE "EtkinleÅŸtir"
+ IDS_TOOLTIP_DISABLE "EdilginleÅŸtir"
+ IDS_TOOLTIP_UPDATE "Sürücü Yazılmını Şimdikileştir"
+ IDS_TOOLTIP_UNINSTALL "Kaldır"
+END
+
+/* Hints */
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_APPNAME "Aygıt Yöneticisi"
+ IDS_HINT_BLANK " "
+ IDS_HINT_PROPERTIES " Şimdiki seçilen için husûsiyet penceresini açar."
+ IDS_HINT_SCAN " Yeni ya da değiştirilmiş tak ve çalıştır aygıtları için tarar."
+ IDS_HINT_ENABLE " Seçili aygıtı etkinleştirir."
+ IDS_HINT_DISABLE " Seçili aygıtı edilginleştirir."
+ IDS_HINT_UPDATE " Seçili aygıt için Sürücü Yazılımını Şimdikileştir yardımcısını başlatır."
+ IDS_HINT_UNINSTALL " Seçili aygıt için sürücüyü kaldırır."
+ IDS_HINT_ADD " Bilgisayara eski (Tak ve Çalıştır olmayan) bir aygıt ekler."
+ IDS_HINT_ABOUT " Aygıt Yöneticisi üzerine."
+ IDS_HINT_EXIT " İzlenceden çıkar."
+
+ IDS_HINT_DEV_BY_TYPE " Donanım türüne göre aygıtları görüntüler."
+ IDS_HINT_DEV_BY_CONN " Bağlantıya göre aygıtları görüntüler."
+ IDS_HINT_RES_BY_TYPE " Türe göre kaynakları görüntüler."
+ IDS_HINT_RES_BY_CONN " Bağlantı türüne göre kaynakları görüntüler."
+ IDS_HINT_SHOW_HIDDEN " Eski aygıtları ve artık kurulu olmayacak aygıtları görüntüler."
+
+ IDS_HINT_SYS_RESTORE " Bu pencereyi düzgülük boyutlarına döndürür."
+ IDS_HINT_SYS_MOVE " Bu pencereyi devindirir."
+ IDS_HINT_SYS_SIZE " Bu pencereyi yeniden boyutlandırır."
+ IDS_HINT_SYS_MINIMIZE " Bu pencereyi bir simgeye küçültür."
+ IDS_HINT_SYS_MAXIMIZE " Bu pencereyi, bu görüntülüğü kaplatana dek genişletir."
+ IDS_HINT_SYS_CLOSE " Bu pencereyi kapatır."
+END
--- /dev/null
+#include <windows.h>
+#include "resource.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+IDI_MAIN_ICON ICON "res/computer.ico"
+IDB_ROOT_IMAGE BITMAP "res/root.bmp"
+
+/* main toolbar icons */
+IDB_TOOLBAR BITMAP DISCARDABLE "res/toolbar.bmp"
+
+// UTF-8
+#pragma code_page(65001)
+
+#ifdef LANGUAGE_BG_BG
+ #include "lang/bg-BG.rc"
+#endif
+#ifdef LANGUAGE_DE_DE
+ #include "lang/de-DE.rc"
+#endif
+#ifdef LANGUAGE_EL_GR
+ #include "lang/el-GR.rc"
+#endif
+#ifdef LANGUAGE_EN_US
+ #include "lang/en-US.rc"
+#endif
+#ifdef LANGUAGE_ES_ES
+ #include "lang/es-ES.rc"
+#endif
+#ifdef LANGUAGE_FR_FR
+ #include "lang/fr-FR.rc"
+#endif
+#ifdef LANGUAGE_HE_IL
+ #include "lang/he-IL.rc"
+#endif
+#ifdef LANGUAGE_ID_ID
+ #include "lang/id-ID.rc"
+#endif
+#ifdef LANGUAGE_IT_IT
+ #include "lang/it-IT.rc"
+#endif
+#ifdef LANGUAGE_JA_JP
+ #include "lang/ja-JP.rc"
+#endif
+#ifdef LANGUAGE_KO_KR
+ #include "lang/ko-KR.rc"
+#endif
+#ifdef LANGUAGE_NB_NO
+ #include "lang/no-NO.rc"
+#endif
+#ifdef LANGUAGE_PL_PL
+ #include "lang/pl-PL.rc"
+#endif
+#ifdef LANGUAGE_PT_BR
+ #include "lang/pt-BR.rc"
+#endif
+#ifdef LANGUAGE_RO_RO
+ #include "lang/ro-RO.rc"
+#endif
+#ifdef LANGUAGE_RU_RU
+ #include "lang/ru-RU.rc"
+#endif
+#ifdef LANGUAGE_SK_SK
+ #include "lang/sk-SK.rc"
+#endif
+#ifdef LANGUAGE_SV_SE
+ #include "lang/sv-SE.rc"
+#endif
+#ifdef LANGUAGE_TH_TH
+ #include "lang/th-TH.rc"
+#endif
+#ifdef LANGUAGE_TR_TR
+ #include "lang/tr-TR.rc"
+#endif
+#ifdef LANGUAGE_UK_UA
+ #include "lang/uk-UA.rc"
+#endif
+#ifdef LANGUAGE_ZH_CN
+ #include "lang/zh-CN.rc"
+#endif
--- /dev/null
+#pragma once
+
+#ifndef __REACTOS__
+
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include <windowsx.h>
+#include <setupapi.h>
+#include <cfgmgr32.h>
+#include <commctrl.h>
+#include <Uxtheme.h>
+#include <Cfgmgr32.h>
+#include <devguid.h>
+#include <process.h>
+
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+#include <tchar.h>
+#include <atlbase.h>
+#include <atlstr.h>
+#include <atlcoll.h>
+
+#include <strsafe.h>
+#else
+
+#include <string.h>
+#include <wchar.h>
+
+#include <tchar.h>
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <wingdi.h>
+#include <winnls.h>
+#include <wincon.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <strsafe.h>
+#include <process.h>
+#include <WindowsX.h>
+#include <strsafe.h>
+
+#include <setupapi.h>
+#include <commctrl.h>
+#include <cfgmgr32.h>
+#include <Uxtheme.h>
+#include <devguid.h>
+
+#include <atlbase.h>
+#include <atlstr.h>
+#include <atlcoll.h>
+
+#endif
\ No newline at end of file
--- /dev/null
+#include <windef.h>
+#include <winuser.h>
+#include <commctrl.h>
+
+#include "resource.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Device Manager"
+#define REACTOS_STR_INTERNAL_NAME "devmgr"
+#define REACTOS_STR_ORIGINAL_FILENAME "devmgr.dll"
+#include <reactos/version.rc>
+
+IDI_DEVMGR ICON "resources/devmgr.ico"
+
+#include <reactos/manifest_dll.rc>
+
+/* UTF-8 */
+#pragma code_page(65001)
+
+#ifdef LANGUAGE_BG_BG
+ #include "lang/bg-BG.rc"
+#endif
+#ifdef LANGUAGE_CS_CZ
+ #include "lang/cs-CZ.rc"
+#endif
+#ifdef LANGUAGE_DE_DE
+ #include "lang/de-DE.rc"
+#endif
+#ifdef LANGUAGE_EL_GR
+ #include "lang/el-GR.rc"
+#endif
+#ifdef LANGUAGE_EN_US
+ #include "lang/en-US.rc"
+#endif
+#ifdef LANGUAGE_ES_ES
+ #include "lang/es-ES.rc"
+#endif
+#ifdef LANGUAGE_HE_IL
+ #include "lang/he-IL.rc"
+#endif
+#ifdef LANGUAGE_FR_FR
+ #include "lang/fr-FR.rc"
+#endif
+#ifdef LANGUAGE_HU_HU
+ #include "lang/hu-HU.rc"
+#endif
+#ifdef LANGUAGE_ID_ID
+ #include "lang/id-ID.rc"
+#endif
+#ifdef LANGUAGE_IT_IT
+ #include "lang/it-IT.rc"
+#endif
+#ifdef LANGUAGE_NB_NO
+ #include "lang/no-NO.rc"
+#endif
+#ifdef LANGUAGE_PL_PL
+ #include "lang/pl-PL.rc"
+#endif
+#ifdef LANGUAGE_PT_BR
+ #include "lang/pt-BR.rc"
+#endif
+#ifdef LANGUAGE_RO_RO
+ #include "lang/ro-RO.rc"
+#endif
+#ifdef LANGUAGE_RU_RU
+ #include "lang/ru-RU.rc"
+#endif
+#ifdef LANGUAGE_SK_SK
+ #include "lang/sk-SK.rc"
+#endif
+#ifdef LANGUAGE_SQ_AL
+ #include "lang/sq-AL.rc"
+#endif
+#ifdef LANGUAGE_TR_TR
+ #include "lang/tr-TR.rc"
+#endif
+#ifdef LANGUAGE_UK_UA
+ #include "lang/uk-UA.rc"
+#endif
--- /dev/null
+# devmgr.dll exports
+
+ 5 stdcall DeviceProperties_RunDLLA(ptr ptr str long)
+ 6 stdcall DeviceProperties_RunDLLW(ptr ptr wstr long)
+ 7 stdcall DevicePropertiesA(ptr str str long)
+ 8 stdcall DevicePropertiesW(ptr wstr wstr long)
+ 9 stdcall DeviceManager_ExecuteA(ptr ptr str long)
+10 stdcall DeviceManager_ExecuteW(ptr ptr wstr long)
+11 stdcall DeviceProblemTextA(ptr long long str long)
+12 stdcall DeviceProblemTextW(ptr long long wstr long)
+13 stdcall DeviceProblemWizardA(ptr str str)
+14 stdcall DeviceProblemWizardW(ptr wstr wstr)
+15 stdcall DeviceManagerPrintA(str str long long ptr)
+16 stdcall DeviceManagerPrintW(wstr wstr long long ptr)
+17 stdcall DeviceAdvancedPropertiesA(ptr str str)
+18 stdcall DeviceAdvancedPropertiesW(ptr wstr wstr)
+19 stdcall DeviceCreateHardwarePage(ptr ptr)
+20 stdcall DeviceCreateHardwarePageEx(ptr ptr long long)
+21 stdcall DevicePropertiesExA(ptr str str long long)
+22 stdcall DevicePropertiesExW(ptr wstr wstr long long)
+23 stdcall DeviceProblenWizard_RunDLLA(ptr ptr str long) DeviceProblemWizard_RunDLLA
+24 stdcall DeviceProblenWizard_RunDLLW(ptr ptr wstr long) DeviceProblemWizard_RunDLLW
+
+@ stub -private DllCanUnloadNow
+@ stub -private DllGetClassObject
+@ stub -private DllRegisterServer
+@ stub -private DllUnregisterServer
--- /dev/null
+/*
+ * ReactOS Device Manager Applet
+ * Copyright (C) 2004 - 2005 ReactOS Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+/*
+ * PROJECT: ReactOS devmgr.dll
+ * FILE: lib/devmgr/devprblm.c
+ * PURPOSE: ReactOS Device Manager
+ * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
+ * UPDATE HISTORY:
+ * 04-04-2004 Created
+ */
+
+#include "precomp.h"
+
+
+BOOL
+ShowDeviceProblemWizard(IN HWND hWndParent OPTIONAL,
+ IN HDEVINFO hDevInfo,
+ IN PSP_DEVINFO_DATA DevInfoData,
+ IN HMACHINE hMachine OPTIONAL)
+{
+ WCHAR szDeviceInstanceId[256];
+ CONFIGRET cr;
+ ULONG Status, ProblemNumber;
+ DWORD dwReboot;
+ BOOL Ret = FALSE;
+
+ /* Get the device instance id */
+ if (!SetupDiGetDeviceInstanceId(hDevInfo,
+ DevInfoData,
+ szDeviceInstanceId,
+ 256,
+ NULL))
+ return FALSE;
+
+ cr = CM_Get_DevNode_Status_Ex(&Status,
+ &ProblemNumber,
+ DevInfoData->DevInst,
+ 0,
+ hMachine);
+ if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
+ {
+ switch (ProblemNumber)
+ {
+ case CM_PROB_DEVLOADER_FAILED:
+ {
+ /* FIXME - only if it's not a root bus devloader */
+ /* FIXME - display the update driver wizard */
+ break;
+ }
+
+ case CM_PROB_OUT_OF_MEMORY:
+ case CM_PROB_ENTRY_IS_WRONG_TYPE:
+ case CM_PROB_LACKED_ARBITRATOR:
+ case CM_PROB_FAILED_START:
+ case CM_PROB_LIAR:
+ case CM_PROB_UNKNOWN_RESOURCE:
+ {
+ /* FIXME - display the update driver wizard */
+ InstallDevInst(hWndParent, szDeviceInstanceId, TRUE, &dwReboot);
+ break;
+ }
+
+ case CM_PROB_BOOT_CONFIG_CONFLICT:
+ case CM_PROB_NORMAL_CONFLICT:
+ case CM_PROB_REENUMERATION:
+ {
+ /* FIXME - display the conflict wizard */
+ break;
+ }
+
+ case CM_PROB_FAILED_FILTER:
+ case CM_PROB_REINSTALL:
+ case CM_PROB_FAILED_INSTALL:
+ {
+ /* FIXME - display the driver (re)installation wizard */
+ InstallDevInst(hWndParent, szDeviceInstanceId, TRUE, &dwReboot);
+ break;
+ }
+
+ case CM_PROB_DEVLOADER_NOT_FOUND:
+ {
+ /* FIXME - 4 cases:
+ 1) if it's a missing system devloader:
+ - fail
+ 2) if it's not a system devloader but still missing:
+ - display the driver reinstallation wizard
+ 3) if it's not a system devloader but the file can be found:
+ - display the update driver wizard
+ 4) if it's a missing or empty software key
+ - display the update driver wizard
+ */
+ break;
+ }
+
+ case CM_PROB_INVALID_DATA:
+ case CM_PROB_PARTIAL_LOG_CONF:
+ case CM_PROB_NO_VALID_LOG_CONF:
+ case CM_PROB_HARDWARE_DISABLED:
+ case CM_PROB_CANT_SHARE_IRQ:
+ case CM_PROB_TRANSLATION_FAILED:
+ case CM_PROB_SYSTEM_SHUTDOWN:
+ case CM_PROB_PHANTOM:
+ /* FIXME - do nothing */
+ break;
+
+ case CM_PROB_NOT_VERIFIED:
+ case CM_PROB_DEVICE_NOT_THERE:
+ /* FIXME - display search hardware wizard */
+ break;
+
+ case CM_PROB_NEED_RESTART:
+ case CM_PROB_WILL_BE_REMOVED:
+ case CM_PROB_MOVED:
+ case CM_PROB_TOO_EARLY:
+ case CM_PROB_DISABLED_SERVICE:
+ /* FIXME - reboot computer */
+ break;
+
+ case CM_PROB_REGISTRY:
+ /* FIXME - check registry */
+ break;
+
+ case CM_PROB_DISABLED:
+ {
+ /* FIXME - if device was disabled by user display the "Enable Device" wizard,
+ otherwise Troubleshoot because the device was disabled by the system */
+ break;
+ }
+
+ case CM_PROB_DEVLOADER_NOT_READY:
+ {
+ /* FIXME - if it's a graphics adapter:
+ - if it's a a secondary adapter and the main adapter
+ couldn't be found
+ - do nothing or default action
+ - else
+ - display the Properties
+ - else
+ - Update driver
+ */
+ break;
+ }
+
+ case CM_PROB_FAILED_ADD:
+ {
+ /* FIXME - display the properties of the sub-device */
+ break;
+ }
+
+ case CM_PROB_NO_SOFTCONFIG:
+ case CM_PROB_IRQ_TRANSLATION_FAILED:
+ case CM_PROB_FAILED_DRIVER_ENTRY:
+ case CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD:
+ case CM_PROB_DRIVER_FAILED_LOAD:
+ case CM_PROB_DRIVER_SERVICE_KEY_INVALID:
+ case CM_PROB_LEGACY_SERVICE_NO_DEVICES:
+ case CM_PROB_DUPLICATE_DEVICE:
+ case CM_PROB_FAILED_POST_START:
+ case CM_PROB_HALTED:
+ case CM_PROB_HELD_FOR_EJECT:
+ case CM_PROB_DRIVER_BLOCKED:
+ case CM_PROB_REGISTRY_TOO_LARGE:
+ default:
+ {
+ /* FIXME - troubleshoot the device */
+ break;
+ }
+ }
+ }
+
+ return Ret;
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DeviceProblemWizardA
+ *
+ * DESCRIPTION
+ * Calls the device problem wizard
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * lpMachineName: Machine Name, NULL is the local machine
+ * lpDeviceID: Specifies the device, also see NOTEs
+ *
+ * RETURN VALUE
+ * TRUE: if no errors occured
+ * FALSE: if errors occured
+ *
+ * @implemented
+ */
+BOOL
+WINAPI
+DeviceProblemWizardA(IN HWND hWndParent OPTIONAL,
+ IN LPCSTR lpMachineName OPTIONAL,
+ IN LPCSTR lpDeviceID)
+{
+ LPWSTR lpMachineNameW = NULL;
+ LPWSTR lpDeviceIDW = NULL;
+ BOOL Ret = FALSE;
+
+ if (lpMachineName != NULL)
+ {
+ if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName,
+ CP_ACP)))
+ {
+ goto Cleanup;
+ }
+ }
+ if (lpDeviceID != NULL)
+ {
+ if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID,
+ CP_ACP)))
+ {
+ goto Cleanup;
+ }
+ }
+
+ Ret = DeviceProblemWizardW(hWndParent,
+ lpMachineNameW,
+ lpDeviceIDW);
+
+Cleanup:
+ if (lpMachineNameW != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpMachineNameW);
+ }
+ if (lpDeviceIDW != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpDeviceIDW);
+ }
+
+ return Ret;
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DeviceProblemWizardW
+ *
+ * DESCRIPTION
+ * Calls the device problem wizard
+ *
+ * ARGUMENTS
+ * hWndParent: Handle to the parent window
+ * lpMachineName: Machine Name, NULL is the local machine
+ * lpDeviceID: Specifies the device, also see NOTEs
+ *
+ * RETURN VALUE
+ * TRUE: if no errors occured
+ * FALSE: if errors occured
+ *
+ * @unimplemented
+ */
+BOOL
+WINAPI
+DeviceProblemWizardW(IN HWND hWndParent OPTIONAL,
+ IN LPCWSTR lpMachineName OPTIONAL,
+ IN LPCWSTR lpDeviceID)
+{
+ HDEVINFO hDevInfo;
+ SP_DEVINFO_DATA DevInfoData;
+ HINSTANCE hComCtl32;
+ CONFIGRET cr;
+ HMACHINE hMachine;
+ BOOL Ret = FALSE;
+
+ if (lpDeviceID == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* dynamically load comctl32 */
+ hComCtl32 = LoadAndInitComctl32();
+ if (hComCtl32 != NULL)
+ {
+ hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
+ hWndParent,
+ lpMachineName,
+ NULL);
+ if (hDevInfo != INVALID_HANDLE_VALUE)
+ {
+ cr = CM_Connect_Machine(lpMachineName,
+ &hMachine);
+ if (cr == CR_SUCCESS)
+ {
+ DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ if (SetupDiOpenDeviceInfo(hDevInfo,
+ lpDeviceID,
+ hWndParent,
+ 0,
+ &DevInfoData))
+ {
+ Ret = ShowDeviceProblemWizard(hWndParent,
+ hDevInfo,
+ &DevInfoData,
+ hMachine);
+ }
+
+ CM_Disconnect_Machine(hMachine);
+ }
+
+ SetupDiDestroyDeviceInfoList(hDevInfo);
+ }
+
+ FreeLibrary(hComCtl32);
+ }
+
+ return Ret;
+}
+
+
+static const UINT ProblemStringId[NUM_CM_PROB] =
+{
+ IDS_DEV_NO_PROBLEM,
+ IDS_DEV_DEVLOADER_FAILED,
+ IDS_DEV_NOT_CONFIGURED,
+ IDS_DEV_OUT_OF_MEMORY,
+ IDS_DEV_ENTRY_IS_WRONG_TYPE,
+ IDS_DEV_LACKED_ARBITRATOR,
+ IDS_DEV_BOOT_CONFIG_CONFLICT,
+ IDS_DEV_FAILED_FILTER,
+ IDS_DEV_DEVLOADER_NOT_FOUND,
+ IDS_DEV_INVALID_DATA,
+ IDS_DEV_FAILED_START,
+ IDS_DEV_LIAR,
+ IDS_DEV_NORMAL_CONFLICT,
+ IDS_DEV_NOT_VERIFIED,
+ IDS_DEV_NEED_RESTART,
+ IDS_DEV_REENUMERATION,
+ IDS_DEV_PARTIAL_LOG_CONF,
+ IDS_DEV_UNKNOWN_RESOURCE,
+ IDS_DEV_REINSTALL,
+ IDS_DEV_REGISTRY,
+ IDS_UNKNOWN, /* CM_PROB_VXDLDR, not used on NT */
+ IDS_DEV_WILL_BE_REMOVED,
+ IDS_DEV_DISABLED,
+ IDS_DEV_DEVLOADER_NOT_READY,
+ IDS_DEV_DEVICE_NOT_THERE,
+ IDS_DEV_MOVED,
+ IDS_DEV_TOO_EARLY,
+ IDS_DEV_NO_VALID_LOG_CONF,
+ IDS_DEV_FAILED_INSTALL,
+ IDS_DEV_HARDWARE_DISABLED,
+ IDS_DEV_CANT_SHARE_IRQ,
+ IDS_DEV_FAILED_ADD,
+ IDS_DEV_DISABLED_SERVICE,
+ IDS_DEV_TRANSLATION_FAILED,
+ IDS_DEV_NO_SOFTCONFIG,
+ IDS_DEV_BIOS_TABLE,
+ IDS_DEV_IRQ_TRANSLATION_FAILED,
+ IDS_DEV_FAILED_DRIVER_ENTRY,
+ IDS_DEV_DRIVER_FAILED_PRIOR_UNLOAD,
+ IDS_DEV_DRIVER_FAILED_LOAD,
+ IDS_DEV_DRIVER_SERVICE_KEY_INVALID,
+ IDS_DEV_LEGACY_SERVICE_NO_DEVICES,
+ IDS_DEV_DUPLICATE_DEVICE,
+ IDS_DEV_FAILED_POST_START,
+ IDS_DEV_HALTED,
+ IDS_DEV_PHANTOM,
+ IDS_DEV_SYSTEM_SHUTDOWN,
+ IDS_DEV_HELD_FOR_EJECT,
+ IDS_DEV_DRIVER_BLOCKED,
+ IDS_DEV_REGISTRY_TOO_LARGE,
+ IDS_DEV_SETPROPERTIES_FAILED
+};
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DeviceProblemTextA
+ *
+ * DESCRIPTION
+ * Gets the problem text from a problem number displayed in the properties dialog
+ *
+ * ARGUMENTS
+ * hMachine: Machine handle or NULL for the local machine
+ * DevInst: Device instance handle
+ * uProblemId: Specifies the problem ID
+ * lpString: Pointer to a buffer where the string is to be copied to. If the buffer
+ * is too small, the return value is the required string length in characters,
+ * excluding the NULL-termination.
+ * uMaxString: Size of the buffer in characters
+ *
+ * RETURN VALUE
+ * The return value is the length of the string in characters.
+ * It returns 0 if an error occured.
+ *
+ * @implemented
+ */
+UINT
+WINAPI
+DeviceProblemTextA(IN HMACHINE hMachine OPTIONAL,
+ IN DEVINST dnDevInst,
+ IN ULONG uProblemId,
+ OUT LPSTR lpString,
+ IN UINT uMaxString)
+{
+ LPWSTR lpBuffer = NULL;
+ UINT Ret = 0;
+
+ if (uMaxString != 0)
+ {
+ lpBuffer = HeapAlloc(GetProcessHeap(),
+ 0,
+ (uMaxString + 1) * sizeof(WCHAR));
+ if (lpBuffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+ }
+
+ Ret = DeviceProblemTextW(hMachine,
+ dnDevInst,
+ uProblemId,
+ lpBuffer,
+ uMaxString);
+
+ if (lpBuffer != NULL)
+ {
+ if (Ret)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpBuffer,
+ (int)Ret,
+ lpString,
+ (int)uMaxString,
+ NULL,
+ NULL);
+ }
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpBuffer);
+ }
+
+ return Ret;
+}
+
+
+/***************************************************************************
+ * NAME EXPORTED
+ * DeviceProblemTextW
+ *
+ * DESCRIPTION
+ * Gets the problem text from a problem number displayed in the properties dialog
+ *
+ * ARGUMENTS
+ * hMachine: Machine handle or NULL for the local machine
+ * DevInst: Device instance handle
+ * uProblemId: Specifies the problem ID
+ * lpString: Pointer to a buffer where the string is to be copied to. If the buffer
+ * is too small, the return value is the required string length in characters,
+ * excluding the NULL-termination.
+ * uMaxString: Size of the buffer in characters
+ *
+ * RETURN VALUE
+ * The return value is the length of the string in characters.
+ * It returns 0 if an error occured.
+ *
+ * @implemented
+ */
+UINT
+WINAPI
+DeviceProblemTextW(IN HMACHINE hMachine OPTIONAL,
+ IN DEVINST dnDevInst,
+ IN ULONG uProblemId,
+ OUT LPWSTR lpString,
+ IN UINT uMaxString)
+{
+ UINT MessageId = IDS_UNKNOWN;
+ UINT Ret = 0;
+
+ if (uProblemId < sizeof(ProblemStringId) / sizeof(ProblemStringId[0]))
+ MessageId = ProblemStringId[uProblemId];
+
+ if (uProblemId == 0)
+ {
+ if (uMaxString != 0)
+ {
+ Ret = LoadString(hDllInstance,
+ MessageId,
+ lpString,
+ (int)uMaxString);
+ }
+ else
+ {
+ Ret = (UINT)LengthOfStrResource(hDllInstance,
+ MessageId);
+ }
+ }
+ else
+ {
+ LPWSTR szProblem, szInfo = L"FIXME";
+ DWORD dwRet;
+ BOOL AdvFormat = FALSE;
+ UINT StringIDs[] =
+ {
+ MessageId,
+ IDS_DEVCODE,
+ };
+
+ switch (uProblemId)
+ {
+ case CM_PROB_DEVLOADER_FAILED:
+ {
+ /* FIXME - if not a root bus devloader then use IDS_DEV_DEVLOADER_FAILED2 */
+ /* FIXME - get the type string (ie. ISAPNP, PCI or BIOS for root bus devloaders,
+ or FLOP, ESDI, SCSI, etc for others */
+ AdvFormat = TRUE;
+ break;
+ }
+
+ case CM_PROB_DEVLOADER_NOT_FOUND:
+ {
+ /* FIXME - 4 cases:
+ 1) if it's a missing system devloader:
+ - get the system devloader name
+ 2) if it's not a system devloader but still missing:
+ - get the devloader name (file name?)
+ 3) if it's not a system devloader but the file can be found:
+ - use IDS_DEV_DEVLOADER_NOT_FOUND2
+ 4) if it's a missing or empty software key
+ - use IDS_DEV_DEVLOADER_NOT_FOUND3
+ - AdvFormat = FALSE!
+ */
+ AdvFormat = TRUE;
+ break;
+ }
+
+ case CM_PROB_INVALID_DATA:
+ /* FIXME - if the device isn't enumerated by the BIOS/ACPI use IDS_DEV_INVALID_DATA2 */
+ AdvFormat = FALSE;
+ break;
+
+ case CM_PROB_NORMAL_CONFLICT:
+ /* FIXME - get resource type (IRQ, DMA, Memory or I/O) */
+ AdvFormat = TRUE;
+ break;
+
+ case CM_PROB_UNKNOWN_RESOURCE:
+ /* FIXME - get the .inf file name */
+ AdvFormat = TRUE;
+ break;
+
+ case CM_PROB_DISABLED:
+ /* FIXME - if the device was disabled by the system use IDS_DEV_DISABLED2 */
+ break;
+
+ case CM_PROB_FAILED_ADD:
+ /* FIXME - get the name of the sub-device with the error */
+ AdvFormat = TRUE;
+ break;
+ }
+
+ if (AdvFormat)
+ {
+ StringIDs[1] = IDS_DEVCODE2;
+ dwRet = LoadAndFormatStringsCat(hDllInstance,
+ StringIDs,
+ sizeof(StringIDs) / sizeof(StringIDs[0]),
+ &szProblem,
+ szInfo,
+ uProblemId);
+ }
+ else
+ {
+ dwRet = LoadAndFormatStringsCat(hDllInstance,
+ StringIDs,
+ sizeof(StringIDs) / sizeof(StringIDs[0]),
+ &szProblem,
+ uProblemId);
+ }
+
+ if (dwRet != 0)
+ {
+ if (uMaxString != 0 && uMaxString >= dwRet)
+ {
+ wcscpy(lpString,
+ szProblem);
+ }
+
+ LocalFree((HLOCAL)szProblem);
+
+ Ret = dwRet;
+ }
+ }
+
+ return Ret;
+}
--- /dev/null
+/*
+ * ReactOS Device Manager Applet
+ * Copyright (C) 2004 - 2005 ReactOS Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+/*
+ * PROJECT: ReactOS devmgr.dll
+ * FILE: lib/devmgr/hwpage.c
+ * PURPOSE: ReactOS Device Manager
+ * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
+ * UPDATE HISTORY:
+ * 04-04-2004 Created
+ */
+
+#include "precomp.h"
+
+
+typedef struct _HWDEVINFO
+{
+ struct _HWCLASSDEVINFO *ClassDevInfo;
+ SP_DEVINFO_DATA DevInfoData;
+ BOOL HideDevice;
+} HWDEVINFO, *PHWDEVINFO;
+
+typedef struct _HWCLASSDEVINFO
+{
+ GUID Guid;
+ HDEVINFO hDevInfo;
+ INT ImageIndex;
+ INT ItemCount;
+ PHWDEVINFO HwDevInfo;
+} HWCLASSDEVINFO, *PHWCLASSDEVINFO;
+
+typedef struct _HARDWARE_PAGE_DATA
+{
+ HWND hWnd;
+ HWND hWndDevList;
+ HINSTANCE hComCtl32; /* only save this to keep track of the references */
+ INT DevListViewHeight;
+ SP_CLASSIMAGELIST_DATA ClassImageListData;
+ HWPAGE_DISPLAYMODE DisplayMode;
+
+ /* parent window subclass info */
+ WNDPROC ParentOldWndProc;
+ HWND hWndParent;
+
+ UINT NumberOfGuids;
+ HWCLASSDEVINFO ClassDevInfo[1];
+ /* struct may be dynamically expanded here! */
+} HARDWARE_PAGE_DATA, *PHARDWARE_PAGE_DATA;
+
+#define CX_TYPECOLUMN_WIDTH 80
+
+static VOID
+InitializeDevicesList(IN PHARDWARE_PAGE_DATA hpd)
+{
+ LVCOLUMN lvc;
+ RECT rcClient;
+ WCHAR szColName[255];
+ int iCol = 0;
+
+ /* set the list view style */
+ (void)ListView_SetExtendedListViewStyle(hpd->hWndDevList,
+ LVS_EX_FULLROWSELECT);
+
+ /* set the list view image list */
+ if (hpd->ClassImageListData.ImageList != NULL)
+ {
+ (void)ListView_SetImageList(hpd->hWndDevList,
+ hpd->ClassImageListData.ImageList,
+ LVSIL_SMALL);
+ }
+
+ GetClientRect(hpd->hWndDevList,
+ &rcClient);
+
+ /* add the list view columns */
+ lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.pszText = szColName;
+
+ if (LoadString(hDllInstance,
+ IDS_NAME,
+ szColName,
+ sizeof(szColName) / sizeof(szColName[0])))
+ {
+ lvc.cx = rcClient.right - CX_TYPECOLUMN_WIDTH -
+ GetSystemMetrics(SM_CXVSCROLL);
+ (void)ListView_InsertColumn(hpd->hWndDevList,
+ iCol++,
+ &lvc);
+ }
+ if (LoadString(hDllInstance,
+ IDS_TYPE,
+ szColName,
+ sizeof(szColName) / sizeof(szColName[0])))
+ {
+ lvc.cx = CX_TYPECOLUMN_WIDTH;
+ (void)ListView_InsertColumn(hpd->hWndDevList,
+ iCol++,
+ &lvc);
+ }
+}
+
+
+static BOOL
+DisplaySelectedDeviceProperties(IN PHARDWARE_PAGE_DATA hpd)
+{
+ PHWDEVINFO HwDevInfo;
+ SP_DEVINFO_DATA DevInfoData;
+ BOOL Ret = FALSE;
+
+ HwDevInfo = (PHWDEVINFO)ListViewGetSelectedItemData(hpd->hWndDevList);
+ if (HwDevInfo != NULL)
+ {
+ /* make a copy of the SP_DEVINFO_DATA structure on the stack, it may
+ become invalid in case the devices are updated */
+ DevInfoData = HwDevInfo->DevInfoData;
+
+ /* display the advanced properties */
+ Ret = DisplayDeviceAdvancedProperties(hpd->hWnd,
+ NULL,
+ HwDevInfo->ClassDevInfo->hDevInfo,
+ &DevInfoData,
+ hpd->hComCtl32,
+ NULL,
+ 0) != -1;
+ }
+
+ return Ret;
+}
+
+
+static VOID
+UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd)
+{
+ PHWDEVINFO HwDevInfo;
+ HWND hBtnTroubleShoot, hBtnProperties;
+
+ hBtnTroubleShoot = GetDlgItem(hpd->hWnd,
+ IDC_TROUBLESHOOT);
+ hBtnProperties = GetDlgItem(hpd->hWnd,
+ IDC_PROPERTIES);
+
+ HwDevInfo = (PHWDEVINFO)ListViewGetSelectedItemData(hpd->hWndDevList);
+ if (HwDevInfo != NULL)
+ {
+ /* update static controls */
+ WCHAR szBuffer[256];
+ LPWSTR szFormatted = NULL;
+
+ /* get the manufacturer string */
+ if (GetDeviceManufacturerString(HwDevInfo->ClassDevInfo->hDevInfo,
+ &HwDevInfo->DevInfoData,
+ szBuffer,
+ sizeof(szBuffer) / sizeof(szBuffer[0])) &&
+ LoadAndFormatString(hDllInstance,
+ IDS_MANUFACTURER,
+ &szFormatted,
+ szBuffer) != 0)
+ {
+ SetDlgItemText(hpd->hWnd,
+ IDC_MANUFACTURER,
+ szFormatted);
+ LocalFree((HLOCAL)szFormatted);
+ }
+
+ /* get the location string */
+ if (GetDeviceLocationString(HwDevInfo->ClassDevInfo->hDevInfo,
+ &HwDevInfo->DevInfoData,
+ 0,
+ szBuffer,
+ sizeof(szBuffer) / sizeof(szBuffer[0])) &&
+ LoadAndFormatString(hDllInstance,
+ IDS_LOCATION,
+ &szFormatted,
+ szBuffer) != 0)
+ {
+ SetDlgItemText(hpd->hWnd,
+ IDC_LOCATION,
+ szFormatted);
+ LocalFree((HLOCAL)szFormatted);
+ }
+
+ if (GetDeviceStatusString(HwDevInfo->DevInfoData.DevInst,
+ NULL,
+ szBuffer,
+ sizeof(szBuffer) / sizeof(szBuffer[0])) &&
+ LoadAndFormatString(hDllInstance,
+ IDS_STATUS,
+ &szFormatted,
+ szBuffer) != 0)
+ {
+ SetDlgItemText(hpd->hWnd,
+ IDC_STATUS,
+ szFormatted);
+ LocalFree((HLOCAL)szFormatted);
+ }
+ }
+ else
+ {
+ /* clear static controls */
+ SetDlgItemText(hpd->hWnd,
+ IDC_MANUFACTURER,
+ NULL);
+ SetDlgItemText(hpd->hWnd,
+ IDC_LOCATION,
+ NULL);
+ SetDlgItemText(hpd->hWnd,
+ IDC_STATUS,
+ NULL);
+ }
+
+ EnableWindow(hBtnTroubleShoot,
+ HwDevInfo != NULL);
+ EnableWindow(hBtnProperties,
+ HwDevInfo != NULL);
+}
+
+
+static VOID
+FreeDevicesList(IN PHARDWARE_PAGE_DATA hpd)
+{
+ PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
+
+ ClassDevInfo = hpd->ClassDevInfo;
+ LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
+
+ /* free the device info set handles and structures */
+ while (ClassDevInfo != LastClassDevInfo)
+ {
+ if (ClassDevInfo->hDevInfo != INVALID_HANDLE_VALUE)
+ {
+ SetupDiDestroyDeviceInfoList(ClassDevInfo->hDevInfo);
+ ClassDevInfo->hDevInfo = INVALID_HANDLE_VALUE;
+ }
+
+ ClassDevInfo->ItemCount = 0;
+ ClassDevInfo->ImageIndex = 0;
+
+ if (ClassDevInfo->HwDevInfo != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ ClassDevInfo->HwDevInfo);
+ ClassDevInfo->HwDevInfo = NULL;
+ }
+
+ ClassDevInfo++;
+ }
+}
+
+
+static VOID
+BuildDevicesList(IN PHARDWARE_PAGE_DATA hpd)
+{
+ PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
+ SP_DEVINFO_DATA DevInfoData;
+
+ DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+
+ ClassDevInfo = hpd->ClassDevInfo;
+ LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
+
+ while (ClassDevInfo != LastClassDevInfo)
+ {
+ ClassDevInfo->ImageIndex = -1;
+
+ /* open a class device handle for the GUID we're processing */
+ ClassDevInfo->hDevInfo = SetupDiGetClassDevs(&ClassDevInfo->Guid,
+ NULL,
+ hpd->hWnd,
+ DIGCF_PRESENT | DIGCF_PROFILE);
+ if (ClassDevInfo->hDevInfo != INVALID_HANDLE_VALUE)
+ {
+ DWORD MemberIndex = 0;
+
+ SetupDiGetClassImageIndex(&hpd->ClassImageListData,
+ &ClassDevInfo->Guid,
+ &ClassDevInfo->ImageIndex);
+
+ /* enumerate all devices in the class */
+ while (SetupDiEnumDeviceInfo(ClassDevInfo->hDevInfo,
+ MemberIndex++,
+ &DevInfoData))
+ {
+ BOOL HideDevice = FALSE;
+
+ if (ClassDevInfo->HwDevInfo != NULL)
+ {
+ PHWDEVINFO HwNewDevInfo = HeapReAlloc(GetProcessHeap(),
+ 0,
+ ClassDevInfo->HwDevInfo,
+ (ClassDevInfo->ItemCount + 1) *
+ sizeof(HWDEVINFO));
+ if (HwNewDevInfo != NULL)
+ {
+ ClassDevInfo->HwDevInfo = HwNewDevInfo;
+ }
+ else
+ {
+ ERR("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
+ ClassDevInfo->ItemCount + 1);
+ break;
+ }
+ }
+ else
+ {
+ ClassDevInfo->HwDevInfo = HeapAlloc(GetProcessHeap(),
+ 0,
+ sizeof(HWDEVINFO));
+ if (ClassDevInfo->HwDevInfo == NULL)
+ {
+ ERR("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
+ break;
+ }
+ }
+
+ /* Find out if the device should be hidden by default */
+ IsDeviceHidden(DevInfoData.DevInst,
+ NULL,
+ &HideDevice);
+
+ /* save all information for the current device */
+ ClassDevInfo->HwDevInfo[ClassDevInfo->ItemCount].ClassDevInfo = ClassDevInfo;
+ ClassDevInfo->HwDevInfo[ClassDevInfo->ItemCount].DevInfoData = DevInfoData;
+ ClassDevInfo->HwDevInfo[ClassDevInfo->ItemCount++].HideDevice = HideDevice;
+ }
+ }
+
+ ClassDevInfo++;
+ }
+}
+
+
+static BOOL
+DeviceIdMatch(IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN LPCWSTR lpDeviceId)
+{
+ DWORD DevIdLen;
+ LPWSTR lpQueriedDeviceId;
+ BOOL Ret = FALSE;
+
+ if (!SetupDiGetDeviceInstanceId(DeviceInfoSet,
+ DeviceInfoData,
+ NULL,
+ 0,
+ &DevIdLen) &&
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if (DevIdLen == wcslen(lpDeviceId) + 1)
+ {
+ lpQueriedDeviceId = HeapAlloc(GetProcessHeap(),
+ 0,
+ DevIdLen * sizeof(WCHAR));
+ if (lpQueriedDeviceId != NULL)
+ {
+ if (SetupDiGetDeviceInstanceId(DeviceInfoSet,
+ DeviceInfoData,
+ lpQueriedDeviceId,
+ DevIdLen,
+ NULL))
+ {
+ Ret = (wcscmp(lpDeviceId,
+ lpQueriedDeviceId) == 0);
+ }
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpQueriedDeviceId);
+ }
+ }
+ }
+
+ return Ret;
+}
+
+
+static VOID
+FillDevicesListViewControl(IN PHARDWARE_PAGE_DATA hpd,
+ IN LPCWSTR lpSelectDeviceId OPTIONAL,
+ IN GUID *SelectedClassGuid OPTIONAL)
+{
+ PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
+ PHWDEVINFO HwDevInfo, LastHwDevInfo;
+ WCHAR szBuffer[255];
+ BOOL SelectedInClass;
+ INT ItemCount = 0;
+
+ BuildDevicesList(hpd);
+
+ ClassDevInfo = hpd->ClassDevInfo;
+ LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
+
+ while (ClassDevInfo != LastClassDevInfo)
+ {
+ if (ClassDevInfo->HwDevInfo != NULL)
+ {
+ HwDevInfo = ClassDevInfo->HwDevInfo;
+ LastHwDevInfo = HwDevInfo + ClassDevInfo->ItemCount;
+
+ SelectedInClass = (SelectedClassGuid != NULL &&
+ IsEqualGUID(SelectedClassGuid,
+ &ClassDevInfo->Guid));
+ while (HwDevInfo != LastHwDevInfo)
+ {
+ INT iItem;
+ LVITEM li = {0};
+
+ /* get the device name */
+ if (!HwDevInfo->HideDevice &&
+ GetDeviceDescriptionString(ClassDevInfo->hDevInfo,
+ &HwDevInfo->DevInfoData,
+ szBuffer,
+ sizeof(szBuffer) / sizeof(szBuffer[0])))
+ {
+ li.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT | LVIF_IMAGE;
+ li.iItem = ItemCount;
+ if ((ItemCount == 0 && lpSelectDeviceId == NULL) ||
+ (SelectedInClass &&
+ DeviceIdMatch(ClassDevInfo->hDevInfo,
+ &HwDevInfo->DevInfoData,
+ lpSelectDeviceId)))
+ {
+ li.state = LVIS_SELECTED;
+ }
+ li.stateMask = LVIS_SELECTED;
+ li.pszText = szBuffer;
+ li.iImage = ClassDevInfo->ImageIndex;
+ li.lParam = (LPARAM)HwDevInfo;
+
+ iItem = ListView_InsertItem(hpd->hWndDevList,
+ &li);
+ if (iItem != -1)
+ {
+ ItemCount++;
+
+ /* get the device type for the second column */
+ if (GetDeviceTypeString(&HwDevInfo->DevInfoData,
+ szBuffer,
+ sizeof(szBuffer) / sizeof(szBuffer[0])))
+ {
+ li.mask = LVIF_TEXT;
+ li.iItem = iItem;
+ li.iSubItem = 1;
+
+ (void)ListView_SetItem(hpd->hWndDevList,
+ &li);
+ }
+ }
+ }
+
+ HwDevInfo++;
+ }
+ }
+
+ ClassDevInfo++;
+ }
+
+ /* update the controls */
+ UpdateControlStates(hpd);
+}
+
+
+static VOID
+UpdateDevicesListViewControl(IN PHARDWARE_PAGE_DATA hpd)
+{
+ PHWDEVINFO HwDevInfo;
+ GUID SelectedClassGuid = {0};
+ LPWSTR lpDeviceId = NULL;
+
+ /* if a device currently is selected, remember the device id so we can
+ select the device after the update if still present */
+ HwDevInfo = (PHWDEVINFO)ListViewGetSelectedItemData(hpd->hWndDevList);
+ if (HwDevInfo != NULL)
+ {
+ DWORD DevIdLen;
+ if (!SetupDiGetDeviceInstanceId(HwDevInfo->ClassDevInfo->hDevInfo,
+ &HwDevInfo->DevInfoData,
+ NULL,
+ 0,
+ &DevIdLen) &&
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ SelectedClassGuid = HwDevInfo->DevInfoData.ClassGuid;
+ lpDeviceId = HeapAlloc(GetProcessHeap(),
+ 0,
+ DevIdLen * sizeof(WCHAR));
+ if (lpDeviceId != NULL &&
+ !SetupDiGetDeviceInstanceId(HwDevInfo->ClassDevInfo->hDevInfo,
+ &HwDevInfo->DevInfoData,
+ lpDeviceId,
+ DevIdLen,
+ NULL))
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpDeviceId);
+ lpDeviceId = NULL;
+ }
+ }
+ }
+
+ /* clear the devices list view control */
+ (void)ListView_DeleteAllItems(hpd->hWndDevList);
+
+ /* free the device list */
+ FreeDevicesList(hpd);
+
+ /* build rebuild the device list and fill the list box again */
+ FillDevicesListViewControl(hpd,
+ lpDeviceId,
+ (lpDeviceId != NULL ?
+ &SelectedClassGuid :
+ NULL));
+
+ if (lpDeviceId != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpDeviceId);
+ }
+}
+
+
+static LRESULT
+CALLBACK
+ParentSubWndProc(IN HWND hwnd,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam)
+{
+ PHARDWARE_PAGE_DATA hpd;
+
+ hpd = (PHARDWARE_PAGE_DATA)GetProp(hwnd,
+ L"DevMgrSubClassInfo");
+ if (hpd != NULL)
+ {
+ if (uMsg == WM_SIZE)
+ {
+ /* resize the hardware page */
+ SetWindowPos(hpd->hWnd,
+ NULL,
+ 0,
+ 0,
+ LOWORD(lParam),
+ HIWORD(lParam),
+ SWP_NOZORDER);
+ }
+ else if (uMsg == WM_DEVICECHANGE && IsWindowVisible(hpd->hWnd))
+ {
+ /* forward a WM_DEVICECHANGE message to the hardware
+ page which wouldn't get the message itself as it is
+ a child window */
+ SendMessage(hpd->hWnd,
+ WM_DEVICECHANGE,
+ wParam,
+ lParam);
+ }
+
+ /* pass the message the the old window proc */
+ return CallWindowProc(hpd->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 VOID
+HardwareDlgResize(IN PHARDWARE_PAGE_DATA hpd,
+ IN INT cx,
+ IN INT cy)
+{
+ HDWP dwp;
+ HWND hControl, hButton;
+ INT Width, x, y;
+ RECT rc, rcButton;
+ POINT pt = {0};
+ POINT ptMargin = {0};
+ POINT ptMarginGroup = {0};
+
+ /* use left margin of the IDC_DEVICES label as the right
+ margin of all controls outside the group box */
+ hControl = GetDlgItem(hpd->hWnd,
+ IDC_DEVICES);
+ GetWindowRect(hControl,
+ &rc);
+ MapWindowPoints(hControl,
+ hpd->hWnd,
+ &ptMargin,
+ 1);
+
+ Width = cx - (2 * ptMargin.x);
+
+ if ((dwp = BeginDeferWindowPos(8)))
+ {
+ /* rc already has the window rect of IDC_DEVICES! */
+ if (!(dwp = DeferWindowPos(dwp,
+ hControl,
+ NULL,
+ 0,
+ 0,
+ Width,
+ rc.bottom - rc.top,
+ SWP_NOMOVE | SWP_NOZORDER)))
+ {
+ return;
+ }
+
+ /* resize the devices list view control */
+ GetWindowRect(hpd->hWndDevList,
+ &rc);
+ MapWindowPoints(hpd->hWndDevList,
+ hpd->hWnd,
+ &pt,
+ 1);
+ y = pt.y + hpd->DevListViewHeight + ptMargin.y;
+ if (!(dwp = DeferWindowPos(dwp,
+ hpd->hWndDevList,
+ NULL,
+ 0,
+ 0,
+ Width,
+ hpd->DevListViewHeight,
+ SWP_NOMOVE | SWP_NOZORDER)))
+ {
+ return;
+ }
+
+ /* resize the group box control */
+ hControl = GetDlgItem(hpd->hWnd,
+ IDC_PROPERTIESGROUP);
+ GetWindowRect(hControl,
+ &rc);
+ if (!(dwp = DeferWindowPos(dwp,
+ hControl,
+ NULL,
+ ptMargin.x,
+ y,
+ Width,
+ cy - y - ptMargin.y,
+ SWP_NOZORDER)))
+ {
+ return;
+ }
+
+ /* use left margin of the IDC_MANUFACTURER label as the right
+ margin of all controls inside the group box */
+ hControl = GetDlgItem(hpd->hWnd,
+ IDC_MANUFACTURER);
+ GetWindowRect(hControl,
+ &rc);
+ MapWindowPoints(hControl,
+ hpd->hWnd,
+ &ptMarginGroup,
+ 1);
+
+ ptMarginGroup.y = ptMargin.y * 2;
+ Width = cx - (2 * ptMarginGroup.x);
+ y += ptMarginGroup.y;
+ if (!(dwp = DeferWindowPos(dwp,
+ hControl,
+ NULL,
+ ptMarginGroup.x,
+ y,
+ Width,
+ rc.bottom - rc.top,
+ SWP_NOZORDER)))
+ {
+ return;
+ }
+ y += rc.bottom - rc.top + (ptMargin.y / 2);
+
+ /* resize the IDC_LOCATION label */
+ hControl = GetDlgItem(hpd->hWnd,
+ IDC_LOCATION);
+ GetWindowRect(hControl,
+ &rc);
+ if (!(dwp = DeferWindowPos(dwp,
+ hControl,
+ NULL,
+ ptMarginGroup.x,
+ y,
+ Width,
+ rc.bottom - rc.top,
+ SWP_NOZORDER)))
+ {
+ return;
+ }
+ y += rc.bottom - rc.top + (ptMargin.y / 2);
+
+ /* measure the size of the buttons */
+ hButton = GetDlgItem(hpd->hWnd,
+ IDC_PROPERTIES);
+ GetWindowRect(hButton,
+ &rcButton);
+
+ /* resize the IDC_STATUS label */
+ hControl = GetDlgItem(hpd->hWnd,
+ IDC_STATUS);
+ GetWindowRect(hControl,
+ &rc);
+ if (!(dwp = DeferWindowPos(dwp,
+ hControl,
+ NULL,
+ ptMarginGroup.x,
+ y,
+ Width,
+ cy - y - (3 * ptMargin.y) -
+ (rcButton.bottom - rcButton.top),
+ SWP_NOZORDER)))
+ {
+ return;
+ }
+
+ /* move the IDC_PROPERTIES button */
+ y = cy - (2 * ptMargin.y) - (rcButton.bottom - rcButton.top);
+ x = cx - ptMarginGroup.x - (rcButton.right - rcButton.left);
+ if (!(dwp = DeferWindowPos(dwp,
+ hButton,
+ NULL,
+ x,
+ y,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER)))
+ {
+ return;
+ }
+
+ /* move the IDC_TROUBLESHOOT button */
+ hButton = GetDlgItem(hpd->hWnd,
+ IDC_TROUBLESHOOT);
+ GetWindowRect(hButton,
+ &rcButton);
+ x -= (ptMargin.x / 2) + (rcButton.right - rcButton.left);
+ if (!(dwp = DeferWindowPos(dwp,
+ hButton,
+ NULL,
+ x,
+ y,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER)))
+ {
+ return;
+ }
+
+ EndDeferWindowPos(dwp);
+ }
+}
+
+
+static VOID
+EnableTroubleShoot(PHARDWARE_PAGE_DATA hpd,
+ BOOL Enable)
+{
+ HWND hBtnTroubleShoot = GetDlgItem(hpd->hWnd,
+ IDC_TROUBLESHOOT);
+
+ ShowWindow(hBtnTroubleShoot,
+ Enable ? SW_SHOW : SW_HIDE);
+}
+
+
+static INT_PTR
+CALLBACK
+HardwareDlgProc(IN HWND hwndDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam)
+{
+ PHARDWARE_PAGE_DATA hpd;
+ INT_PTR Ret = FALSE;
+
+ hpd = (PHARDWARE_PAGE_DATA)GetWindowLongPtr(hwndDlg,
+ DWL_USER);
+
+ if (hpd != NULL || uMsg == WM_INITDIALOG)
+ {
+ switch (uMsg)
+ {
+ case WM_NOTIFY:
+ {
+ NMHDR *pnmh = (NMHDR*)lParam;
+ if (pnmh->hwndFrom == hpd->hWndDevList)
+ {
+ switch (pnmh->code)
+ {
+ case LVN_ITEMCHANGED:
+ {
+ LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
+
+ if ((pnmv->uChanged & LVIF_STATE) &&
+ ((pnmv->uOldState & (LVIS_FOCUSED | LVIS_SELECTED)) ||
+ (pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))))
+ {
+ UpdateControlStates(hpd);
+ }
+ break;
+ }
+
+ case NM_DBLCLK:
+ {
+ DisplaySelectedDeviceProperties(hpd);
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_TROUBLESHOOT:
+ {
+ /* FIXME - start the help using the command in the window text */
+ break;
+ }
+
+ case IDC_PROPERTIES:
+ {
+ DisplaySelectedDeviceProperties(hpd);
+ break;
+ }
+ }
+ break;
+ }
+
+ case WM_SIZE:
+ HardwareDlgResize(hpd,
+ (INT)LOWORD(lParam),
+ (INT)HIWORD(lParam));
+ break;
+
+ case WM_SETTEXT:
+ {
+ LPCWSTR szWndText = (LPCWSTR)lParam;
+ EnableTroubleShoot(hpd,
+ (szWndText != NULL && szWndText[0] != L'\0'));
+ break;
+ }
+
+ case WM_DEVICECHANGE:
+ {
+ /* FIXME - don't call UpdateDevicesListViewControl for all events */
+ UpdateDevicesListViewControl(hpd);
+ Ret = TRUE;
+ break;
+ }
+
+ case WM_INITDIALOG:
+ {
+ hpd = (PHARDWARE_PAGE_DATA)lParam;
+ if (hpd != NULL)
+ {
+ HWND hWndParent;
+
+ hpd->hWnd = hwndDlg;
+ SetWindowLongPtr(hwndDlg,
+ DWL_USER,
+ (DWORD_PTR)hpd);
+
+ hpd->ClassImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
+
+ SetupDiGetClassImageList(&hpd->ClassImageListData);
+
+ /* calculate the size of the devices list view control */
+ hpd->hWndDevList = GetDlgItem(hwndDlg,
+ IDC_LV_DEVICES);
+ if (hpd->hWndDevList != NULL)
+ {
+ RECT rcClient;
+ GetClientRect(hpd->hWndDevList,
+ &rcClient);
+ hpd->DevListViewHeight = rcClient.bottom;
+
+ if (hpd->DisplayMode == HWPD_LARGELIST)
+ {
+ hpd->DevListViewHeight = (hpd->DevListViewHeight * 3) / 2;
+ }
+ }
+
+ /* subclass the parent window */
+ hWndParent = GetAncestor(hwndDlg,
+ GA_PARENT);
+ if (hWndParent != NULL)
+ {
+ RECT rcClient;
+
+ if (GetClientRect(hWndParent,
+ &rcClient) &&
+