diff --git a/base/system/services/rpcserver.c b/base/system/services/rpcserver.c index 8feb95e2c5c..d91fa4422f8 100644 --- a/base/system/services/rpcserver.c +++ b/base/system/services/rpcserver.c @@ -6726,6 +6726,7 @@ RI_ScSendPnPMessage( DWORD PacketSize; PSERVICE pService; ULONG_PTR Ptr; + DWORD dwControlsAccepted, dwCurrentState; DWORD dwError = ERROR_SUCCESS; DPRINT("RI_ScSendPnPMessage(%p %lx %lu %lu %p)\n", @@ -6734,6 +6735,46 @@ RI_ScSendPnPMessage( /* FIXME: Verify the status handle */ pService = (PSERVICE)hServiceStatus; + /* Fail, if the service is a driver */ + if (pService->Status.dwServiceType & SERVICE_DRIVER) + return ERROR_INVALID_SERVICE_CONTROL; + + dwControlsAccepted = pService->Status.dwControlsAccepted; + dwCurrentState = pService->Status.dwCurrentState; + + /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */ + if (pService->lpImage == NULL || dwCurrentState == SERVICE_STOPPED) + return ERROR_SERVICE_NOT_ACTIVE; + + /* The service cannot accept a control code if it is not running */ + if (dwCurrentState != SERVICE_RUNNING) + return ERROR_SERVICE_CANNOT_ACCEPT_CTRL; + + /* Check if the control code is acceptable to the service */ + switch (dwControl) + { + case SERVICE_CONTROL_DEVICEEVENT: + break; + + case SERVICE_CONTROL_HARDWAREPROFILECHANGE: + if ((dwControlsAccepted & SERVICE_ACCEPT_HARDWAREPROFILECHANGE) == 0) + return ERROR_INVALID_SERVICE_CONTROL; + break; + + case SERVICE_CONTROL_POWEREVENT: + if ((dwControlsAccepted & SERVICE_ACCEPT_POWEREVENT) == 0) + return ERROR_INVALID_SERVICE_CONTROL; + break; + + case SERVICE_CONTROL_SESSIONCHANGE: + if ((dwControlsAccepted & SERVICE_ACCEPT_SESSIONCHANGE) == 0) + return ERROR_INVALID_SERVICE_CONTROL; + break; + + default: + return ERROR_INVALID_SERVICE_CONTROL; + } + /* Calculate the total size of the control packet: * initial structure, event type and event data */ PacketSize = sizeof(SCM_CONTROL_PACKET) + sizeof(DWORD) + dwEventSize;