Synchronize with trunk.
[reactos.git] / base / services / umpnpmgr / umpnpmgr.c
index 64d8b45..1225426 100644 (file)
 /* INCLUDES *****************************************************************/
 //#define HAVE_SLIST_ENTRY_IMPLEMENTED
 #define WIN32_NO_STATUS
-#include <windows.h>
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+#include <stdarg.h>
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <winsvc.h>
 #include <stdio.h>
-#include <cmtypes.h>
 #include <cmfuncs.h>
 #include <rtlfuncs.h>
 #include <setypes.h>
 #include <umpnpmgr/sysguid.h>
-#include <wdmguid.h>
 #include <cfgmgr32.h>
 #include <regstr.h>
 #include <userenv.h>
-
-#include <rpc.h>
-#include <rpcdce.h>
-
-#include "pnp_s.h"
+#include <pnp_s.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -187,8 +187,7 @@ DWORD PNP_Disconnect(
     handle_t hBinding)
 {
     UNREFERENCED_PARAMETER(hBinding);
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    return CR_SUCCESS;
 }
 
 
@@ -197,8 +196,7 @@ DWORD PNP_Connect(
     handle_t hBinding)
 {
     UNREFERENCED_PARAMETER(hBinding);
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    return CR_SUCCESS;
 }
 
 
@@ -538,14 +536,33 @@ DWORD PNP_GetDeviceRegProp(
     PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
     CONFIGRET ret = CR_SUCCESS;
     LPWSTR lpValueName = NULL;
-    HKEY hKey = 0;
+    HKEY hKey = NULL;
+    LONG lError;
     NTSTATUS Status;
 
     UNREFERENCED_PARAMETER(hBinding);
-    UNREFERENCED_PARAMETER(ulFlags);
 
     DPRINT("PNP_GetDeviceRegProp() called\n");
 
+    if (pulTransferLen == NULL || pulLength == NULL)
+    {
+        ret = CR_INVALID_POINTER;
+        goto done;
+    }
+
+    if (ulFlags != 0)
+    {
+        ret = CR_INVALID_FLAG;
+        goto done;
+    }
+
+    /* FIXME: Check pDeviceID */
+
+    if (*pulLength < *pulTransferLen)
+        *pulLength = *pulTransferLen;
+
+    *pulTransferLen = 0;
+
     switch (ulProperty)
     {
         case CM_DRP_DEVICEDESC:
@@ -628,8 +645,65 @@ DWORD PNP_GetDeviceRegProp(
             lpValueName = NULL;
             break;
 
+        case CM_DRP_SECURITY:
+            lpValueName = L"Security";
+            break;
+
+        case CM_DRP_DEVTYPE:
+            lpValueName = L"DeviceType";
+            break;
+
+        case CM_DRP_EXCLUSIVE:
+            lpValueName = L"Exclusive";
+            break;
+
+        case CM_DRP_CHARACTERISTICS:
+            lpValueName = L"DeviceCharacteristics";
+            break;
+
+        case CM_DRP_ADDRESS:
+            lpValueName = NULL;
+            break;
+
+        case CM_DRP_UI_NUMBER_DESC_FORMAT:
+            lpValueName = L"UINumberDescFormat";
+            break;
+
+        case CM_DRP_DEVICE_POWER_DATA:
+            lpValueName = NULL;
+            break;
+
+        case CM_DRP_REMOVAL_POLICY:
+            lpValueName = NULL;
+            break;
+
+        case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
+            lpValueName = NULL;
+            break;
+
+        case CM_DRP_REMOVAL_POLICY_OVERRIDE:
+            lpValueName = L"RemovalPolicy";
+            break;
+
+        case CM_DRP_INSTALL_STATE:
+            lpValueName = NULL;
+            break;
+
+#if (WINVER >= _WIN32_WINNT_WS03)
+        case CM_DRP_LOCATION_PATHS:
+            lpValueName = NULL;
+            break;
+#endif
+
+#if (WINVER >= _WIN32_WINNT_WIN7)
+        case CM_DRP_BASE_CONTAINERID:
+            lpValueName = NULL;
+            break;
+#endif
+
         default:
-            return CR_INVALID_PROPERTY;
+            ret = CR_INVALID_PROPERTY;
+            goto done;
     }
 
     DPRINT("Value name: %S\n", lpValueName);
@@ -637,24 +711,37 @@ DWORD PNP_GetDeviceRegProp(
     if (lpValueName)
     {
         /* Retrieve information from the Registry */
-        if (RegOpenKeyExW(hEnumKey,
-                          pDeviceID,
-                          0,
-                          KEY_ALL_ACCESS,
-                          &hKey))
-            return CR_INVALID_DEVNODE;
-
-        if (RegQueryValueExW(hKey,
-                             lpValueName,
-                             NULL,
-                             pulRegDataType,
-                             Buffer,
-                             pulLength))
-            ret = CR_REGISTRY_ERROR;
-
-        /* FIXME: Check buffer size */
+        lError = RegOpenKeyExW(hEnumKey,
+                               pDeviceID,
+                               0,
+                               KEY_QUERY_VALUE,
+                               &hKey);
+        if (lError != ERROR_SUCCESS)
+        {
+            hKey = NULL;
+            *pulLength = 0;
+            ret = CR_INVALID_DEVNODE;
+            goto done;
+        }
 
-        RegCloseKey(hKey);
+        lError = RegQueryValueExW(hKey,
+                                  lpValueName,
+                                  NULL,
+                                  pulRegDataType,
+                                  Buffer,
+                                  pulLength);
+        if (lError != ERROR_SUCCESS)
+        {
+            if (lError == ERROR_MORE_DATA)
+            {
+                ret = CR_BUFFER_SMALL;
+            }
+            else
+            {
+                *pulLength = 0;
+                ret = CR_NO_SUCH_VALUE;
+            }
+        }
     }
     else
     {
@@ -662,36 +749,69 @@ DWORD PNP_GetDeviceRegProp(
         RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
                              pDeviceID);
         PlugPlayData.Buffer = Buffer;
-        PlugPlayData.BufferSize = *pulTransferLen;
+        PlugPlayData.BufferSize = *pulLength;
 
         switch (ulProperty)
         {
-#if 0
             case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
-                PlugPlayData.Property = DevicePropertyPhysicalDeviceObjectName;
+                PlugPlayData.Property = 0xb; // DevicePropertyPhysicalDeviceObjectName;
                 break;
 
             case CM_DRP_UI_NUMBER:
-                PlugPlayData.Property = DevicePropertyUINumber;
+                PlugPlayData.Property = 0x11; // DevicePropertyUINumber;
                 break;
 
             case CM_DRP_BUSTYPEGUID:
-                PlugPlayData.Property = DevicePropertyBusTypeGuid;
+                PlugPlayData.Property = 0xc; // DevicePropertyBusTypeGuid;
                 break;
 
             case CM_DRP_LEGACYBUSTYPE:
-                PlugPlayData.Property = DevicePropertyLegacyBusType;
+                PlugPlayData.Property = 0xd; // DevicePropertyLegacyBusType;
                 break;
 
             case CM_DRP_BUSNUMBER:
-                PlugPlayData.Property = DevicePropertyBusNumber;
+                PlugPlayData.Property = 0xe; // DevicePropertyBusNumber;
                 break;
-#endif
 
             case CM_DRP_ENUMERATOR_NAME:
-                PlugPlayData.Property = 15; //DevicePropertyEnumeratorName;
+                PlugPlayData.Property = 0xf; // DevicePropertyEnumeratorName;
+                break;
+
+            case CM_DRP_ADDRESS:
+                PlugPlayData.Property = 0x10; // DevicePropertyAddress;
+                break;
+
+#if 0
+            /* FIXME: This property is not supported by IoGetDeviceProperty */
+            case CM_DRP_DEVICE_POWER_DATA:
+#endif
+
+            case CM_DRP_REMOVAL_POLICY:
+                PlugPlayData.Property = 0x12; // DevicePropertyRemovalPolicy
                 break;
 
+#if 0
+            /* FIXME: This property is not supported by IoGetDeviceProperty */
+            case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
+#endif
+
+            case CM_DRP_INSTALL_STATE:
+                PlugPlayData.Property = 0x12; // DevicePropertyInstallState;
+                break;
+
+#if 0
+            /* FIXME: This property is not supported by IoGetDeviceProperty */
+#if (WINVER >= _WIN32_WINNT_WS03)
+            case CM_DRP_LOCATION_PATHS:
+#endif
+#endif
+
+#if (WINVER >= _WIN32_WINNT_WIN7)
+            case CM_DRP_BASE_CONTAINERID:
+                PlugPlayData.Property = 0x16; // DevicePropertyContainerID;
+                break;
+#endif
+
             default:
                 return CR_INVALID_PROPERTY;
         }
@@ -709,6 +829,12 @@ DWORD PNP_GetDeviceRegProp(
         }
     }
 
+done:
+    *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
+
+    if (hKey != NULL)
+        RegCloseKey(hKey);
+
     DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
 
     return ret;
@@ -793,6 +919,30 @@ DWORD PNP_SetDeviceRegProp(
             lpValueName = L"LowerFilters";
             break;
 
+        case CM_DRP_SECURITY:
+            lpValueName = L"Security";
+            break;
+
+        case CM_DRP_DEVTYPE:
+            lpValueName = L"DeviceType";
+            break;
+
+        case CM_DRP_EXCLUSIVE:
+            lpValueName = L"Exclusive";
+            break;
+
+        case CM_DRP_CHARACTERISTICS:
+            lpValueName = L"DeviceCharacteristics";
+            break;
+
+        case CM_DRP_UI_NUMBER_DESC_FORMAT:
+            lpValueName = L"UINumberDescFormat";
+            break;
+
+        case CM_DRP_REMOVAL_POLICY_OVERRIDE:
+            lpValueName = L"RemovalPolicy";
+            break;
+
         default:
             return CR_INVALID_PROPERTY;
     }
@@ -802,7 +952,7 @@ DWORD PNP_SetDeviceRegProp(
     if (RegOpenKeyExW(hEnumKey,
                       pDeviceId,
                       0,
-                      KEY_ALL_ACCESS, /* FIXME: so much? */
+                      KEY_SET_VALUE,
                       &hKey))
         return CR_INVALID_DEVNODE;
 
@@ -1087,23 +1237,365 @@ DWORD PNP_GetClassRegProp(
     PNP_RPC_STRING_LEN *pulLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    CONFIGRET ret = CR_SUCCESS;
+    LPWSTR lpValueName = NULL;
+    HKEY hInstKey = NULL;
+    HKEY hPropKey = NULL;
+    LONG lError;
+
+    UNREFERENCED_PARAMETER(hBinding);
+
+    DPRINT("PNP_GetClassRegProp() called\n");
+
+    if (pulTransferLen == NULL || pulLength == NULL)
+    {
+        ret = CR_INVALID_POINTER;
+        goto done;
+    }
+
+    if (ulFlags != 0)
+    {
+        ret = CR_INVALID_FLAG;
+        goto done;
+    }
+
+    if (*pulLength < *pulTransferLen)
+        *pulLength = *pulTransferLen;
+
+    *pulTransferLen = 0;
+
+    switch (ulProperty)
+    {
+        case CM_CRP_SECURITY:
+            lpValueName = L"Security";
+            break;
+
+        case CM_CRP_DEVTYPE:
+            lpValueName = L"DeviceType";
+            break;
+
+        case CM_CRP_EXCLUSIVE:
+            lpValueName = L"Exclusive";
+            break;
+
+        case CM_CRP_CHARACTERISTICS:
+            lpValueName = L"DeviceCharacteristics";
+            break;
+
+        default:
+            ret = CR_INVALID_PROPERTY;
+            goto done;
+    }
+
+    DPRINT("Value name: %S\n", lpValueName);
+
+    lError = RegOpenKeyExW(hClassKey,
+                           pszClassGuid,
+                           0,
+                           KEY_READ,
+                           &hInstKey);
+    if (lError != ERROR_SUCCESS)
+    {
+        *pulLength = 0;
+        ret = CR_NO_SUCH_REGISTRY_KEY;
+        goto done;
+    }
+
+    lError = RegOpenKeyExW(hInstKey,
+                           L"Properties",
+                           0,
+                           KEY_READ,
+                           &hPropKey);
+    if (lError != ERROR_SUCCESS)
+    {
+        *pulLength = 0;
+        ret = CR_NO_SUCH_REGISTRY_KEY;
+        goto done;
+    }
+
+    lError = RegQueryValueExW(hPropKey,
+                              lpValueName,
+                              NULL,
+                              pulRegDataType,
+                              Buffer,
+                              pulLength);
+    if (lError != ERROR_SUCCESS)
+    {
+        if (lError == ERROR_MORE_DATA)
+        {
+            ret = CR_BUFFER_SMALL;
+        }
+        else
+        {
+            *pulLength = 0;
+            ret = CR_NO_SUCH_VALUE;
+        }
+    }
+
+done:;
+    if (ret == CR_SUCCESS)
+        *pulTransferLen = *pulLength;
+
+    if (hPropKey != NULL)
+        RegCloseKey(hPropKey);
+
+    if (hInstKey != NULL)
+        RegCloseKey(hInstKey);
+
+    DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
+
+    return ret;
 }
 
 
 /* Function 27 */
 DWORD PNP_SetClassRegProp(
     handle_t hBinding,
-    LPWSTR *pszClassGuid,
+    LPWSTR pszClassGuid,
     DWORD ulProperty,
     DWORD ulDataType,
     BYTE *Buffer,
     PNP_PROP_SIZE ulLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    CONFIGRET ret = CR_SUCCESS;
+    LPWSTR lpValueName = NULL;
+    HKEY hInstKey = 0;
+    HKEY hPropKey = 0;
+    LONG lError;
+
+    UNREFERENCED_PARAMETER(hBinding);
+
+    DPRINT("PNP_SetClassRegProp() called\n");
+
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
+
+    switch (ulProperty)
+    {
+        case CM_CRP_SECURITY:
+            lpValueName = L"Security";
+            break;
+
+        case CM_CRP_DEVTYPE:
+            lpValueName = L"DeviceType";
+            break;
+
+        case CM_CRP_EXCLUSIVE:
+            lpValueName = L"Exclusive";
+            break;
+
+        case CM_CRP_CHARACTERISTICS:
+            lpValueName = L"DeviceCharacteristics";
+            break;
+
+        default:
+            return CR_INVALID_PROPERTY;
+    }
+
+    lError = RegOpenKeyExW(hClassKey,
+                           pszClassGuid,
+                           0,
+                           KEY_WRITE,
+                           &hInstKey);
+    if (lError != ERROR_SUCCESS)
+    {
+        ret = CR_NO_SUCH_REGISTRY_KEY;
+        goto done;
+    }
+
+    /* FIXME: Set security descriptor */
+    lError = RegCreateKeyExW(hInstKey,
+                             L"Properties",
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             KEY_ALL_ACCESS,
+                             NULL,
+                             &hPropKey,
+                             NULL);
+    if (lError != ERROR_SUCCESS)
+    {
+        ret = CR_REGISTRY_ERROR;
+        goto done;
+    }
+
+    if (ulLength == 0)
+    {
+        if (RegDeleteValueW(hPropKey,
+                            lpValueName))
+            ret = CR_REGISTRY_ERROR;
+    }
+    else
+    {
+        if (RegSetValueExW(hPropKey,
+                           lpValueName,
+                           0,
+                           ulDataType,
+                           Buffer,
+                           ulLength))
+            ret = CR_REGISTRY_ERROR;
+    }
+
+done:;
+    if (hPropKey != NULL)
+        RegCloseKey(hPropKey);
+
+    if (hInstKey != NULL)
+        RegCloseKey(hInstKey);
+
+    return ret;
+}
+
+
+static VOID
+SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
+                      OUT LPWSTR pszEnumerator,
+                      OUT LPWSTR pszDevice,
+                      OUT LPWSTR pszInstance)
+{
+    WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
+    LPWSTR lpEnumerator = NULL;
+    LPWSTR lpDevice = NULL;
+    LPWSTR lpInstance = NULL;
+    LPWSTR ptr;
+
+    wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
+
+    *pszEnumerator = 0;
+    *pszDevice = 0;
+    *pszInstance = 0;
+
+    lpEnumerator = szLocalDeviceInstanceID;
+
+    ptr = wcschr(lpEnumerator, L'\\');
+    if (ptr != NULL)
+    {
+        *ptr = 0;
+        lpDevice = ++ptr;
+
+        ptr = wcschr(lpDevice, L'\\');
+        if (ptr != NULL)
+        {
+            *ptr = 0;
+            lpInstance = ++ptr;
+        }
+    }
+
+    if (lpEnumerator != NULL)
+        wcscpy(pszEnumerator, lpEnumerator);
+
+    if (lpDevice != NULL)
+        wcscpy(pszDevice, lpDevice);
+
+    if (lpInstance != NULL)
+        wcscpy(pszInstance, lpInstance);
+}
+
+
+static CONFIGRET
+CreateDeviceInstance(LPWSTR pszDeviceID)
+{
+    WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
+    WCHAR szDevice[MAX_DEVICE_ID_LEN];
+    WCHAR szInstance[MAX_DEVICE_ID_LEN];
+    HKEY hKeyEnumerator;
+    HKEY hKeyDevice;
+    HKEY hKeyInstance;
+    HKEY hKeyControl;
+    LONG lError;
+
+    /* Split the instance ID */
+    SplitDeviceInstanceID(pszDeviceID,
+                          szEnumerator,
+                          szDevice,
+                          szInstance);
+
+    /* Open or create the enumerator key */
+    lError = RegCreateKeyExW(hEnumKey,
+                             szEnumerator,
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             KEY_ALL_ACCESS,
+                             NULL,
+                             &hKeyEnumerator,
+                             NULL);
+    if (lError != ERROR_SUCCESS)
+    {
+        return CR_REGISTRY_ERROR;
+    }
+
+    /* Open or create the device key */
+    lError = RegCreateKeyExW(hKeyEnumerator,
+                             szDevice,
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             KEY_ALL_ACCESS,
+                             NULL,
+                             &hKeyDevice,
+                             NULL);
+
+    /* Close the enumerator key */
+    RegCloseKey(hKeyEnumerator);
+
+    if (lError != ERROR_SUCCESS)
+    {
+        return CR_REGISTRY_ERROR;
+    }
+
+    /* Try to open the instance key and fail if it exists */
+    lError = RegOpenKeyExW(hKeyDevice,
+                           szInstance,
+                           0,
+                           KEY_SET_VALUE,
+                           &hKeyInstance);
+    if (lError == ERROR_SUCCESS)
+    {
+        DPRINT1("Instance %S already exists!\n", szInstance);
+        RegCloseKey(hKeyInstance);
+        RegCloseKey(hKeyDevice);
+        return CR_ALREADY_SUCH_DEVINST;
+    }
+
+    /* Create a new instance key */
+    lError = RegCreateKeyExW(hKeyDevice,
+                             szInstance,
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             KEY_ALL_ACCESS,
+                             NULL,
+                             &hKeyInstance,
+                             NULL);
+
+    /* Close the device key */
+    RegCloseKey(hKeyDevice);
+
+    if (lError != ERROR_SUCCESS)
+    {
+        return CR_REGISTRY_ERROR;
+    }
+
+    /* Create the 'Control' sub key */
+    lError = RegCreateKeyExW(hKeyInstance,
+                             L"Control",
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             KEY_ALL_ACCESS,
+                             NULL,
+                             &hKeyControl,
+                             NULL);
+    if (lError == ERROR_SUCCESS)
+    {
+        RegCloseKey(hKeyControl);
+    }
+
+    RegCloseKey(hKeyInstance);
+
+    return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
 }
 
 
@@ -1115,8 +1607,25 @@ DWORD PNP_CreateDevInst(
     PNP_RPC_STRING_LEN ulLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    CONFIGRET ret = CR_SUCCESS;
+
+    DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID);
+
+    if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
+    {
+        /* FIXME */
+        DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret);
+        ret = CR_CALL_NOT_IMPLEMENTED;
+        goto done;
+    }
+
+    /* Create the device instance */
+    ret = CreateDeviceInstance(pszDeviceID);
+
+done:;
+    DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
+
+    return ret;
 }
 
 
@@ -1637,8 +2146,128 @@ DWORD PNP_GetHwProfInfo(
     DWORD ulProfileInfoSize,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    WCHAR szProfileName[5];
+    HKEY hKeyConfig = NULL;
+    HKEY hKeyProfiles = NULL;
+    HKEY hKeyProfile = NULL;
+    DWORD dwDisposition;
+    DWORD dwSize;
+    LONG lError;
+    CONFIGRET ret = CR_SUCCESS;
+
+    UNREFERENCED_PARAMETER(hBinding);
+
+    DPRINT("PNP_GetHwProfInfo() called\n");
+
+    if (ulProfileInfoSize == 0)
+    {
+        ret = CR_INVALID_DATA;
+        goto done;
+    }
+
+    if (ulFlags != 0)
+    {
+        ret = CR_INVALID_FLAG;
+        goto done;
+    }
+
+    /* Initialize the profile information */
+    pHWProfileInfo->HWPI_ulHWProfile = 0;
+    pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
+    pHWProfileInfo->HWPI_dwFlags = 0;
+
+    /* Open the 'IDConfigDB' key */
+    lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+                             L"System\\CurrentControlSet\\Control\\IDConfigDB",
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             KEY_QUERY_VALUE,
+                             NULL,
+                             &hKeyConfig,
+                             &dwDisposition);
+    if (lError != ERROR_SUCCESS)
+    {
+        ret = CR_REGISTRY_ERROR;
+        goto done;
+    }
+
+    /* Open the 'Hardware Profiles' subkey */
+    lError = RegCreateKeyExW(hKeyConfig,
+                             L"Hardware Profiles",
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+                             NULL,
+                             &hKeyProfiles,
+                             &dwDisposition);
+    if (lError != ERROR_SUCCESS)
+    {
+        ret = CR_REGISTRY_ERROR;
+        goto done;
+    }
+
+    if (ulIndex == (ULONG)-1)
+    {
+        dwSize = sizeof(ULONG);
+        lError = RegQueryValueExW(hKeyConfig,
+                                  L"CurrentConfig",
+                                  NULL,
+                                  NULL,
+                                  (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
+                                  &dwSize);
+        if (lError != ERROR_SUCCESS)
+        {
+            pHWProfileInfo->HWPI_ulHWProfile = 0;
+            ret = CR_REGISTRY_ERROR;
+            goto done;
+        }
+    }
+    else
+    {
+        /* FIXME: not implemented yet */
+        ret = CR_CALL_NOT_IMPLEMENTED;
+        goto done;
+    }
+
+    swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
+
+    lError = RegOpenKeyExW(hKeyProfiles,
+                           szProfileName,
+                           0,
+                           KEY_QUERY_VALUE,
+                           &hKeyProfile);
+    if (lError != ERROR_SUCCESS)
+    {
+        ret = CR_REGISTRY_ERROR;
+        goto done;
+    }
+
+    dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
+    lError = RegQueryValueExW(hKeyProfile,
+                              L"FriendlyName",
+                              NULL,
+                              NULL,
+                              (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
+                              &dwSize);
+    if (lError != ERROR_SUCCESS)
+    {
+        ret = CR_REGISTRY_ERROR;
+        goto done;
+    }
+
+done:
+    if (hKeyProfile != NULL)
+        RegCloseKey(hKeyProfile);
+
+    if (hKeyProfiles != NULL)
+        RegCloseKey(hKeyProfiles);
+
+    if (hKeyConfig != NULL)
+        RegCloseKey(hKeyConfig);
+
+    return ret;
 }
 
 
@@ -1886,7 +2515,6 @@ PNP_RunDetection(
     handle_t hBinding,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
     return CR_CALL_NOT_IMPLEMENTED;
 }
 
@@ -1920,8 +2548,86 @@ DWORD PNP_GetCustomDevProp(
     PNP_RPC_STRING_LEN *pulLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    HKEY hDeviceKey = NULL;
+    HKEY hParamKey = NULL;
+    LONG lError;
+    CONFIGRET ret = CR_SUCCESS;
+
+    UNREFERENCED_PARAMETER(hBinding);
+
+    DPRINT("PNP_GetCustomDevProp() called\n");
+
+    if (pulTransferLen == NULL || pulLength == NULL)
+    {
+        ret = CR_INVALID_POINTER;
+        goto done;
+    }
+
+    if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
+    {
+        ret = CR_INVALID_FLAG;
+        goto done;
+    }
+
+    if (*pulLength < *pulTransferLen)
+        *pulLength = *pulTransferLen;
+
+    *pulTransferLen = 0;
+
+    lError = RegOpenKeyExW(hEnumKey,
+                           pDeviceID,
+                           0,
+                           KEY_READ,
+                           &hDeviceKey);
+    if (lError != ERROR_SUCCESS)
+    {
+        ret = CR_REGISTRY_ERROR;
+        goto done;
+    }
+
+    lError = RegOpenKeyExW(hDeviceKey,
+                           L"Device Parameters",
+                           0,
+                           KEY_READ,
+                           &hParamKey);
+    if (lError != ERROR_SUCCESS)
+    {
+        ret = CR_REGISTRY_ERROR;
+        goto done;
+    }
+
+    lError = RegQueryValueExW(hParamKey,
+                              CustomPropName,
+                              NULL,
+                              pulRegDataType,
+                              Buffer,
+                              pulLength);
+    if (lError != ERROR_SUCCESS)
+    {
+        if (lError == ERROR_MORE_DATA)
+        {
+            ret = CR_BUFFER_SMALL;
+        }
+        else
+        {
+            *pulLength = 0;
+            ret = CR_NO_SUCH_VALUE;
+        }
+    }
+
+done:;
+    if (ret == CR_SUCCESS)
+        *pulTransferLen = *pulLength;
+
+    if (hParamKey != NULL)
+        RegCloseKey(hParamKey);
+
+    if (hDeviceKey != NULL)
+        RegCloseKey(hDeviceKey);
+
+    DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
+
+    return ret;
 }
 
 
@@ -1930,6 +2636,8 @@ DWORD PNP_GetVersionInternal(
     handle_t hBinding,
     WORD *pwVersion)
 {
+    *pwVersion = 0x501;
+    return CR_SUCCESS;
     UNIMPLEMENTED;
     return CR_CALL_NOT_IMPLEMENTED;
 }
@@ -2076,8 +2784,6 @@ DWORD PNP_DeleteServiceDevices(
 static BOOL
 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
 {
-    PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
-    NTSTATUS Status;
     BOOL DeviceInstalled = FALSE;
     DWORD BytesWritten;
     DWORD Value;
@@ -2086,6 +2792,7 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
     PROCESS_INFORMATION ProcessInfo;
     STARTUPINFOW StartupInfo;
     UUID RandomUuid;
+    HKEY DeviceKey;
 
     /* The following lengths are constant (see below), they cannot overflow */
     WCHAR CommandLine[116];
@@ -2097,27 +2804,29 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
 
     ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
 
-    RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
-                         DeviceInstance);
-    PlugPlayData.Operation = 0; /* Get status */
-
-    /* Get device status */
-    Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
-                               (PVOID)&PlugPlayData,
-                               sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
-    if (!NT_SUCCESS(Status))
+    if (RegOpenKeyExW(hEnumKey,
+                      DeviceInstance,
+                      0,
+                      KEY_QUERY_VALUE,
+                      &DeviceKey) == ERROR_SUCCESS)
     {
-        DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance, Status);
-        return FALSE;
-    }
+        if (RegQueryValueExW(DeviceKey,
+                             L"Class",
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL) == ERROR_SUCCESS)
+        {
+            DPRINT("No need to install: %S\n", DeviceInstance);
+            RegCloseKey(DeviceKey);
+            return TRUE;
+        }
 
-    if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0)
-    {
-        /* Device is already started, or disabled due to some problem. Don't install it */
-        DPRINT("No need to install '%S'\n", DeviceInstance);
-        return TRUE;
+        RegCloseKey(DeviceKey);
     }
 
+    DPRINT1("Installing: %S\n", DeviceInstance);
+
     /* Create a random UUID for the named pipe */
     UuidCreate(&RandomUuid);
     swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
@@ -2177,8 +2886,11 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
     /* Wait for the function to connect to our pipe */
     if(!ConnectNamedPipe(hPipe, NULL))
     {
-        DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
-        goto cleanup;
+        if (GetLastError() != ERROR_PIPE_CONNECTED)
+        {
+            DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
+            goto cleanup;
+        }
     }
 
     /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
@@ -2222,6 +2934,8 @@ cleanup:
     if(ProcessInfo.hThread)
         CloseHandle(ProcessInfo.hThread);
 
+    DPRINT1("Success? %d\n", DeviceInstalled);
+
     return DeviceInstalled;
 }
 
@@ -2314,7 +3028,7 @@ IsConsoleBoot(VOID)
     if (rc != ERROR_SUCCESS)
         goto cleanup;
 
-    /* Check for CMDCONS in SystemStartOptions */
+    /* Check for CONSOLE switch in SystemStartOptions */
     CurrentOption = SystemStartOptions;
     while (CurrentOption)
     {
@@ -2455,6 +3169,30 @@ PnpEventThread(LPVOID lpParameter)
             DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
             /* FIXME: ? */
         }
+        else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
+        {
+            DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
+        }
+        else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
+        {
+            DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
+        }
+        else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
+        {
+            DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
+        }
+        else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
+        {
+            DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
+        }
+        else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
+        {
+            DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
+        }
+        else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
+        {
+            DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
+        }
         else
         {
             DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
@@ -2509,6 +3247,8 @@ ServiceControlHandler(DWORD dwControl,
     {
         case SERVICE_CONTROL_STOP:
             DPRINT1("  SERVICE_CONTROL_STOP received\n");
+            /* Stop listening to RPC Messages */
+            RpcMgmtStopServerListening(NULL);
             UpdateServiceStatus(SERVICE_STOPPED);
             return ERROR_SUCCESS;
 
@@ -2530,6 +3270,8 @@ ServiceControlHandler(DWORD dwControl,
 
         case SERVICE_CONTROL_SHUTDOWN:
             DPRINT1("  SERVICE_CONTROL_SHUTDOWN received\n");
+            /* Stop listening to RPC Messages */
+            RpcMgmtStopServerListening(NULL);
             UpdateServiceStatus(SERVICE_STOPPED);
             return ERROR_SUCCESS;