mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 18:24:02 +00:00
466 lines
12 KiB
C
466 lines
12 KiB
C
/*
|
|
* PROJECT: ReactOS Device Managment
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: base/system/devmgmt/enumdevices.c
|
|
* PURPOSE: Enumerates all devices on the local machine
|
|
* COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
|
|
*
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
static SP_CLASSIMAGELIST_DATA ImageListData;
|
|
static HDEVINFO hDevInfo;
|
|
|
|
|
|
VOID
|
|
FreeDeviceStrings(HWND hTreeView)
|
|
{
|
|
HTREEITEM hItem;
|
|
|
|
hItem = TreeView_GetRoot(hTreeView);
|
|
|
|
if (hItem)
|
|
{
|
|
hItem = TreeView_GetChild(hTreeView,
|
|
hItem);
|
|
/* loop the parent items */
|
|
while (hItem)
|
|
{
|
|
hItem = TreeView_GetChild(hTreeView,
|
|
hItem);
|
|
if (hItem == NULL)
|
|
break;
|
|
|
|
/* loop the child items and free the DeviceID */
|
|
while (TRUE)
|
|
{
|
|
HTREEITEM hOldItem;
|
|
TV_ITEM tvItem;
|
|
//TCHAR Buf[100];
|
|
|
|
tvItem.hItem = hItem;
|
|
tvItem.mask = TVIF_PARAM;// | TVIF_TEXT;
|
|
//tvItem.pszText = Buf;
|
|
//tvItem.cchTextMax = 99;
|
|
|
|
(void)TreeView_GetItem(hTreeView, &tvItem);
|
|
|
|
//MessageBox(NULL, Buf, NULL, 0);
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
(LPTSTR)tvItem.lParam);
|
|
|
|
hOldItem = hItem;
|
|
|
|
hItem = TreeView_GetNextSibling(hTreeView,
|
|
hItem);
|
|
if (hItem == NULL)
|
|
{
|
|
hItem = hOldItem;
|
|
break;
|
|
}
|
|
}
|
|
|
|
hItem = TreeView_GetParent(hTreeView,
|
|
hItem);
|
|
hItem = TreeView_GetNextSibling(hTreeView,
|
|
hItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
OpenPropSheet(HWND hTreeView,
|
|
HTREEITEM hItem)
|
|
{
|
|
TV_ITEM tvItem;
|
|
|
|
tvItem.hItem = hItem;
|
|
tvItem.mask = TVIF_PARAM;
|
|
|
|
if (TreeView_GetItem(hTreeView, &tvItem) &&
|
|
(LPTSTR)tvItem.lParam != NULL)
|
|
{
|
|
DevicePropertiesExW(hTreeView,
|
|
NULL,
|
|
(LPTSTR)tvItem.lParam,
|
|
DPF_EXTENDED,
|
|
FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static HTREEITEM
|
|
InsertIntoTreeView(HWND hTreeView,
|
|
HTREEITEM hRoot,
|
|
LPTSTR lpLabel,
|
|
LPTSTR DeviceID,
|
|
INT DevImage,
|
|
LONG DevProb)
|
|
{
|
|
TV_ITEM 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 = lstrlen(lpLabel);
|
|
tvi.lParam = (LPARAM)DeviceID;
|
|
tvi.iImage = DevImage;
|
|
tvi.iSelectedImage = DevImage;
|
|
|
|
if (DevProb != 0)
|
|
{
|
|
tvi.stateMask = TVIS_OVERLAYMASK;
|
|
|
|
if (DevProb == CM_PROB_DISABLED)
|
|
{
|
|
/* FIXME: set the overlay icon */
|
|
}
|
|
|
|
}
|
|
|
|
tvins.item = tvi;
|
|
tvins.hParent = hRoot;
|
|
|
|
return TreeView_InsertItem(hTreeView, &tvins);
|
|
}
|
|
|
|
|
|
static INT
|
|
EnumDeviceClasses(INT ClassIndex,
|
|
LPTSTR DevClassName,
|
|
LPTSTR DevClassDesc,
|
|
BOOL *DevPresent,
|
|
INT *ClassImage)
|
|
{
|
|
GUID ClassGuid;
|
|
HKEY KeyClass;
|
|
TCHAR ClassName[MAX_CLASS_NAME_LEN];
|
|
DWORD RequiredSize = MAX_CLASS_NAME_LEN;
|
|
UINT Ret;
|
|
|
|
*DevPresent = FALSE;
|
|
*DevClassName = _T('\0');
|
|
|
|
Ret = CM_Enumerate_Classes(ClassIndex,
|
|
&ClassGuid,
|
|
0);
|
|
if (Ret != CR_SUCCESS)
|
|
{
|
|
/* all classes enumerated */
|
|
if(Ret == CR_NO_SUCH_VALUE)
|
|
{
|
|
hDevInfo = NULL;
|
|
return -1;
|
|
}
|
|
|
|
if (Ret == CR_INVALID_DATA)
|
|
{
|
|
; /*FIXME: what should we do here? */
|
|
}
|
|
|
|
/* handle other errors... */
|
|
}
|
|
|
|
if (SetupDiClassNameFromGuid(&ClassGuid,
|
|
ClassName,
|
|
RequiredSize,
|
|
&RequiredSize))
|
|
{
|
|
lstrcpy(DevClassName, ClassName);
|
|
}
|
|
|
|
if (!SetupDiGetClassImageIndex(&ImageListData,
|
|
&ClassGuid,
|
|
ClassImage))
|
|
{
|
|
/* FIXME: can we do this?
|
|
* Set the blank icon: IDI_SETUPAPI_BLANK = 41
|
|
* it'll be image 24 in the imagelist */
|
|
*ClassImage = 24;
|
|
}
|
|
|
|
/* Get device info for all devices of a particular class */
|
|
hDevInfo = SetupDiGetClassDevs(&ClassGuid,
|
|
NULL,
|
|
NULL,
|
|
DIGCF_PRESENT);
|
|
if (hDevInfo == INVALID_HANDLE_VALUE)
|
|
{
|
|
hDevInfo = NULL;
|
|
return 0;
|
|
}
|
|
|
|
KeyClass = SetupDiOpenClassRegKeyEx(&ClassGuid,
|
|
MAXIMUM_ALLOWED,
|
|
DIOCR_INSTALLER,
|
|
NULL,
|
|
0);
|
|
if (KeyClass != INVALID_HANDLE_VALUE)
|
|
{
|
|
|
|
LONG dwSize = MAX_DEV_LEN;
|
|
|
|
if (RegQueryValue(KeyClass,
|
|
NULL,
|
|
DevClassDesc,
|
|
&dwSize) != ERROR_SUCCESS)
|
|
{
|
|
*DevClassDesc = _T('\0');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -3;
|
|
}
|
|
|
|
*DevPresent = TRUE;
|
|
|
|
RegCloseKey(KeyClass);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static LONG
|
|
EnumDevices(INT index,
|
|
LPTSTR DeviceClassName,
|
|
LPTSTR DeviceName,
|
|
LPTSTR *DeviceID)
|
|
{
|
|
SP_DEVINFO_DATA DeviceInfoData;
|
|
CONFIGRET cr;
|
|
ULONG Status, ProblemNumber;
|
|
DWORD DevIdSize;
|
|
|
|
*DeviceName = _T('\0');
|
|
*DeviceID = NULL;
|
|
|
|
ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
|
|
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
|
|
|
if (!SetupDiEnumDeviceInfo(hDevInfo,
|
|
index,
|
|
&DeviceInfoData))
|
|
{
|
|
/* no such device */
|
|
return -1;
|
|
}
|
|
|
|
/* get the device ID */
|
|
if (!SetupDiGetDeviceInstanceId(hDevInfo,
|
|
&DeviceInfoData,
|
|
NULL,
|
|
0,
|
|
&DevIdSize))
|
|
{
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
(*DeviceID) = (LPTSTR)HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
DevIdSize * sizeof(TCHAR));
|
|
if (*DeviceID)
|
|
{
|
|
if (!SetupDiGetDeviceInstanceId(hDevInfo,
|
|
&DeviceInfoData,
|
|
*DeviceID,
|
|
DevIdSize,
|
|
NULL))
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
*DeviceID);
|
|
*DeviceID = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* get the device's friendly name */
|
|
if (!SetupDiGetDeviceRegistryProperty(hDevInfo,
|
|
&DeviceInfoData,
|
|
SPDRP_FRIENDLYNAME,
|
|
0,
|
|
(BYTE*)DeviceName,
|
|
MAX_DEV_LEN,
|
|
NULL))
|
|
{
|
|
/* if the friendly name fails, try the description instead */
|
|
SetupDiGetDeviceRegistryProperty(hDevInfo,
|
|
&DeviceInfoData,
|
|
SPDRP_DEVICEDESC,
|
|
0,
|
|
(BYTE*)DeviceName,
|
|
MAX_DEV_LEN,
|
|
NULL);
|
|
}
|
|
|
|
cr = CM_Get_DevNode_Status_Ex(&Status,
|
|
&ProblemNumber,
|
|
DeviceInfoData.DevInst,
|
|
0,
|
|
NULL);
|
|
if (cr == CR_SUCCESS && (Status & DN_HAS_PROBLEM))
|
|
{
|
|
return ProblemNumber;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
ListDevicesByType(HWND hTreeView,
|
|
HTREEITEM hRoot)
|
|
{
|
|
HTREEITEM hDevItem;
|
|
TCHAR DevName[MAX_DEV_LEN];
|
|
TCHAR DevDesc[MAX_DEV_LEN];
|
|
LPTSTR DeviceID = NULL;
|
|
BOOL DevExist = FALSE;
|
|
INT ClassRet;
|
|
INT index = 0;
|
|
INT DevImage;
|
|
|
|
do
|
|
{
|
|
ClassRet = EnumDeviceClasses(index,
|
|
DevName,
|
|
DevDesc,
|
|
&DevExist,
|
|
&DevImage);
|
|
|
|
if ((ClassRet != -1) && (DevExist))
|
|
{
|
|
TCHAR DeviceName[MAX_DEV_LEN];
|
|
INT DevIndex = 0;
|
|
LONG Ret;
|
|
|
|
if (DevDesc[0] != _T('\0'))
|
|
{
|
|
hDevItem = InsertIntoTreeView(hTreeView,
|
|
hRoot,
|
|
DevDesc,
|
|
NULL,
|
|
DevImage,
|
|
0);
|
|
}
|
|
else
|
|
{
|
|
hDevItem = InsertIntoTreeView(hTreeView,
|
|
hRoot,
|
|
DevName,
|
|
NULL,
|
|
DevImage,
|
|
0);
|
|
}
|
|
|
|
do
|
|
{
|
|
Ret = EnumDevices(DevIndex,
|
|
DevName,
|
|
DeviceName,
|
|
&DeviceID);
|
|
if (Ret >= 0)
|
|
{
|
|
InsertIntoTreeView(hTreeView,
|
|
hDevItem,
|
|
DeviceName,
|
|
DeviceID,
|
|
DevImage,
|
|
Ret);
|
|
}
|
|
|
|
DevIndex++;
|
|
|
|
} while (Ret != -1);
|
|
|
|
/* kill InfoList initialized in EnumDeviceClasses */
|
|
if (hDevInfo)
|
|
{
|
|
SetupDiDestroyDeviceInfoList(hDevInfo);
|
|
hDevInfo = NULL;
|
|
}
|
|
|
|
/* don't insert classes with no devices */
|
|
if (!TreeView_GetChild(hTreeView,
|
|
hDevItem))
|
|
{
|
|
(void)TreeView_DeleteItem(hTreeView,
|
|
hDevItem);
|
|
}
|
|
else
|
|
{
|
|
(void)TreeView_SortChildren(hTreeView,
|
|
hDevItem,
|
|
0);
|
|
}
|
|
}
|
|
|
|
index++;
|
|
|
|
} while (ClassRet != -1);
|
|
|
|
(void)TreeView_Expand(hTreeView,
|
|
hRoot,
|
|
TVE_EXPAND);
|
|
|
|
(void)TreeView_SortChildren(hTreeView,
|
|
hRoot,
|
|
0);
|
|
}
|
|
|
|
|
|
HTREEITEM
|
|
InitTreeView(HWND hTreeView)
|
|
{
|
|
HTREEITEM hRoot;
|
|
HBITMAP hComp;
|
|
TCHAR ComputerName[MAX_PATH];
|
|
DWORD dwSize = MAX_PATH;
|
|
INT RootImage;
|
|
|
|
(void)TreeView_DeleteAllItems(hTreeView);
|
|
|
|
/* get the device image List */
|
|
ImageListData.cbSize = sizeof(ImageListData);
|
|
SetupDiGetClassImageList(&ImageListData);
|
|
|
|
hComp = LoadBitmap(hInstance,
|
|
MAKEINTRESOURCE(IDB_ROOT_IMAGE));
|
|
|
|
ImageList_Add(ImageListData.ImageList,
|
|
hComp,
|
|
NULL);
|
|
|
|
DeleteObject(hComp);
|
|
|
|
(void)TreeView_SetImageList(hTreeView,
|
|
ImageListData.ImageList,
|
|
TVSIL_NORMAL);
|
|
|
|
if (!GetComputerName(ComputerName,
|
|
&dwSize))
|
|
{
|
|
ComputerName[0] = _T('\0');
|
|
}
|
|
|
|
RootImage = ImageList_GetImageCount(ImageListData.ImageList) - 1;
|
|
|
|
/* insert the root item into the tree */
|
|
hRoot = InsertIntoTreeView(hTreeView,
|
|
NULL,
|
|
ComputerName,
|
|
NULL,
|
|
RootImage,
|
|
0);
|
|
|
|
return hRoot;
|
|
}
|