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/umpn... ============================================================================== --- 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/databa... ============================================================================== --- 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)