[SETUPAPI] Update some functions to the current coding style, add annotations and...
[reactos.git] / dll / win32 / setupapi / cfgmgr.c
index 6d68087..b45e6de 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "setupapi_private.h"
 
+#include <dbt.h>
 #include <pnp_c.h>
 
 #include "rpc_private.h"
@@ -59,6 +60,31 @@ typedef struct _LOG_CONF_INFO
 #define LOG_CONF_MAGIC 0x464E434C  /* "LCNF" */
 
 
+typedef struct _NOTIFY_DATA
+{
+    ULONG ulMagic;
+    ULONG ulNotifyData;
+} NOTIFY_DATA, *PNOTIFY_DATA;
+
+#define NOTIFY_MAGIC 0x44556677
+
+
+typedef struct _INTERNAL_RANGE_ELEMENT
+{
+    struct _INTERNAL_RANGE_ELEMENT *Next;
+    ULONG ulDummy;
+} INTERNAL_RANGE_ELEMENT, *PINTERNAL_RANGE_ELEMENT;
+
+typedef struct _INTERNAL_RANGE_LIST
+{
+    ULONG ulMagic;
+    PINTERNAL_RANGE_ELEMENT Current;
+    PINTERNAL_RANGE_ELEMENT First;
+} INTERNAL_RANGE_LIST, *PINTERNAL_RANGE_LIST;
+
+#define RANGE_LIST_MAGIC 0x33445566
+
+
 static BOOL GuidToString(LPGUID Guid, LPWSTR String)
 {
     LPWSTR lpString;
@@ -85,18 +111,296 @@ RpcStatusToCmStatus(RPC_STATUS Status)
 }
 
 
+static
+ULONG
+GetRegistryPropertyType(
+    ULONG ulProperty)
+{
+    switch (ulProperty)
+    {
+        case CM_DRP_DEVICEDESC:
+        case CM_DRP_SERVICE:
+        case CM_DRP_CLASS:
+        case CM_DRP_CLASSGUID:
+        case CM_DRP_DRIVER:
+        case CM_DRP_MFG:
+        case CM_DRP_FRIENDLYNAME:
+        case CM_DRP_LOCATION_INFORMATION:
+        case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
+        case CM_DRP_ENUMERATOR_NAME:
+        case CM_DRP_SECURITY_SDS:
+        case CM_DRP_UI_NUMBER_DESC_FORMAT:
+            return REG_SZ;
+
+        case CM_DRP_HARDWAREID:
+        case CM_DRP_COMPATIBLEIDS:
+        case CM_DRP_UPPERFILTERS:
+        case CM_DRP_LOWERFILTERS:
+            return REG_MULTI_SZ;
+
+        case CM_DRP_CONFIGFLAGS:
+        case CM_DRP_CAPABILITIES:
+        case CM_DRP_UI_NUMBER:
+        case CM_DRP_LEGACYBUSTYPE:
+        case CM_DRP_BUSNUMBER:
+        case CM_DRP_DEVTYPE:
+        case CM_DRP_EXCLUSIVE:
+        case CM_DRP_CHARACTERISTICS:
+        case CM_DRP_ADDRESS:
+        case CM_DRP_REMOVAL_POLICY:
+        case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
+        case CM_DRP_REMOVAL_POLICY_OVERRIDE:
+        case CM_DRP_INSTALL_STATE:
+            return REG_DWORD;
+
+        case CM_DRP_BUSTYPEGUID:
+        case CM_DRP_SECURITY:
+        case CM_DRP_DEVICE_POWER_DATA:
+        default:
+            return REG_BINARY;
+    }
+
+    return REG_NONE;
+}
+
+
+static
+VOID
+SplitDeviceInstanceId(
+    _In_ PWSTR pszDeviceInstanceId,
+    _Out_ PWSTR pszDeviceId,
+    _Out_ PWSTR pszInstanceId)
+{
+    PWCHAR ptr;
+
+    wcscpy(pszDeviceId, pszDeviceInstanceId);
+
+    ptr = wcschr(pszDeviceId, L'\\');
+    if (ptr != NULL)
+    {
+        *ptr = UNICODE_NULL;
+        ptr++;
+
+        wcscpy(pszInstanceId, ptr);
+    }
+    else
+    {
+        *pszInstanceId = UNICODE_NULL;
+    }
+}
+
+
+static
+CONFIGRET
+GetDeviceInstanceKeyPath(
+    _In_ RPC_BINDING_HANDLE BindingHandle,
+    _In_ PWSTR pszDeviceInst,
+    _Out_ PWSTR pszKeyPath,
+    _Out_ PWSTR pszInstancePath,
+    _In_ ULONG ulHardwareProfile,
+    _In_ ULONG ulFlags)
+{
+    PWSTR pszBuffer = NULL;
+    ULONG ulType = 0;
+    ULONG ulTransferLength, ulLength;
+    CONFIGRET ret = CR_SUCCESS;
+
+    TRACE("GetDeviceInstanceKeyPath()\n");
+
+    if (ulFlags & CM_REGISTRY_SOFTWARE)
+    {
+        /* Software Key Path */
+        ret = CR_CALL_NOT_IMPLEMENTED;
+    }
+    else
+    {
+        /* Hardware Key Path */
+
+        ulTransferLength = 300 * sizeof(WCHAR);
+        ulLength = 300 * sizeof(WCHAR);
+
+        pszBuffer = MyMalloc(ulTransferLength);
+        if (pszBuffer == NULL)
+        {
+            ERR("MyMalloc() failed\n");
+            ret = CR_OUT_OF_MEMORY;
+            goto done;
+        }
+
+        ret = PNP_GetDeviceRegProp(BindingHandle,
+                                   pszDeviceInst,
+                                   CM_DRP_DRIVER,
+                                   &ulType,
+                                   (PVOID)pszBuffer,
+                                   &ulTransferLength,
+                                   &ulLength,
+                                   0);
+        if (ret != CR_SUCCESS)
+        {
+            ERR("PNP_GetDeviceRegProp() failed (Error %lu)\n", ret);
+            goto done;
+        }
+
+        TRACE("szBuffer: %S\n", pszBuffer);
+
+        SplitDeviceInstanceId(pszBuffer,
+                              pszBuffer,
+                              pszInstancePath);
+
+        TRACE("szBuffer: %S\n", pszBuffer);
+
+        if (ulFlags & CM_REGISTRY_CONFIG)
+        {
+            if (ulHardwareProfile == 0)
+            {
+                wsprintfW(pszKeyPath,
+                          L"%s\\%s\\%s\\%s",
+                          L"System\\CurrentControlSet\\Hardware Profiles",
+                          L"Current",
+                          L"System\\CurrentControlSet\\Control\\Class",
+                          pszBuffer);
+            }
+            else
+            {
+                wsprintfW(pszKeyPath,
+                          L"%s\\%04lu\\%s\\%s",
+                          L"System\\CurrentControlSet\\Hardware Profiles",
+                          ulHardwareProfile,
+                          L"System\\CurrentControlSet\\Control\\Class",
+                          pszBuffer);
+            }
+        }
+        else
+        {
+            wsprintfW(pszKeyPath,
+                      L"%s\\%s",
+                      L"System\\CurrentControlSet\\Control\\Class",
+                      pszBuffer);
+        }
+    }
+
+done:
+    if (pszBuffer != NULL)
+        MyFree(pszBuffer);
+
+    return ret;
+}
+
+
+/***********************************************************************
+ * CMP_GetBlockedDriverInfo [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CMP_GetBlockedDriverInfo(
+    _Out_opt_ LPWSTR pszNames,
+    _Inout_ PULONG pulLength,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
+{
+    RPC_BINDING_HANDLE BindingHandle = NULL;
+    ULONG ulTransferLength;
+    CONFIGRET ret;
+
+    TRACE("CMP_GetBlockedDriverInfo(%p %p %lx %p)\n",
+          pszNames, pulLength, ulFlags, hMachine);
+
+    if (hMachine != NULL)
+    {
+        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
+        if (BindingHandle == NULL)
+            return CR_FAILURE;
+    }
+    else
+    {
+        if (!PnpGetLocalHandles(&BindingHandle, NULL))
+            return CR_FAILURE;
+    }
+
+    ulTransferLength = *pulLength;
+
+    RpcTryExcept
+    {
+        ret = PNP_GetBlockedDriverInfo(BindingHandle,
+                                       (PBYTE)pszNames,
+                                       &ulTransferLength,
+                                       pulLength,
+                                       ulFlags);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        ret = RpcStatusToCmStatus(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return ret;
+}
+
+
+/***********************************************************************
+ * CMP_GetServerSideDeviceInstallFlags [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CMP_GetServerSideDeviceInstallFlags(
+    _Out_ PULONG pulSSDIFlags,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
+{
+    RPC_BINDING_HANDLE BindingHandle = NULL;
+    CONFIGRET ret;
+
+    TRACE("CMP_GetServerSideDeviceInstallFlags(%p %lx %p)\n",
+          pulSSDIFlags, ulFlags, hMachine);
+
+    if (pulSSDIFlags == NULL)
+        return CR_INVALID_POINTER;
+
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
+
+    if (hMachine != NULL)
+    {
+        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
+        if (BindingHandle == NULL)
+            return CR_FAILURE;
+    }
+    else
+    {
+        if (!PnpGetLocalHandles(&BindingHandle, NULL))
+            return CR_FAILURE;
+    }
+
+    RpcTryExcept
+    {
+        ret = PNP_GetServerSideDeviceInstallFlags(BindingHandle,
+                                                  pulSSDIFlags,
+                                                  ulFlags);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        ret = RpcStatusToCmStatus(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return ret;
+}
+
+
 /***********************************************************************
  * CMP_Init_Detection [SETUPAPI.@]
  */
-CONFIGRET WINAPI CMP_Init_Detection(
-    DWORD dwMagic)
+CONFIGRET
+WINAPI
+CMP_Init_Detection(
+    _In_ ULONG ulMagic)
 {
     RPC_BINDING_HANDLE BindingHandle = NULL;
     CONFIGRET ret;
 
-    TRACE("%lu\n", dwMagic);
+    TRACE("CMP_Init_Detection(%lu)\n", ulMagic);
 
-    if (dwMagic != CMP_MAGIC)
+    if (ulMagic != CMP_MAGIC)
         return CR_INVALID_DATA;
 
     if (!PnpGetLocalHandles(&BindingHandle, NULL))
@@ -121,30 +425,95 @@ CONFIGRET WINAPI CMP_Init_Detection(
  */
 CONFIGRET
 WINAPI
-CMP_RegisterNotification(IN HANDLE hRecipient,
-                         IN LPVOID lpvNotificationFilter,
-                         IN DWORD dwFlags,
-                         OUT PULONG pluhDevNotify)
+CMP_RegisterNotification(
+    _In_ HANDLE hRecipient,
+    _In_ LPVOID lpvNotificationFilter,
+    _In_ ULONG ulFlags,
+    _Out_ PHDEVNOTIFY phDevNotify)
 {
-    FIXME("Stub %p %p %lu %p\n", hRecipient, lpvNotificationFilter, dwFlags, pluhDevNotify);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return CR_FAILURE;
+    RPC_BINDING_HANDLE BindingHandle = NULL;
+    PNOTIFY_DATA pNotifyData = NULL;
+    CONFIGRET ret = CR_SUCCESS;
+
+    TRACE("CMP_RegisterNotification(%p %p %lu %p)\n",
+          hRecipient, lpvNotificationFilter, ulFlags, phDevNotify);
+
+    if ((hRecipient == NULL) ||
+        (lpvNotificationFilter == NULL) ||
+        (phDevNotify == NULL))
+        return CR_INVALID_POINTER;
+
+    if (ulFlags & ~0x7)
+        return CR_INVALID_FLAG;
+
+    if (((PDEV_BROADCAST_HDR)lpvNotificationFilter)->dbch_size < sizeof(DEV_BROADCAST_HDR))
+        return CR_INVALID_DATA;
+
+    if (!PnpGetLocalHandles(&BindingHandle, NULL))
+        return CR_FAILURE;
+
+    pNotifyData = HeapAlloc(GetProcessHeap(),
+                            HEAP_ZERO_MEMORY,
+                            sizeof(NOTIFY_DATA));
+    if (pNotifyData == NULL)
+        return CR_OUT_OF_MEMORY;
+
+    pNotifyData->ulMagic = NOTIFY_MAGIC;
+
+/*
+    if (dwFlags & DEVICE_NOTIFY_SERVICE_HANDLE == DEVICE_NOTYFY_WINDOW_HANDLE)
+    {
+
+    }
+    else if (dwFlags & DEVICE_NOTIFY_SERVICE_HANDLE == DEVICE_NOTYFY_SERVICE_HANDLE)
+    {
+
+    }
+*/
+
+    RpcTryExcept
+    {
+        ret = PNP_RegisterNotification(BindingHandle,
+                                       ulFlags,
+                                       &pNotifyData->ulNotifyData);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        ret = RpcStatusToCmStatus(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    if (ret == CR_SUCCESS)
+    {
+        *phDevNotify = (HDEVNOTIFY)pNotifyData;
+    }
+    else
+    {
+        if (pNotifyData != NULL)
+            HeapFree(GetProcessHeap(), 0, pNotifyData);
+
+        *phDevNotify = (HDEVNOTIFY)NULL;
+    }
+
+    return ret;
 }
 
 
 /***********************************************************************
  * CMP_Report_LogOn [SETUPAPI.@]
  */
-CONFIGRET WINAPI CMP_Report_LogOn(
-    DWORD dwMagic,
-    DWORD dwProcessId)
+CONFIGRET
+WINAPI
+CMP_Report_LogOn(
+    _In_ DWORD dwMagic,
+    _In_ DWORD dwProcessId)
 {
     RPC_BINDING_HANDLE BindingHandle = NULL;
     CONFIGRET ret = CR_SUCCESS;
     BOOL bAdmin;
     DWORD i;
 
-    TRACE("%lu\n", dwMagic);
+    TRACE("CMP_Report_LogOn(%lu %lu)\n", dwMagic, dwProcessId);
 
     if (dwMagic != CMP_MAGIC)
         return CR_INVALID_DATA;
@@ -183,22 +552,55 @@ CONFIGRET WINAPI CMP_Report_LogOn(
  */
 CONFIGRET
 WINAPI
-CMP_UnregisterNotification(IN HDEVNOTIFY handle)
+CMP_UnregisterNotification(
+    _In_ HDEVNOTIFY hDevNotify)
 {
-    FIXME("Stub %p\n", handle);
-    return CR_SUCCESS;
+    RPC_BINDING_HANDLE BindingHandle = NULL;
+    PNOTIFY_DATA pNotifyData;
+    CONFIGRET ret = CR_SUCCESS;
+
+    TRACE("CMP_UnregisterNotification(%p)\n", hDevNotify);
+
+    pNotifyData = (PNOTIFY_DATA)hDevNotify;
+
+    if ((pNotifyData == NULL) ||
+        (pNotifyData->ulMagic != NOTIFY_MAGIC))
+        return CR_INVALID_POINTER;
+
+    if (!PnpGetLocalHandles(&BindingHandle, NULL))
+        return CR_FAILURE;
+
+    RpcTryExcept
+    {
+        ret = PNP_UnregisterNotification(BindingHandle,
+                                         pNotifyData->ulNotifyData);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        ret = RpcStatusToCmStatus(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    if (ret == CR_SUCCESS)
+        HeapFree(GetProcessHeap(), 0, pNotifyData);
+
+    return ret;
 }
 
 
 /***********************************************************************
  * CMP_WaitNoPendingInstallEvents [SETUPAPI.@]
  */
-DWORD WINAPI CMP_WaitNoPendingInstallEvents(
-    DWORD dwTimeout)
+DWORD
+WINAPI
+CMP_WaitNoPendingInstallEvents(
+    _In_ DWORD dwTimeout)
 {
     HANDLE hEvent;
     DWORD ret;
 
+    TRACE("CMP_WaitNoPendingInstallEvents(%lu)\n", dwTimeout);
+
     hEvent = OpenEventW(SYNCHRONIZE, FALSE, L"Global\\PnP_No_Pending_Install_Events");
     if (hEvent == NULL)
        return WAIT_FAILED;
@@ -214,14 +616,26 @@ DWORD WINAPI CMP_WaitNoPendingInstallEvents(
  */
 CONFIGRET
 WINAPI
-CMP_WaitServicesAvailable(HMACHINE hMachine)
+CMP_WaitServicesAvailable(
+    _In_opt_ HMACHINE hMachine)
 {
     RPC_BINDING_HANDLE BindingHandle = NULL;
     CONFIGRET ret = CR_SUCCESS;
     WORD Version;
 
-    if (!PnpGetLocalHandles(&BindingHandle, NULL))
-        return CR_FAILURE;
+    TRACE("CMP_WaitServicesAvailable(%p)\n", hMachine);
+
+    if (hMachine != NULL)
+    {
+        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
+        if (BindingHandle == NULL)
+            return CR_FAILURE;
+    }
+    else
+    {
+        if (!PnpGetLocalHandles(&BindingHandle, NULL))
+            return CR_FAILURE;
+    }
 
     RpcTryExcept
     {
@@ -443,6 +857,23 @@ CONFIGRET WINAPI CM_Add_ID_ExW(
 }
 
 
+/***********************************************************************
+ * CM_Add_Range [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Add_Range(
+    _In_ DWORDLONG ullStartValue,
+    _In_ DWORDLONG ullEndValue,
+    _In_ RANGE_LIST rlh,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Add_Range(%I64u %I64u %p %lx)\n",
+          ullStartValue, ullEndValue, rlh, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /***********************************************************************
  * CM_Add_Res_Des [SETUPAPI.@]
  */
@@ -555,7 +986,7 @@ CONFIGRET WINAPI CM_Connect_MachineW(
         }
     }
 
-    phMachine = (PHMACHINE)pMachine;
+    *phMachine = (PHMACHINE)pMachine;
 
     return CR_SUCCESS;
 }
@@ -694,6 +1125,39 @@ CONFIGRET WINAPI CM_Create_DevNode_ExW(
 }
 
 
+/***********************************************************************
+ * CM_Create_Range_List [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Create_Range_List(
+    _Out_ PRANGE_LIST prlh,
+    _In_ ULONG ulFlags)
+{
+    PINTERNAL_RANGE_LIST pRangeList = NULL;
+
+    FIXME("CM_Create_Range_List(%p %lx)\n", prlh, ulFlags);
+
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
+
+    if (prlh == NULL)
+        return CR_INVALID_POINTER;
+
+    pRangeList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(INTERNAL_RANGE_LIST));
+    if (pRangeList == NULL)
+        return CR_OUT_OF_MEMORY;
+
+    pRangeList->ulMagic = RANGE_LIST_MAGIC;
+
+    // TODO: More initialization
+
+    *prlh = (RANGE_LIST)pRangeList;
+
+    return CR_SUCCESS;
+}
+
+
 /***********************************************************************
  * CM_Delete_Class_Key [SETUPAPI.@]
  */
@@ -780,6 +1244,23 @@ CONFIGRET WINAPI CM_Delete_DevNode_Key_Ex(
 }
 
 
+/***********************************************************************
+ * CM_Delete_Range [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Delete_Range(
+    _In_ DWORDLONG ullStartValue,
+    _In_ DWORDLONG ullEndValue,
+    _In_ RANGE_LIST rlh,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Delete_Range(%I64u %I64u %p %lx)\n",
+          ullStartValue, ullEndValue, rlh, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /***********************************************************************
  * CM_Disable_DevNode [SETUPAPI.@]
  */
@@ -879,6 +1360,22 @@ CONFIGRET WINAPI CM_Disconnect_Machine(HMACHINE hMachine)
 }
 
 
+/***********************************************************************
+ * CM_Dup_Range_List [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Dup_Range_List(
+    _In_ RANGE_LIST rlhOld,
+    _In_ RANGE_LIST rlhNew,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Dup_Range_List(%p %p %lx)\n",
+          rlhOld, rlhNew, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /***********************************************************************
  * CM_Enable_DevNode [SETUPAPI.@]
  */
@@ -1145,6 +1642,44 @@ CONFIGRET WINAPI CM_Enumerate_Enumerators_ExW(
 }
 
 
+/***********************************************************************
+ * CM_Find_Range [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Find_Range(
+    _Out_ PDWORDLONG pullStart,
+    _In_ DWORDLONG ullStart,
+    _In_ ULONG ulLength,
+    _In_ DWORDLONG ullAlignment,
+    _In_ DWORDLONG ullEnd,
+    _In_ RANGE_LIST rlh,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Find_Range(%p %I64u %lu %I64u %I64u %p %lx)\n",
+          pullStart, ullStart, ulLength, ullAlignment, ullEnd, rlh, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/***********************************************************************
+ * CM_First_Range [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_First_Range(
+    _In_ RANGE_LIST rlh,
+    _Out_ PDWORDLONG pullStart,
+    _Out_ PDWORDLONG pullEnd,
+    _Out_ PRANGE_ELEMENT preElement,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_First_Range(%p %p %p %p %lx)\n",
+          rlh, pullStart, pullEnd, preElement, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /***********************************************************************
  * CM_Free_Log_Conf [SETUPAPI.@]
  */
@@ -1229,7 +1764,36 @@ CONFIGRET WINAPI CM_Free_Log_Conf_Handle(
     if (pLogConfInfo == NULL || pLogConfInfo->ulMagic != LOG_CONF_MAGIC)
         return CR_INVALID_LOG_CONF;
 
-    HeapFree(GetProcessHeap(), 0, pLogConfInfo);
+    HeapFree(GetProcessHeap(), 0, pLogConfInfo);
+
+    return CR_SUCCESS;
+}
+
+
+/***********************************************************************
+ * CM_Free_Range_List [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Free_Range_List(
+    _In_ RANGE_LIST RangeList,
+    _In_ ULONG ulFlags)
+{
+    PINTERNAL_RANGE_LIST pRangeList;
+
+    FIXME("CM_Free_Range_List(%p %lx)\n", RangeList, ulFlags);
+
+    pRangeList = (PINTERNAL_RANGE_LIST)RangeList;
+
+    if (pRangeList == NULL || pRangeList->ulMagic != RANGE_LIST_MAGIC)
+        return CR_INVALID_RANGE_LIST;
+
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
+
+    // TODO: Free the list of ranges
+
+    HeapFree(GetProcessHeap(), 0, pRangeList);
 
     return CR_SUCCESS;
 }
@@ -1588,10 +2152,68 @@ CONFIGRET WINAPI CM_Get_Class_Registry_PropertyA(
     LPGUID ClassGuid, ULONG ulProperty, PULONG pulRegDataType,
     PVOID Buffer, PULONG pulLength, ULONG ulFlags, HMACHINE hMachine)
 {
-    FIXME("%p %lu %p %p %p %lx %lx\n",
+    PWSTR BufferW = NULL;
+    ULONG ulLength = 0;
+    ULONG ulType;
+    CONFIGRET ret;
+
+    TRACE("%p %lu %p %p %p %lx %lx\n",
           ClassGuid, ulProperty, pulRegDataType, Buffer, pulLength,
           ulFlags, hMachine);
-    return CR_CALL_NOT_IMPLEMENTED;
+
+    if (pulLength == NULL)
+        return CR_INVALID_POINTER;
+
+    if (ulProperty < CM_CRP_MIN || ulProperty > CM_CRP_MAX)
+        return CR_INVALID_PROPERTY;
+
+    ulType = GetRegistryPropertyType(ulProperty);
+    if (ulType == REG_SZ || ulType == REG_MULTI_SZ)
+    {
+        /* Get the required buffer size */
+        ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
+                                              NULL, &ulLength, ulFlags, hMachine);
+        if (ret != CR_BUFFER_SMALL)
+            return ret;
+
+        /* Allocate the unicode buffer */
+        BufferW = HeapAlloc(GetProcessHeap(), 0, ulLength);
+        if (BufferW == NULL)
+            return CR_OUT_OF_MEMORY;
+
+        /* Get the property */
+        ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
+                                              BufferW, &ulLength, ulFlags, hMachine);
+        if (ret != CR_SUCCESS)
+        {
+            HeapFree(GetProcessHeap(), 0, BufferW);
+            return ret;
+        }
+
+        /* Do W->A conversion */
+        *pulLength = WideCharToMultiByte(CP_ACP,
+                                         0,
+                                         BufferW,
+                                         lstrlenW(BufferW) + 1,
+                                         Buffer,
+                                         *pulLength,
+                                         NULL,
+                                         NULL);
+
+        /* Release the unicode buffer */
+        HeapFree(GetProcessHeap(), 0, BufferW);
+
+        if (*pulLength == 0)
+            ret = CR_FAILURE;
+    }
+    else
+    {
+        /* Get the property */
+        ret = CM_Get_Class_Registry_PropertyW(ClassGuid, ulProperty, pulRegDataType,
+                                              Buffer, pulLength, ulFlags, hMachine);
+    }
+
+    return ret;
 }
 
 
@@ -3781,13 +4403,50 @@ WORD WINAPI CM_Get_Version_Ex(HMACHINE hMachine)
 }
 
 
+/***********************************************************************
+ * CM_Intersect_Range_List [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Intersect_Range_List(
+    _In_ RANGE_LIST rlhOld1,
+    _In_ RANGE_LIST rlhOld2,
+    _In_ RANGE_LIST rlhNew,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Intersect_Range_List(%p %p %p %lx)\n",
+          rlhOld1, rlhOld2, rlhNew, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/***********************************************************************
+ * CM_Invert_Range_List [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Invert_Range_List(
+    _In_ RANGE_LIST rlhOld,
+    _In_ RANGE_LIST rlhNew,
+    _In_ DWORDLONG ullMaxValue,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Invert_Range_List(%p %p %I64u %lx)\n",
+          rlhOld, rlhNew, ullMaxValue, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /***********************************************************************
  * CM_Is_Dock_Station_Present [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Is_Dock_Station_Present(
-    PBOOL pbPresent)
+CONFIGRET
+WINAPI
+CM_Is_Dock_Station_Present(
+    _Out_ PBOOL pbPresent)
 {
-    TRACE("%p\n", pbPresent);
+    TRACE("CM_Is_Dock_Station_Present(%p)\n",
+          pbPresent);
     return CM_Is_Dock_Station_Present_Ex(pbPresent, NULL);
 }
 
@@ -3795,13 +4454,17 @@ CONFIGRET WINAPI CM_Is_Dock_Station_Present(
 /***********************************************************************
  * CM_Is_Dock_Station_Present_Ex [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Is_Dock_Station_Present_Ex(
-    PBOOL pbPresent, HMACHINE hMachine)
+CONFIGRET
+WINAPI
+CM_Is_Dock_Station_Present_Ex(
+    _Out_ PBOOL pbPresent,
+    _In_opt_ HMACHINE hMachine)
 {
     RPC_BINDING_HANDLE BindingHandle = NULL;
     CONFIGRET ret;
 
-    TRACE("%p %lx\n", pbPresent, hMachine);
+    TRACE("CM_Is_Dock_Station_Present_Ex(%p %lx)\n",
+          pbPresent, hMachine);
 
     if (pbPresent == NULL)
         return CR_INVALID_POINTER;
@@ -3838,10 +4501,13 @@ CONFIGRET WINAPI CM_Is_Dock_Station_Present_Ex(
 /***********************************************************************
  * CM_Is_Version_Available_Ex [SETUPAPI.@]
  */
-BOOL WINAPI CM_Is_Version_Available(
-     WORD wVersion)
+BOOL
+WINAPI
+CM_Is_Version_Available(
+     _In_ WORD wVersion)
 {
-    TRACE("%hu\n", wVersion);
+    TRACE("CM_Is_Version_Available(%hu)\n",
+          wVersion);
     return CM_Is_Version_Available_Ex(wVersion, NULL);
 }
 
@@ -3849,14 +4515,18 @@ BOOL WINAPI CM_Is_Version_Available(
 /***********************************************************************
  * CM_Is_Version_Available_Ex [SETUPAPI.@]
  */
-BOOL WINAPI CM_Is_Version_Available_Ex(
-    WORD wVersion, HMACHINE hMachine)
+BOOL
+WINAPI
+CM_Is_Version_Available_Ex(
+    _In_ WORD wVersion,
+    _In_opt_ HMACHINE hMachine)
 {
     RPC_BINDING_HANDLE BindingHandle = NULL;
     WORD wServerVersion;
     CONFIGRET ret;
 
-    TRACE("%hu %lx\n", wVersion, hMachine);
+    TRACE("CM_Is_Version_Available_Ex(%hu %lx)\n",
+          wVersion, hMachine);
 
     if (wVersion <= 0x400)
         return TRUE;
@@ -3893,10 +4563,15 @@ BOOL WINAPI CM_Is_Version_Available_Ex(
 /***********************************************************************
  * CM_Locate_DevNodeA [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Locate_DevNodeA(
-    PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags)
+CONFIGRET
+WINAPI
+CM_Locate_DevNodeA(
+    _Out_ PDEVINST pdnDevInst,
+    _In_opt_ DEVINSTID_A pDeviceID,
+    _In_ ULONG ulFlags)
 {
-    TRACE("%p %s %lu\n", pdnDevInst, pDeviceID, ulFlags);
+    TRACE("CM_Locate_DevNodeA(%p %s %lu)\n",
+          pdnDevInst, pDeviceID, ulFlags);
     return CM_Locate_DevNode_ExA(pdnDevInst, pDeviceID, ulFlags, NULL);
 }
 
@@ -3904,10 +4579,15 @@ CONFIGRET WINAPI CM_Locate_DevNodeA(
 /***********************************************************************
  * CM_Locate_DevNodeW [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Locate_DevNodeW(
-    PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags)
+CONFIGRET
+WINAPI
+CM_Locate_DevNodeW(
+    _Out_ PDEVINST pdnDevInst,
+    _In_opt_ DEVINSTID_W pDeviceID,
+    _In_ ULONG ulFlags)
 {
-    TRACE("%p %s %lu\n", pdnDevInst, debugstr_w(pDeviceID), ulFlags);
+    TRACE("CM_Locate_DevNodeW(%p %s %lu)\n",
+          pdnDevInst, debugstr_w(pDeviceID), ulFlags);
     return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL);
 }
 
@@ -3915,13 +4595,19 @@ CONFIGRET WINAPI CM_Locate_DevNodeW(
 /***********************************************************************
  * CM_Locate_DevNode_ExA [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Locate_DevNode_ExA(
-    PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags, HMACHINE hMachine)
+CONFIGRET
+WINAPI
+CM_Locate_DevNode_ExA(
+    _Out_ PDEVINST pdnDevInst,
+    _In_opt_ DEVINSTID_A pDeviceID,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
 {
     DEVINSTID_W pDevIdW = NULL;
     CONFIGRET ret = CR_SUCCESS;
 
-    TRACE("%p %s %lu %lx\n", pdnDevInst, pDeviceID, ulFlags, hMachine);
+    TRACE("CM_Locate_DevNode_ExA(%p %s %lu %lx)\n",
+          pdnDevInst, pDeviceID, ulFlags, hMachine);
 
     if (pDeviceID != NULL)
     {
@@ -3941,15 +4627,21 @@ CONFIGRET WINAPI CM_Locate_DevNode_ExA(
 /***********************************************************************
  * CM_Locate_DevNode_ExW [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Locate_DevNode_ExW(
-    PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags, HMACHINE hMachine)
+CONFIGRET
+WINAPI
+CM_Locate_DevNode_ExW(
+    _Out_ PDEVINST pdnDevInst,
+    _In_opt_ DEVINSTID_W pDeviceID,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
 {
     WCHAR DeviceIdBuffer[MAX_DEVICE_ID_LEN];
     RPC_BINDING_HANDLE BindingHandle = NULL;
     HSTRING_TABLE StringTable = NULL;
     CONFIGRET ret = CR_SUCCESS;
 
-    TRACE("%p %s %lu %lx\n", pdnDevInst, debugstr_w(pDeviceID), ulFlags, hMachine);
+    TRACE("CM_Locate_DevNode_ExW(%p %s %lu %lx)\n",
+          pdnDevInst, debugstr_w(pDeviceID), ulFlags, hMachine);
 
     if (pdnDevInst == NULL)
         return CR_INVALID_POINTER;
@@ -4021,14 +4713,38 @@ CONFIGRET WINAPI CM_Locate_DevNode_ExW(
 }
 
 
+/***********************************************************************
+ * CM_Merge_Range_List [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Merge_Range_List(
+    _In_ RANGE_LIST rlhOld1,
+    _In_ RANGE_LIST rlhOld2,
+    _In_ RANGE_LIST rlhNew,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Merge_Range_List(%p %p %p %lx)\n",
+          rlhOld1, rlhOld2, rlhNew, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /***********************************************************************
  * CM_Modify_Res_Des [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Modify_Res_Des(
-    PRES_DES prdResDes, RES_DES rdResDes, RESOURCEID ResourceID,
-    PCVOID ResourceData, ULONG ResourceLen, ULONG ulFlags)
-{
-    TRACE("%p %p %lx %p %lu %lx", prdResDes, rdResDes, ResourceID, ResourceData,
+CONFIGRET
+WINAPI
+CM_Modify_Res_Des(
+    _Out_ PRES_DES prdResDes,
+    _In_ RES_DES rdResDes,
+    _In_ RESOURCEID ResourceID,
+    _In_ PCVOID ResourceData,
+    _In_ ULONG ResourceLen,
+    _In_ ULONG ulFlags)
+{
+    TRACE("CM_Modify_Res_Des(%p %p %lx %p %lu %lx)\n",
+          prdResDes, rdResDes, ResourceID, ResourceData,
           ResourceLen, ulFlags);
     return CM_Modify_Res_Des_Ex(prdResDes, rdResDes, ResourceID, ResourceData,
                                 ResourceLen, ulFlags, NULL);
@@ -4038,11 +4754,19 @@ CONFIGRET WINAPI CM_Modify_Res_Des(
 /***********************************************************************
  * CM_Modify_Res_Des_Ex [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Modify_Res_Des_Ex(
-    PRES_DES prdResDes, RES_DES rdResDes, RESOURCEID ResourceID, PCVOID ResourceData,
-    ULONG ResourceLen, ULONG ulFlags, HMACHINE hMachine)
-{
-    FIXME("%p %p %lx %p %lu %lx %lx", prdResDes, rdResDes, ResourceID, ResourceData,
+CONFIGRET
+WINAPI
+CM_Modify_Res_Des_Ex(
+    _Out_ PRES_DES prdResDes,
+    _In_ RES_DES rdResDes,
+    _In_ RESOURCEID ResourceID,
+    _In_ PCVOID ResourceData,
+    _In_ ULONG ResourceLen,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
+{
+    FIXME("CM_Modify_Res_Des_Ex(%p %p %lx %p %lu %lx %lx)\n",
+          prdResDes, rdResDes, ResourceID, ResourceData,
           ResourceLen, ulFlags, hMachine);
     return CR_CALL_NOT_IMPLEMENTED;
 }
@@ -4051,10 +4775,15 @@ CONFIGRET WINAPI CM_Modify_Res_Des_Ex(
 /***********************************************************************
  * CM_Move_DevNode [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Move_DevNode(
-    DEVINST dnFromDevInst, DEVINST dnToDevInst, ULONG ulFlags)
+CONFIGRET
+WINAPI
+CM_Move_DevNode(
+    _In_ DEVINST dnFromDevInst,
+    _In_ DEVINST dnToDevInst,
+    _In_ ULONG ulFlags)
 {
-    TRACE("%lx %lx %lx\n", dnFromDevInst, dnToDevInst, ulFlags);
+    TRACE("CM_Move_DevNode(%lx %lx %lx)\n",
+          dnFromDevInst, dnToDevInst, ulFlags);
     return CM_Move_DevNode_Ex(dnFromDevInst, dnToDevInst, ulFlags, NULL);
 }
 
@@ -4062,9 +4791,13 @@ CONFIGRET WINAPI CM_Move_DevNode(
 /***********************************************************************
  * CM_Move_DevNode_Ex [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Move_DevNode_Ex(
-    DEVINST dnFromDevInst, DEVINST dnToDevInst, ULONG ulFlags,
-    HMACHINE hMachine)
+CONFIGRET
+WINAPI
+CM_Move_DevNode_Ex(
+    _In_ DEVINST dnFromDevInst,
+    _In_ DEVINST dnToDevInst,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
 {
     RPC_BINDING_HANDLE BindingHandle = NULL;
     HSTRING_TABLE StringTable = NULL;
@@ -4072,7 +4805,7 @@ CONFIGRET WINAPI CM_Move_DevNode_Ex(
     LPWSTR lpToDevInst;
     CONFIGRET ret;
 
-    FIXME("%lx %lx %lx %lx\n",
+    FIXME("CM_Move_DevNode_Ex(%lx %lx %lx %lx)\n",
           dnFromDevInst, dnToDevInst, ulFlags, hMachine);
 
     if (!pSetupIsUserAdmin())
@@ -4126,14 +4859,37 @@ CONFIGRET WINAPI CM_Move_DevNode_Ex(
 }
 
 
+/***********************************************************************
+ * CM_Next_Range [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Next_Range(
+    _Inout_ PRANGE_ELEMENT preElement,
+    _Out_ PDWORDLONG pullStart,
+    _Out_ PDWORDLONG pullEnd,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Next_Range(%p %p %p %lx)\n",
+          preElement, pullStart, pullEnd, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /***********************************************************************
  * CM_Open_Class_KeyA [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Open_Class_KeyA(
-    LPGUID pClassGuid, LPCSTR pszClassName, REGSAM samDesired,
-    REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags)
-{
-    TRACE("%p %s %lx %lx %p %lx\n",
+CONFIGRET
+WINAPI
+CM_Open_Class_KeyA(
+    _In_opt_ LPGUID pClassGuid,
+    _In_opt_ LPCSTR pszClassName,
+    _In_ REGSAM samDesired,
+    _In_ REGDISPOSITION Disposition,
+    _Out_ PHKEY phkClass,
+    _In_ ULONG ulFlags)
+{
+    TRACE("CM_Open_Class_KeyA(%p %s %lx %lx %p %lx)\n",
           debugstr_guid(pClassGuid), pszClassName,
           samDesired, Disposition, phkClass, ulFlags);
 
@@ -4145,11 +4901,17 @@ CONFIGRET WINAPI CM_Open_Class_KeyA(
 /***********************************************************************
  * CM_Open_Class_KeyW [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Open_Class_KeyW(
-    LPGUID pClassGuid, LPCWSTR pszClassName, REGSAM samDesired,
-    REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags)
-{
-    TRACE("%p %s %lx %lx %p %lx\n",
+CONFIGRET
+WINAPI
+CM_Open_Class_KeyW(
+    _In_opt_ LPGUID pClassGuid,
+    _In_opt_ LPCWSTR pszClassName,
+    _In_ REGSAM samDesired,
+    _In_ REGDISPOSITION Disposition,
+    _Out_ PHKEY phkClass,
+    _In_ ULONG ulFlags)
+{
+    TRACE("CM_Open_Class_KeyW%p %s %lx %lx %p %lx)\n",
           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
           samDesired, Disposition, phkClass, ulFlags);
 
@@ -4161,15 +4923,21 @@ CONFIGRET WINAPI CM_Open_Class_KeyW(
 /***********************************************************************
  * CM_Open_Class_Key_ExA [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Open_Class_Key_ExA(
-    LPGUID pClassGuid, LPCSTR pszClassName, REGSAM samDesired,
-    REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags,
-    HMACHINE hMachine)
+CONFIGRET
+WINAPI
+CM_Open_Class_Key_ExA(
+    _In_opt_ LPGUID pClassGuid,
+    _In_opt_ LPCSTR pszClassName,
+    _In_ REGSAM samDesired,
+    _In_ REGDISPOSITION Disposition,
+    _Out_ PHKEY phkClass,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
 {
     LPWSTR pszClassNameW = NULL;
     CONFIGRET ret;
 
-    TRACE("%p %s %lx %lx %p %lx %lx\n",
+    TRACE("CM_Open_Class_Key_ExA(%p %s %lx %lx %p %lx %lx)\n",
           debugstr_guid(pClassGuid), pszClassName,
           samDesired, Disposition, phkClass, ulFlags, hMachine);
 
@@ -4192,10 +4960,16 @@ CONFIGRET WINAPI CM_Open_Class_Key_ExA(
 /***********************************************************************
  * CM_Open_Class_Key_ExW [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Open_Class_Key_ExW(
-    LPGUID pClassGuid, LPCWSTR pszClassName, REGSAM samDesired,
-    REGDISPOSITION Disposition, PHKEY phkClass, ULONG ulFlags,
-    HMACHINE hMachine)
+CONFIGRET
+WINAPI
+CM_Open_Class_Key_ExW(
+    _In_opt_ LPGUID pClassGuid,
+    _In_opt_ LPCWSTR pszClassName,
+    _In_ REGSAM samDesired,
+    _In_ REGDISPOSITION Disposition,
+    _Out_ PHKEY phkClass,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
 {
     WCHAR szKeyName[MAX_PATH];
     LPWSTR lpGuidString;
@@ -4203,7 +4977,7 @@ CONFIGRET WINAPI CM_Open_Class_Key_ExW(
     DWORD dwError;
     HKEY hKey;
 
-    TRACE("%p %s %lx %lx %p %lx %lx\n",
+    TRACE("CM_Open_Class_Key_ExW(%p %s %lx %lx %p %lx %lx)\n",
           debugstr_guid(pClassGuid), debugstr_w(pszClassName),
           samDesired, Disposition, phkClass, ulFlags, hMachine);
 
@@ -4288,12 +5062,18 @@ CONFIGRET WINAPI CM_Open_Class_Key_ExW(
 /***********************************************************************
  * CM_Open_DevNode_Key [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Open_DevNode_Key(
-    DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile,
-    REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags)
-{
-    TRACE("%lx %lx %lu %lx %p %lx\n", dnDevNode, samDesired,
-          ulHardwareProfile, Disposition, phkDevice, ulFlags);
+CONFIGRET
+WINAPI
+CM_Open_DevNode_Key(
+    _In_ DEVINST dnDevNode,
+    _In_ REGSAM samDesired,
+    _In_ ULONG ulHardwareProfile,
+    _In_ REGDISPOSITION Disposition,
+    _Out_ PHKEY phkDevice,
+    _In_ ULONG ulFlags)
+{
+    TRACE("CM_Open_DevNode_Key(%lx %lx %lu %lx %p %lx)\n",
+          dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags);
     return CM_Open_DevNode_Key_Ex(dnDevNode, samDesired, ulHardwareProfile,
                                   Disposition, phkDevice, ulFlags, NULL);
 }
@@ -4302,15 +5082,115 @@ CONFIGRET WINAPI CM_Open_DevNode_Key(
 /***********************************************************************
  * CM_Open_DevNode_Key_Ex [SETUPAPI.@]
  */
-CONFIGRET WINAPI CM_Open_DevNode_Key_Ex(
-    DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile,
-    REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags,
-    HMACHINE hMachine)
+CONFIGRET
+WINAPI
+CM_Open_DevNode_Key_Ex(
+    _In_ DEVINST dnDevNode,
+    _In_ REGSAM samDesired,
+    _In_ ULONG ulHardwareProfile,
+    _In_ REGDISPOSITION Disposition,
+    _Out_ PHKEY phkDevice,
+    _In_ ULONG ulFlags,
+    _In_opt_ HMACHINE hMachine)
 {
-    FIXME("%lx %lx %lu %lx %p %lx %lx\n", dnDevNode, samDesired,
-          ulHardwareProfile, Disposition, phkDevice, ulFlags, hMachine);
+    RPC_BINDING_HANDLE BindingHandle = NULL;
+    HSTRING_TABLE StringTable = NULL;
+    LPWSTR pszDevInst, pszKeyPath = NULL, pszInstancePath = NULL;
+    LONG lError;
+    CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
 
-    return CR_CALL_NOT_IMPLEMENTED;
+    FIXME("CM_Open_DevNode_Key_Ex(%lx %lx %lu %lx %p %lx %lx)\n",
+          dnDevNode, samDesired, ulHardwareProfile, Disposition, phkDevice, ulFlags, hMachine);
+
+    if (phkDevice == NULL)
+        return CR_INVALID_POINTER;
+
+    *phkDevice = NULL;
+
+    if (dnDevNode == 0)
+        return CR_INVALID_DEVNODE;
+
+    if (ulFlags & ~CM_REGISTRY_BITS)
+        return CR_INVALID_FLAG;
+
+    if (Disposition & ~RegDisposition_Bits)
+        return CR_INVALID_DATA;
+
+    if (hMachine != NULL)
+    {
+        BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle;
+        if (BindingHandle == NULL)
+            return CR_FAILURE;
+
+        StringTable = ((PMACHINE_INFO)hMachine)->StringTable;
+        if (StringTable == 0)
+            return CR_FAILURE;
+    }
+    else
+    {
+        if (!PnpGetLocalHandles(&BindingHandle, &StringTable))
+            return CR_FAILURE;
+    }
+
+    pszDevInst = pSetupStringTableStringFromId(StringTable, dnDevNode);
+    if (pszDevInst == NULL)
+        return CR_INVALID_DEVNODE;
+
+    TRACE("pszDevInst: %S\n", pszDevInst);
+
+    pszKeyPath = MyMalloc(1024);
+    if (pszKeyPath == NULL)
+    {
+        ret = CR_OUT_OF_MEMORY;
+        goto done;
+    }
+
+    pszInstancePath = MyMalloc(1024);
+    if (pszInstancePath == NULL)
+    {
+        ret = CR_OUT_OF_MEMORY;
+        goto done;
+    }
+
+    ret = GetDeviceInstanceKeyPath(BindingHandle,
+                                   pszDevInst,
+                                   pszKeyPath,
+                                   pszInstancePath,
+                                   ulHardwareProfile,
+                                   ulFlags);
+    if (ret != CR_SUCCESS)
+        goto done;
+
+    TRACE("pszKeyPath: %S\n", pszKeyPath);
+    TRACE("pszInstancePath: %S\n", pszInstancePath);
+
+    wcscat(pszKeyPath, L"\\");
+    wcscat(pszKeyPath, pszInstancePath);
+
+    TRACE("pszKeyPath: %S\n", pszKeyPath);
+
+    // FIXME: Disposition
+    // FIXME: hMachine
+
+    lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                           pszKeyPath,
+                           0,
+                           samDesired,
+                           phkDevice);
+    if (lError != ERROR_SUCCESS)
+    {
+        *phkDevice = NULL;
+        ret = CR_NO_SUCH_REGISTRY_KEY;
+    }
+
+done:
+    if (pszInstancePath != NULL)
+        MyFree(pszInstancePath);
+
+    if (pszKeyPath != NULL)
+        MyFree(pszKeyPath);
+
+    return ret;
 }
 
 
@@ -5334,6 +6214,9 @@ CONFIGRET WINAPI CM_Set_DevNode_Registry_Property_ExA(
     if (Buffer == NULL && ulLength != 0)
         return CR_INVALID_POINTER;
 
+    if (ulProperty < CM_DRP_MIN || ulProperty > CM_DRP_MAX)
+        return CR_INVALID_PROPERTY;
+
     if (Buffer == NULL)
     {
         ret = CM_Set_DevNode_Registry_Property_ExW(dnDevInst,
@@ -5346,87 +6229,7 @@ CONFIGRET WINAPI CM_Set_DevNode_Registry_Property_ExA(
     else
     {
         /* Get property type */
-        switch (ulProperty)
-        {
-            case CM_DRP_DEVICEDESC:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_HARDWAREID:
-                ulType = REG_MULTI_SZ;
-                break;
-
-            case CM_DRP_COMPATIBLEIDS:
-                ulType = REG_MULTI_SZ;
-                break;
-
-            case CM_DRP_SERVICE:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_CLASS:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_CLASSGUID:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_DRIVER:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_CONFIGFLAGS:
-                ulType = REG_DWORD;
-                break;
-
-            case CM_DRP_MFG:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_FRIENDLYNAME:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_LOCATION_INFORMATION:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_UPPERFILTERS:
-                ulType = REG_MULTI_SZ;
-                break;
-
-            case CM_DRP_LOWERFILTERS:
-                ulType = REG_MULTI_SZ;
-                break;
-
-            case CM_DRP_SECURITY:
-                ulType = REG_BINARY;
-                break;
-
-            case CM_DRP_DEVTYPE:
-                ulType = REG_DWORD;
-                break;
-
-            case CM_DRP_EXCLUSIVE:
-                ulType = REG_DWORD;
-                break;
-
-            case CM_DRP_CHARACTERISTICS:
-                ulType = REG_DWORD;
-                break;
-
-            case CM_DRP_UI_NUMBER_DESC_FORMAT:
-                ulType = REG_SZ;
-                break;
-
-            case CM_DRP_REMOVAL_POLICY_OVERRIDE:
-                ulType = REG_DWORD;
-                break;
-
-            default:
-                return CR_INVALID_PROPERTY;
-        }
+        ulType = GetRegistryPropertyType(ulProperty);
 
         /* Allocate buffer if needed */
         if (ulType == REG_SZ ||
@@ -5522,87 +6325,8 @@ CONFIGRET WINAPI CM_Set_DevNode_Registry_Property_ExW(
     if (lpDevInst == NULL)
         return CR_INVALID_DEVNODE;
 
-    switch (ulProperty)
-    {
-        case CM_DRP_DEVICEDESC:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_HARDWAREID:
-            ulType = REG_MULTI_SZ;
-            break;
-
-        case CM_DRP_COMPATIBLEIDS:
-            ulType = REG_MULTI_SZ;
-            break;
-
-        case CM_DRP_SERVICE:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_CLASS:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_CLASSGUID:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_DRIVER:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_CONFIGFLAGS:
-            ulType = REG_DWORD;
-            break;
-
-        case CM_DRP_MFG:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_FRIENDLYNAME:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_LOCATION_INFORMATION:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_UPPERFILTERS:
-            ulType = REG_MULTI_SZ;
-            break;
-
-        case CM_DRP_LOWERFILTERS:
-            ulType = REG_MULTI_SZ;
-            break;
-
-        case CM_DRP_SECURITY:
-            ulType = REG_BINARY;
-            break;
-
-        case CM_DRP_DEVTYPE:
-            ulType = REG_DWORD;
-            break;
-
-        case CM_DRP_EXCLUSIVE:
-            ulType = REG_DWORD;
-            break;
-
-        case CM_DRP_CHARACTERISTICS:
-            ulType = REG_DWORD;
-            break;
-
-        case CM_DRP_UI_NUMBER_DESC_FORMAT:
-            ulType = REG_SZ;
-            break;
-
-        case CM_DRP_REMOVAL_POLICY_OVERRIDE:
-            ulType = REG_DWORD;
-            break;
-
-        default:
-            return CR_INVALID_PROPERTY;
-    }
+    /* Get property type */
+    ulType = GetRegistryPropertyType(ulProperty);
 
     RpcTryExcept
     {
@@ -5854,6 +6578,23 @@ CONFIGRET WINAPI CM_Setup_DevNode_Ex(
 }
 
 
+/***********************************************************************
+ * CM_Test_Range_Available [SETUPAPI.@]
+ */
+CONFIGRET
+WINAPI
+CM_Test_Range_Available(
+    _In_ DWORDLONG ullStartValue,
+    _In_ DWORDLONG ullEndValue,
+    _In_ RANGE_LIST rlh,
+    _In_ ULONG ulFlags)
+{
+    FIXME("CM_Test_Range_Available(%I64u %I64u %p %lx)\n",
+          ullStartValue, ullEndValue, rlh, ulFlags);
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /***********************************************************************
  * CM_Uninstall_DevNode [SETUPAPI.@]
  */