server/windows/USBEventSvc/OpenSecUSBEventSvc/OpenSecUSBEventSvc.cpp
author mb
Tue, 03 Dec 2013 18:04:46 +0100
changeset 7 903480cebdfb
child 9 50b1cfe9576b
permissions -rw-r--r--
added vmmanager and USBEventSvc
mb@7
     1
#include <InitGuid.h>
mb@7
     2
#include <Windows.h>
mb@7
     3
#include <SetupApi.h>
mb@7
     4
mb@7
     5
#include <tchar.h>
mb@7
     6
#include <strsafe.h>
mb@7
     7
#include <dbt.h>
mb@7
     8
#include <usbiodef.h>
mb@7
     9
#include <Winhttp.h>
mb@7
    10
#include "OpenSecUSBEventSvcLog.h"
mb@7
    11
mb@7
    12
#pragma comment(lib, "advapi32.lib")
mb@7
    13
mb@7
    14
#define SVCNAME TEXT("OpenSecUSBEventSvc")
mb@7
    15
mb@7
    16
//sc create "USBEventSvc" binPath= "C:\Users\BarthaM\Documents\Visual Studio 2010\Projects\USBEventSvc\Debug\USBEventSvc.exe"
mb@7
    17
//sc delete "USBEventSvc"
mb@7
    18
mb@7
    19
// USB Raw Device Interface Class GUID
mb@7
    20
//{ 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51,0xed } }
mb@7
    21
// Disk Device Interface Class GUID
mb@7
    22
//{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } }
mb@7
    23
mb@7
    24
// This GUID is for all USB serial host PnP drivers
mb@7
    25
//GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72, 0x8a, 0x6d, 0xb5, 0x4c, 0x2b, 0x4f, 0xc8, 0x35 };
mb@7
    26
mb@7
    27
GUID WceusbshGUID = { 0x88bae032, 0x5a81, 0x49f0, 0xbc, 0x3d, 0xa4, 0xff, 0x13, 0x82, 0x16, 0xd6 };
mb@7
    28
//DEFINE_GUID(GUID_CLASS_STORAGE_VOLUME, 0x53F5630DL, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B);
mb@7
    29
mb@7
    30
mb@7
    31
SERVICE_STATUS          gSvcStatus;
mb@7
    32
SERVICE_STATUS_HANDLE   gSvcStatusHandle = NULL;
mb@7
    33
HANDLE                  ghSvcStopEvent = NULL;
mb@7
    34
HDEVNOTIFY				ghDeviceNotify;
mb@7
    35
mb@7
    36
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
mb@7
    37
mb@7
    38
VOID SvcInstall(void);
mb@7
    39
VOID WINAPI SvcCtrlHandler(DWORD);
mb@7
    40
VOID WINAPI SvcMain(DWORD, LPTSTR *);
mb@7
    41
mb@7
    42
VOID ReportSvcStatus(DWORD, DWORD, DWORD);
mb@7
    43
VOID SvcInit(DWORD, LPTSTR *);
mb@7
    44
VOID SvcReportEvent(WORD, LPTSTR);
mb@7
    45
mb@7
    46
mb@7
    47
// DoRegisterDeviceInterfaceToHwnd
mb@7
    48
//     Registers an HWND for notification of changes in the device interfaces
mb@7
    49
//     for the specified interface class GUID. 
mb@7
    50
// Parameters:
mb@7
    51
//     InterfaceClassGuid - The interface class GUID for the device 
mb@7
    52
//         interfaces. 
mb@7
    53
//     hWnd - Window handle to receive notifications.
mb@7
    54
//     hDeviceNotify - Receives the device notification handle. On failure, 
mb@7
    55
//         this value is NULL.
mb@7
    56
// Return Value:
mb@7
    57
//     If the function succeeds, the return value is TRUE.
mb@7
    58
//     If the function fails, the return value is FALSE.
mb@7
    59
// Note:
mb@7
    60
//     RegisterDeviceNotification also allows a service handle be used,
mb@7
    61
//     so a similar wrapper function to this one supporting that scenario
mb@7
    62
//     could be made from this template.
mb@7
    63
mb@7
    64
BOOL DoRegisterDeviceInterfaceToHwnd(void) {
mb@7
    65
	DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
mb@7
    66
	ZeroMemory(&NotificationFilter, sizeof (NotificationFilter));
mb@7
    67
	NotificationFilter.dbcc_size = sizeof (DEV_BROADCAST_DEVICEINTERFACE);
mb@7
    68
	NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
mb@7
    69
	NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
mb@7
    70
	memcpy(&(NotificationFilter.dbcc_classguid), &(GUID_DEVINTERFACE_USB_DEVICE), sizeof(struct _GUID));
mb@7
    71
mb@7
    72
	ghDeviceNotify = RegisterDeviceNotification(gSvcStatusHandle,
mb@7
    73
		&NotificationFilter, 
mb@7
    74
		DEVICE_NOTIFY_SERVICE_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
mb@7
    75
mb@7
    76
	if (NULL == ghDeviceNotify) {
mb@7
    77
		SvcReportEvent(EVENTLOG_ERROR_TYPE, _T("RegisterDeviceNotification failed!"));
mb@7
    78
		return FALSE;
mb@7
    79
	}
mb@7
    80
	return TRUE;
mb@7
    81
}
mb@7
    82
mb@7
    83
//
mb@7
    84
// Purpose: 
mb@7
    85
//   Entry point for the process
mb@7
    86
//
mb@7
    87
// Parameters:
mb@7
    88
//   None
mb@7
    89
// 
mb@7
    90
// Return value:
mb@7
    91
//   None
mb@7
    92
//
mb@7
    93
void __cdecl _tmain(int argc, TCHAR *argv[]) {
mb@7
    94
	// If command-line parameter is "install", install the service. 
mb@7
    95
	// Otherwise, the service is probably being started by the SCM.
mb@7
    96
	if (lstrcmpi(argv[1], TEXT("install")) == 0){
mb@7
    97
		SvcInstall();
mb@7
    98
		return;
mb@7
    99
	}
mb@7
   100
mb@7
   101
	// TO_DO: Add any additional services for the process to this table.
mb@7
   102
	SERVICE_TABLE_ENTRY DispatchTable[] = {
mb@7
   103
		{ SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
mb@7
   104
		{ NULL, NULL }
mb@7
   105
	};
mb@7
   106
mb@7
   107
	// This call returns when the service has stopped. 
mb@7
   108
	// The process should simply terminate when the call returns.
mb@7
   109
	if (!StartServiceCtrlDispatcher(DispatchTable)) {
mb@7
   110
		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("StartServiceCtrlDispatcher"));
mb@7
   111
	}
mb@7
   112
}
mb@7
   113
mb@7
   114
// Purpose: 
mb@7
   115
//   Installs a service in the SCM database
mb@7
   116
//
mb@7
   117
// Parameters:
mb@7
   118
//   None
mb@7
   119
// 
mb@7
   120
// Return value:
mb@7
   121
//   None
mb@7
   122
//
mb@7
   123
VOID SvcInstall() {
mb@7
   124
	SC_HANDLE schSCManager;
mb@7
   125
	SC_HANDLE schService;
mb@7
   126
	TCHAR szPath[MAX_PATH];
mb@7
   127
mb@7
   128
	if (!GetModuleFileName(NULL, szPath, MAX_PATH)) {
mb@7
   129
		printf("Cannot install service (%d)\n", GetLastError());
mb@7
   130
		return;
mb@7
   131
	}
mb@7
   132
mb@7
   133
	// Get a handle to the SCM database. local computer, ServicesActive database, full access rights 
mb@7
   134
	schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
mb@7
   135
	if (NULL == schSCManager) {
mb@7
   136
		printf("Open SCManager failed (%d)\n", GetLastError());
mb@7
   137
		return;
mb@7
   138
	}
mb@7
   139
mb@7
   140
	// Create the service
mb@7
   141
	schService = CreateService(
mb@7
   142
		schSCManager,              // SCM database 
mb@7
   143
		SVCNAME,                   // name of service 
mb@7
   144
		SVCNAME,                   // service name to display 
mb@7
   145
		SERVICE_ALL_ACCESS,        // desired access 
mb@7
   146
		SERVICE_WIN32_OWN_PROCESS, // service type 
mb@7
   147
		SERVICE_DEMAND_START,      // start type 
mb@7
   148
		SERVICE_ERROR_NORMAL,      // error control type 
mb@7
   149
		szPath,                    // path to service's binary 
mb@7
   150
		NULL,                      // no load ordering group 
mb@7
   151
		NULL,                      // no tag identifier 
mb@7
   152
		NULL,                      // no dependencies 
mb@7
   153
		NULL,                      // LocalSystem account 
mb@7
   154
		NULL);                     // no password 
mb@7
   155
mb@7
   156
	if (schService == NULL) {
mb@7
   157
		printf("CreateService failed (%d)\n", GetLastError());
mb@7
   158
		CloseServiceHandle(schSCManager);
mb@7
   159
		return;
mb@7
   160
	}
mb@7
   161
	else printf("Service installed successfully\n");
mb@7
   162
mb@7
   163
	CloseServiceHandle(schService);
mb@7
   164
	CloseServiceHandle(schSCManager);
mb@7
   165
}
mb@7
   166
mb@7
   167
//
mb@7
   168
// Purpose: 
mb@7
   169
//   Entry point for the service
mb@7
   170
//
mb@7
   171
// Parameters:
mb@7
   172
//   dwArgc - Number of arguments in the lpszArgv array
mb@7
   173
//   lpszArgv - Array of strings. The first string is the name of
mb@7
   174
//     the service and subsequent strings are passed by the process
mb@7
   175
//     that called the StartService function to start the service.
mb@7
   176
// 
mb@7
   177
// Return value:
mb@7
   178
//   None.
mb@7
   179
//
mb@7
   180
VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv) {
mb@7
   181
	// Register the handler function for the service
mb@7
   182
	gSvcStatusHandle = RegisterServiceCtrlHandlerEx(SVCNAME, (LPHANDLER_FUNCTION_EX)SvcCtrlHandler, 0);
mb@7
   183
	if (!gSvcStatusHandle) {
mb@7
   184
		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("RegisterServiceCtrlHandler"));
mb@7
   185
		return;
mb@7
   186
	}
mb@7
   187
mb@7
   188
	// These SERVICE_STATUS members remain as set here
mb@7
   189
	gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
mb@7
   190
	gSvcStatus.dwServiceSpecificExitCode = 0;
mb@7
   191
mb@7
   192
	// Report initial status to the SCM
mb@7
   193
	ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
mb@7
   194
mb@7
   195
	if (!DoRegisterDeviceInterfaceToHwnd()) {
mb@7
   196
		// Terminate on failure.
mb@7
   197
		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("DoRegisterDeviceInterfaceToHwnd"));
mb@7
   198
		ExitProcess(1);
mb@7
   199
	}
mb@7
   200
	
mb@7
   201
	// default security attributes, manual reset, not signaled, no name
mb@7
   202
	ghSvcStopEvent = CreateEvent(NULL, TRUE, FALSE,	NULL);
mb@7
   203
	if (ghSvcStopEvent == NULL) {
mb@7
   204
		ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
mb@7
   205
		return;
mb@7
   206
	}
mb@7
   207
mb@7
   208
	// Report running status when initialization is complete.
mb@7
   209
	ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
mb@7
   210
	SvcReportEvent(EVENTLOG_INFORMATION_TYPE, TEXT("OpenSecUSBEventSvc is running"));
mb@7
   211
mb@7
   212
	// Wait until our worker thread exits signaling that the service needs to stop
mb@7
   213
	WaitForSingleObject(ghSvcStopEvent, INFINITE);
mb@7
   214
	
mb@7
   215
	SvcReportEvent(EVENTLOG_INFORMATION_TYPE, TEXT("OpenSecUSBEventSvc is exiting"));
mb@7
   216
	// Perform any cleanup tasks
mb@7
   217
	CloseHandle(ghSvcStopEvent);
mb@7
   218
mb@7
   219
	// Report running status when initialization is complete.
mb@7
   220
	ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
mb@7
   221
}
mb@7
   222
mb@7
   223
void NotifyOpenSecManager (void) {
mb@7
   224
	HINTERNET	hSession = NULL,
mb@7
   225
				hConnect = NULL,
mb@7
   226
				hRequest = NULL;
mb@7
   227
	BOOL		bResults = FALSE;
mb@7
   228
mb@7
   229
	//devices_json = url_encode(devices_json);
mb@7
   230
	// Use WinHttpOpen to obtain a session handle.
mb@7
   231
	hSession = WinHttpOpen(L"OpenSecUSBEventSvc", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
mb@7
   232
	if (!hSession) {
mb@7
   233
		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpOpen failed! "));
mb@7
   234
		return;
mb@7
   235
	}
mb@7
   236
	// Specify an HTTP server.
mb@7
   237
	hConnect = WinHttpConnect(hSession, L"localhost", 8080, 0);
mb@7
   238
	if (!hConnect) {
mb@7
   239
		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpConnect failed! "));
mb@7
   240
		return;
mb@7
   241
	}
mb@7
   242
mb@7
   243
	// Create an HTTP request handle.
mb@7
   244
	hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/device_change", NULL, WINHTTP_NO_REFERER, NULL, NULL);
mb@7
   245
	if(!hRequest) {
mb@7
   246
		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpOpenRequest failed! "));
mb@7
   247
		return;
mb@7
   248
	}
mb@7
   249
mb@7
   250
	// Send a request.
mb@7
   251
	bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
mb@7
   252
	if (!bResults) {
mb@7
   253
		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpSendRequest failed! "));
mb@7
   254
		return;
mb@7
   255
	}
mb@7
   256
mb@7
   257
	// End the request.
mb@7
   258
	//if (bResults)
mb@7
   259
	//	bResults = WinHttpReceiveResponse(hRequest, NULL);
mb@7
   260
mb@7
   261
	//DWORD dwSize = 0;
mb@7
   262
	//LPVOID lpOutBuffer = NULL;
mb@7
   263
	//if (bResults) {
mb@7
   264
	//	WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
mb@7
   265
	//	// Allocate memory for the buffer.
mb@7
   266
	//	if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
mb@7
   267
	//		lpOutBuffer = new WCHAR[dwSize / sizeof(WCHAR)];
mb@7
   268
	//		// Now, use WinHttpQueryHeaders to retrieve the header.
mb@7
   269
	//		bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, lpOutBuffer, &dwSize, WINHTTP_NO_HEADER_INDEX);
mb@7
   270
	//	}
mb@7
   271
	//}
mb@7
   272
	//// Print the header contents.
mb@7
   273
	//if (bResults)
mb@7
   274
	//	printf("Header contents: \n%S", lpOutBuffer);
mb@7
   275
	//// Free the allocated memory.
mb@7
   276
	//delete [] lpOutBuffer;
mb@7
   277
mb@7
   278
}
mb@7
   279
mb@7
   280
//
mb@7
   281
// Purpose: 
mb@7
   282
//   Sets the current service status and reports it to the SCM.
mb@7
   283
//
mb@7
   284
// Parameters:
mb@7
   285
//   dwCurrentState - The current state (see SERVICE_STATUS)
mb@7
   286
//   dwWin32ExitCode - The system error code
mb@7
   287
//   dwWaitHint - Estimated time for pending operation, 
mb@7
   288
//     in milliseconds
mb@7
   289
// 
mb@7
   290
// Return value:
mb@7
   291
//   None
mb@7
   292
//
mb@7
   293
VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) {
mb@7
   294
	static DWORD dwCheckPoint = 1;
mb@7
   295
	// Fill in the SERVICE_STATUS structure.
mb@7
   296
	gSvcStatus.dwCurrentState = dwCurrentState;
mb@7
   297
	gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
mb@7
   298
	gSvcStatus.dwWaitHint = dwWaitHint;
mb@7
   299
mb@7
   300
	if (dwCurrentState == SERVICE_START_PENDING)
mb@7
   301
		gSvcStatus.dwControlsAccepted = 0;
mb@7
   302
	else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
mb@7
   303
mb@7
   304
	if ((dwCurrentState == SERVICE_RUNNING) ||
mb@7
   305
		(dwCurrentState == SERVICE_STOPPED))
mb@7
   306
		gSvcStatus.dwCheckPoint = 0;
mb@7
   307
	else gSvcStatus.dwCheckPoint = dwCheckPoint++;
mb@7
   308
mb@7
   309
	// Report the status of the service to the SCM.
mb@7
   310
	SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
mb@7
   311
}
mb@7
   312
mb@7
   313
// Purpose: 
mb@7
   314
//   Called by SCM whenever a control code is sent to the service
mb@7
   315
//   using the ControlService function.
mb@7
   316
//
mb@7
   317
// Parameters:
mb@7
   318
//   dwCtrl - control code
mb@7
   319
// 
mb@7
   320
// Return value:
mb@7
   321
//   None
mb@7
   322
//
mb@7
   323
VOID WINAPI SvcCtrlHandler(DWORD dwCtrl) {
mb@7
   324
	// Handle the requested control code. 
mb@7
   325
	switch (dwCtrl) {
mb@7
   326
		case SERVICE_CONTROL_STOP:
mb@7
   327
			UnregisterDeviceNotification(ghDeviceNotify);
mb@7
   328
			ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
mb@7
   329
			// Signal the service to stop.
mb@7
   330
			SetEvent(ghSvcStopEvent);
mb@7
   331
			ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
mb@7
   332
			return;
mb@7
   333
mb@7
   334
		case SERVICE_CONTROL_INTERROGATE:
mb@7
   335
			break;
mb@7
   336
mb@7
   337
		case SERVICE_CONTROL_DEVICEEVENT:
mb@7
   338
			SvcReportEvent(EVENTLOG_INFORMATION_TYPE, _T("Received SERVICE_CONTROL_DEVICEEVENT"));
mb@7
   339
			//NotifyOpenSecManager();
mb@7
   340
			break;
mb@7
   341
mb@7
   342
		default:
mb@7
   343
			break;
mb@7
   344
	}
mb@7
   345
}
mb@7
   346
mb@7
   347
//
mb@7
   348
// Purpose: 
mb@7
   349
//   Logs messages to the event log
mb@7
   350
//
mb@7
   351
// Parameters:
mb@7
   352
//   szFunction - name of function that failed
mb@7
   353
// 
mb@7
   354
// Return value:
mb@7
   355
//   None
mb@7
   356
//
mb@7
   357
// Remarks:
mb@7
   358
//   The service must have an entry in the Application event log.
mb@7
   359
//
mb@7
   360
VOID SvcReportEvent(WORD type, LPTSTR szFunction) {
mb@7
   361
	HANDLE hEventSource;
mb@7
   362
	LPCTSTR lpszStrings[2];
mb@7
   363
	TCHAR Buffer[80];
mb@7
   364
mb@7
   365
	hEventSource = RegisterEventSource(NULL, SVCNAME);
mb@7
   366
mb@7
   367
	if (NULL != hEventSource) {
mb@7
   368
		if (type == EVENTLOG_ERROR_TYPE)
mb@7
   369
			StringCchPrintf(Buffer, 80, TEXT("Error has occured. %s failed with %d"), szFunction, GetLastError());
mb@7
   370
		else
mb@7
   371
			StringCchPrintf(Buffer, 80, TEXT("%s"), szFunction);
mb@7
   372
mb@7
   373
		lpszStrings[0] = SVCNAME;
mb@7
   374
		lpszStrings[1] = Buffer;
mb@7
   375
mb@7
   376
		if (type == EVENTLOG_ERROR_TYPE)
mb@7
   377
			ReportEvent(hEventSource,       
mb@7
   378
				type, // event type
mb@7
   379
				0,                   // event category
mb@7
   380
				SVC_ERROR,           // event identifier
mb@7
   381
				NULL,                // no security identifier
mb@7
   382
				2,                   // size of lpszStrings array
mb@7
   383
				0,                   // no binary data
mb@7
   384
				lpszStrings,         // array of strings
mb@7
   385
				NULL);               // no binary data
mb@7
   386
		else
mb@7
   387
			ReportEvent(hEventSource,
mb@7
   388
				type, // event type
mb@7
   389
				0,                   // event category
mb@7
   390
				SVC_ERROR,		     // event identifier
mb@7
   391
				NULL,                // no security identifier
mb@7
   392
				2,                   // size of lpszStrings array
mb@7
   393
				0,                   // no binary data
mb@7
   394
				lpszStrings,         // array of strings
mb@7
   395
				NULL);               // no binary data
mb@7
   396
mb@7
   397
		DeregisterEventSource(hEventSource);
mb@7
   398
	}
mb@7
   399
}