2
Copyright (c) 2006 Talha Tariq [ talha.tariq@gmail.com ]
3
All rights are reserved.
5
Permission to use, copy, modify, and distribute this software
6
for any purpose and without any fee is hereby granted,
7
provided this notice is included in its entirety in the
8
documentation and in the source files.
10
This software and any related documentation is provided "as is"
11
without any warranty of any kind, either express or implied,
12
including, without limitation, the implied warranties of
13
merchantibility or fitness for a particular purpose. The entire
14
risk arising out of use or performance of the software remains
24
#include "RemComSvc.h"
25
#include "../RemCom.h"
27
SERVICE_STATUS ServiceStatus;
28
SERVICE_STATUS_HANDLE ServiceStatusHandle;
30
HANDLE hStopServiceEvent = NULL;
32
VOID WINAPI RemComStart (DWORD argc, LPTSTR *argv); // prototype for the starting point of the service
33
VOID WINAPI RemComCtrlHandler (DWORD opcode); // prototype for the control handler callback function of the service
34
DWORD IsService( BOOL& );
35
void CommunicationPoolThread(PVOID);
38
int _tmain( int, LPTSTR* )
40
SERVICE_TABLE_ENTRY DispatchTable[] = {
41
{ SERVICENAME, RemComStart },
46
// This process should be a service :)
47
IsService( bService );
49
// _tprintf( _T("A service Cannot be started directly.\n") );
50
CommunicationPoolThread(NULL);
54
return StartServiceCtrlDispatcher( DispatchTable);
60
// Open service manager
61
SC_HANDLE hSCM = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
67
SC_HANDLE hService = ::OpenService( hSCM, SERVICENAME, SERVICE_ALL_ACCESS );
71
::CloseServiceHandle(hSCM);
75
// Deletes service from service database
76
DeleteService( hService );
79
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
80
ServiceStatus.dwCheckPoint = 0;
81
ServiceStatus.dwWaitHint = 0;
82
ServiceStatus.dwWin32ExitCode = 0;
83
ServiceStatus.dwServiceSpecificExitCode = 0;
84
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
86
::CloseServiceHandle(hService);
87
::CloseServiceHandle(hSCM);
91
VOID WINAPI RemComStart (DWORD, LPTSTR* )
94
DWORD specificError = 0;
96
// Prepare the ServiceStatus structure that will be used for the
97
// comunication with SCM(Service Control Manager).
98
// If you fully under stand the members of this structure, feel
99
// free to change these values :o)
100
ServiceStatus.dwServiceType = SERVICE_WIN32;
101
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
102
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
103
ServiceStatus.dwWin32ExitCode = 0;
104
ServiceStatus.dwServiceSpecificExitCode = 0;
105
ServiceStatus.dwCheckPoint = 0;
106
ServiceStatus.dwWaitHint = 0;
108
// Here we register the control handler for our service.
109
// We tell the SCM about a call back function that SCM will
110
// call when user tries to Start, Stop or Pause your service.
111
ServiceStatusHandle = RegisterServiceCtrlHandler(
112
TEXT("Service"), RemComCtrlHandler );
114
if (ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
117
// Handle error condition
118
if (status != NO_ERROR)
120
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
121
ServiceStatus.dwCheckPoint = 0;
122
ServiceStatus.dwWaitHint = 0;
123
ServiceStatus.dwWin32ExitCode = status;
124
ServiceStatus.dwServiceSpecificExitCode = specificError;
126
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
130
// Initialization complete - report running status.
131
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
132
ServiceStatus.dwCheckPoint = 0;
133
ServiceStatus.dwWaitHint = 0;
135
if (!SetServiceStatus (ServiceStatusHandle, &ServiceStatus))
136
status = GetLastError();
139
// Start the main thread
140
hStopServiceEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
141
_beginthread( _ServiceMain, 0, NULL );
147
// Service Ctrl handler
148
VOID WINAPI RemComCtrlHandler (DWORD Opcode)
154
case SERVICE_CONTROL_STOP:
155
// Signal the event to stop the main thread
156
SetEvent( hStopServiceEvent );
158
ServiceStatus.dwWin32ExitCode = 0;
159
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
160
ServiceStatus.dwCheckPoint = 0;
161
ServiceStatus.dwWaitHint = 0;
163
if (!SetServiceStatus (ServiceStatusHandle,
166
status = GetLastError();
170
case SERVICE_CONTROL_INTERROGATE:
171
// Fall through to send current status.
175
// Send current status.
176
if (!SetServiceStatus (ServiceStatusHandle, &ServiceStatus))
178
status = GetLastError();
183
// This process is a service or is not ?
184
DWORD IsService( BOOL& isService )
186
DWORD pID = GetCurrentProcessId();
187
HANDLE hProcessToken = NULL;
188
DWORD groupLength = 50;
189
PTOKEN_GROUPS groupInfo = NULL;
191
SID_IDENTIFIER_AUTHORITY siaNt = SECURITY_NT_AUTHORITY;
192
PSID pInteractiveSid = NULL;
193
PSID pServiceSid = NULL;
195
DWORD dwRet = NO_ERROR;
198
BOOL isInteractive = FALSE;
203
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pID );
206
if (!::OpenProcessToken( hProcess, TOKEN_QUERY, &hProcessToken) )
208
dwRet = ::GetLastError();
212
// allocate a buffer of default size
213
groupInfo = (PTOKEN_GROUPS)::LocalAlloc(0, groupLength);
214
if (groupInfo == NULL)
216
dwRet = ::GetLastError();
220
// try to get the info
221
if (!::GetTokenInformation(hProcessToken, TokenGroups,
222
groupInfo, groupLength, &groupLength))
224
// if buffer was too small, allocate to proper size, otherwise error
225
if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
227
dwRet = ::GetLastError();
231
::LocalFree(groupInfo);
233
groupInfo = (PTOKEN_GROUPS)::LocalAlloc(0, groupLength);
234
if (groupInfo == NULL)
236
dwRet = ::GetLastError();
240
if (!GetTokenInformation(hProcessToken, TokenGroups,
241
groupInfo, groupLength, &groupLength))
243
dwRet = ::GetLastError();
248
// create comparison sids
249
if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_INTERACTIVE_RID,
250
0, 0, 0, 0, 0, 0, 0, &pInteractiveSid))
252
dwRet = ::GetLastError();
256
if (!AllocateAndInitializeSid(&siaNt, 1, SECURITY_SERVICE_RID,
257
0, 0, 0, 0, 0, 0, 0, &pServiceSid))
259
dwRet = ::GetLastError();
264
for (ndx = 0; ndx < groupInfo->GroupCount ; ndx += 1)
266
SID_AND_ATTRIBUTES sanda = groupInfo->Groups[ndx];
267
PSID pSid = sanda.Sid;
269
if (::EqualSid(pSid, pInteractiveSid))
271
isInteractive = TRUE;
275
else if (::EqualSid(pSid, pServiceSid))
278
isInteractive = FALSE;
283
if ( !( isService || isInteractive ) )
288
::FreeSid( pServiceSid );
290
if ( pInteractiveSid )
291
::FreeSid( pInteractiveSid );
294
::LocalFree( groupInfo );
297
::CloseHandle( hProcessToken );
300
::CloseHandle( hProcess );