2004-04-04 21:49:15 +00:00
|
|
|
/*
|
2004-09-28 16:05:24 +00:00
|
|
|
* ReactOS Device Manager Applet
|
2005-11-25 14:17:30 +00:00
|
|
|
* Copyright (C) 2004 - 2005 ReactOS Team
|
2004-04-04 21:49:15 +00:00
|
|
|
*
|
2004-09-28 16:05:24 +00:00
|
|
|
* 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.
|
2004-04-04 21:49:15 +00:00
|
|
|
*
|
2004-09-28 16:05:24 +00:00
|
|
|
* 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.
|
2004-04-04 21:49:15 +00:00
|
|
|
*
|
2004-09-28 16:05:24 +00:00
|
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
2004-04-04 21:49:15 +00:00
|
|
|
*/
|
2005-01-06 13:58:04 +00:00
|
|
|
/* $Id$
|
2004-04-04 21:49:15 +00:00
|
|
|
*
|
|
|
|
* PROJECT: ReactOS devmgr.dll
|
2005-11-25 15:36:14 +00:00
|
|
|
* FILE: lib/devmgr/hwpage.c
|
2004-04-04 21:49:15 +00:00
|
|
|
* PURPOSE: ReactOS Device Manager
|
2005-11-25 14:17:30 +00:00
|
|
|
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
|
2004-04-04 21:49:15 +00:00
|
|
|
* UPDATE HISTORY:
|
|
|
|
* 04-04-2004 Created
|
|
|
|
*/
|
2005-11-25 14:17:30 +00:00
|
|
|
#include <precomp.h>
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
typedef VOID (WINAPI *PINITCOMMONCONTROLS)(VOID);
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
HWPD_STANDARDLIST = 0,
|
|
|
|
HWPD_LARGELIST,
|
|
|
|
HWPD_MAX = HWPD_LARGELIST
|
|
|
|
} HWPAGE_DISPLAYMODE, *PHWPAGE_DISPLAYMODE;
|
|
|
|
|
|
|
|
typedef struct _HWDEVINFO
|
|
|
|
{
|
|
|
|
struct _HWCLASSDEVINFO *ClassDevInfo;
|
|
|
|
SP_DEVINFO_DATA DevInfoData;
|
|
|
|
} HWDEVINFO, *PHWDEVINFO;
|
|
|
|
|
|
|
|
typedef struct _HWCLASSDEVINFO
|
|
|
|
{
|
|
|
|
GUID Guid;
|
|
|
|
HDEVINFO hDevInfo;
|
2005-11-25 23:36:32 +00:00
|
|
|
INT ImageIndex;
|
2005-11-25 14:17:30 +00:00
|
|
|
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 */
|
2005-11-25 16:30:41 +00:00
|
|
|
INT DevListViewHeight;
|
2005-11-25 14:17:30 +00:00
|
|
|
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 */
|
|
|
|
ListView_SetExtendedListViewStyle(hpd->hWndDevList,
|
|
|
|
LVS_EX_FULLROWSELECT);
|
|
|
|
|
|
|
|
/* set the list view image list */
|
|
|
|
if (hpd->ClassImageListData.ImageList != NULL)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
ListView_InsertColumn(hpd->hWndDevList,
|
|
|
|
iCol++,
|
|
|
|
&lvc);
|
|
|
|
}
|
|
|
|
if (LoadString(hDllInstance,
|
|
|
|
IDS_TYPE,
|
|
|
|
szColName,
|
|
|
|
sizeof(szColName) / sizeof(szColName[0])))
|
|
|
|
{
|
|
|
|
lvc.cx = CX_TYPECOLUMN_WIDTH;
|
|
|
|
ListView_InsertColumn(hpd->hWndDevList,
|
|
|
|
iCol++,
|
|
|
|
&lvc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-26 02:12:58 +00:00
|
|
|
static BOOL
|
|
|
|
DisplaySelectedDeviceProperties(IN PHARDWARE_PAGE_DATA hpd)
|
|
|
|
{
|
|
|
|
PHWDEVINFO HwDevInfo;
|
|
|
|
BOOL Ret = FALSE;
|
|
|
|
|
|
|
|
HwDevInfo = (PHWDEVINFO)ListViewGetSelectedItemData(hpd->hWndDevList);
|
|
|
|
if (HwDevInfo != NULL)
|
|
|
|
{
|
|
|
|
PWSTR szDeviceInstanceId = NULL;
|
|
|
|
DWORD DeviceInstanceIdLen = 0;
|
|
|
|
|
|
|
|
/* find out how much size is needed for the buffer */
|
|
|
|
if (SetupDiGetDeviceInstanceId(HwDevInfo->ClassDevInfo->hDevInfo,
|
|
|
|
&HwDevInfo->DevInfoData,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&DeviceInstanceIdLen))
|
|
|
|
{
|
|
|
|
DPRINT1("SetupDiGetDeviceInterfaceDetail unexpectedly returned TRUE!\n");
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
{
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
szDeviceInstanceId = HeapAlloc(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
DeviceInstanceIdLen * sizeof(WCHAR));
|
|
|
|
if (szDeviceInstanceId == NULL)
|
|
|
|
{
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read the device instance id */
|
|
|
|
if (!SetupDiGetDeviceInstanceId(HwDevInfo->ClassDevInfo->hDevInfo,
|
|
|
|
&HwDevInfo->DevInfoData,
|
|
|
|
szDeviceInstanceId,
|
|
|
|
DeviceInstanceIdLen,
|
|
|
|
&DeviceInstanceIdLen))
|
|
|
|
{
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* display the properties dialog */
|
|
|
|
Ret = DeviceAdvancedProperties(hpd->hWnd,
|
|
|
|
NULL,
|
|
|
|
szDeviceInstanceId) >= 0;
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (szDeviceInstanceId != NULL)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
szDeviceInstanceId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-25 14:17:30 +00:00
|
|
|
static VOID
|
|
|
|
UpdateControlStates(IN PHARDWARE_PAGE_DATA hpd)
|
|
|
|
{
|
|
|
|
PHWDEVINFO HwDevInfo;
|
2005-11-25 23:36:32 +00:00
|
|
|
HWND hBtnTroubleShoot, hBtnProperties;
|
|
|
|
|
|
|
|
hBtnTroubleShoot = GetDlgItem(hpd->hWnd,
|
|
|
|
IDC_TROUBLESHOOT);
|
|
|
|
hBtnProperties = GetDlgItem(hpd->hWnd,
|
|
|
|
IDC_PROPERTIES);
|
2005-11-25 14:17:30 +00:00
|
|
|
|
|
|
|
HwDevInfo = (PHWDEVINFO)ListViewGetSelectedItemData(hpd->hWndDevList);
|
|
|
|
if (HwDevInfo != NULL)
|
|
|
|
{
|
2005-11-25 23:36:32 +00:00
|
|
|
/* update static controls */
|
2005-11-26 00:25:25 +00:00
|
|
|
CONFIGRET cRet;
|
|
|
|
DWORD RegDataType;
|
|
|
|
ULONG DataSize;
|
2005-11-25 23:36:32 +00:00
|
|
|
WCHAR szBuffer[256];
|
|
|
|
LPWSTR szFormatted = NULL;
|
|
|
|
|
2005-11-26 00:25:25 +00:00
|
|
|
/* get the manufacturer string */
|
2005-11-25 23:36:32 +00:00
|
|
|
if (!SetupDiGetDeviceRegistryProperty(HwDevInfo->ClassDevInfo->hDevInfo,
|
|
|
|
&HwDevInfo->DevInfoData,
|
|
|
|
SPDRP_MFG,
|
|
|
|
&RegDataType,
|
|
|
|
(PBYTE)szBuffer,
|
|
|
|
sizeof(szBuffer),
|
|
|
|
NULL) ||
|
|
|
|
RegDataType != REG_SZ)
|
|
|
|
{
|
|
|
|
szBuffer[0] = L'\0';
|
2005-11-26 02:12:58 +00:00
|
|
|
LoadString(hDllInstance,
|
|
|
|
IDS_UNKNOWN,
|
|
|
|
szBuffer,
|
|
|
|
sizeof(szBuffer) / sizeof(szBuffer[0]));
|
2005-11-25 23:36:32 +00:00
|
|
|
}
|
2005-11-26 00:25:25 +00:00
|
|
|
/* FIXME - check string for NULL termination! */
|
2005-11-25 23:36:32 +00:00
|
|
|
if (LoadAndFormatString(hDllInstance,
|
|
|
|
IDS_MANUFACTURER,
|
|
|
|
&szFormatted,
|
|
|
|
szBuffer) != 0)
|
|
|
|
{
|
|
|
|
SetDlgItemText(hpd->hWnd,
|
|
|
|
IDC_MANUFACTURER,
|
|
|
|
szFormatted);
|
|
|
|
LocalFree((HLOCAL)szFormatted);
|
|
|
|
}
|
|
|
|
|
2005-11-26 00:25:25 +00:00
|
|
|
/* get the location string */
|
|
|
|
DataSize = sizeof(szBuffer);
|
|
|
|
cRet = CM_Get_DevNode_Registry_Property(HwDevInfo->DevInfoData.DevInst,
|
|
|
|
CM_DRP_LOCATION_INFORMATION,
|
|
|
|
&RegDataType,
|
|
|
|
szBuffer,
|
|
|
|
&DataSize,
|
|
|
|
0);
|
|
|
|
if (cRet != CR_SUCCESS ||
|
|
|
|
RegDataType != REG_SZ)
|
|
|
|
{
|
|
|
|
szBuffer[0] = L'\0';
|
2005-11-26 02:12:58 +00:00
|
|
|
LoadString(hDllInstance,
|
|
|
|
IDS_UNKNOWN,
|
|
|
|
szBuffer,
|
|
|
|
sizeof(szBuffer) / sizeof(szBuffer[0]));
|
2005-11-26 00:25:25 +00:00
|
|
|
}
|
|
|
|
/* FIXME - check string for NULL termination! */
|
|
|
|
|
|
|
|
if (szBuffer[0] >= L'0' && szBuffer[0] <= L'9')
|
|
|
|
{
|
|
|
|
/* convert the string to an integer value and create a
|
|
|
|
formatted string */
|
2005-11-26 01:08:19 +00:00
|
|
|
ULONG ulLocation = (ULONG)wcstoul(szBuffer,
|
|
|
|
NULL,
|
|
|
|
10);
|
2005-11-26 00:25:25 +00:00
|
|
|
if (LoadAndFormatString(hDllInstance,
|
|
|
|
IDS_LOCATIONSTR,
|
|
|
|
&szFormatted,
|
|
|
|
ulLocation,
|
|
|
|
szBuffer) != 0)
|
|
|
|
{
|
|
|
|
wcsncpy(szBuffer,
|
|
|
|
szFormatted,
|
|
|
|
(sizeof(szBuffer) / sizeof(szBuffer[0])) - 1);
|
|
|
|
szBuffer[(sizeof(szBuffer) / sizeof(szBuffer[0])) - 1] = L'\0';
|
|
|
|
LocalFree((HLOCAL)szFormatted);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LoadAndFormatString(hDllInstance,
|
|
|
|
IDS_LOCATION,
|
|
|
|
&szFormatted,
|
|
|
|
szBuffer) != 0)
|
|
|
|
{
|
|
|
|
SetDlgItemText(hpd->hWnd,
|
|
|
|
IDC_LOCATION,
|
|
|
|
szFormatted);
|
|
|
|
LocalFree((HLOCAL)szFormatted);
|
|
|
|
}
|
|
|
|
|
2005-11-26 01:08:19 +00:00
|
|
|
/* FIXME - get the device status text */
|
|
|
|
LoadString(hDllInstance,
|
|
|
|
IDS_UNKNOWN,
|
|
|
|
szBuffer,
|
|
|
|
sizeof(szBuffer) / sizeof(szBuffer[0]));
|
|
|
|
|
|
|
|
if (LoadAndFormatString(hDllInstance,
|
|
|
|
IDS_STATUS,
|
|
|
|
&szFormatted,
|
|
|
|
szBuffer) != 0)
|
|
|
|
{
|
|
|
|
SetDlgItemText(hpd->hWnd,
|
|
|
|
IDC_STATUS,
|
|
|
|
szFormatted);
|
|
|
|
LocalFree((HLOCAL)szFormatted);
|
|
|
|
}
|
2005-11-25 14:17:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-11-25 23:36:32 +00:00
|
|
|
/* 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);
|
2005-11-26 00:25:25 +00:00
|
|
|
EnableWindow(hBtnProperties,
|
|
|
|
HwDevInfo != NULL);
|
2005-11-25 23:36:32 +00:00
|
|
|
}
|
|
|
|
|
2005-11-26 01:08:19 +00:00
|
|
|
|
2005-11-25 23:36:32 +00:00
|
|
|
static VOID
|
|
|
|
FreeDevicesList(IN PHARDWARE_PAGE_DATA hpd)
|
|
|
|
{
|
|
|
|
PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
|
|
|
|
|
|
|
|
ClassDevInfo = hpd->ClassDevInfo;
|
|
|
|
LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
|
|
|
|
|
2005-11-26 01:08:19 +00:00
|
|
|
/* free the device info set handles and structures */
|
2005-11-25 23:36:32 +00:00
|
|
|
while (ClassDevInfo != LastClassDevInfo)
|
|
|
|
{
|
|
|
|
if (ClassDevInfo->hDevInfo != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
SetupDiDestroyDeviceInfoList(ClassDevInfo->hDevInfo);
|
2005-11-26 01:08:19 +00:00
|
|
|
ClassDevInfo->hDevInfo = INVALID_HANDLE_VALUE;
|
2005-11-25 23:36:32 +00:00
|
|
|
}
|
2005-11-26 01:08:19 +00:00
|
|
|
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo->ItemCount = 0;
|
|
|
|
ClassDevInfo->ImageIndex = 0;
|
|
|
|
|
|
|
|
if (ClassDevInfo->HwDevInfo != NULL)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
ClassDevInfo->HwDevInfo);
|
|
|
|
ClassDevInfo->HwDevInfo = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassDevInfo++;
|
2005-11-25 14:17:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VOID
|
2005-11-25 23:36:32 +00:00
|
|
|
BuildDevicesList(IN PHARDWARE_PAGE_DATA hpd)
|
2005-11-25 14:17:30 +00:00
|
|
|
{
|
2005-11-25 23:36:32 +00:00
|
|
|
PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
|
2005-11-25 14:17:30 +00:00
|
|
|
SP_DEVINFO_DATA DevInfoData;
|
|
|
|
|
|
|
|
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
|
|
|
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo = hpd->ClassDevInfo;
|
|
|
|
LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
|
2005-11-25 14:17:30 +00:00
|
|
|
|
2005-11-25 23:36:32 +00:00
|
|
|
while (ClassDevInfo != LastClassDevInfo)
|
2005-11-25 14:17:30 +00:00
|
|
|
{
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo->ImageIndex = -1;
|
2005-11-26 01:08:19 +00:00
|
|
|
|
|
|
|
/* open a class device handle for the GUID we're processing */
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo->hDevInfo = SetupDiGetClassDevs(&ClassDevInfo->Guid,
|
|
|
|
NULL,
|
|
|
|
hpd->hWnd,
|
|
|
|
DIGCF_PRESENT);
|
|
|
|
if (ClassDevInfo->hDevInfo != INVALID_HANDLE_VALUE)
|
2005-11-25 14:17:30 +00:00
|
|
|
{
|
|
|
|
DWORD MemberIndex = 0;
|
|
|
|
|
|
|
|
SetupDiGetClassImageIndex(&hpd->ClassImageListData,
|
2005-11-25 23:36:32 +00:00
|
|
|
&ClassDevInfo->Guid,
|
|
|
|
&ClassDevInfo->ImageIndex);
|
2005-11-25 14:17:30 +00:00
|
|
|
|
2005-11-26 01:08:19 +00:00
|
|
|
/* enumerate all devices in the class */
|
2005-11-25 23:36:32 +00:00
|
|
|
while (SetupDiEnumDeviceInfo(ClassDevInfo->hDevInfo,
|
2005-11-25 14:17:30 +00:00
|
|
|
MemberIndex++,
|
|
|
|
&DevInfoData))
|
|
|
|
{
|
2005-11-25 23:36:32 +00:00
|
|
|
if (ClassDevInfo->HwDevInfo != NULL)
|
2005-11-25 14:17:30 +00:00
|
|
|
{
|
|
|
|
PHWDEVINFO HwNewDevInfo = HeapReAlloc(GetProcessHeap(),
|
|
|
|
0,
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo->HwDevInfo,
|
|
|
|
(ClassDevInfo->ItemCount + 1) *
|
2005-11-25 14:17:30 +00:00
|
|
|
sizeof(HWDEVINFO));
|
|
|
|
if (HwNewDevInfo != NULL)
|
|
|
|
{
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo->HwDevInfo = HwNewDevInfo;
|
2005-11-25 14:17:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Unable to allocate memory for %d SP_DEVINFO_DATA structures!\n",
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo->ItemCount + 1);
|
2005-11-25 14:17:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo->HwDevInfo = HeapAlloc(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
sizeof(HWDEVINFO));
|
|
|
|
if (ClassDevInfo->HwDevInfo == NULL)
|
2005-11-25 14:17:30 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Unable to allocate memory for a SP_DEVINFO_DATA structures!\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-26 01:08:19 +00:00
|
|
|
/* save all information for the current device */
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo->HwDevInfo[ClassDevInfo->ItemCount].ClassDevInfo = ClassDevInfo;
|
|
|
|
ClassDevInfo->HwDevInfo[ClassDevInfo->ItemCount++].DevInfoData = DevInfoData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassDevInfo++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VOID
|
2005-11-26 01:08:19 +00:00
|
|
|
FillDevicesListViewControl(IN PHARDWARE_PAGE_DATA hpd)
|
2005-11-25 23:36:32 +00:00
|
|
|
{
|
|
|
|
PHWCLASSDEVINFO ClassDevInfo, LastClassDevInfo;
|
|
|
|
PHWDEVINFO HwDevInfo, LastHwDevInfo;
|
|
|
|
WCHAR szBuffer[255];
|
|
|
|
INT ItemCount = 0;
|
|
|
|
|
|
|
|
BuildDevicesList(hpd);
|
|
|
|
|
|
|
|
ClassDevInfo = hpd->ClassDevInfo;
|
|
|
|
LastClassDevInfo = ClassDevInfo + hpd->NumberOfGuids;
|
2005-11-25 16:30:41 +00:00
|
|
|
|
2005-11-25 23:36:32 +00:00
|
|
|
while (ClassDevInfo != LastClassDevInfo)
|
|
|
|
{
|
|
|
|
if (ClassDevInfo->HwDevInfo != NULL)
|
|
|
|
{
|
|
|
|
HwDevInfo = ClassDevInfo->HwDevInfo;
|
|
|
|
LastHwDevInfo = HwDevInfo + ClassDevInfo->ItemCount;
|
|
|
|
|
|
|
|
while (HwDevInfo != LastHwDevInfo)
|
|
|
|
{
|
|
|
|
DWORD RegDataType;
|
|
|
|
INT iItem;
|
|
|
|
LVITEM li;
|
|
|
|
|
2005-11-26 01:08:19 +00:00
|
|
|
/* get the device name */
|
2005-11-25 23:36:32 +00:00
|
|
|
if ((SetupDiGetDeviceRegistryProperty(ClassDevInfo->hDevInfo,
|
|
|
|
&HwDevInfo->DevInfoData,
|
2005-11-25 14:17:30 +00:00
|
|
|
SPDRP_FRIENDLYNAME,
|
|
|
|
&RegDataType,
|
|
|
|
(PBYTE)szBuffer,
|
|
|
|
sizeof(szBuffer),
|
|
|
|
NULL) ||
|
2005-11-25 23:36:32 +00:00
|
|
|
SetupDiGetDeviceRegistryProperty(ClassDevInfo->hDevInfo,
|
|
|
|
&HwDevInfo->DevInfoData,
|
2005-11-25 14:17:30 +00:00
|
|
|
SPDRP_DEVICEDESC,
|
|
|
|
&RegDataType,
|
|
|
|
(PBYTE)szBuffer,
|
|
|
|
sizeof(szBuffer),
|
|
|
|
NULL)) &&
|
|
|
|
RegDataType == REG_SZ)
|
|
|
|
{
|
|
|
|
/* FIXME - check string for NULL termination! */
|
|
|
|
|
|
|
|
li.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT | LVIF_IMAGE;
|
|
|
|
li.iItem = ItemCount;
|
|
|
|
li.iSubItem = 0;
|
|
|
|
li.state = (ItemCount == 0 ? LVIS_SELECTED : 0);
|
|
|
|
li.stateMask = LVIS_SELECTED;
|
|
|
|
li.pszText = szBuffer;
|
2005-11-25 23:36:32 +00:00
|
|
|
li.iImage = ClassDevInfo->ImageIndex;
|
|
|
|
li.lParam = (LPARAM)HwDevInfo;
|
2005-11-25 14:17:30 +00:00
|
|
|
|
|
|
|
iItem = ListView_InsertItem(hpd->hWndDevList,
|
|
|
|
&li);
|
|
|
|
if (iItem != -1)
|
|
|
|
{
|
|
|
|
ItemCount++;
|
|
|
|
|
2005-11-26 01:08:19 +00:00
|
|
|
/* get the device type for the second column */
|
2005-11-25 23:36:32 +00:00
|
|
|
if (SetupDiGetClassDescription(&ClassDevInfo->Guid,
|
2005-11-25 14:17:30 +00:00
|
|
|
szBuffer,
|
|
|
|
sizeof(szBuffer) / sizeof(szBuffer[0]),
|
|
|
|
NULL))
|
|
|
|
{
|
|
|
|
li.mask = LVIF_TEXT;
|
|
|
|
li.iItem = iItem;
|
|
|
|
li.iSubItem = 1;
|
|
|
|
|
|
|
|
ListView_SetItem(hpd->hWndDevList,
|
|
|
|
&li);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-11-25 23:36:32 +00:00
|
|
|
|
|
|
|
HwDevInfo++;
|
2005-11-25 14:17:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-25 23:36:32 +00:00
|
|
|
ClassDevInfo++;
|
2005-11-25 14:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* update the controls */
|
|
|
|
UpdateControlStates(hpd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
2005-11-25 16:30:41 +00:00
|
|
|
INT Width, x, y;
|
2005-11-25 14:17:30 +00:00
|
|
|
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);
|
2005-11-25 16:30:41 +00:00
|
|
|
y = pt.y + hpd->DevListViewHeight + ptMargin.y;
|
2005-11-25 14:17:30 +00:00
|
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
|
|
hpd->hWndDevList,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
Width,
|
2005-11-25 16:30:41 +00:00
|
|
|
hpd->DevListViewHeight,
|
2005-11-25 14:17:30 +00:00
|
|
|
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;
|
|
|
|
}
|
2005-11-25 15:36:14 +00:00
|
|
|
y += rc.bottom - rc.top + (ptMargin.y / 2);
|
2005-11-25 14:17:30 +00:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
2005-11-25 15:36:14 +00:00
|
|
|
y += rc.bottom - rc.top + (ptMargin.y / 2);
|
2005-11-25 14:17:30 +00:00
|
|
|
|
|
|
|
/* 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);
|
2005-11-25 15:36:14 +00:00
|
|
|
x -= (ptMargin.x / 2) + (rcButton.right - rcButton.left);
|
2005-11-25 14:17:30 +00:00
|
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
|
|
hButton,
|
|
|
|
NULL,
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
SWP_NOSIZE | SWP_NOZORDER)))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
EndDeferWindowPos(dwp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-25 22:01:19 +00:00
|
|
|
static VOID
|
|
|
|
EnableTroubleShoot(PHARDWARE_PAGE_DATA hpd,
|
|
|
|
BOOL Enable)
|
|
|
|
{
|
|
|
|
HWND hBtnTroubleShoot = GetDlgItem(hpd->hWnd,
|
|
|
|
IDC_TROUBLESHOOT);
|
|
|
|
|
|
|
|
ShowWindow(hBtnTroubleShoot,
|
|
|
|
Enable ? SW_SHOW : SW_HIDE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-25 14:17:30 +00:00
|
|
|
static INT_PTR
|
|
|
|
CALLBACK
|
|
|
|
HardwareDlgProc(IN HWND hwndDlg,
|
|
|
|
IN UINT uMsg,
|
|
|
|
IN WPARAM wParam,
|
|
|
|
IN LPARAM lParam)
|
|
|
|
{
|
|
|
|
PHARDWARE_PAGE_DATA hpd;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-11-26 01:08:19 +00:00
|
|
|
case WM_COMMAND:
|
|
|
|
{
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case IDC_TROUBLESHOOT:
|
|
|
|
{
|
|
|
|
/* FIXME - start the help using the command in the window text */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case IDC_PROPERTIES:
|
|
|
|
{
|
2005-11-26 02:12:58 +00:00
|
|
|
DisplaySelectedDeviceProperties(hpd);
|
2005-11-26 01:08:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-11-25 14:17:30 +00:00
|
|
|
case WM_SIZE:
|
|
|
|
HardwareDlgResize(hpd,
|
|
|
|
(INT)LOWORD(lParam),
|
|
|
|
(INT)HIWORD(lParam));
|
|
|
|
break;
|
|
|
|
|
2005-11-25 22:01:19 +00:00
|
|
|
case WM_SETTEXT:
|
|
|
|
{
|
|
|
|
LPCWSTR szWndText = (LPCWSTR)lParam;
|
|
|
|
EnableTroubleShoot(hpd,
|
|
|
|
(szWndText != NULL && szWndText[0] != L'\0'));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-11-25 14:17:30 +00:00
|
|
|
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);
|
|
|
|
|
2005-11-25 16:30:41 +00:00
|
|
|
/* calculate the size of the devices list view control */
|
2005-11-25 14:17:30 +00:00
|
|
|
hpd->hWndDevList = GetDlgItem(hwndDlg,
|
|
|
|
IDC_LV_DEVICES);
|
2005-11-25 16:30:41 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2005-11-25 14:17:30 +00:00
|
|
|
|
|
|
|
/* subclass the parent window */
|
|
|
|
hWndParent = GetAncestor(hwndDlg,
|
|
|
|
GA_PARENT);
|
|
|
|
if (hWndParent != NULL)
|
|
|
|
{
|
|
|
|
RECT rcClient;
|
|
|
|
|
|
|
|
if (GetClientRect(hWndParent,
|
|
|
|
&rcClient) &&
|
|
|
|
SetWindowPos(hwndDlg,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
rcClient.right,
|
|
|
|
rcClient.bottom,
|
|
|
|
SWP_NOZORDER))
|
|
|
|
{
|
|
|
|
/* subclass the parent window. This is not safe
|
|
|
|
if the parent window belongs to another thread! */
|
|
|
|
hpd->ParentOldWndProc = (WNDPROC)SetWindowLongPtr(hWndParent,
|
|
|
|
GWLP_WNDPROC,
|
|
|
|
(LONG_PTR)ParentSubWndProc);
|
|
|
|
|
|
|
|
if (hpd->ParentOldWndProc != NULL &&
|
|
|
|
SetProp(hWndParent,
|
|
|
|
L"DevMgrSubClassInfo",
|
|
|
|
(HANDLE)hpd))
|
|
|
|
{
|
|
|
|
hpd->hWndParent = hWndParent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize the devices list view control */
|
|
|
|
InitializeDevicesList(hpd);
|
|
|
|
|
|
|
|
/* fill the devices list view control */
|
2005-11-26 01:08:19 +00:00
|
|
|
FillDevicesListViewControl(hpd);
|
2005-11-25 22:01:19 +00:00
|
|
|
|
|
|
|
/* decide whether to show or hide the troubleshoot button */
|
|
|
|
EnableTroubleShoot(hpd,
|
|
|
|
GetWindowTextLength(hwndDlg) != 0);
|
2005-11-25 14:17:30 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_DESTROY:
|
|
|
|
{
|
2005-11-25 23:36:32 +00:00
|
|
|
/* free devices list */
|
|
|
|
FreeDevicesList(hpd);
|
2005-11-25 14:17:30 +00:00
|
|
|
|
|
|
|
/* restore the old window proc of the subclassed parent window */
|
|
|
|
if (hpd->hWndParent != NULL && hpd->ParentOldWndProc != NULL)
|
|
|
|
{
|
|
|
|
SetWindowLongPtr(hpd->hWndParent,
|
|
|
|
GWLP_WNDPROC,
|
|
|
|
(LONG_PTR)hpd->ParentOldWndProc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hpd->ClassImageListData.ImageList != NULL)
|
|
|
|
{
|
|
|
|
SetupDiDestroyClassImageList(&hpd->ClassImageListData);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free the reference to comctl32 */
|
|
|
|
FreeLibrary(hpd->hComCtl32);
|
|
|
|
hpd->hComCtl32 = NULL;
|
|
|
|
|
|
|
|
/* free the allocated resources */
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
hpd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* NAME EXPORTED
|
|
|
|
* DeviceCreateHardwarePageEx
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* Creates a hardware page
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* hWndParent: Handle to the parent window
|
|
|
|
* lpGuids: An array of guids of devices that are to be listed
|
|
|
|
* uNumberOfGuids: Numbers of guids in the Guids array
|
2005-11-26 01:08:19 +00:00
|
|
|
* DisplayMode: Sets the size of the device list view control
|
2005-11-25 14:17:30 +00:00
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* Returns the handle of the hardware page window that has been created or
|
|
|
|
* NULL if it failed.
|
|
|
|
*/
|
|
|
|
HWND
|
|
|
|
WINAPI
|
|
|
|
DeviceCreateHardwarePageEx(IN HWND hWndParent,
|
|
|
|
IN LPGUID lpGuids,
|
|
|
|
IN UINT uNumberOfGuids,
|
|
|
|
IN HWPAGE_DISPLAYMODE DisplayMode)
|
|
|
|
{
|
|
|
|
PHARDWARE_PAGE_DATA hpd;
|
|
|
|
PINITCOMMONCONTROLS pInitCommonControls;
|
|
|
|
|
|
|
|
/* allocate the HARDWARE_PAGE_DATA structure. Make sure it is
|
|
|
|
zeroed because the initialization code assumes that in
|
|
|
|
failure cases! */
|
|
|
|
hpd = HeapAlloc(GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
FIELD_OFFSET(HARDWARE_PAGE_DATA,
|
|
|
|
ClassDevInfo) +
|
|
|
|
(uNumberOfGuids * sizeof(HWCLASSDEVINFO)));
|
|
|
|
if (hpd != NULL)
|
|
|
|
{
|
|
|
|
HWND hWnd;
|
|
|
|
UINT i;
|
|
|
|
|
|
|
|
hpd->DisplayMode = ((DisplayMode > HWPD_MAX) ? HWPD_STANDARDLIST : DisplayMode);
|
|
|
|
|
|
|
|
/* initialize the HARDWARE_PAGE_DATA structure */
|
|
|
|
hpd->NumberOfGuids = uNumberOfGuids;
|
|
|
|
for (i = 0;
|
|
|
|
i < uNumberOfGuids;
|
|
|
|
i++)
|
|
|
|
{
|
2005-11-26 01:08:19 +00:00
|
|
|
hpd->ClassDevInfo[i].hDevInfo = INVALID_HANDLE_VALUE;
|
2005-11-25 14:17:30 +00:00
|
|
|
hpd->ClassDevInfo[i].Guid = lpGuids[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* load comctl32.dll dynamically */
|
|
|
|
hpd->hComCtl32 = LoadLibrary(TEXT("comctl32.dll"));
|
|
|
|
if (hpd->hComCtl32 == NULL)
|
|
|
|
{
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize the common controls */
|
|
|
|
pInitCommonControls = (PINITCOMMONCONTROLS)GetProcAddress(hpd->hComCtl32,
|
|
|
|
"InitCommonControls");
|
|
|
|
if (pInitCommonControls == NULL)
|
|
|
|
{
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
pInitCommonControls();
|
|
|
|
|
|
|
|
/* create the dialog */
|
|
|
|
hWnd = CreateDialogParam(hDllInstance,
|
|
|
|
MAKEINTRESOURCE(IDD_HARDWARE),
|
|
|
|
hWndParent,
|
|
|
|
HardwareDlgProc,
|
|
|
|
(LPARAM)hpd);
|
|
|
|
if (hWnd != NULL)
|
|
|
|
{
|
|
|
|
return hWnd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Cleanup:
|
|
|
|
/* oops, something went wrong... */
|
|
|
|
if (hpd->hComCtl32 != NULL)
|
|
|
|
{
|
|
|
|
FreeLibrary(hpd->hComCtl32);
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
hpd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2004-04-04 21:49:15 +00:00
|
|
|
}
|
|
|
|
|
2005-11-25 14:17:30 +00:00
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* NAME EXPORTED
|
|
|
|
* DeviceCreateHardwarePage
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* Creates a hardware page
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* hWndParent: Handle to the parent window
|
|
|
|
* lpGuid: Guid of the device
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* Returns the handle of the hardware page window that has been created or
|
|
|
|
* NULL if it failed.
|
|
|
|
*
|
|
|
|
* REVISIONS
|
|
|
|
*
|
|
|
|
* NOTE
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
HWND
|
|
|
|
WINAPI
|
|
|
|
DeviceCreateHardwarePage(IN HWND hWndParent,
|
|
|
|
IN LPGUID lpGuid)
|
|
|
|
{
|
|
|
|
return DeviceCreateHardwarePageEx(hWndParent,
|
|
|
|
lpGuid,
|
|
|
|
1,
|
|
|
|
HWPD_LARGELIST);
|
|
|
|
}
|