Fix PNP_QueryArbitratorFreeData() and PNP_QueryArbitratorFreeSize() prototypes.
[reactos.git] / reactos / base / services / umpnpmgr / umpnpmgr.c
index 2d4603c..64d8b45 100644 (file)
@@ -12,9 +12,9 @@
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 /*
  * COPYRIGHT:        See COPYING in the top level directory
 
 /* GLOBALS ******************************************************************/
 
-static VOID CALLBACK
-ServiceMain(DWORD argc, LPTSTR *argv);
-
-static SERVICE_TABLE_ENTRY ServiceTable[2] =
+static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv);
+static WCHAR ServiceName[] = L"PlugPlay";
+static SERVICE_TABLE_ENTRYW ServiceTable[] =
 {
-    {TEXT("PlugPlay"), ServiceMain},
+    {ServiceName, ServiceMain},
     {NULL, NULL}
 };
 
+static SERVICE_STATUS_HANDLE ServiceStatusHandle;
+static SERVICE_STATUS ServiceStatus;
+
 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
 
 static HKEY hEnumKey = NULL;
@@ -92,20 +94,37 @@ static DWORD WINAPI
 RpcServerThread(LPVOID lpParameter)
 {
     RPC_STATUS Status;
+    BOOLEAN RegisteredProtSeq = FALSE;
 
     UNREFERENCED_PARAMETER(lpParameter);
 
     DPRINT("RpcServerThread() called\n");
 
+#if 0
+    /* XP-compatible protocol sequence/endpoint */
     Status = RpcServerUseProtseqEpW(L"ncacn_np",
                                     20,
-                                    L"\\pipe\\umpnpmgr",
+                                    L"\\pipe\\ntsvcs",
                                     NULL);  // Security descriptor
-    if (Status != RPC_S_OK)
-    {
+    if (Status == RPC_S_OK)
+        RegisteredProtSeq = TRUE;
+    else
+        DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
+#endif
+
+    /* Vista-compatible protocol sequence/endpoint */
+    Status = RpcServerUseProtseqEpW(L"ncacn_np",
+                                    20,
+                                    L"\\pipe\\plugplay",
+                                    NULL);  // Security descriptor
+    if (Status == RPC_S_OK)
+        RegisteredProtSeq = TRUE;
+    else
         DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
+
+    /* Make sure there's a usable endpoint */
+    if (RegisteredProtSeq == FALSE)
         return 0;
-    }
 
     Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
                                  NULL,
@@ -135,7 +154,7 @@ RpcServerThread(LPVOID lpParameter)
 }
 
 
-void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
+void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
 {
     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
 }
@@ -667,11 +686,11 @@ DWORD PNP_GetDeviceRegProp(
             case CM_DRP_BUSNUMBER:
                 PlugPlayData.Property = DevicePropertyBusNumber;
                 break;
+#endif
 
             case CM_DRP_ENUMERATOR_NAME:
-                PlugPlayData.Property = DevicePropertyEnumeratorName;
+                PlugPlayData.Property = 15; //DevicePropertyEnumeratorName;
                 break;
-#endif
 
             default:
                 return CR_INVALID_PROPERTY;
@@ -831,8 +850,24 @@ DWORD PNP_CreateKey(
     DWORD samDesired,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    HKEY hKey = 0;
+
+    if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+                        pszSubKey,
+                        0,
+                        NULL,
+                        0,
+                        KEY_ALL_ACCESS,
+                        NULL,
+                        &hKey,
+                        NULL))
+        return CR_REGISTRY_ERROR;
+
+    /* FIXME: Set security key */
+
+    RegCloseKey(hKey);
+
+    return CR_SUCCESS;
 }
 
 
@@ -1085,53 +1120,102 @@ DWORD PNP_CreateDevInst(
 }
 
 
+static CONFIGRET
+MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
+                   LPWSTR pszDeviceInstanceSource)
+{
+    DPRINT("MoveDeviceInstance: not implemented\n");
+    /* FIXME */
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+static CONFIGRET
+SetupDeviceInstance(LPWSTR pszDeviceInstance,
+                    DWORD ulFlags)
+{
+    DPRINT("SetupDeviceInstance: not implemented\n");
+    /* FIXME */
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+static CONFIGRET
+EnableDeviceInstance(LPWSTR pszDeviceInstance)
+{
+    PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
+    CONFIGRET ret = CR_SUCCESS;
+    NTSTATUS Status;
+
+    DPRINT("Enable device instance\n");
+
+    RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
+    Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
+    if (!NT_SUCCESS(Status))
+        ret = NtStatusToCrError(Status);
+
+    return ret;
+}
+
+
+static CONFIGRET
+DisableDeviceInstance(LPWSTR pszDeviceInstance)
+{
+    DPRINT("DisableDeviceInstance: not implemented\n");
+    /* FIXME */
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
+static CONFIGRET
+ReenumerateDeviceInstance(LPWSTR pszDeviceInstance)
+{
+    DPRINT("ReenumerateDeviceInstance: not implemented\n");
+    /* FIXME */
+    return CR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /* Function 29 */
-#define PNP_DEVINST_SETUP       0x3
-#define PNP_DEVINST_ENABLE      0x4
-#define PNP_DEVINST_REENUMERATE 0x7
 DWORD PNP_DeviceInstanceAction(
     handle_t hBinding,
-    DWORD ulMajorAction,
-    DWORD ulMinorAction,
+    DWORD ulAction,
+    DWORD ulFlags,
     LPWSTR pszDeviceInstance1,
     LPWSTR pszDeviceInstance2)
 {
     CONFIGRET ret = CR_SUCCESS;
-    NTSTATUS Status;
 
     UNREFERENCED_PARAMETER(hBinding);
-    UNREFERENCED_PARAMETER(ulMinorAction);
-    UNREFERENCED_PARAMETER(pszDeviceInstance2);
 
     DPRINT("PNP_DeviceInstanceAction() called\n");
 
-    switch (ulMajorAction)
+    switch (ulAction)
     {
+        case PNP_DEVINST_MOVE:
+            ret = MoveDeviceInstance(pszDeviceInstance1,
+                                     pszDeviceInstance2);
+            break;
+
         case PNP_DEVINST_SETUP:
-            DPRINT("Setup device instance\n");
-            /* FIXME */
-            ret = CR_CALL_NOT_IMPLEMENTED;
+            ret = SetupDeviceInstance(pszDeviceInstance1,
+                                      ulFlags);
             break;
 
         case PNP_DEVINST_ENABLE:
-        {
-            PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
-            DPRINT("Enable device instance\n");
-            RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance1);
-            Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
-            if (!NT_SUCCESS(Status))
-                ret = NtStatusToCrError(Status);
+            ret = EnableDeviceInstance(pszDeviceInstance1);
+            break;
+
+        case PNP_DEVINST_DISABLE:
+            ret = DisableDeviceInstance(pszDeviceInstance1);
             break;
-        }
 
         case PNP_DEVINST_REENUMERATE:
-            DPRINT("Reenumerate device instance\n");
-            /* FIXME */
-            ret = CR_CALL_NOT_IMPLEMENTED;
+            ret = ReenumerateDeviceInstance(pszDeviceInstance1);
             break;
 
         default:
-            DPRINT1("Unknown function %lu\n", ulMajorAction);
+            DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
             ret = CR_CALL_NOT_IMPLEMENTED;
     }
 
@@ -1478,8 +1562,70 @@ DWORD PNP_HwProfFlags(
     DWORD ulNameLength,
     DWORD ulFlags)
 {
-    UNIMPLEMENTED;
-    return CR_CALL_NOT_IMPLEMENTED;
+    CONFIGRET ret = CR_SUCCESS;
+    WCHAR szKeyName[MAX_PATH];
+    HKEY hKey;
+    HKEY hDeviceKey;
+    DWORD dwSize;
+
+    UNREFERENCED_PARAMETER(hBinding);
+
+    DPRINT("PNP_HwProfFlags() called\n");
+
+    if (ulConfig == 0)
+    {
+        wcscpy(szKeyName,
+               L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
+    }
+    else
+    {
+        swprintf(szKeyName,
+                 L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
+                 ulConfig);
+    }
+
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                      szKeyName,
+                      0,
+                      KEY_QUERY_VALUE,
+                      &hKey) != ERROR_SUCCESS)
+        return CR_REGISTRY_ERROR;
+
+    if (ulAction == PNP_GET_HWPROFFLAGS)
+    {
+         if (RegOpenKeyExW(hKey,
+                           pDeviceID,
+                           0,
+                           KEY_QUERY_VALUE,
+                           &hDeviceKey) != ERROR_SUCCESS)
+         {
+            *pulValue = 0;
+         }
+         else
+         {
+             dwSize = sizeof(DWORD);
+             if (!RegQueryValueExW(hDeviceKey,
+                                   L"CSConfigFlags",
+                                   NULL,
+                                   NULL,
+                                   (LPBYTE)pulValue,
+                                   &dwSize) != ERROR_SUCCESS)
+             {
+                 *pulValue = 0;
+             }
+
+             RegCloseKey(hDeviceKey);
+         }
+    }
+    else if (ulAction == PNP_SET_HWPROFFLAGS)
+    {
+        /* FIXME: not implemented yet */
+        ret = CR_CALL_NOT_IMPLEMENTED;
+    }
+
+    RegCloseKey(hKey);
+
+    return ret;
 }
 
 
@@ -1698,7 +1844,9 @@ DWORD PNP_QueryResConfList(
 
 /* Function 55 */
 DWORD PNP_SetHwProf(
-    handle_t hBinding)
+    handle_t hBinding,
+    DWORD ulHardwareProfile,
+    DWORD ulFlags)
 {
     UNIMPLEMENTED;
     return CR_CALL_NOT_IMPLEMENTED;
@@ -1707,7 +1855,12 @@ DWORD PNP_SetHwProf(
 
 /* Function 56 */
 DWORD PNP_QueryArbitratorFreeData(
-    handle_t hBinding)
+    handle_t hBinding,
+    BYTE *pData,
+    DWORD DataLen,
+    LPWSTR pDeviceID,
+    RESOURCEID ResourceID,
+    DWORD ulFlags)
 {
     UNIMPLEMENTED;
     return CR_CALL_NOT_IMPLEMENTED;
@@ -1716,7 +1869,11 @@ DWORD PNP_QueryArbitratorFreeData(
 
 /* Function 57 */
 DWORD PNP_QueryArbitratorFreeSize(
-    handle_t hBinding)
+    handle_t hBinding,
+    DWORD *pulSize,
+    LPWSTR pDeviceID,
+    RESOURCEID ResourceID,
+    DWORD ulFlags)
 {
     UNIMPLEMENTED;
     return CR_CALL_NOT_IMPLEMENTED;
@@ -2273,7 +2430,7 @@ PnpEventThread(LPVOID lpParameter)
             DWORD len;
             DWORD DeviceIdLength;
 
-            DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
+            DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
 
             DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
             if (DeviceIdLength)
@@ -2293,6 +2450,11 @@ PnpEventThread(LPVOID lpParameter)
                 }
             }
         }
+        else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
+        {
+            DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
+            /* FIXME: ? */
+        }
         else
         {
             DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
@@ -2312,6 +2474,72 @@ PnpEventThread(LPVOID lpParameter)
 }
 
 
+static VOID
+UpdateServiceStatus(DWORD dwState)
+{
+    ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+    ServiceStatus.dwCurrentState = dwState;
+    ServiceStatus.dwControlsAccepted = 0;
+    ServiceStatus.dwWin32ExitCode = 0;
+    ServiceStatus.dwServiceSpecificExitCode = 0;
+    ServiceStatus.dwCheckPoint = 0;
+
+    if (dwState == SERVICE_START_PENDING ||
+        dwState == SERVICE_STOP_PENDING ||
+        dwState == SERVICE_PAUSE_PENDING ||
+        dwState == SERVICE_CONTINUE_PENDING)
+        ServiceStatus.dwWaitHint = 10000;
+    else
+        ServiceStatus.dwWaitHint = 0;
+
+    SetServiceStatus(ServiceStatusHandle,
+                     &ServiceStatus);
+}
+
+
+static DWORD WINAPI
+ServiceControlHandler(DWORD dwControl,
+                      DWORD dwEventType,
+                      LPVOID lpEventData,
+                      LPVOID lpContext)
+{
+    DPRINT1("ServiceControlHandler() called\n");
+
+    switch (dwControl)
+    {
+        case SERVICE_CONTROL_STOP:
+            DPRINT1("  SERVICE_CONTROL_STOP received\n");
+            UpdateServiceStatus(SERVICE_STOPPED);
+            return ERROR_SUCCESS;
+
+        case SERVICE_CONTROL_PAUSE:
+            DPRINT1("  SERVICE_CONTROL_PAUSE received\n");
+            UpdateServiceStatus(SERVICE_PAUSED);
+            return ERROR_SUCCESS;
+
+        case SERVICE_CONTROL_CONTINUE:
+            DPRINT1("  SERVICE_CONTROL_CONTINUE received\n");
+            UpdateServiceStatus(SERVICE_RUNNING);
+            return ERROR_SUCCESS;
+
+        case SERVICE_CONTROL_INTERROGATE:
+            DPRINT1("  SERVICE_CONTROL_INTERROGATE received\n");
+            SetServiceStatus(ServiceStatusHandle,
+                             &ServiceStatus);
+            return ERROR_SUCCESS;
+
+        case SERVICE_CONTROL_SHUTDOWN:
+            DPRINT1("  SERVICE_CONTROL_SHUTDOWN received\n");
+            UpdateServiceStatus(SERVICE_STOPPED);
+            return ERROR_SUCCESS;
+
+        default :
+            DPRINT1("  Control %lu received\n");
+            return ERROR_CALL_NOT_IMPLEMENTED;
+    }
+}
+
+
 static VOID CALLBACK
 ServiceMain(DWORD argc, LPTSTR *argv)
 {
@@ -2323,6 +2551,17 @@ ServiceMain(DWORD argc, LPTSTR *argv)
 
     DPRINT("ServiceMain() called\n");
 
+    ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
+                                                        ServiceControlHandler,
+                                                        NULL);
+    if (!ServiceStatusHandle)
+    {
+        DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
+        return;
+    }
+
+    UpdateServiceStatus(SERVICE_START_PENDING);
+
     hThread = CreateThread(NULL,
                            0,
                            PnpEventThread,
@@ -2350,6 +2589,8 @@ ServiceMain(DWORD argc, LPTSTR *argv)
     if (hThread != NULL)
         CloseHandle(hThread);
 
+    UpdateServiceStatus(SERVICE_RUNNING);
+
     DPRINT("ServiceMain() done\n");
 }