xref: /reactos/win32ss/printing/base/spoolsv/main.c (revision 1734f297)
1 /*
2  * PROJECT:     ReactOS Print Spooler Service
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Main functions
5  * COPYRIGHT:   Copyright 2015 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 SERVICE_STATUS_HANDLE hServiceStatus;
11 SERVICE_STATUS ServiceStatus;
12 WCHAR wszServiceName[] = L"Spooler";
13 
14 static void
15 _UpdateServiceStatus(DWORD dwNewStatus, DWORD dwCheckPoint)
16 {
17     ServiceStatus.dwCheckPoint = dwCheckPoint;
18     ServiceStatus.dwCurrentState = dwNewStatus;
19     SetServiceStatus(hServiceStatus, &ServiceStatus);
20 }
21 
22 static DWORD WINAPI
23 _ServiceControlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
24 {
25     switch (dwControl)
26     {
27         case SERVICE_CONTROL_SHUTDOWN:
28         case SERVICE_CONTROL_STOP:
29             _UpdateServiceStatus(SERVICE_STOP_PENDING, 1);
30             RpcMgmtStopServerListening(NULL);
31             _UpdateServiceStatus(SERVICE_STOPPED, 0);
32             return NO_ERROR;
33 
34         case SERVICE_CONTROL_INTERROGATE:
35             return NO_ERROR;
36 
37         default:
38             return ERROR_CALL_NOT_IMPLEMENTED;
39     }
40 }
41 
42 static VOID WINAPI
43 _ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
44 {
45     HANDLE hThread;
46 
47     UNREFERENCED_PARAMETER(dwArgc);
48     UNREFERENCED_PARAMETER(lpszArgv);
49 
50     // Register our service for control
51     hServiceStatus = RegisterServiceCtrlHandlerExW(wszServiceName, _ServiceControlHandlerEx, NULL);
52 
53     // Report initial SERVICE_START_PENDING status
54     ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
55     ServiceStatus.dwServiceSpecificExitCode = 0;
56     ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
57     ServiceStatus.dwWaitHint = 4000;
58     ServiceStatus.dwWin32ExitCode = NO_ERROR;
59     _UpdateServiceStatus(SERVICE_START_PENDING, 0);
60 
61     // Create a thread for serving RPC requests
62     hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)LrpcThreadProc, NULL, 0, NULL);
63     if (!hThread)
64     {
65         ERR("CreateThread failed with error %u!\n", GetLastError());
66         _UpdateServiceStatus(SERVICE_STOPPED, 0);
67         return;
68     }
69 
70     // We don't need the thread handle. Keeping it open blocks the thread from terminating.
71     CloseHandle(hThread);
72 
73     // Initialize the routing layer in spoolss.dll
74     if (!InitializeRouter(hServiceStatus))
75     {
76         ERR("InitializeRouter failed with error %lu!\n", GetLastError());
77         _UpdateServiceStatus(SERVICE_STOPPED, 0);
78         return;
79     }
80 
81     // We're alive!
82     _UpdateServiceStatus(SERVICE_RUNNING, 0);
83 }
84 
85 int
86 wmain(int argc, WCHAR* argv[])
87 {
88     SERVICE_TABLE_ENTRYW ServiceTable[] =
89     {
90         {wszServiceName, _ServiceMain},
91         {NULL, NULL}
92     };
93 
94     UNREFERENCED_PARAMETER(argc);
95     UNREFERENCED_PARAMETER(argv);
96 
97     StartServiceCtrlDispatcherW(ServiceTable);
98 
99     return 0;
100 }
101