[UMPNPMGR]
[reactos.git] / reactos / base / services / umpnpmgr / umpnpmgr.c
index 398812a..f2cc8b9 100644 (file)
@@ -19,7 +19,7 @@
 /*
  * 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
  *                   HervĂ© Poussineau (hpoussin@reactos.org)
@@ -37,6 +37,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>
@@ -488,8 +490,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 +568,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;
 }
 
 
@@ -813,7 +948,7 @@ PNP_GetDeviceRegProp(
 #endif
 
             case CM_DRP_REMOVAL_POLICY:
-                PlugPlayData.Property = 0x12; // DevicePropertyRemovalPolicy
+                PlugPlayData.Property = 0x13; // DevicePropertyRemovalPolicy
                 break;
 
 #if 0
@@ -856,7 +991,9 @@ PNP_GetDeviceRegProp(
     }
 
 done:
-    *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
+
+    if (pulTransferLen)
+        *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
 
     if (hKey != NULL)
         RegCloseKey(hKey);
@@ -1793,7 +1930,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));
@@ -2720,10 +2857,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;
 }
 
 
@@ -2731,10 +2886,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;
 }
 
 
@@ -3402,8 +3565,16 @@ PnpEventThread(LPVOID lpParameter)
         }
         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);
         }
         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
         {
@@ -3415,11 +3586,29 @@ 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);
         }
         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);
         }
         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
         {
@@ -3512,7 +3701,7 @@ ServiceControlHandler(DWORD dwControl,
             return ERROR_SUCCESS;
 
         default :
-            DPRINT1("  Control %lu received\n");
+            DPRINT1("  Control %lu received\n", dwControl);
             return ERROR_CALL_NOT_IMPLEMENTED;
     }
 }