SetupApi에서 CfgMgr32로 코드 포팅
이 항목에서는 Setupapi.dll 기능을 사용하여 대신 Cfgmgr32.dll 사용하는 코드를 이식하는 방법을 보여 주는 코드 예제를 제공합니다. 코드를 포팅하면 SetupApi를 지원하지 않는 UWP(유니버설 Windows 플랫폼)에서 코드를 실행할 수 있습니다. CfgMgr32의 하위 집합은 UWP에서 지원됩니다. 특히 API 집합(Windows 8 이상) 또는 api-ms-win-devices-config-l1-1-1.dll
API 집합(Windows 8.1 이상)을 통해 api-ms-win-devices-config-l1-1-0.dll
노출되는 기능입니다. Windows 10 이상에서는 에 연결하기만 하면됩니다onecore.lib
.
위의 API 집합에서 함수 목록을 보려면 Windows API 집합 또는 Onecore.lib: api-ms-win-devices-config-l1-1-1.dllAPI 를 참조하세요.
다음 섹션에는 애플리케이션에서 일반적으로 사용하는 코드 예제가 포함되어 있습니다.
- 현재 디바이스 목록을 가져와 각 디바이스에 대한 속성을 검색합니다.
- 인터페이스 목록을 가져와서 각 인터페이스를 노출하는 디바이스를 가져와서 디바이스에서 속성을 가져옵니다.
- 특정 디바이스에서 속성 가져오기
- 디바이스 사용 안 함
- 디바이스 사용
- 디바이스 다시 시작
현재 디바이스 목록을 가져와 각 디바이스에 대한 속성을 검색합니다.
이 예제에서는 SetupDiGetClassDevs 를 사용하여 모든 현재 디바이스 목록을 가져오고 이를 반복하여 각 디바이스의 디바이스 설명을 검색합니다.
VOID
GetDevicePropertiesSetupapi(
VOID
)
{
HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
SP_DEVINFO_DATA DeviceInfoData;
DWORD Index;
WCHAR DeviceDesc[2048];
DEVPROPTYPE PropertyType;
DeviceInfoSet = SetupDiGetClassDevs(NULL,
NULL,
NULL,
DIGCF_ALLCLASSES | DIGCF_PRESENT);
if (DeviceInfoSet == INVALID_HANDLE_VALUE)
{
goto Exit;
}
ZeroMemory(&DeviceInfoData, sizeof(DeviceInfoData));
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
for (Index = 0;
SetupDiEnumDeviceInfo(DeviceInfoSet,
Index,
&DeviceInfoData);
Index++)
{
// Query a property on the device. For example, the device description.
if (!SetupDiGetDeviceProperty(DeviceInfoSet,
&DeviceInfoData,
&DEVPKEY_Device_DeviceDesc,
&PropertyType,
(PBYTE)DeviceDesc,
sizeof(DeviceDesc),
NULL,
0))
{
// The error can be retrieved with GetLastError();
continue;
}
if (PropertyType != DEVPROP_TYPE_STRING)
{
continue;
}
}
if (GetLastError() != ERROR_NO_MORE_ITEMS)
{
goto Exit;
}
Exit:
if (DeviceInfoSet != INVALID_HANDLE_VALUE)
{
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
return;
}
이 예제에서는 CM_Get_Device_ID_List 사용하여 모든 현재 디바이스의 목록을 가져오고 이를 반복하여 각 디바이스의 디바이스 설명을 검색합니다.
VOID
GetDevicePropertiesCfgmgr32(
VOID
)
{
CONFIGRET cr = CR_SUCCESS;
PWSTR DeviceList = NULL;
ULONG DeviceListLength = 0;
PWSTR CurrentDevice;
DEVINST Devinst;
WCHAR DeviceDesc[2048];
DEVPROPTYPE PropertyType;
ULONG PropertySize;
DWORD Index = 0;
cr = CM_Get_Device_ID_List_Size(&DeviceListLength,
NULL,
CM_GETIDLIST_FILTER_PRESENT);
if (cr != CR_SUCCESS)
{
goto Exit;
}
DeviceList = (PWSTR)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
DeviceListLength * sizeof(WCHAR));
if (DeviceList == NULL) {
goto Exit;
}
cr = CM_Get_Device_ID_List(NULL,
DeviceList,
DeviceListLength,
CM_GETIDLIST_FILTER_PRESENT);
if (cr != CR_SUCCESS)
{
goto Exit;
}
for (CurrentDevice = DeviceList;
*CurrentDevice;
CurrentDevice += wcslen(CurrentDevice) + 1)
{
// If the list of devices also includes non-present devices,
// CM_LOCATE_DEVNODE_PHANTOM should be used in place of
// CM_LOCATE_DEVNODE_NORMAL.
cr = CM_Locate_DevNode(&Devinst,
CurrentDevice,
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS)
{
goto Exit;
}
// Query a property on the device. For example, the device description.
PropertySize = sizeof(DeviceDesc);
cr = CM_Get_DevNode_Property(Devinst,
&DEVPKEY_Device_DeviceDesc,
&PropertyType,
(PBYTE)DeviceDesc,
&PropertySize,
0);
if (cr != CR_SUCCESS)
{
Index++;
continue;
}
if (PropertyType != DEVPROP_TYPE_STRING)
{
Index++;
continue;
}
Index++;
}
Exit:
if (DeviceList != NULL)
{
HeapFree(GetProcessHeap(),
0,
DeviceList);
}
return;
}
인터페이스 목록을 가져와서 각 인터페이스를 노출하는 디바이스를 가져와서 디바이스에서 속성을 가져옵니다.
이 예제에서는 SetupDiGetClassDevs를 사용하여 클래스 GUID_DEVINTERFACE_VOLUME 모든 인터페이스 목록을 가져옵니다. 각 인터페이스에 대해 인터페이스를 노출하는 디바이스를 가져오고 해당 디바이스의 속성을 가져옵니다.
VOID
GetInterfacesAndDevicePropertySetupapi(
VOID
)
{
HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
SP_DEVINFO_DATA DeviceInfoData;
DWORD Index;
WCHAR DeviceDesc[2048];
DEVPROPTYPE PropertyType;
DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME,
NULL,
NULL,
DIGCF_DEVICEINTERFACE);
if (DeviceInfoSet == INVALID_HANDLE_VALUE)
{
goto Exit;
}
ZeroMemory(&DeviceInterfaceData, sizeof(DeviceInterfaceData));
DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
for (Index = 0;
SetupDiEnumDeviceInterfaces(DeviceInfoSet,
NULL,
&GUID_DEVINTERFACE_VOLUME,
Index,
&DeviceInterfaceData);
Index++)
{
ZeroMemory(&DeviceInfoData, sizeof(DeviceInfoData));
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
if ((!SetupDiGetDeviceInterfaceDetail(DeviceInfoSet,
&DeviceInterfaceData,
NULL,
0,
NULL,
&DeviceInfoData)) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
// The error can be retrieved with GetLastError();
goto Exit;
}
// Query a property on the device. For example, the device description.
if (!SetupDiGetDeviceProperty(DeviceInfoSet,
&DeviceInfoData,
&DEVPKEY_Device_DeviceDesc,
&PropertyType,
(PBYTE)DeviceDesc,
sizeof(DeviceDesc),
NULL,
0))
{
// The error can be retrieved with GetLastError();
goto Exit;
}
if (PropertyType != DEVPROP_TYPE_STRING)
{
goto Exit;
}
}
if (GetLastError() != ERROR_NO_MORE_ITEMS)
{
goto Exit;
}
Exit:
if (DeviceInfoSet != INVALID_HANDLE_VALUE)
{
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
return;
}
이 예제에서는 CM_Get_Device_Interface_List 사용하여 클래스 GUID_DEVINTERFACE_VOLUME 모든 인터페이스 목록을 가져옵니다. 각 인터페이스에 대해 인터페이스를 노출하는 디바이스를 가져오고 해당 디바이스의 속성을 가져옵니다.
VOID
GetInterfacesAndDevicePropertyCfgmgr32(
VOID
)
{
CONFIGRET cr = CR_SUCCESS;
PWSTR DeviceInterfaceList = NULL;
ULONG DeviceInterfaceListLength = 0;
PWSTR CurrentInterface;
WCHAR CurrentDevice[MAX_DEVICE_ID_LEN];
DEVINST Devinst;
WCHAR DeviceDesc[2048];
DEVPROPTYPE PropertyType;
ULONG PropertySize;
DWORD Index = 0;
do {
cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListLength,
(LPGUID)&GUID_DEVINTERFACE_VOLUME,
NULL,
CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES);
if (cr != CR_SUCCESS)
{
break;
}
if (DeviceInterfaceList != NULL) {
HeapFree(GetProcessHeap(),
0,
DeviceInterfaceList);
}
DeviceInterfaceList = (PWSTR)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
DeviceInterfaceListLength * sizeof(WCHAR));
if (DeviceInterfaceList == NULL)
{
cr = CR_OUT_OF_MEMORY;
break;
}
cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_VOLUME,
NULL,
DeviceInterfaceList,
DeviceInterfaceListLength,
CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES);
} while (cr == CR_BUFFER_SMALL);
if (cr != CR_SUCCESS)
{
goto Exit;
}
for (CurrentInterface = DeviceInterfaceList;
*CurrentInterface;
CurrentInterface += wcslen(CurrentInterface) + 1)
{
PropertySize = sizeof(CurrentDevice);
cr = CM_Get_Device_Interface_Property(CurrentInterface,
&DEVPKEY_Device_InstanceId,
&PropertyType,
(PBYTE)CurrentDevice,
&PropertySize,
0);
if (cr != CR_SUCCESS)
{
goto Exit;
}
if (PropertyType != DEVPROP_TYPE_STRING)
{
goto Exit;
}
// Since the list of interfaces includes all interfaces, enabled or not, the
// device that exposed that interface may currently be non-present, so
// CM_LOCATE_DEVNODE_PHANTOM should be used.
cr = CM_Locate_DevNode(&Devinst,
CurrentDevice,
CM_LOCATE_DEVNODE_PHANTOM);
if (cr != CR_SUCCESS)
{
goto Exit;
}
// Query a property on the device. For example, the device description.
PropertySize = sizeof(DeviceDesc);
cr = CM_Get_DevNode_Property(Devinst,
&DEVPKEY_Device_DeviceDesc,
&PropertyType,
(PBYTE)DeviceDesc,
&PropertySize,
0);
if (cr != CR_SUCCESS)
{
goto Exit;
}
if (PropertyType != DEVPROP_TYPE_STRING)
{
goto Exit;
}
Index++;
}
Exit:
if (DeviceInterfaceList != NULL)
{
HeapFree(GetProcessHeap(),
0,
DeviceInterfaceList);
}
return;
}
특정 디바이스에서 속성 가져오기
이 예제에서는 특정 디바이스에 대한 디바이스 instance 경로를 사용하고 SetupDiGetDeviceProperty를 사용하여 해당 디바이스에서 속성을 검색합니다.
VOID
GetDevicePropertySpecificDeviceSetupapi(
VOID
)
{
HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
SP_DEVINFO_DATA DeviceInfoData;
WCHAR DeviceDesc[2048];
DEVPROPTYPE PropertyType;
DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
if (DeviceInfoSet == INVALID_HANDLE_VALUE)
{
goto Exit;
}
ZeroMemory(&DeviceInfoData, sizeof(DeviceInfoData));
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
if (!SetupDiOpenDeviceInfo(DeviceInfoSet,
MY_DEVICE,
NULL,
0,
&DeviceInfoData))
{
// The error can be retrieved with GetLastError();
goto Exit;
}
// Query a property on the device. For example, the device description.
if (!SetupDiGetDeviceProperty(DeviceInfoSet,
&DeviceInfoData,
&DEVPKEY_Device_DeviceDesc,
&PropertyType,
(PBYTE)DeviceDesc,
sizeof(DeviceDesc),
NULL,
0)) {
// The error can be retrieved with GetLastError();
goto Exit;
}
if (PropertyType != DEVPROP_TYPE_STRING)
{
goto Exit;
}
Exit:
if (DeviceInfoSet != INVALID_HANDLE_VALUE)
{
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
return;
}
이 예제에서는 특정 디바이스에 대한 디바이스 instance 경로를 사용하고 CM_Get_DevNode_Property 사용하여 해당 디바이스에서 속성을 검색합니다.
void
GetDevicePropertySpecificDeviceCfgmgr32(
VOID
)
{
CONFIGRET cr = CR_SUCCESS;
DEVINST Devinst;
WCHAR DeviceDesc[2048];
DEVPROPTYPE PropertyType;
ULONG PropertySize;
// If MY_DEVICE could be a non-present device, CM_LOCATE_DEVNODE_PHANTOM
// should be used in place of CM_LOCATE_DEVNODE_NORMAL.
cr = CM_Locate_DevNode(&Devinst,
MY_DEVICE,
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS)
{
goto Exit;
}
// Query a property on the device. For example, the device description.
PropertySize = sizeof(DeviceDesc);
cr = CM_Get_DevNode_Property(Devinst,
&DEVPKEY_Device_DeviceDesc,
&PropertyType,
(PBYTE)DeviceDesc,
&PropertySize,
0);
if (cr != CR_SUCCESS)
{
goto Exit;
}
if (PropertyType != DEVPROP_TYPE_STRING)
{
goto Exit;
}
Exit:
return;
}
디바이스 사용 안 함
이 예제에서는 CfgMgr32를 사용하여 디바이스를 사용하지 않도록 설정하는 방법을 보여줍니다. SetupApi를 사용하여 이 작업을 수행하려면 DICS_DISABLE 지정하는DIF_PROPERTYCHANGEInstallFunction과 함께 SetupDiCallClassInstaller를 사용합니다.
참고 기본적으로 SetupDiCallClassInstaller 를 호출하면 다시 부팅 시 디바이스가 비활성화된 상태로 유지됩니다. CM_Disable_DevNode 호출할 때 다시 부팅 시 디바이스를 사용하지 않도록 설정하려면 CM_DISABLE_PERSIST 플래그를 지정해야 합니다.
cr = CM_Locate_DevNode(&devinst,
(DEVINSTID_W)DeviceInstanceId,
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS) {
goto Exit;
}
cr = CM_Disable_DevNode(devinst, 0);
if (cr != CR_SUCCESS) {
goto Exit;
}
디바이스 사용
이 예제에서는 CfgMgr32를 사용하여 디바이스를 사용하도록 설정하는 방법을 보여 줍니다. SetupApi를 사용하여 이 작업을 수행하려면 DIF_PROPERTYCHANGE InstallFunction과 함께 SetupDiCallClassInstaller를 사용하여 DICS_ENABLE 지정합니다.
cr = CM_Locate_DevNode(&devinst,
(DEVINSTID_W)DeviceInstanceId,
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS) {
goto Exit;
}
cr = CM_Enable_DevNode(devinst, 0);
if (cr != CR_SUCCESS) {
goto Exit;
}
디바이스 다시 시작
이 예제에서는 CfgMgr32를 사용하여 디바이스를 다시 시작하는 방법을 보여줍니다. SetupApi를 사용하여 이 작업을 수행하려면 DIF_PROPERTYCHANGE InstallFunction과 함께 SetupDiCallClassInstaller를 사용하여 DICS_PROPCHANGE 지정합니다.
cr = CM_Locate_DevNode(&devinst,
(DEVINSTID_W)DeviceInstanceId,
CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS) {
goto Exit;
}
cr = CM_Query_And_Remove_SubTree(devinst,
NULL,
NULL,
0,
CM_REMOVE_NO_RESTART);
if (cr != CR_SUCCESS) {
goto Exit;
}
cr = CM_Setup_DevNode(devinst,
CM_SETUP_DEVNODE_READY);
if (cr != CR_SUCCESS) {
goto Exit;
}