10 #include "OpenSecUSBEventSvcLog.h"
12 #pragma comment(lib, "advapi32.lib")
14 #define SVCNAME TEXT("OpenSecUSBEventSvc")
16 //sc create "USBEventSvc" binPath= "C:\Users\BarthaM\Documents\Visual Studio 2010\Projects\USBEventSvc\Debug\USBEventSvc.exe"
17 //sc delete "USBEventSvc"
19 // USB Raw Device Interface Class GUID
20 //{ 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51,0xed } }
21 // Disk Device Interface Class GUID
22 //{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } }
24 // This GUID is for all USB serial host PnP drivers
25 //GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72, 0x8a, 0x6d, 0xb5, 0x4c, 0x2b, 0x4f, 0xc8, 0x35 };
27 GUID WceusbshGUID = { 0x88bae032, 0x5a81, 0x49f0, 0xbc, 0x3d, 0xa4, 0xff, 0x13, 0x82, 0x16, 0xd6 };
28 //DEFINE_GUID(GUID_CLASS_STORAGE_VOLUME, 0x53F5630DL, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B);
31 SERVICE_STATUS gSvcStatus;
32 SERVICE_STATUS_HANDLE gSvcStatusHandle = NULL;
33 HANDLE ghSvcStopEvent = NULL;
34 HDEVNOTIFY ghDeviceNotify;
36 DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
38 VOID SvcInstall(void);
39 VOID WINAPI SvcCtrlHandler(DWORD);
40 VOID WINAPI SvcMain(DWORD, LPTSTR *);
42 VOID ReportSvcStatus(DWORD, DWORD, DWORD);
43 VOID SvcInit(DWORD, LPTSTR *);
44 VOID SvcReportEvent(WORD, LPTSTR);
47 // DoRegisterDeviceInterfaceToHwnd
48 // Registers an HWND for notification of changes in the device interfaces
49 // for the specified interface class GUID.
51 // InterfaceClassGuid - The interface class GUID for the device
53 // hWnd - Window handle to receive notifications.
54 // hDeviceNotify - Receives the device notification handle. On failure,
55 // this value is NULL.
57 // If the function succeeds, the return value is TRUE.
58 // If the function fails, the return value is FALSE.
60 // RegisterDeviceNotification also allows a service handle be used,
61 // so a similar wrapper function to this one supporting that scenario
62 // could be made from this template.
64 BOOL DoRegisterDeviceInterfaceToHwnd(void) {
65 DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
66 ZeroMemory(&NotificationFilter, sizeof (NotificationFilter));
67 NotificationFilter.dbcc_size = sizeof (DEV_BROADCAST_DEVICEINTERFACE);
68 NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
69 NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
70 memcpy(&(NotificationFilter.dbcc_classguid), &(GUID_DEVINTERFACE_USB_DEVICE), sizeof(struct _GUID));
72 ghDeviceNotify = RegisterDeviceNotification(gSvcStatusHandle,
74 DEVICE_NOTIFY_SERVICE_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
76 if (NULL == ghDeviceNotify) {
77 SvcReportEvent(EVENTLOG_ERROR_TYPE, _T("RegisterDeviceNotification failed!"));
85 // Entry point for the process
93 void __cdecl _tmain(int argc, TCHAR *argv[]) {
94 // If command-line parameter is "install", install the service.
95 // Otherwise, the service is probably being started by the SCM.
96 if (lstrcmpi(argv[1], TEXT("install")) == 0){
101 // TO_DO: Add any additional services for the process to this table.
102 SERVICE_TABLE_ENTRY DispatchTable[] = {
103 { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
107 // This call returns when the service has stopped.
108 // The process should simply terminate when the call returns.
109 if (!StartServiceCtrlDispatcher(DispatchTable)) {
110 SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("StartServiceCtrlDispatcher"));
115 // Installs a service in the SCM database
124 SC_HANDLE schSCManager;
125 SC_HANDLE schService;
126 TCHAR szPath[MAX_PATH];
128 if (!GetModuleFileName(NULL, szPath, MAX_PATH)) {
129 printf("Cannot install service (%d)\n", GetLastError());
133 // Get a handle to the SCM database. local computer, ServicesActive database, full access rights
134 schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
135 if (NULL == schSCManager) {
136 printf("Open SCManager failed (%d)\n", GetLastError());
140 // Create the service
141 schService = CreateService(
142 schSCManager, // SCM database
143 SVCNAME, // name of service
144 SVCNAME, // service name to display
145 SERVICE_ALL_ACCESS, // desired access
146 SERVICE_WIN32_OWN_PROCESS, // service type
147 SERVICE_DEMAND_START, // start type
148 SERVICE_ERROR_NORMAL, // error control type
149 szPath, // path to service's binary
150 NULL, // no load ordering group
151 NULL, // no tag identifier
152 NULL, // no dependencies
153 NULL, // LocalSystem account
154 NULL); // no password
156 if (schService == NULL) {
157 printf("CreateService failed (%d)\n", GetLastError());
158 CloseServiceHandle(schSCManager);
161 else printf("Service installed successfully\n");
163 CloseServiceHandle(schService);
164 CloseServiceHandle(schSCManager);
169 // Entry point for the service
172 // dwArgc - Number of arguments in the lpszArgv array
173 // lpszArgv - Array of strings. The first string is the name of
174 // the service and subsequent strings are passed by the process
175 // that called the StartService function to start the service.
180 VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv) {
181 // Register the handler function for the service
182 gSvcStatusHandle = RegisterServiceCtrlHandlerEx(SVCNAME, (LPHANDLER_FUNCTION_EX)SvcCtrlHandler, 0);
183 if (!gSvcStatusHandle) {
184 SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("RegisterServiceCtrlHandler"));
188 // These SERVICE_STATUS members remain as set here
189 gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
190 gSvcStatus.dwServiceSpecificExitCode = 0;
192 // Report initial status to the SCM
193 ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
195 if (!DoRegisterDeviceInterfaceToHwnd()) {
196 // Terminate on failure.
197 SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("DoRegisterDeviceInterfaceToHwnd"));
201 // default security attributes, manual reset, not signaled, no name
202 ghSvcStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
203 if (ghSvcStopEvent == NULL) {
204 ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
208 // Report running status when initialization is complete.
209 ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
210 SvcReportEvent(EVENTLOG_INFORMATION_TYPE, TEXT("OpenSecUSBEventSvc is running"));
212 // Wait until our worker thread exits signaling that the service needs to stop
213 WaitForSingleObject(ghSvcStopEvent, INFINITE);
215 SvcReportEvent(EVENTLOG_INFORMATION_TYPE, TEXT("OpenSecUSBEventSvc is exiting"));
216 // Perform any cleanup tasks
217 CloseHandle(ghSvcStopEvent);
219 // Report running status when initialization is complete.
220 ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
223 void NotifyOpenSecManager (void) {
224 HINTERNET hSession = NULL,
227 BOOL bResults = FALSE;
229 //devices_json = url_encode(devices_json);
230 // Use WinHttpOpen to obtain a session handle.
231 hSession = WinHttpOpen(L"OpenSecUSBEventSvc", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
233 SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpOpen failed! "));
236 // Specify an HTTP server.
237 hConnect = WinHttpConnect(hSession, L"localhost", 8080, 0);
239 SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpConnect failed! "));
243 // Create an HTTP request handle.
244 hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/device_change", NULL, WINHTTP_NO_REFERER, NULL, NULL);
246 SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpOpenRequest failed! "));
251 bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
253 SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpSendRequest failed! "));
259 // bResults = WinHttpReceiveResponse(hRequest, NULL);
262 //LPVOID lpOutBuffer = NULL;
264 // WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
265 // // Allocate memory for the buffer.
266 // if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
267 // lpOutBuffer = new WCHAR[dwSize / sizeof(WCHAR)];
268 // // Now, use WinHttpQueryHeaders to retrieve the header.
269 // bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, lpOutBuffer, &dwSize, WINHTTP_NO_HEADER_INDEX);
272 //// Print the header contents.
274 // printf("Header contents: \n%S", lpOutBuffer);
275 //// Free the allocated memory.
276 //delete [] lpOutBuffer;
282 // Sets the current service status and reports it to the SCM.
285 // dwCurrentState - The current state (see SERVICE_STATUS)
286 // dwWin32ExitCode - The system error code
287 // dwWaitHint - Estimated time for pending operation,
293 VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) {
294 static DWORD dwCheckPoint = 1;
295 // Fill in the SERVICE_STATUS structure.
296 gSvcStatus.dwCurrentState = dwCurrentState;
297 gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
298 gSvcStatus.dwWaitHint = dwWaitHint;
300 if (dwCurrentState == SERVICE_START_PENDING)
301 gSvcStatus.dwControlsAccepted = 0;
302 else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
304 if ((dwCurrentState == SERVICE_RUNNING) ||
305 (dwCurrentState == SERVICE_STOPPED))
306 gSvcStatus.dwCheckPoint = 0;
307 else gSvcStatus.dwCheckPoint = dwCheckPoint++;
309 // Report the status of the service to the SCM.
310 SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
314 // Called by SCM whenever a control code is sent to the service
315 // using the ControlService function.
318 // dwCtrl - control code
323 VOID WINAPI SvcCtrlHandler(DWORD dwCtrl) {
324 // Handle the requested control code.
326 case SERVICE_CONTROL_STOP:
327 UnregisterDeviceNotification(ghDeviceNotify);
328 ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
329 // Signal the service to stop.
330 SetEvent(ghSvcStopEvent);
331 ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
334 case SERVICE_CONTROL_INTERROGATE:
337 case SERVICE_CONTROL_DEVICEEVENT:
338 SvcReportEvent(EVENTLOG_INFORMATION_TYPE, _T("Received SERVICE_CONTROL_DEVICEEVENT"));
339 //NotifyOpenSecManager();
349 // Logs messages to the event log
352 // szFunction - name of function that failed
358 // The service must have an entry in the Application event log.
360 VOID SvcReportEvent(WORD type, LPTSTR szFunction) {
362 LPCTSTR lpszStrings[2];
365 hEventSource = RegisterEventSource(NULL, SVCNAME);
367 if (NULL != hEventSource) {
368 if (type == EVENTLOG_ERROR_TYPE)
369 StringCchPrintf(Buffer, 80, TEXT("Error has occured. %s failed with %d"), szFunction, GetLastError());
371 StringCchPrintf(Buffer, 80, TEXT("%s"), szFunction);
373 lpszStrings[0] = SVCNAME;
374 lpszStrings[1] = Buffer;
376 if (type == EVENTLOG_ERROR_TYPE)
377 ReportEvent(hEventSource,
380 SVC_ERROR, // event identifier
381 NULL, // no security identifier
382 2, // size of lpszStrings array
384 lpszStrings, // array of strings
385 NULL); // no binary data
387 ReportEvent(hEventSource,
390 SVC_ERROR, // event identifier
391 NULL, // no security identifier
392 2, // size of lpszStrings array
394 lpszStrings, // array of strings
395 NULL); // no binary data
397 DeregisterEventSource(hEventSource);