[UMPNPMGR] Minor formatting, and enable a DPRINT1 in case NtGetPlugPlayEvent() fails...
[reactos.git] / base / services / umpnpmgr / umpnpmgr.c
index d6e6afa..e7e86e7 100644 (file)
 /*
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
- * FILE:             services/umpnpmgr/umpnpmgr.c
+ * FILE:             base/services/umpnpmgr/umpnpmgr.c
  * PURPOSE:          User-mode Plug and Play manager
- * PROGRAMMER:       Eric Kohl
+ * PROGRAMMER:       Eric Kohl (eric.kohl@reactos.org)
  *                   HervĂ© Poussineau (hpoussin@reactos.org)
  *                   Colin Finck (colin@reactos.org)
  */
 
 /* INCLUDES *****************************************************************/
 
-//#define HAVE_SLIST_ENTRY_IMPLEMENTED
 #define WIN32_NO_STATUS
 #define _INC_WINDOWS
 #define COM_NO_WINDOWS_H
@@ -37,6 +36,8 @@
 #include <winbase.h>
 #include <winreg.h>
 #include <winsvc.h>
+#include <winuser.h>
+#include <dbt.h>
 #include <stdio.h>
 #include <cmfuncs.h>
 #include <rtlfuncs.h>
@@ -67,20 +68,12 @@ static HANDLE hUserToken = NULL;
 static HANDLE hInstallEvent = NULL;
 static HANDLE hNoPendingInstalls = NULL;
 
-#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
 static SLIST_HEADER DeviceInstallListHead;
-#else
-static LIST_ENTRY DeviceInstallListHead;
-#endif
 static HANDLE hDeviceInstallListNotEmpty;
 
 typedef struct
 {
-#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
     SLIST_ENTRY ListEntry;
-#else
-    LIST_ENTRY ListEntry;
-#endif
     WCHAR DeviceIds[1];
 } DeviceInstallParams;
 
@@ -167,14 +160,25 @@ NtStatusToCrError(NTSTATUS Status)
 {
     switch (Status)
     {
-        case STATUS_NO_SUCH_DEVICE:
-            return CR_NO_SUCH_DEVINST;
         case STATUS_NOT_IMPLEMENTED:
             return CR_CALL_NOT_IMPLEMENTED;
 
+        case STATUS_INVALID_PARAMETER:
+            return CR_INVALID_DATA;
+
+        case STATUS_NO_SUCH_DEVICE:
+            return CR_NO_SUCH_DEVINST;
+
+        case STATUS_ACCESS_DENIED:
+            return CR_ACCESS_DENIED;
+
+        case STATUS_BUFFER_TOO_SMALL:
+            return CR_BUFFER_SMALL;
+
+        case STATUS_OBJECT_NAME_NOT_FOUND:
+            return CR_NO_SUCH_VALUE;
+
         default:
-            /* FIXME: add more mappings */
-            DPRINT1("Unable to map status 0x%08lx\n", Status);
             return CR_FAILURE;
     }
 }
@@ -264,7 +268,7 @@ PNP_ReportLogOn(
     /* Get the users token */
     hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
 
-    if(!hProcess)
+    if (!hProcess)
     {
         DPRINT1("OpenProcess failed with error %u\n", GetLastError());
         goto cleanup;
@@ -276,7 +280,7 @@ PNP_ReportLogOn(
         hUserToken = NULL;
     }
 
-    if(!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
+    if (!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
     {
         DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
         goto cleanup;
@@ -289,7 +293,7 @@ PNP_ReportLogOn(
     ReturnValue = CR_SUCCESS;
 
 cleanup:
-    if(hProcess)
+    if (hProcess)
         CloseHandle(hProcess);
 
     return ReturnValue;
@@ -488,8 +492,75 @@ PNP_GetDeviceList(
     PNP_RPC_STRING_LEN *pulLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
+    CONFIGRET ret = CR_SUCCESS;
+    NTSTATUS Status;
+
+    DPRINT("PNP_GetDeviceList() called\n");
+
+    if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
+        return CR_INVALID_FLAG;
+
+    if (pulLength == NULL || pszFilter == NULL)
+        return CR_INVALID_POINTER;
+
+//    if (Buffer == NULL)
+//        return CR_INVALID_POINTER;
+
+    if (ulFlags &
+        (CM_GETIDLIST_FILTER_BUSRELATIONS |
+         CM_GETIDLIST_FILTER_POWERRELATIONS |
+         CM_GETIDLIST_FILTER_REMOVALRELATIONS |
+         CM_GETIDLIST_FILTER_EJECTRELATIONS))
+    {
+        RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
+                             pszFilter);
+        if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
+        {
+            PlugPlayData.Relations = 3;
+        }
+        else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
+        {
+            PlugPlayData.Relations = 2;
+        }
+        else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
+        {
+            PlugPlayData.Relations = 1;
+        }
+        else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
+        {
+            PlugPlayData.Relations = 0;
+        }
+
+        PlugPlayData.BufferSize = *pulLength * sizeof(WCHAR);
+        PlugPlayData.Buffer = Buffer;
+
+        Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
+                                   (PVOID)&PlugPlayData,
+                                   sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
+        if (NT_SUCCESS(Status))
+        {
+            *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
+        }
+        else
+        {
+            ret = NtStatusToCrError(Status);
+        }
+    }
+    else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
+    {
+        ret = CR_CALL_NOT_IMPLEMENTED;
+    }
+    else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
+    {
+        ret = CR_CALL_NOT_IMPLEMENTED;
+    }
+    else /* CM_GETIDLIST_FILTER_NONE */
+    {
+        ret = CR_CALL_NOT_IMPLEMENTED;
+    }
+
+    return ret;
 }
 
 
@@ -499,11 +570,77 @@ WINAPI
 PNP_GetDeviceListSize(
     handle_t hBinding,
     LPWSTR pszFilter,
-    PNP_RPC_BUFFER_SIZE *pulLen,
+    PNP_RPC_BUFFER_SIZE *pulLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
+    CONFIGRET ret = CR_SUCCESS;
+    NTSTATUS Status;
+
+    DPRINT("PNP_GetDeviceListSize() called\n");
+
+    if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
+        return CR_INVALID_FLAG;
+
+    if (pulLength == NULL || pszFilter == NULL)
+        return CR_INVALID_POINTER;
+
+    *pulLength = 0;
+
+    if (ulFlags &
+        (CM_GETIDLIST_FILTER_BUSRELATIONS |
+         CM_GETIDLIST_FILTER_POWERRELATIONS |
+         CM_GETIDLIST_FILTER_REMOVALRELATIONS |
+         CM_GETIDLIST_FILTER_EJECTRELATIONS))
+    {
+        RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
+                             pszFilter);
+        if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
+        {
+            PlugPlayData.Relations = 3;
+        }
+        else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
+        {
+            PlugPlayData.Relations = 2;
+        }
+        else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
+        {
+            PlugPlayData.Relations = 1;
+        }
+        else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
+        {
+            PlugPlayData.Relations = 0;
+        }
+
+        PlugPlayData.BufferSize = 0;
+        PlugPlayData.Buffer = NULL;
+
+        Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
+                                   (PVOID)&PlugPlayData,
+                                   sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
+        if (NT_SUCCESS(Status))
+        {
+            *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
+        }
+        else
+        {
+            ret = NtStatusToCrError(Status);
+        }
+    }
+    else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
+    {
+        ret = CR_CALL_NOT_IMPLEMENTED;
+    }
+    else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
+    {
+        ret = CR_CALL_NOT_IMPLEMENTED;
+    }
+    else /* CM_GETIDLIST_FILTER_NONE */
+    {
+        ret = CR_CALL_NOT_IMPLEMENTED;
+    }
+
+    return ret;
 }
 
 
@@ -636,7 +773,7 @@ PNP_GetDeviceRegProp(
             break;
 
         case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME;
             break;
 
         case CM_DRP_CAPABILITIES:
@@ -644,7 +781,7 @@ PNP_GetDeviceRegProp(
             break;
 
         case CM_DRP_UI_NUMBER:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_UI_NUMBER;
             break;
 
         case CM_DRP_UPPERFILTERS:
@@ -656,19 +793,19 @@ PNP_GetDeviceRegProp(
             break;
 
         case CM_DRP_BUSTYPEGUID:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID;
             break;
 
         case CM_DRP_LEGACYBUSTYPE:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE;
             break;
 
         case CM_DRP_BUSNUMBER:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER;
             break;
 
         case CM_DRP_ENUMERATOR_NAME:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_ENUMERATOR_NAME;
             break;
 
         case CM_DRP_SECURITY:
@@ -688,7 +825,7 @@ PNP_GetDeviceRegProp(
             break;
 
         case CM_DRP_ADDRESS:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_ADDRESS;
             break;
 
         case CM_DRP_UI_NUMBER_DESC_FORMAT:
@@ -696,15 +833,15 @@ PNP_GetDeviceRegProp(
             break;
 
         case CM_DRP_DEVICE_POWER_DATA:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_POWER_DATA;
             break;
 
         case CM_DRP_REMOVAL_POLICY:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY;
             break;
 
         case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT;
             break;
 
         case CM_DRP_REMOVAL_POLICY_OVERRIDE:
@@ -712,18 +849,18 @@ PNP_GetDeviceRegProp(
             break;
 
         case CM_DRP_INSTALL_STATE:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE;
             break;
 
 #if (WINVER >= _WIN32_WINNT_WS03)
         case CM_DRP_LOCATION_PATHS:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_LOCATION_PATHS;
             break;
 #endif
 
 #if (WINVER >= _WIN32_WINNT_WIN7)
         case CM_DRP_BASE_CONTAINERID:
-            lpValueName = NULL;
+            PlugPlayData.Property = PNP_PROPERTY_CONTAINERID;
             break;
 #endif
 
@@ -777,71 +914,6 @@ PNP_GetDeviceRegProp(
         PlugPlayData.Buffer = Buffer;
         PlugPlayData.BufferSize = *pulLength;
 
-        switch (ulProperty)
-        {
-            case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
-                PlugPlayData.Property = 0xb; // DevicePropertyPhysicalDeviceObjectName;
-                break;
-
-            case CM_DRP_UI_NUMBER:
-                PlugPlayData.Property = 0x11; // DevicePropertyUINumber;
-                break;
-
-            case CM_DRP_BUSTYPEGUID:
-                PlugPlayData.Property = 0xc; // DevicePropertyBusTypeGuid;
-                break;
-
-            case CM_DRP_LEGACYBUSTYPE:
-                PlugPlayData.Property = 0xd; // DevicePropertyLegacyBusType;
-                break;
-
-            case CM_DRP_BUSNUMBER:
-                PlugPlayData.Property = 0xe; // DevicePropertyBusNumber;
-                break;
-
-            case CM_DRP_ENUMERATOR_NAME:
-                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;
-        }
-
         Status = NtPlugPlayControl(PlugPlayControlProperty,
                                    (PVOID)&PlugPlayData,
                                    sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
@@ -856,7 +928,8 @@ PNP_GetDeviceRegProp(
     }
 
 done:
-    *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
+    if (pulTransferLen)
+        *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
 
     if (hKey != NULL)
         RegCloseKey(hKey);
@@ -1131,9 +1204,10 @@ PNP_GetClassName(
     DPRINT("PNP_GetClassName() called\n");
 
     lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
-    if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
+    if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
         lstrcatW(szKeyName, pszClassGuid);
-    else return CR_INVALID_DATA;
+    else
+        return CR_INVALID_DATA;
 
     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                       szKeyName,
@@ -1792,7 +1866,7 @@ EnableDeviceInstance(LPWSTR pszDeviceInstance)
     CONFIGRET ret = CR_SUCCESS;
     NTSTATUS Status;
 
-    DPRINT("Enable device instance\n");
+    DPRINT("Enable device instance %S\n", pszDeviceInstance);
 
     RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
     Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
@@ -1813,11 +1887,36 @@ DisableDeviceInstance(LPWSTR pszDeviceInstance)
 
 
 static CONFIGRET
-ReenumerateDeviceInstance(LPWSTR pszDeviceInstance)
+ReenumerateDeviceInstance(
+    _In_ LPWSTR pszDeviceInstance,
+    _In_ ULONG ulFlags)
 {
-    DPRINT("ReenumerateDeviceInstance: not implemented\n");
-    /* FIXME */
-    return CR_CALL_NOT_IMPLEMENTED;
+    PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData;
+    CONFIGRET ret = CR_SUCCESS;
+    NTSTATUS Status;
+
+    DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n",
+           pszDeviceInstance, ulFlags);
+
+    if (ulFlags & ~CM_REENUMERATE_BITS)
+        return CR_INVALID_FLAG;
+
+    if (ulFlags & CM_REENUMERATE_RETRY_INSTALLATION)
+    {
+        DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n");
+    }
+
+    RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance,
+                         pszDeviceInstance);
+    EnumerateDeviceData.Flags = 0;
+
+    Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice,
+                               &EnumerateDeviceData,
+                               sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA));
+    if (!NT_SUCCESS(Status))
+        ret = NtStatusToCrError(Status);
+
+    return ret;
 }
 
 
@@ -1858,7 +1957,8 @@ PNP_DeviceInstanceAction(
             break;
 
         case PNP_DEVINST_REENUMERATE:
-            ret = ReenumerateDeviceInstance(pszDeviceInstance1);
+            ret = ReenumerateDeviceInstance(pszDeviceInstance1,
+                                            ulFlags);
             break;
 
         default:
@@ -2274,12 +2374,12 @@ PNP_HwProfFlags(
          else
          {
              dwSize = sizeof(DWORD);
-             if (!RegQueryValueExW(hDeviceKey,
-                                   L"CSConfigFlags",
-                                   NULL,
-                                   NULL,
-                                   (LPBYTE)pulValue,
-                                   &dwSize) != ERROR_SUCCESS)
+             if (RegQueryValueExW(hDeviceKey,
+                                  L"CSConfigFlags",
+                                  NULL,
+                                  NULL,
+                                  (LPBYTE)pulValue,
+                                  &dwSize) != ERROR_SUCCESS)
              {
                  *pulValue = 0;
              }
@@ -2637,7 +2737,11 @@ PNP_DetectResourceConflict(
     BOOL *pbConflictDetected,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
+    DPRINT("PNP_DetectResourceConflict()\n");
+
+    if (pbConflictDetected != NULL)
+        *pbConflictDetected = FALSE;
+
     return CR_CALL_NOT_IMPLEMENTED;
 }
 
@@ -2719,10 +2823,28 @@ PNP_RunDetection(
 DWORD
 WINAPI
 PNP_RegisterNotification(
-    handle_t hBinding)
+    handle_t hBinding,
+    DWORD ulFlags,
+    DWORD *pulNotify)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+#if 0
+    PNOTIFY_DATA pNotifyData;
+#endif
+
+    DPRINT1("PNP_RegisterNotification(%p 0x%lx %p)\n",
+           hBinding, ulFlags, pulNotify);
+
+#if 0
+    pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_DATA));
+    if (pNotifyData == NULL)
+        return CR_OUT_OF_MEMORY;
+
+    *pulNotify = (DWORD)pNotifyData;
+#endif
+
+    *pulNotify = 1;
+
+    return CR_SUCCESS;
 }
 
 
@@ -2730,10 +2852,18 @@ PNP_RegisterNotification(
 DWORD
 WINAPI
 PNP_UnregisterNotification(
-    handle_t hBinding)
+    handle_t hBinding,
+    DWORD ulNotify)
 {
+    DPRINT1("PNP_UnregisterNotification(%p 0x%lx)\n",
+           hBinding, ulNotify);
+
+#if 0
     UNIMPLEMENTED;
     return CR_CALL_NOT_IMPLEMENTED;
+#endif
+
+    return CR_SUCCESS;
 }
 
 
@@ -2840,6 +2970,8 @@ PNP_GetVersionInternal(
     handle_t hBinding,
     WORD *pwVersion)
 {
+    UNREFERENCED_PARAMETER(hBinding);
+
     *pwVersion = 0x501;
     return CR_SUCCESS;
 }
@@ -2868,8 +3000,21 @@ PNP_GetServerSideDeviceInstallFlags(
     DWORD *pulSSDIFlags,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    UNREFERENCED_PARAMETER(hBinding);
+
+    DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n",
+            hBinding, pulSSDIFlags, ulFlags);
+
+    if (pulSSDIFlags == NULL)
+        return CR_INVALID_POINTER;
+
+    if (ulFlags != 0)
+        return CR_INVALID_FLAG;
+
+    /* FIXME */
+    *pulSSDIFlags = 0;
+
+    return CR_SUCCESS;
 }
 
 
@@ -3015,6 +3160,7 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
     BOOL DeviceInstalled = FALSE;
     DWORD BytesWritten;
     DWORD Value;
+    HANDLE hInstallEvent;
     HANDLE hPipe = INVALID_HANDLE_VALUE;
     LPVOID Environment = NULL;
     PROCESS_INFORMATION ProcessInfo;
@@ -3050,12 +3196,28 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
             return TRUE;
         }
 
+        BytesWritten = sizeof(DWORD);
+        if (RegQueryValueExW(DeviceKey,
+                             L"ConfigFlags",
+                             NULL,
+                             NULL,
+                             (PBYTE)&Value,
+                             &BytesWritten) == ERROR_SUCCESS)
+        {
+            if (Value & CONFIGFLAG_FAILEDINSTALL)
+            {
+                DPRINT("No need to install: %S\n", DeviceInstance);
+                RegCloseKey(DeviceKey);
+                return TRUE;
+            }
+        }
+
         RegCloseKey(DeviceKey);
     }
 
     DPRINT1("Installing: %S\n", DeviceInstance);
 
-    /* Create a random UUID for the named pipe */
+    /* Create a random UUID for the named pipe & event*/
     UuidCreate(&RandomUuid);
     swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
         RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
@@ -3063,12 +3225,21 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
         RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
         RandomUuid.Data4[6], RandomUuid.Data4[7]);
 
+    /* Create the event */
+    wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
+    wcscat(InstallEventName, UuidString);
+    hInstallEvent = CreateEventW(NULL, TRUE, FALSE, InstallEventName);
+    if (!hInstallEvent)
+    {
+        DPRINT1("CreateEventW('%ls') failed with error %lu\n", InstallEventName, GetLastError());
+        goto cleanup;
+    }
+
     /* Create the named pipe */
     wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
     wcscat(PipeName, UuidString);
     hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
-
-    if(hPipe == INVALID_HANDLE_VALUE)
+    if (hPipe == INVALID_HANDLE_VALUE)
     {
         DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
         goto cleanup;
@@ -3081,16 +3252,16 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
     ZeroMemory(&StartupInfo, sizeof(StartupInfo));
     StartupInfo.cb = sizeof(StartupInfo);
 
-    if(hUserToken)
+    if (hUserToken)
     {
         /* newdev has to run under the environment of the current user */
-        if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
+        if (!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
         {
             DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
             goto cleanup;
         }
 
-        if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
+        if (!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
         {
             DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
             goto cleanup;
@@ -3104,7 +3275,7 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
            (ShowWizard is only set to FALSE for these two modes) */
         ASSERT(!ShowWizard);
 
-        if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
+        if (!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
         {
             DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
             goto cleanup;
@@ -3112,7 +3283,7 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
     }
 
     /* Wait for the function to connect to our pipe */
-    if(!ConnectNamedPipe(hPipe, NULL))
+    if (!ConnectNamedPipe(hPipe, NULL))
     {
         if (GetLastError() != ERROR_PIPE_CONNECTED)
         {
@@ -3122,9 +3293,6 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
     }
 
     /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
-    wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
-    wcscat(InstallEventName, UuidString);
-
     Value = sizeof(InstallEventName);
     WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
     WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
@@ -3140,26 +3308,23 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
     /* Wait for newdev.dll to finish processing */
     WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
 
-    /* The following check for success is probably not compatible to Windows, but should do its job */
-    if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
-    {
-        DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
-        goto cleanup;
-    }
-
-    DeviceInstalled = Value;
+    /* If the event got signalled, this is success */
+    DeviceInstalled = WaitForSingleObject(hInstallEvent, 0) == WAIT_OBJECT_0;
 
 cleanup:
-    if(hPipe != INVALID_HANDLE_VALUE)
+    if (hInstallEvent)
+        CloseHandle(hInstallEvent);
+
+    if (hPipe != INVALID_HANDLE_VALUE)
         CloseHandle(hPipe);
 
-    if(Environment)
+    if (Environment)
         DestroyEnvironmentBlock(Environment);
 
-    if(ProcessInfo.hProcess)
+    if (ProcessInfo.hProcess)
         CloseHandle(ProcessInfo.hProcess);
 
-    if(ProcessInfo.hThread)
+    if (ProcessInfo.hThread)
         CloseHandle(ProcessInfo.hThread);
 
     if (!DeviceInstalled)
@@ -3287,11 +3452,7 @@ cleanup:
 static DWORD WINAPI
 DeviceInstallThread(LPVOID lpParameter)
 {
-#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
     PSLIST_ENTRY ListEntry;
-#else
-    PLIST_ENTRY ListEntry;
-#endif
     DeviceInstallParams* Params;
     BOOL showWizard;
 
@@ -3303,14 +3464,8 @@ DeviceInstallThread(LPVOID lpParameter)
 
     while (TRUE)
     {
-#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
         ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
-#else
-        if ((BOOL)IsListEmpty(&DeviceInstallListHead))
-            ListEntry = NULL;
-        else
-            ListEntry = RemoveHeadList(&DeviceInstallListHead);
-#endif
+
         if (ListEntry == NULL)
         {
             SetEvent(hNoPendingInstalls);
@@ -3347,10 +3502,10 @@ PnpEventThread(LPVOID lpParameter)
     {
         DPRINT("Calling NtGetPlugPlayEvent()\n");
 
-        /* Wait for the next pnp event */
+        /* Wait for the next PnP event */
         Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
 
-        /* Resize the buffer for the PnP event if it's too small. */
+        /* Resize the buffer for the PnP event if it's too small */
         if (Status == STATUS_BUFFER_TOO_SMALL)
         {
             PnpEventSize += 0x400;
@@ -3363,11 +3518,11 @@ PnpEventThread(LPVOID lpParameter)
 
         if (!NT_SUCCESS(Status))
         {
-            DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
+            DPRINT1("NtGetPlugPlayEvent() failed (Status 0x%08lx)\n", Status);
             break;
         }
 
-        /* Process the pnp event */
+        /* Process the PnP event */
         DPRINT("Received PnP Event\n");
         if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
         {
@@ -3380,25 +3535,30 @@ PnpEventThread(LPVOID lpParameter)
             DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
             if (DeviceIdLength)
             {
-                /* Queue device install (will be dequeued by DeviceInstallThread */
+                /* Queue device install (will be dequeued by DeviceInstallThread) */
                 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
                 Params = HeapAlloc(GetProcessHeap(), 0, len);
                 if (Params)
                 {
                     wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
-#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
                     InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
-#else
-                    InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
-#endif
                     SetEvent(hDeviceInstallListNotEmpty);
                 }
             }
         }
         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
         {
+//            DWORD dwRecipient;
+
             DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
-            /* FIXME: ? */
+
+//            dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
+//            BroadcastSystemMessageW(BSF_POSTMESSAGE,
+//                                    &dwRecipient,
+//                                    WM_DEVICECHANGE,
+//                                    DBT_DEVNODES_CHANGED,
+//                                    0);
+            SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
         }
         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
         {
@@ -3410,11 +3570,31 @@ PnpEventThread(LPVOID lpParameter)
         }
         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
         {
+//            DWORD dwRecipient;
+
             DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
+
+//            dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
+//            BroadcastSystemMessageW(BSF_POSTMESSAGE,
+//                                    &dwRecipient,
+//                                    WM_DEVICECHANGE,
+//                                    DBT_DEVNODES_CHANGED,
+//                                    0);
+            SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
         }
         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
         {
+//            DWORD dwRecipient;
+
             DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
+
+//            dwRecipient = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
+//            BroadcastSystemMessageW(BSF_POSTMESSAGE,
+//                                    &dwRecipient,
+//                                    WM_DEVICECHANGE,
+//                                    DBT_DEVNODES_CHANGED,
+//                                    0);
+            SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
         }
         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
         {
@@ -3433,7 +3613,7 @@ PnpEventThread(LPVOID lpParameter)
                 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
         }
 
-        /* Dequeue the current pnp event and signal the next one */
+        /* Dequeue the current PnP event and signal the next one */
         NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
     }
 
@@ -3507,7 +3687,7 @@ ServiceControlHandler(DWORD dwControl,
             return ERROR_SUCCESS;
 
         default :
-            DPRINT1("  Control %lu received\n");
+            DPRINT1("  Control %lu received\n", dwControl);
             return ERROR_CALL_NOT_IMPLEMENTED;
     }
 }
@@ -3605,11 +3785,7 @@ InitializePnPManager(VOID)
         return dwError;
     }
 
-#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
     InitializeSListHead(&DeviceInstallListHead);
-#else
-    InitializeListHead(&DeviceInstallListHead);
-#endif
 
     dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                             L"System\\CurrentControlSet\\Enum",