Author: ekohl
Date: Fri Feb 19 21:03:11 2010
New Revision: 45626
URL:
http://svn.reactos.org/svn/reactos?rev=45626&view=rev
Log:
[SERVICES] Set default status to SERVICE_START_PENDING when starting a service.
[SYSSETUP] Wait until PlugPlay service is up. Bug #4142.
[UMPNPMGR] Update the service control manager's status information.
Patches by Dmitry Gorbachev.
Modified:
trunk/reactos/base/services/umpnpmgr/umpnpmgr.c
trunk/reactos/base/system/services/database.c
trunk/reactos/dll/win32/syssetup/install.c
Modified: trunk/reactos/base/services/umpnpmgr/umpnpmgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/services/umpnpmgr/ump…
==============================================================================
--- trunk/reactos/base/services/umpnpmgr/umpnpmgr.c [iso-8859-1] (original)
+++ trunk/reactos/base/services/umpnpmgr/umpnpmgr.c [iso-8859-1] Fri Feb 19 21:03:11 2010
@@ -51,12 +51,11 @@
/* GLOBALS ******************************************************************/
-static VOID CALLBACK
-ServiceMain(DWORD argc, LPTSTR *argv);
-
-static SERVICE_TABLE_ENTRY ServiceTable[2] =
-{
- {TEXT("PlugPlay"), ServiceMain},
+static VOID CALLBACK ServiceMain(DWORD, LPWSTR *);
+static WCHAR ServiceName[] = L"PlugPlay";
+static SERVICE_TABLE_ENTRYW ServiceTable[] =
+{
+ {ServiceName, ServiceMain},
{NULL, NULL}
};
@@ -2446,16 +2445,92 @@
}
-static VOID CALLBACK
-ServiceMain(DWORD argc, LPTSTR *argv)
+static DWORD WINAPI
+ServiceControlHandler(DWORD dwControl,
+ DWORD dwEventType,
+ LPVOID lpEventData,
+ LPVOID lpContext)
+{
+ /* FIXME */
+ DPRINT1("ServiceControlHandler() called (control code %lu)\n", dwControl);
+ return ERROR_SUCCESS;
+}
+
+
+static DWORD
+ServiceInit(VOID)
{
HANDLE hThread;
DWORD dwThreadId;
-
- UNREFERENCED_PARAMETER(argc);
- UNREFERENCED_PARAMETER(argv);
-
- DPRINT("ServiceMain() called\n");
+ DWORD dwError;
+ BOOLEAN OldValue;
+
+ /* We need this privilege for using CreateProcessAsUserW */
+ RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE,
+ TRUE,
+ FALSE,
+ &OldValue);
+
+ hInstallEvent = CreateEvent(NULL,
+ TRUE,
+ SetupIsActive()/*FALSE*/,
+ NULL);
+ if (hInstallEvent == NULL)
+ {
+ dwError = GetLastError();
+ DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
+ return dwError;
+ }
+
+ hDeviceInstallListNotEmpty = CreateEvent(NULL,
+ FALSE,
+ FALSE,
+ NULL);
+ if (hDeviceInstallListNotEmpty == NULL)
+ {
+ dwError = GetLastError();
+ DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
+ return dwError;
+ }
+
+ hNoPendingInstalls = CreateEventW(NULL,
+ TRUE,
+ FALSE,
+
L"Global\\PnP_No_Pending_Install_Events");
+ if (hNoPendingInstalls == NULL)
+ {
+ dwError = GetLastError();
+ DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
+ return dwError;
+ }
+
+#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
+ InitializeSListHead(&DeviceInstallListHead);
+#else
+ InitializeListHead(&DeviceInstallListHead);
+#endif
+
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Enum",
+ 0,
+ KEY_ALL_ACCESS,
+ &hEnumKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
+ return dwError;
+ }
+
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Control\\Class",
+ 0,
+ KEY_ALL_ACCESS,
+ &hClassKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
+ return dwError;
+ }
hThread = CreateThread(NULL,
0,
@@ -2463,8 +2538,11 @@
NULL,
0,
&dwThreadId);
- if (hThread != NULL)
- CloseHandle(hThread);
+ if (hThread == NULL)
+ {
+ return GetLastError();
+ }
+ CloseHandle(hThread);
hThread = CreateThread(NULL,
0,
@@ -2472,8 +2550,11 @@
NULL,
0,
&dwThreadId);
- if (hThread != NULL)
- CloseHandle(hThread);
+ if (hThread == NULL)
+ {
+ return GetLastError();
+ }
+ CloseHandle(hThread);
hThread = CreateThread(NULL,
0,
@@ -2481,87 +2562,80 @@
NULL,
0,
&dwThreadId);
- if (hThread != NULL)
- CloseHandle(hThread);
-
- DPRINT("ServiceMain() done\n");
-}
-
-
-int
-wmain(int argc, WCHAR *argv[])
-{
- BOOLEAN OldValue;
+ if (hThread == NULL)
+ {
+ return GetLastError();
+ }
+ CloseHandle(hThread);
+
+ return ERROR_SUCCESS;
+}
+
+
+static VOID CALLBACK
+ServiceMain(DWORD argc,
+ LPWSTR *argv)
+{
+ SERVICE_STATUS ServiceStatus;
+ SERVICE_STATUS_HANDLE ServiceStatusHandle;
DWORD dwError;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
- DPRINT("Umpnpmgr: main() started\n");
-
- /* We need this privilege for using CreateProcessAsUserW */
- RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
-
- hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
- if (hInstallEvent == NULL)
+ DPRINT("ServiceMain() called\n");
+
+ ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
+ ServiceControlHandler,
+ NULL);
+ if (!ServiceStatusHandle)
{
dwError = GetLastError();
- DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
- return dwError;
- }
-
- hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (hDeviceInstallListNotEmpty == NULL)
- {
- dwError = GetLastError();
- DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
- return dwError;
- }
-
- hNoPendingInstalls = CreateEventW(NULL,
- TRUE,
- FALSE,
-
L"Global\\PnP_No_Pending_Install_Events");
- if (hNoPendingInstalls == NULL)
- {
- dwError = GetLastError();
- DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
- return dwError;
- }
-
-#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
- InitializeSListHead(&DeviceInstallListHead);
-#else
- InitializeListHead(&DeviceInstallListHead);
-#endif
-
- dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- L"System\\CurrentControlSet\\Enum",
- 0,
- KEY_ALL_ACCESS,
- &hEnumKey);
+ DPRINT1("RegisterServiceCtrlHandlerW() failed! (Error %lu)\n",
dwError);
+ return;
+ }
+
+ ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+ ServiceStatus.dwControlsAccepted = 0;
+ ServiceStatus.dwWin32ExitCode = NO_ERROR;
+ ServiceStatus.dwServiceSpecificExitCode = 0;
+ ServiceStatus.dwCheckPoint = 0;
+ ServiceStatus.dwWaitHint = 2000;
+
+ SetServiceStatus(ServiceStatusHandle,
+ &ServiceStatus);
+
+ dwError = ServiceInit();
if (dwError != ERROR_SUCCESS)
{
- DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
- return dwError;
- }
-
- dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- L"System\\CurrentControlSet\\Control\\Class",
- 0,
- KEY_ALL_ACCESS,
- &hClassKey);
- if (dwError != ERROR_SUCCESS)
- {
- DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
- return dwError;
- }
-
- StartServiceCtrlDispatcher(ServiceTable);
-
- DPRINT("Umpnpmgr: main() done\n");
-
- ExitThread(0);
+ DPRINT1("Service stopped\n");
+ ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ }
+ else
+ {
+ ServiceStatus.dwCurrentState = SERVICE_RUNNING;
+ }
+
+ SetServiceStatus(ServiceStatusHandle,
+ &ServiceStatus);
+
+ DPRINT("ServiceMain() done\n");
+}
+
+
+int
+wmain(int argc,
+ WCHAR *argv[])
+{
+ UNREFERENCED_PARAMETER(argc);
+ UNREFERENCED_PARAMETER(argv);
+
+ DPRINT1("Umpnpmgr: main() started\n");
+
+ StartServiceCtrlDispatcherW(ServiceTable);
+
+ DPRINT1("Umpnpmgr: main() done\n");
return 0;
}
Modified: trunk/reactos/base/system/services/database.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/datab…
==============================================================================
--- trunk/reactos/base/system/services/database.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/services/database.c [iso-8859-1] Fri Feb 19 21:03:11 2010
@@ -1054,7 +1054,7 @@
{
Group->ServicesRunning = TRUE;
}
- Service->Status.dwCurrentState = SERVICE_RUNNING;
+ Service->Status.dwCurrentState = SERVICE_START_PENDING;
}
#if 0
else
Modified: trunk/reactos/dll/win32/syssetup/install.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/syssetup/install…
==============================================================================
--- trunk/reactos/dll/win32/syssetup/install.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/syssetup/install.c [iso-8859-1] Fri Feb 19 21:03:11 2010
@@ -20,7 +20,7 @@
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: System setup
- * FILE: lib/syssetup/install.c
+ * FILE: dll/win32/syssetup/install.c
* PROGRAMER: Eric Kohl
*/
@@ -473,30 +473,100 @@
static BOOL
EnableUserModePnpManager(VOID)
{
+ SERVICE_STATUS_PROCESS ServiceStatus;
SC_HANDLE hSCManager = NULL;
SC_HANDLE hService = NULL;
+ DWORD dwStartTickCount;
+ DWORD dwOldCheckPoint;
+ DWORD BytesNeeded = 0;
+ DWORD dwWaitTime;
+ DWORD dwMaxWait;
BOOL ret = FALSE;
hSCManager = OpenSCManager(NULL, NULL, 0);
if (hSCManager == NULL)
goto cleanup;
- hService = OpenServiceW(hSCManager, L"PlugPlay", SERVICE_CHANGE_CONFIG |
SERVICE_START);
+ hService = OpenServiceW(hSCManager,
+ L"PlugPlay",
+ SERVICE_CHANGE_CONFIG | SERVICE_START |
SERVICE_QUERY_STATUS);
if (hService == NULL)
goto cleanup;
- ret = ChangeServiceConfigW(
- hService,
- SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ ret = ChangeServiceConfigW(hService,
+ SERVICE_NO_CHANGE,
+ SERVICE_AUTO_START,
+ SERVICE_NO_CHANGE,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL);
if (!ret)
goto cleanup;
ret = StartServiceW(hService, 0, NULL);
if (!ret)
+ {
+ /* If the service is already running, just return TRUE */
+ ret = GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
goto cleanup;
-
- ret = TRUE;
+ }
+
+ ret = QueryServiceStatusEx(hService,
+ SC_STATUS_PROCESS_INFO,
+ (LPBYTE)&ServiceStatus,
+ sizeof(SERVICE_STATUS_PROCESS),
+ &BytesNeeded);
+ if (!ret)
+ goto cleanup;
+
+ /* We don't want to wait for more than 30 seconds */
+ dwMaxWait = 30000;
+ dwStartTickCount = GetTickCount();
+
+ /* Loop until it's running */
+ while (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
+ {
+ dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+ dwWaitTime = ServiceStatus.dwWaitHint / 10;
+
+ /* Get the latest status info */
+ if (!QueryServiceStatusEx(hService,
+ SC_STATUS_PROCESS_INFO,
+ (LPBYTE)&ServiceStatus,
+ sizeof(SERVICE_STATUS_PROCESS),
+ &BytesNeeded))
+ {
+ /* Something went wrong... */
+ break;
+ }
+
+ /* Is the service making progress? */
+ if (ServiceStatus.dwCheckPoint > dwOldCheckPoint)
+ {
+ /* It is, get the latest tickcount to reset the max wait time */
+ dwStartTickCount = GetTickCount();
+ dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+ }
+ else
+ {
+ /* It's not, make sure we haven't exceeded our wait time */
+ if (GetTickCount() >= dwStartTickCount + dwMaxWait)
+ {
+ /* We have, give up */
+ break;
+ }
+ }
+
+ /* Adjust the wait hint times */
+ if (dwWaitTime < 200)
+ dwWaitTime = 200;
+ else if (dwWaitTime > 10000)
+ dwWaitTime = 10000;
+
+ /* Wait before trying again */
+ Sleep(dwWaitTime);
+ }
+
+ ret = ServiceStatus.dwCurrentState == SERVICE_RUNNING;
cleanup:
if (hSCManager != NULL)