[UMPNPMGR]
[reactos.git] / reactos / base / services / umpnpmgr / umpnpmgr.c
index 95944c6..b53fb55 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;
 }
 
 
@@ -3016,6 +3179,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;
@@ -3056,7 +3220,7 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
 
     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,
@@ -3064,11 +3228,20 @@ 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)
     {
         DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
@@ -3123,9 +3296,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);
@@ -3141,16 +3311,13 @@ 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 (hInstallEvent)
+        CloseHandle(hInstallEvent);
+
     if (hPipe != INVALID_HANDLE_VALUE)
         CloseHandle(hPipe);
 
@@ -3398,8 +3565,17 @@ 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);
+            SendMessageW(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0);
         }
         else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
         {
@@ -3411,11 +3587,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))
         {
@@ -3508,7 +3704,7 @@ ServiceControlHandler(DWORD dwControl,
             return ERROR_SUCCESS;
 
         default :
-            DPRINT1("  Control %lu received\n");
+            DPRINT1("  Control %lu received\n", dwControl);
             return ERROR_CALL_NOT_IMPLEMENTED;
     }
 }