[UMPNPMGR][USETUP] Use PlugPlayControlStartDevice in usetup and umpnpmgr
[reactos.git] / base / services / umpnpmgr / rpcserver.c
index bef58c8..cf49713 100644 (file)
@@ -36,7 +36,7 @@
 
 /* GLOBALS ******************************************************************/
 
-static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
+static WCHAR szRootDeviceInstanceID[] = L"HTREE\\ROOT\\0";
 
 
 /* FUNCTIONS *****************************************************************/
@@ -191,10 +191,40 @@ SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
 }
 
 
+static
+CONFIGRET
+ClearDeviceStatus(
+    _In_ LPWSTR pszDeviceID,
+    _In_ DWORD ulStatus,
+    _In_ DWORD ulProblem)
+{
+    PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
+    CONFIGRET ret = CR_SUCCESS;
+    NTSTATUS Status;
+
+    DPRINT1("ClearDeviceStatus(%S 0x%lx 0x%lx)\n",
+            pszDeviceID, ulStatus, ulProblem);
+
+    RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
+                         pszDeviceID);
+    PlugPlayData.Operation = PNP_CLEAR_DEVICE_STATUS;
+    PlugPlayData.DeviceStatus = ulStatus;
+    PlugPlayData.DeviceProblem = ulProblem;
+
+    Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
+                               (PVOID)&PlugPlayData,
+                               sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
+    if (!NT_SUCCESS(Status))
+        ret = NtStatusToCrError(Status);
+
+    return ret;
+}
+
+
 static
 CONFIGRET
 GetDeviceStatus(
-    _In_ LPWSTR pDeviceID,
+    _In_ LPWSTR pszDeviceID,
     _Out_ DWORD *pulStatus,
     _Out_ DWORD *pulProblem)
 {
@@ -203,11 +233,11 @@ GetDeviceStatus(
     NTSTATUS Status;
 
     DPRINT("GetDeviceStatus(%S %p %p)\n",
-           pDeviceID, pulStatus, pulProblem);
+           pszDeviceID, pulStatus, pulProblem);
 
     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
-                         pDeviceID);
-    PlugPlayData.Operation = 0; /* Get status */
+                         pszDeviceID);
+    PlugPlayData.Operation = PNP_GET_DEVICE_STATUS;
 
     Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
                                (PVOID)&PlugPlayData,
@@ -226,6 +256,285 @@ GetDeviceStatus(
 }
 
 
+static
+CONFIGRET
+SetDeviceStatus(
+    _In_ LPWSTR pszDeviceID,
+    _In_ DWORD ulStatus,
+    _In_ DWORD ulProblem)
+{
+    PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
+    CONFIGRET ret = CR_SUCCESS;
+    NTSTATUS Status;
+
+    DPRINT1("SetDeviceStatus(%S 0x%lx 0x%lx)\n",
+            pszDeviceID, ulStatus, ulProblem);
+
+    RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
+                         pszDeviceID);
+    PlugPlayData.Operation = PNP_SET_DEVICE_STATUS;
+    PlugPlayData.DeviceStatus = ulStatus;
+    PlugPlayData.DeviceProblem = ulProblem;
+
+    Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
+                               (PVOID)&PlugPlayData,
+                               sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
+    if (!NT_SUCCESS(Status))
+        ret = NtStatusToCrError(Status);
+
+    return ret;
+}
+
+
+static
+CONFIGRET
+DisableDeviceInstance(
+    _In_ LPWSTR pszDeviceInstance,
+    _Inout_opt_ PPNP_VETO_TYPE pVetoType,
+    _Inout_opt_ LPWSTR pszVetoName,
+    _In_ DWORD ulNameLength)
+{
+    PLUGPLAY_CONTROL_QUERY_REMOVE_DATA QueryRemoveData;
+    CONFIGRET ret = CR_SUCCESS;
+    NTSTATUS Status;
+
+    DPRINT1("DisableDeviceInstance(%S %p %p %lu)\n",
+            pszDeviceInstance, pVetoType, pszVetoName, ulNameLength);
+
+    RtlInitUnicodeString(&QueryRemoveData.DeviceInstance,
+                         pszDeviceInstance);
+
+    QueryRemoveData.Flags = 0;
+    QueryRemoveData.VetoType = 0;
+    QueryRemoveData.VetoName = pszVetoName;
+    QueryRemoveData.NameLength = ulNameLength;
+
+    Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
+                               &QueryRemoveData,
+                               sizeof(PLUGPLAY_CONTROL_QUERY_REMOVE_DATA));
+    if (Status == STATUS_NO_SUCH_DEVICE)
+    {
+        ret = CR_INVALID_DEVNODE;
+    }
+    else if (Status == STATUS_PLUGPLAY_QUERY_VETOED)
+    {
+        if (pVetoType != NULL)
+            *pVetoType = QueryRemoveData.VetoType;
+
+        ret = CR_REMOVE_VETOED;
+    }
+    else if (!NT_SUCCESS(Status))
+    {
+        ret = NtStatusToCrError(Status);
+    }
+
+    return ret;
+}
+
+
+static
+BOOL
+IsValidDeviceInstanceID(
+    _In_ PWSTR pszDeviceInstanceID)
+{
+    INT nPartLength[3] = {0, 0, 0};
+    INT nLength = 0, nParts = 0;
+    PWCHAR p;
+
+    DPRINT("IsValidDeviceInstanceID(%S)\n",
+           pszDeviceInstanceID);
+
+    if (pszDeviceInstanceID == NULL)
+    {
+        DPRINT("Device instance ID is NULL!\n");
+        return FALSE;
+    }
+
+    p = pszDeviceInstanceID;
+    while (*p != UNICODE_NULL)
+    {
+        if (*p == L'\\')
+        {
+            nParts++;
+            if (nParts >= 3)
+            {
+                DPRINT("Too many separators: %d\n", nParts);
+                return FALSE;
+            }
+        }
+        else
+        {
+            nPartLength[nParts]++;
+        }
+
+        nLength++;
+        if (nLength >= MAX_DEVICE_ID_LEN)
+        {
+            DPRINT("Too long: %d\n", nLength);
+            return FALSE;
+        }
+
+        p++;
+    }
+
+    if (nParts != 2)
+    {
+        DPRINT("Invalid number of separtors: %d\n", nParts);
+        return FALSE;
+    }
+
+    if ((nPartLength[0] == 0) ||
+        (nPartLength[1] == 0) ||
+        (nPartLength[2] == 0))
+    {
+        DPRINT("Invalid part lengths: %d %d %d\n",
+               nPartLength[0], nPartLength[1], nPartLength[2]);
+        return FALSE;
+    }
+
+    DPRINT("Valid device instance ID!\n");
+
+    return TRUE;
+}
+
+
+static
+BOOL
+IsRootDeviceInstanceID(
+    _In_ PWSTR pszDeviceInstanceID)
+{
+    if (_wcsicmp(pszDeviceInstanceID, szRootDeviceInstanceID) == 0)
+        return TRUE;
+
+    return FALSE;
+}
+
+
+static
+CONFIGRET
+OpenConfigurationKey(
+    _In_ LPCWSTR pszDeviceID,
+    _Out_ PHKEY phKey)
+{
+    WCHAR szKeyName[MAX_PATH];
+    HKEY hInstanceKey;
+    DWORD dwError;
+
+    /* Build the full device instance key name */
+    wcscpy(szKeyName, L"System\\CurrentControlSet\\Enum\\");
+    wcscat(szKeyName, pszDeviceID);
+
+    /* Open the device instance key */
+    dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                            szKeyName,
+                            0,
+                            KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY,
+                            &hInstanceKey);
+    if (dwError != ERROR_SUCCESS)
+        return CR_INVALID_DEVINST;
+
+    /* Create or open the LogConf key */
+    dwError = RegCreateKeyExW(hInstanceKey,
+                              L"LogConf",
+                              0,
+                              NULL,
+                              REG_OPTION_NON_VOLATILE,
+                              KEY_ALL_ACCESS,
+                              NULL,
+                              phKey,
+                              NULL);
+
+    /* Close the device instance key */
+    RegCloseKey(hInstanceKey);
+
+    if (dwError != ERROR_SUCCESS)
+        return CR_REGISTRY_ERROR;
+
+    return CR_SUCCESS;
+}
+
+
+static
+CONFIGRET
+GetConfigurationData(
+    _In_ HKEY hKey,
+    _In_ ULONG ulLogConfType,
+    _Out_ PULONG pulRegDataType,
+    _Out_ PULONG pulDataSize,
+    _Out_ LPBYTE *ppBuffer)
+{
+    LPCWSTR pszValueName;
+
+    switch (ulLogConfType)
+    {
+        case BOOT_LOG_CONF:
+            pszValueName = L"BootConfig";
+            *pulRegDataType = REG_RESOURCE_LIST;
+            break;
+
+        case ALLOC_LOG_CONF:
+            pszValueName = L"AllocConfig";
+            *pulRegDataType = REG_RESOURCE_LIST;
+            break;
+
+        case FORCED_LOG_CONF:
+            pszValueName = L"ForcedConfig";
+            *pulRegDataType = REG_RESOURCE_LIST;
+            break;
+
+        case FILTERED_LOG_CONF:
+            pszValueName = L"FilteredConfigVector";
+            *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
+            break;
+
+        case BASIC_LOG_CONF:
+            pszValueName = L"BasicConfigVector";
+            *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
+            break;
+
+        case OVERRIDE_LOG_CONF:
+            pszValueName = L"OverrideConfigVector";
+            *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
+            break;
+
+        default:
+            DPRINT1("Unsupported configuration type!\n");
+            return CR_FAILURE;
+    }
+
+    /* Get the configuration data size */
+    if (RegQueryValueExW(hKey,
+                         pszValueName,
+                         NULL,
+                         NULL,
+                         NULL,
+                         pulDataSize) != ERROR_SUCCESS)
+    {
+        return CR_INVALID_LOG_CONF;
+    }
+
+    /* Allocate the buffer */
+    *ppBuffer = HeapAlloc(GetProcessHeap(), 0, *pulDataSize);
+    if (*ppBuffer == NULL)
+    {
+        return CR_OUT_OF_MEMORY;
+    }
+
+    /* Retrieve the configuration data */
+    if (RegQueryValueExW(hKey,
+                         pszValueName,
+                         NULL,
+                         NULL,
+                         (LPBYTE)*ppBuffer,
+                         pulDataSize) != ERROR_SUCCESS)
+    {
+        return CR_INVALID_LOG_CONF;
+    }
+
+    return CR_SUCCESS;
+}
+
+
 /* PUBLIC FUNCTIONS **********************************************************/
 
 /* Function 0 */
@@ -259,7 +568,11 @@ PNP_GetVersion(
 {
     UNREFERENCED_PARAMETER(hBinding);
 
+    DPRINT("PNP_GetVersion(%p %p)\n",
+           hBinding, pVersion);
+
     *pVersion = 0x0400;
+
     return CR_SUCCESS;
 }
 
@@ -275,7 +588,11 @@ PNP_GetGlobalState(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(ulFlags);
 
+    DPRINT("PNP_GetGlobalState(%p %p 0x%08lx)\n",
+           hBinding, pulState, ulFlags);
+
     *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
+
     return CR_SUCCESS;
 }
 
@@ -288,7 +605,9 @@ PNP_InitDetection(
 {
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_InitDetection() called\n");
+    DPRINT("PNP_InitDetection(%p)\n",
+           hBinding);
+
     return CR_SUCCESS;
 }
 
@@ -307,7 +626,8 @@ PNP_ReportLogOn(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(Admin);
 
-    DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
+    DPRINT("PNP_ReportLogOn(%p %u, %u)\n",
+           hBinding, Admin, ProcessId);
 
     /* Get the users token */
     hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
@@ -358,8 +678,11 @@ PNP_ValidateDeviceInstance(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
-           pDeviceID, ulFlags);
+    DPRINT("PNP_ValidateDeviceInstance(%p %S 0x%08lx)\n",
+           hBinding, pDeviceID, ulFlags);
+
+    if (!IsValidDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
 
     if (RegOpenKeyExW(hEnumKey,
                       pDeviceID,
@@ -396,21 +719,23 @@ PNP_GetRootDeviceInstance(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_GetRootDeviceInstance() called\n");
+    DPRINT("PNP_GetRootDeviceInstance(%p %S %lu)\n",
+           hBinding, pDeviceID, ulLength);
 
     if (!pDeviceID)
     {
         ret = CR_INVALID_POINTER;
         goto Done;
     }
-    if (ulLength < lstrlenW(szRootDeviceId) + 1)
+
+    if (ulLength < lstrlenW(szRootDeviceInstanceID) + 1)
     {
         ret = CR_BUFFER_SMALL;
         goto Done;
     }
 
     lstrcpyW(pDeviceID,
-             szRootDeviceId);
+             szRootDeviceInstanceID);
 
 Done:
     DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
@@ -437,9 +762,12 @@ PNP_GetRelatedDeviceInstance(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT("PNP_GetRelatedDeviceInstance() called\n");
-    DPRINT("  Relationship %ld\n", ulRelationship);
-    DPRINT("  DeviceId %S\n", pDeviceID);
+    DPRINT("PNP_GetRelatedDeviceInstance(%p %lu %S %p %p 0x%lx)\n",
+           hBinding, ulRelationship, pDeviceID, pRelatedDeviceId,
+           pulLength, ulFlags);
+
+    if (!IsValidDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
 
     RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
                          pDeviceID);
@@ -486,7 +814,9 @@ PNP_EnumerateSubKeys(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT("PNP_EnumerateSubKeys() called\n");
+    DPRINT("PNP_EnumerateSubKeys(%p %lu %lu %p %lu %p 0x%08lx)\n",
+           hBinding, ulBranch, ulIndex, Buffer, ulLength,
+           pulRequiredLen, ulFlags);
 
     switch (ulBranch)
     {
@@ -901,7 +1231,8 @@ PNP_GetDeviceList(
     WCHAR szInstance[MAX_DEVICE_ID_LEN];
     CONFIGRET ret = CR_SUCCESS;
 
-    DPRINT("PNP_GetDeviceList() called\n");
+    DPRINT("PNP_GetDeviceList(%p %S %p %p 0x%08lx)\n",
+           hBinding, pszFilter, Buffer, pulLength, ulFlags);
 
     if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
         return CR_INVALID_FLAG;
@@ -1270,7 +1601,7 @@ PNP_GetDeviceListSize(
     WCHAR szInstance[MAX_DEVICE_ID_LEN];
     CONFIGRET ret = CR_SUCCESS;
 
-    DPRINT("PNP_GetDeviceListSize(%p %S %p 0x%lx)\n",
+    DPRINT("PNP_GetDeviceListSize(%p %S %p 0x%08lx)\n",
            hBinding, pszFilter, pulLength, ulFlags);
 
     if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
@@ -1347,7 +1678,11 @@ PNP_GetDepth(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT("PNP_GetDepth() called\n");
+    DPRINT("PNP_GetDepth(%p %S %p 0x%08lx)\n",
+           hBinding, pszDeviceID, pulDepth, ulFlags);
+
+    if (!IsValidDeviceInstanceID(pszDeviceID))
+        return CR_INVALID_DEVINST;
 
     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
                          pszDeviceID);
@@ -1392,7 +1727,9 @@ PNP_GetDeviceRegProp(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_GetDeviceRegProp() called\n");
+    DPRINT("PNP_GetDeviceRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n",
+           hBinding, pDeviceID, ulProperty, pulRegDataType, Buffer,
+           pulTransferLen, pulLength, ulFlags);
 
     if (pulTransferLen == NULL || pulLength == NULL)
     {
@@ -1406,7 +1743,12 @@ PNP_GetDeviceRegProp(
         goto done;
     }
 
-    /* FIXME: Check pDeviceID */
+    /* Check pDeviceID */
+    if (!IsValidDeviceInstanceID(pDeviceID))
+    {
+        ret = CR_INVALID_DEVINST;
+        goto done;
+    }
 
     if (*pulLength < *pulTransferLen)
         *pulLength = *pulTransferLen;
@@ -1461,6 +1803,7 @@ PNP_GetDeviceRegProp(
 
         case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
             PlugPlayData.Property = PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME;
+            *pulRegDataType = REG_SZ;
             break;
 
         case CM_DRP_CAPABILITIES:
@@ -1481,18 +1824,22 @@ PNP_GetDeviceRegProp(
 
         case CM_DRP_BUSTYPEGUID:
             PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID;
+            *pulRegDataType = REG_BINARY;
             break;
 
         case CM_DRP_LEGACYBUSTYPE:
             PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE;
+            *pulRegDataType = REG_DWORD;
             break;
 
         case CM_DRP_BUSNUMBER:
             PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER;
+            *pulRegDataType = REG_DWORD;
             break;
 
         case CM_DRP_ENUMERATOR_NAME:
             PlugPlayData.Property = PNP_PROPERTY_ENUMERATOR_NAME;
+            *pulRegDataType = REG_SZ;
             break;
 
         case CM_DRP_SECURITY:
@@ -1513,6 +1860,7 @@ PNP_GetDeviceRegProp(
 
         case CM_DRP_ADDRESS:
             PlugPlayData.Property = PNP_PROPERTY_ADDRESS;
+            *pulRegDataType = REG_DWORD;
             break;
 
         case CM_DRP_UI_NUMBER_DESC_FORMAT:
@@ -1521,33 +1869,40 @@ PNP_GetDeviceRegProp(
 
         case CM_DRP_DEVICE_POWER_DATA:
             PlugPlayData.Property = PNP_PROPERTY_POWER_DATA;
+            *pulRegDataType = REG_BINARY;
             break;
 
         case CM_DRP_REMOVAL_POLICY:
             PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY;
+            *pulRegDataType = REG_DWORD;
             break;
 
         case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
             PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT;
+            *pulRegDataType = REG_DWORD;
             break;
 
         case CM_DRP_REMOVAL_POLICY_OVERRIDE:
             lpValueName = L"RemovalPolicy";
+            *pulRegDataType = REG_DWORD;
             break;
 
         case CM_DRP_INSTALL_STATE:
             PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE;
+            *pulRegDataType = REG_DWORD;
             break;
 
 #if (WINVER >= _WIN32_WINNT_WS03)
         case CM_DRP_LOCATION_PATHS:
             PlugPlayData.Property = PNP_PROPERTY_LOCATION_PATHS;
+            *pulRegDataType = REG_MULTI_SZ;
             break;
 #endif
 
 #if (WINVER >= _WIN32_WINNT_WIN7)
         case CM_DRP_BASE_CONTAINERID:
             PlugPlayData.Property = PNP_PROPERTY_CONTAINERID;
+            *pulRegDataType = REG_SZ;
             break;
 #endif
 
@@ -1646,12 +2001,12 @@ PNP_SetDeviceRegProp(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT("PNP_SetDeviceRegProp() called\n");
+    DPRINT("PNP_SetDeviceRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n",
+           hBinding, pDeviceId, ulProperty, ulDataType, Buffer,
+           ulLength, ulFlags);
 
-    DPRINT("DeviceId: %S\n", pDeviceId);
-    DPRINT("Property: %lu\n", ulProperty);
-    DPRINT("DataType: %lu\n", ulDataType);
-    DPRINT("Length: %lu\n", ulLength);
+    if (!IsValidDeviceInstanceID(pDeviceId))
+        return CR_INVALID_DEVINST;
 
     switch (ulProperty)
     {
@@ -1790,6 +2145,9 @@ PNP_GetClassInstance(
     DPRINT("PNP_GetClassInstance(%p %S %p %lu)\n",
            hBinding, pDeviceId, pszClassInstance, ulLength);
 
+    if (!IsValidDeviceInstanceID(pDeviceId))
+        return CR_INVALID_DEVINST;
+
     ulTransferLength = ulLength;
     ret = PNP_GetDeviceRegProp(hBinding,
                                pDeviceId,
@@ -1891,24 +2249,58 @@ PNP_CreateKey(
     DWORD samDesired,
     DWORD ulFlags)
 {
-    HKEY hKey = 0;
+    HKEY hDeviceKey = NULL, hParametersKey = NULL;
+    DWORD dwError;
+    CONFIGRET ret = CR_SUCCESS;
 
-    if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
-                        pszSubKey,
-                        0,
-                        NULL,
-                        0,
-                        KEY_ALL_ACCESS,
-                        NULL,
-                        &hKey,
-                        NULL))
-        return CR_REGISTRY_ERROR;
+    UNREFERENCED_PARAMETER(hBinding);
+    UNREFERENCED_PARAMETER(samDesired);
 
-    /* FIXME: Set security key */
+    DPRINT("PNP_CreateKey(%p %S 0x%lx 0x%08lx)\n",
+           hBinding, pszSubKey, samDesired, ulFlags);
 
-    RegCloseKey(hKey);
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
 
-    return CR_SUCCESS;
+    if (!IsValidDeviceInstanceID(pszSubKey))
+        return CR_INVALID_DEVINST;
+
+    dwError = RegOpenKeyExW(hEnumKey,
+                            pszSubKey,
+                            0,
+                            KEY_WRITE,
+                            &hDeviceKey);
+    if (dwError != ERROR_SUCCESS)
+    {
+        ret = CR_INVALID_DEVNODE;
+        goto done;
+    }
+
+    dwError = RegCreateKeyExW(hDeviceKey,
+                              L"Device Parameters",
+                              0,
+                              NULL,
+                              REG_OPTION_NON_VOLATILE,
+                              KEY_ALL_ACCESS,
+                              NULL,
+                              &hParametersKey,
+                              NULL);
+    if (dwError != ERROR_SUCCESS)
+    {
+        ret = CR_REGISTRY_ERROR;
+        goto done;
+    }
+
+    /* FIXME: Set key security */
+
+done:
+    if (hParametersKey != NULL)
+        RegCloseKey(hParametersKey);
+
+    if (hDeviceKey != NULL)
+        RegCloseKey(hDeviceKey);
+
+    return ret;
 }
 
 
@@ -1941,6 +2333,9 @@ PNP_GetClassCount(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(ulFlags);
 
+    DPRINT("PNP_GetClassCount(%p %p 0x%08lx)\n",
+           hBinding, pulClassCount, ulFlags);
+
     dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                             REGSTR_PATH_CLASS,
                             0,
@@ -1987,7 +2382,8 @@ PNP_GetClassName(
     UNREFERENCED_PARAMETER(hBinding);
     UNREFERENCED_PARAMETER(ulFlags);
 
-    DPRINT("PNP_GetClassName() called\n");
+    DPRINT("PNP_GetClassName(%p %S %p %p 0x%08lx)\n",
+           hBinding, pszClassGuid, Buffer, pulLength, ulFlags);
 
     lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
     if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
@@ -2038,7 +2434,8 @@ PNP_DeleteClassKey(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
+    DPRINT("PNP_DeleteClassKey(%p %S 0x%08lx)\n",
+           hBinding, pszClassGuid, ulFlags);
 
     if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
     {
@@ -2091,6 +2488,12 @@ PNP_GetInterfaceDeviceList(
 
     UNREFERENCED_PARAMETER(hBinding);
 
+    DPRINT("PNP_GetInterfaceDeviceList(%p %p %S %p %p 0x%08lx)\n",
+           hBinding, InterfaceGuid, pszDeviceID, Buffer, pulLength, ulFlags);
+
+    if (!IsValidDeviceInstanceID(pszDeviceID))
+        return CR_INVALID_DEVINST;
+
     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
                          pszDeviceID);
 
@@ -2111,7 +2514,7 @@ PNP_GetInterfaceDeviceList(
         ret = NtStatusToCrError(Status);
     }
 
-    DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret);
+    DPRINT("PNP_GetInterfaceDeviceList() done (returns %lx)\n", ret);
     return ret;
 }
 
@@ -2132,7 +2535,11 @@ PNP_GetInterfaceDeviceListSize(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_GetInterfaceDeviceListSize() called\n");
+    DPRINT("PNP_GetInterfaceDeviceListSize(%p %p %p %S 0x%08lx)\n",
+           hBinding, pulLen, InterfaceGuid, pszDeviceID, ulFlags);
+
+    if (!IsValidDeviceInstanceID(pszDeviceID))
+        return CR_INVALID_DEVINST;
 
     RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
                          pszDeviceID);
@@ -2211,7 +2618,9 @@ PNP_GetClassRegProp(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_GetClassRegProp() called\n");
+    DPRINT("PNP_GetClassRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n",
+           hBinding, pszClassGuid, ulProperty, pulRegDataType,
+           Buffer, pulTransferLen, pulLength, ulFlags);
 
     if (pulTransferLen == NULL || pulLength == NULL)
     {
@@ -2334,7 +2743,9 @@ PNP_SetClassRegProp(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_SetClassRegProp() called\n");
+    DPRINT("PNP_SetClassRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n",
+           hBinding, pszClassGuid, ulProperty, ulDataType,
+           Buffer, ulLength, ulFlags);
 
     if (ulFlags != 0)
         return CR_INVALID_FLAG;
@@ -2534,7 +2945,18 @@ PNP_CreateDevInst(
 {
     CONFIGRET ret = CR_SUCCESS;
 
-    DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID);
+    DPRINT("PNP_CreateDevInst(%p %S %S %lu 0x%08lx)\n",
+           hBinding, pszParentDeviceID, pszDeviceID, ulLength, ulFlags);
+
+    if (ulFlags & ~CM_CREATE_DEVNODE_BITS)
+        return CR_INVALID_FLAG;
+
+    if (pszDeviceID == NULL || pszParentDeviceID == NULL)
+        return CR_INVALID_POINTER;
+
+    /* Fail, if the parent device is not the root device */
+    if (!IsRootDeviceInstanceID(pszParentDeviceID))
+        return CR_INVALID_DEVINST;
 
     if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
     {
@@ -2581,36 +3003,92 @@ PNP_CreateDevInst(
 
 
 static CONFIGRET
-MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
-                   LPWSTR pszDeviceInstanceSource)
+SetupDeviceInstance(
+    _In_ LPWSTR pszDeviceInstance,
+    _In_ DWORD ulMinorAction)
 {
-    DPRINT("MoveDeviceInstance: not implemented\n");
-    /* FIXME */
-    return CR_CALL_NOT_IMPLEMENTED;
-}
+    HKEY hDeviceKey = NULL;
+    DWORD dwDisableCount, dwSize;
+    DWORD ulStatus, ulProblem;
+    DWORD dwError;
+    CONFIGRET ret = CR_SUCCESS;
 
+    DPRINT1("SetupDeviceInstance(%S 0x%08lx)\n",
+            pszDeviceInstance, ulMinorAction);
 
-static CONFIGRET
-SetupDeviceInstance(LPWSTR pszDeviceInstance,
-                    DWORD ulFlags)
-{
-    DPRINT("SetupDeviceInstance: not implemented\n");
-    /* FIXME */
-    return CR_CALL_NOT_IMPLEMENTED;
+    if (IsRootDeviceInstanceID(pszDeviceInstance))
+        return CR_INVALID_DEVINST;
+
+    if (ulMinorAction & ~CM_SETUP_BITS)
+        return CR_INVALID_FLAG;
+
+    if ((ulMinorAction == CM_SETUP_DOWNLOAD) ||
+        (ulMinorAction == CM_SETUP_WRITE_LOG_CONFS))
+        return CR_SUCCESS;
+
+    dwError = RegOpenKeyExW(hEnumKey,
+                            pszDeviceInstance,
+                            0,
+                            KEY_READ,
+                            &hDeviceKey);
+    if (dwError != ERROR_SUCCESS)
+        return CR_INVALID_DEVNODE;
+
+    dwSize = sizeof(dwDisableCount);
+    dwError = RegQueryValueExW(hDeviceKey,
+                               L"DisableCount",
+                               NULL,
+                               NULL,
+                               (LPBYTE)&dwDisableCount,
+                               &dwSize);
+    if ((dwError == ERROR_SUCCESS) &&
+        (dwDisableCount > 0))
+    {
+        goto done;
+    }
+
+    GetDeviceStatus(pszDeviceInstance,
+                    &ulStatus,
+                    &ulProblem);
+
+    if (ulStatus & DN_STARTED)
+    {
+        goto done;
+    }
+
+    if (ulStatus & DN_HAS_PROBLEM)
+    {
+        ret = ClearDeviceStatus(pszDeviceInstance,
+                                DN_HAS_PROBLEM,
+                                ulProblem);
+    }
+
+    if (ret != CR_SUCCESS)
+        goto done;
+
+
+    /* FIXME: Start the device */
+
+done:
+    if (hDeviceKey != NULL)
+        RegCloseKey(hDeviceKey);
+
+    return ret;
 }
 
 
 static CONFIGRET
-EnableDeviceInstance(LPWSTR pszDeviceInstance)
+EnableDeviceInstance(
+    _In_ LPWSTR pszDeviceInstance)
 {
-    PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
+    PLUGPLAY_CONTROL_DEVICE_CONTROL_DATA ControlData;
     CONFIGRET ret = CR_SUCCESS;
     NTSTATUS Status;
 
     DPRINT("Enable device instance %S\n", pszDeviceInstance);
 
-    RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
-    Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
+    RtlInitUnicodeString(&ControlData.DeviceInstance, pszDeviceInstance);
+    Status = NtPlugPlayControl(PlugPlayControlStartDevice, &ControlData, sizeof(ControlData));
     if (!NT_SUCCESS(Status))
         ret = NtStatusToCrError(Status);
 
@@ -2618,31 +3096,22 @@ EnableDeviceInstance(LPWSTR pszDeviceInstance)
 }
 
 
-static CONFIGRET
-DisableDeviceInstance(LPWSTR pszDeviceInstance)
-{
-    DPRINT("DisableDeviceInstance: not implemented\n");
-    /* FIXME */
-    return CR_CALL_NOT_IMPLEMENTED;
-}
-
-
 static CONFIGRET
 ReenumerateDeviceInstance(
     _In_ LPWSTR pszDeviceInstance,
-    _In_ ULONG ulFlags)
+    _In_ ULONG ulMinorAction)
 {
     PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData;
     CONFIGRET ret = CR_SUCCESS;
     NTSTATUS Status;
 
     DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n",
-           pszDeviceInstance, ulFlags);
+           pszDeviceInstance, ulMinorAction);
 
-    if (ulFlags & ~CM_REENUMERATE_BITS)
+    if (ulMinorAction & ~CM_REENUMERATE_BITS)
         return CR_INVALID_FLAG;
 
-    if (ulFlags & CM_REENUMERATE_RETRY_INSTALLATION)
+    if (ulMinorAction & CM_REENUMERATE_RETRY_INSTALLATION)
     {
         DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n");
     }
@@ -2666,8 +3135,8 @@ DWORD
 WINAPI
 PNP_DeviceInstanceAction(
     handle_t hBinding,
-    DWORD ulAction,
-    DWORD ulFlags,
+    DWORD ulMajorAction,
+    DWORD ulMinorAction,
     LPWSTR pszDeviceInstance1,
     LPWSTR pszDeviceInstance2)
 {
@@ -2675,35 +3144,28 @@ PNP_DeviceInstanceAction(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_DeviceInstanceAction() called\n");
+    DPRINT("PNP_DeviceInstanceAction(%p %lu 0x%08lx %S %S)\n",
+           hBinding, ulMajorAction, ulMinorAction,
+           pszDeviceInstance1, pszDeviceInstance2);
 
-    switch (ulAction)
+    switch (ulMajorAction)
     {
-        case PNP_DEVINST_MOVE:
-            ret = MoveDeviceInstance(pszDeviceInstance1,
-                                     pszDeviceInstance2);
-            break;
-
         case PNP_DEVINST_SETUP:
             ret = SetupDeviceInstance(pszDeviceInstance1,
-                                      ulFlags);
+                                      ulMinorAction);
             break;
 
         case PNP_DEVINST_ENABLE:
             ret = EnableDeviceInstance(pszDeviceInstance1);
             break;
 
-        case PNP_DEVINST_DISABLE:
-            ret = DisableDeviceInstance(pszDeviceInstance1);
-            break;
-
         case PNP_DEVINST_REENUMERATE:
             ret = ReenumerateDeviceInstance(pszDeviceInstance1,
-                                            ulFlags);
+                                            ulMinorAction);
             break;
 
         default:
-            DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
+            DPRINT1("Unknown device action %lu: not implemented\n", ulMajorAction);
             ret = CR_CALL_NOT_IMPLEMENTED;
     }
 
@@ -2729,6 +3191,9 @@ PNP_GetDeviceStatus(
     DPRINT("PNP_GetDeviceStatus(%p %S %p %p)\n",
            hBinding, pDeviceID, pulStatus, pulProblem, ulFlags);
 
+    if (!IsValidDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
+
     return GetDeviceStatus(pDeviceID, pulStatus, pulProblem);
 }
 
@@ -2758,10 +3223,25 @@ PNP_DisableDevInst(
     DWORD ulNameLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    UNREFERENCED_PARAMETER(hBinding);
+
+    DPRINT1("PNP_DisableDevInst(%p %S %p %p %lu 0x%08lx)\n",
+            hBinding, pDeviceID, pVetoType, pszVetoName, ulNameLength, ulFlags);
+
+    if (ulFlags & ~CM_DISABLE_BITS)
+        return CR_INVALID_FLAG;
+
+    if (!IsValidDeviceInstanceID(pDeviceID) ||
+        IsRootDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
+
+    return DisableDeviceInstance(pDeviceID,
+                                 pVetoType,
+                                 pszVetoName,
+                                 ulNameLength);
 }
 
+
 /* Function 33 */
 DWORD
 WINAPI
@@ -2835,10 +3315,8 @@ PNP_AddID(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT("PNP_AddID() called\n");
-    DPRINT("  DeviceInstance: %S\n", pszDeviceID);
-    DPRINT("  DeviceId: %S\n", pszID);
-    DPRINT("  Flags: %lx\n", ulFlags);
+    DPRINT("PNP_AddID(%p %S %S 0x%08lx)\n",
+           hBinding, pszDeviceID, pszID, ulFlags);
 
     if (RegOpenKeyExW(hEnumKey,
                       pszDeviceID,
@@ -2934,8 +3412,18 @@ PNP_RegisterDriver(
     LPWSTR pszDeviceID,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    DPRINT("PNP_RegisterDriver(%p %S 0x%lx)\n",
+           hBinding, pszDeviceID, ulFlags);
+
+    if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
+        return CR_INVALID_FLAG;
+
+    if (!IsValidDeviceInstanceID(pszDeviceID))
+        return CR_INVALID_DEVINST;
+
+    SetDeviceStatus(pszDeviceID, 0, 0);
+
+    return CR_SUCCESS;
 }
 
 
@@ -2961,6 +3449,10 @@ PNP_QueryRemove(
     if (ulFlags & ~CM_REMOVE_BITS)
         return CR_INVALID_FLAG;
 
+    if (!IsValidDeviceInstanceID(pszDeviceID) ||
+        IsRootDeviceInstanceID(pszDeviceID))
+        return CR_INVALID_DEVINST;
+
     if (pVetoType != NULL)
         *pVetoType = PNP_VetoTypeUnknown;
 
@@ -2972,6 +3464,7 @@ PNP_QueryRemove(
                          pszDeviceID);
     PlugPlayData.VetoName = pszVetoName;
     PlugPlayData.NameLength = ulNameLength;
+//    PlugPlayData.Flags =
 
     Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
                                &PlugPlayData,
@@ -2994,8 +3487,40 @@ PNP_RequestDeviceEject(
     DWORD ulNameLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData;
+    NTSTATUS Status;
+    DWORD ret = CR_SUCCESS;
+
+    DPRINT1("PNP_RequestDeviceEject(%p %S %p %p %lu 0x%lx)\n",
+            hBinding, pszDeviceID, pVetoType, pszVetoName,
+            ulNameLength, ulFlags);
+
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
+
+    if (!IsValidDeviceInstanceID(pszDeviceID))
+        return CR_INVALID_DEVINST;
+
+    if (pVetoType != NULL)
+        *pVetoType = PNP_VetoTypeUnknown;
+
+    if (pszVetoName != NULL && ulNameLength > 0)
+        *pszVetoName = UNICODE_NULL;
+
+    RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData));
+    RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
+                         pszDeviceID);
+    PlugPlayData.VetoName = pszVetoName;
+    PlugPlayData.NameLength = ulNameLength;
+//    PlugPlayData.Flags =
+
+    Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
+                               &PlugPlayData,
+                               sizeof(PlugPlayData));
+    if (!NT_SUCCESS(Status))
+        ret = NtStatusToCrError(Status);
+
+    return ret;
 }
 
 
@@ -3014,7 +3539,8 @@ PNP_IsDockStationPresent(
 
     UNREFERENCED_PARAMETER(hBinding);
 
-    DPRINT1("PNP_IsDockStationPresent() called\n");
+    DPRINT1("PNP_IsDockStationPresent(%p %p)\n",
+            hBinding, Present);
 
     *Present = FALSE;
 
@@ -3060,8 +3586,29 @@ WINAPI
 PNP_RequestEjectPC(
     handle_t hBinding)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    WCHAR szDockDeviceInstance[MAX_DEVICE_ID_LEN];
+    PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA DockData;
+    NTSTATUS Status;
+
+    DPRINT("PNP_RequestEjectPC(%p)\n", hBinding);
+
+    /* Retrieve the dock device */
+    DockData.DeviceInstanceLength = ARRAYSIZE(szDockDeviceInstance);
+    DockData.DeviceInstance = szDockDeviceInstance;
+
+    Status = NtPlugPlayControl(PlugPlayControlRetrieveDock,
+                               &DockData,
+                               sizeof(DockData));
+    if (!NT_SUCCESS(Status))
+        return NtStatusToCrError(Status);
+
+    /* Eject the dock device */
+    return PNP_RequestDeviceEject(hBinding,
+                                  szDockDeviceInstance,
+                                  NULL,
+                                  NULL,
+                                  0,
+                                  0);
 }
 
 
@@ -3089,6 +3636,9 @@ PNP_HwProfFlags(
 
     DPRINT("PNP_HwProfFlags() called\n");
 
+    if (!IsValidDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
+
     if (ulConfig == 0)
     {
         wcscpy(szKeyName,
@@ -3321,8 +3871,92 @@ PNP_GetFirstLogConf(
     DWORD *pulLogConfTag,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    HKEY hConfigKey = NULL;
+    DWORD RegDataType = 0;
+    ULONG ulDataSize = 0;
+    LPBYTE lpData = NULL;
+    CONFIGRET ret = CR_SUCCESS;
+
+    DPRINT("PNP_GetFirstLogConf(%p %S %lu %p 0x%08lx)\n",
+           hBinding, pDeviceID, ulLogConfType, pulLogConfTag, ulFlags);
+
+    if (pulLogConfTag == NULL)
+        return CR_INVALID_POINTER;
+
+    *pulLogConfTag = (DWORD)0;
+
+    if (ulFlags & ~LOG_CONF_BITS)
+        return CR_INVALID_FLAG;
+
+    if (!IsValidDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
+
+    ret = OpenConfigurationKey(pDeviceID,
+                               &hConfigKey);
+    if (ret != CR_SUCCESS)
+    {
+        DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    ret = GetConfigurationData(hConfigKey,
+                               ulLogConfType,
+                               &RegDataType,
+                               &ulDataSize,
+                               &lpData);
+    if (ret != CR_SUCCESS)
+    {
+        DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    DPRINT("Data size %lu\n", ulDataSize);
+    if (ulDataSize == 0 || lpData == NULL)
+    {
+        DPRINT1("No config data available!\n");
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    /* Get the first tag */
+    if (RegDataType == REG_RESOURCE_LIST)
+    {
+        DPRINT("REG_RESOURCE_LIST\n");
+
+        DPRINT("ResourceList->Count %lu\n", ((PCM_RESOURCE_LIST)lpData)->Count);
+        if (((PCM_RESOURCE_LIST)lpData)->Count == 0)
+        {
+            DPRINT1("No resource descriptors!\n");
+            ret = CR_NO_MORE_LOG_CONF;
+            goto done;
+        }
+
+        DPRINT("lpData %p\n", lpData);
+        DPRINT("&List[0] %p\n", &(((PCM_RESOURCE_LIST)lpData)->List[0]));
+
+        *pulLogConfTag = (DWORD)((DWORD_PTR)&(((PCM_RESOURCE_LIST)lpData)->List[0]) - (DWORD_PTR)lpData);
+        DPRINT("Offset (Tag): 0x%08lx\n", *pulLogConfTag);
+    }
+    else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
+    {
+        DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
+        /* FIXME */
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+done:
+    if (lpData != NULL)
+        HeapFree(GetProcessHeap(), 0, lpData);
+
+    if (hConfigKey != NULL)
+        RegCloseKey(hConfigKey);
+
+    DPRINT("PNP_GetFirstLogConf() returns %lu\n", ret);
+
+    return ret;
 }
 
 
@@ -3337,8 +3971,82 @@ PNP_GetNextLogConf(
     DWORD *pulNextTag,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    HKEY hConfigKey = NULL;
+    DWORD RegDataType = 0;
+    ULONG ulDataSize = 0;
+    LPBYTE lpData = NULL;
+    CONFIGRET ret = CR_SUCCESS;
+
+    DPRINT("PNP_GetNextLogConf(%p %S %lu %ul %p 0x%08lx)\n",
+           hBinding, pDeviceID, ulLogConfType, ulCurrentTag, pulNextTag, ulFlags);
+
+    if (pulNextTag == NULL)
+        return CR_INVALID_POINTER;
+
+    *pulNextTag = (DWORD)0;
+
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
+
+    if (!IsValidDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
+
+    ret = OpenConfigurationKey(pDeviceID,
+                               &hConfigKey);
+    if (ret != CR_SUCCESS)
+    {
+        DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    ret = GetConfigurationData(hConfigKey,
+                               ulLogConfType,
+                               &RegDataType,
+                               &ulDataSize,
+                               &lpData);
+    if (ret != CR_SUCCESS)
+    {
+        DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    DPRINT("Data size %lu\n", ulDataSize);
+
+    if (ulDataSize == 0 || lpData == NULL)
+    {
+        DPRINT1("No config data available!\n");
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    /* FIXME: Get the next tag */
+    if (RegDataType == REG_RESOURCE_LIST)
+    {
+        DPRINT1("FIXME: REG_RESOURCE_LIST\n");
+        /* FIXME */
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+    else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
+    {
+        DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
+        /* FIXME */
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+done:
+    if (lpData != NULL)
+        HeapFree(GetProcessHeap(), 0, lpData);
+
+    if (hConfigKey != NULL)
+        RegCloseKey(hConfigKey);
+
+    DPRINT("PNP_GetNextLogConf() returns %lu\n", ret);
+
+    return ret;
 }
 
 
@@ -3410,8 +4118,83 @@ PNP_GetNextResDes(
     DWORD *pulNextResTag,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    HKEY hConfigKey = NULL;
+    DWORD RegDataType = 0;
+    ULONG ulDataSize = 0;
+    LPBYTE lpData = NULL;
+    CONFIGRET ret = CR_SUCCESS;
+
+    DPRINT1("PNP_GetNextResDes(%p %S 0x%lx %lu %lu %ul %p %p 0x%08lx)\n",
+           hBinding, pDeviceID, ulLogConfTag, ulLogConfType, ResourceID,
+           ulResourceTag, pulNextResType, pulNextResTag, ulFlags);
+
+    if (pulNextResType == NULL)
+        return CR_INVALID_POINTER;
+
+    *pulNextResType = 0;
+
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
+
+    if (!IsValidDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
+
+    ret = OpenConfigurationKey(pDeviceID,
+                               &hConfigKey);
+    if (ret != CR_SUCCESS)
+    {
+        DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    ret = GetConfigurationData(hConfigKey,
+                               ulLogConfType,
+                               &RegDataType,
+                               &ulDataSize,
+                               &lpData);
+    if (ret != CR_SUCCESS)
+    {
+        DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    DPRINT1("Data size %lu\n", ulDataSize);
+
+    if (ulDataSize == 0 || lpData == NULL)
+    {
+        DPRINT1("No config data available!\n");
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+    /* Get the next resource descriptor */
+    if (RegDataType == REG_RESOURCE_LIST)
+    {
+        DPRINT1("FIXME: REG_RESOURCE_LIST\n");
+        /* FIXME */
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+    else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
+    {
+        DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
+        /* FIXME */
+        ret = CR_NO_MORE_LOG_CONF;
+        goto done;
+    }
+
+done:
+    if (lpData != NULL)
+        HeapFree(GetProcessHeap(), 0, lpData);
+
+    if (hConfigKey != NULL)
+        RegCloseKey(hConfigKey);
+
+    DPRINT1("PNP_GetNextResDes() returns %lu\n", ret);
+
+    return ret;
 }
 
 
@@ -3697,6 +4480,9 @@ PNP_GetCustomDevProp(
         goto done;
     }
 
+    if (!IsValidDeviceInstanceID(pDeviceID))
+        return CR_INVALID_DEVINST;
+
     if (*pulLength < *pulTransferLen)
         *pulLength = *pulTransferLen;