xref: /reactos/base/services/wuauserv/wuauserv.c (revision e4930be4)
1 /*
2 * PROJECT:          ReactOS Update Service
3 * LICENSE:          GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE:          Automatic Updates service stub.
5 *                   Stub is required for some application at the installation phase.
6 * COPYRIGHT:        Copyright 2018 Denis Malikov (filedem@gmail.com)
7 */
8 
9 #include "wuauserv.h"
10 
11 /* GLOBALS ******************************************************************/
12 
13 static WCHAR ServiceName[] = L"wuauserv";
14 
15 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
16 static SERVICE_STATUS ServiceStatus;
17 
18 static HANDLE hStopEvent = NULL;
19 
20 /* FUNCTIONS *****************************************************************/
21 
22 static VOID
23 UpdateServiceStatus(DWORD dwState)
24 {
25     ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
26     ServiceStatus.dwCurrentState = dwState;
27     ServiceStatus.dwControlsAccepted = 0;
28     ServiceStatus.dwWin32ExitCode = 0;
29     ServiceStatus.dwServiceSpecificExitCode = 0;
30     ServiceStatus.dwCheckPoint = 0;
31 
32     if (dwState == SERVICE_START_PENDING ||
33         dwState == SERVICE_STOP_PENDING ||
34         dwState == SERVICE_PAUSE_PENDING ||
35         dwState == SERVICE_CONTINUE_PENDING)
36         ServiceStatus.dwWaitHint = 1000;
37     else
38         ServiceStatus.dwWaitHint = 0;
39 
40     if (dwState == SERVICE_RUNNING)
41         ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
42 
43     SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
44     DPRINT1("WU UpdateServiceStatus(%lu) called\n", dwState);
45 }
46 
47 static DWORD WINAPI
48 ServiceControlHandler(DWORD dwControl,
49                       DWORD dwEventType,
50                       LPVOID lpEventData,
51                       LPVOID lpContext)
52 {
53     switch (dwControl)
54     {
55         case SERVICE_CONTROL_STOP:
56             DPRINT1("WU ServiceControlHandler(SERVICE_CONTROL_STOP) received\n");
57             SetEvent(hStopEvent);
58             UpdateServiceStatus(SERVICE_STOP_PENDING);
59             return ERROR_SUCCESS;
60 
61         case SERVICE_CONTROL_PAUSE:
62             DPRINT1("WU ServiceControlHandler(SERVICE_CONTROL_PAUSE) received\n");
63             UpdateServiceStatus(SERVICE_PAUSED);
64             return ERROR_SUCCESS;
65 
66         case SERVICE_CONTROL_CONTINUE:
67             DPRINT1("WU ServiceControlHandler(SERVICE_CONTROL_CONTINUE) received\n");
68             UpdateServiceStatus(SERVICE_RUNNING);
69             return ERROR_SUCCESS;
70 
71         case SERVICE_CONTROL_INTERROGATE:
72             DPRINT1("WU ServiceControlHandler(SERVICE_CONTROL_INTERROGATE) received\n");
73             SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
74             return ERROR_SUCCESS;
75 
76         case SERVICE_CONTROL_SHUTDOWN:
77             DPRINT1("WU ServiceControlHandler(SERVICE_CONTROL_SHUTDOWN) received\n");
78             SetEvent(hStopEvent);
79             UpdateServiceStatus(SERVICE_STOP_PENDING);
80             return ERROR_SUCCESS;
81 
82         default :
83             DPRINT1("WU ServiceControlHandler(Control %lu) received\n", dwControl);
84             return ERROR_CALL_NOT_IMPLEMENTED;
85     }
86 }
87 
88 VOID WINAPI
89 ServiceMain(DWORD argc, LPTSTR *argv)
90 {
91     UNREFERENCED_PARAMETER(argc);
92     UNREFERENCED_PARAMETER(argv);
93 
94     DPRINT("WU ServiceMain() called\n");
95 
96     ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
97                                                         ServiceControlHandler,
98                                                         NULL);
99     if (!ServiceStatusHandle)
100     {
101         DPRINT1("RegisterServiceCtrlHandlerExW() failed (Error %lu)\n", GetLastError());
102         return;
103     }
104 
105     hStopEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
106     if (hStopEvent == NULL)
107     {
108         DPRINT1("CreateEvent() failed (Error %lu)\n", GetLastError());
109         goto done;
110     }
111 
112     UpdateServiceStatus(SERVICE_RUNNING);
113 
114     WaitForSingleObject(hStopEvent, INFINITE);
115     CloseHandle(hStopEvent);
116 
117 done:
118     UpdateServiceStatus(SERVICE_STOPPED);
119 }
120 
121 BOOL WINAPI
122 DllMain(HINSTANCE hinstDLL,
123         DWORD fdwReason,
124         LPVOID lpvReserved)
125 {
126     switch (fdwReason)
127     {
128         case DLL_PROCESS_ATTACH:
129             DisableThreadLibraryCalls(hinstDLL);
130             break;
131 
132         case DLL_PROCESS_DETACH:
133             break;
134     }
135 
136     return TRUE;
137 }
138