server/windows/USBEventSvc/OpenSecUSBEventSvc/OpenSecUSBEventSvc.cpp
author mb
Wed, 04 Dec 2013 14:41:20 +0100
changeset 9 50b1cfe9576b
parent 7 903480cebdfb
child 12 11dc05750aea
permissions -rw-r--r--
removed unnecessary stuff
     1 #include <InitGuid.h>
     2 #include <Windows.h>
     3 #include <SetupApi.h>
     4 
     5 #include <tchar.h>
     6 #include <strsafe.h>
     7 #include <dbt.h>
     8 #include <usbiodef.h>
     9 #include <Winhttp.h>
    10 #include "OpenSecUSBEventSvcLog.h"
    11 
    12 #pragma comment(lib, "advapi32.lib")
    13 
    14 #define SVCNAME TEXT("OpenSecUSBEventSvc")
    15 
    16 //sc create "USBEventSvc" binPath= "C:\Users\BarthaM\Documents\Visual Studio 2010\Projects\USBEventSvc\Debug\USBEventSvc.exe"
    17 //sc delete "USBEventSvc"
    18 
    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 } }
    23 
    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 };
    26 
    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);
    29 
    30 
    31 SERVICE_STATUS          gSvcStatus;
    32 SERVICE_STATUS_HANDLE   gSvcStatusHandle = NULL;
    33 HANDLE                  ghSvcStopEvent = NULL;
    34 HDEVNOTIFY				ghDeviceNotify;
    35 
    36 DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
    37 
    38 VOID SvcInstall(void);
    39 VOID WINAPI SvcCtrlHandler(DWORD);
    40 VOID WINAPI SvcMain(DWORD, LPTSTR *);
    41 
    42 VOID ReportSvcStatus(DWORD, DWORD, DWORD);
    43 VOID SvcInit(DWORD, LPTSTR *);
    44 VOID SvcReportEvent(WORD, LPTSTR);
    45 
    46 
    47 // DoRegisterDeviceInterfaceToHwnd
    48 //     Registers an HWND for notification of changes in the device interfaces
    49 //     for the specified interface class GUID. 
    50 // Parameters:
    51 //     InterfaceClassGuid - The interface class GUID for the device 
    52 //         interfaces. 
    53 //     hWnd - Window handle to receive notifications.
    54 //     hDeviceNotify - Receives the device notification handle. On failure, 
    55 //         this value is NULL.
    56 // Return Value:
    57 //     If the function succeeds, the return value is TRUE.
    58 //     If the function fails, the return value is FALSE.
    59 // Note:
    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.
    63 
    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));
    71 
    72 	ghDeviceNotify = RegisterDeviceNotification(gSvcStatusHandle,
    73 		&NotificationFilter,
    74 		DEVICE_NOTIFY_SERVICE_HANDLE);// | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
    75 
    76 	if (NULL == ghDeviceNotify) {
    77 		SvcReportEvent(EVENTLOG_ERROR_TYPE, _T("RegisterDeviceNotification failed!"));
    78 		return FALSE;
    79 	}
    80 	return TRUE;
    81 }
    82 
    83 //
    84 // Purpose: 
    85 //   Entry point for the process
    86 //
    87 // Parameters:
    88 //   None
    89 // 
    90 // Return value:
    91 //   None
    92 //
    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){
    97 		SvcInstall();
    98 		return;
    99 	}
   100 
   101 	// TO_DO: Add any additional services for the process to this table.
   102 	SERVICE_TABLE_ENTRY DispatchTable[] = {
   103 		{ SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
   104 		{ NULL, NULL }
   105 	};
   106 
   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"));
   111 	}
   112 }
   113 
   114 // Purpose: 
   115 //   Installs a service in the SCM database
   116 //
   117 // Parameters:
   118 //   None
   119 // 
   120 // Return value:
   121 //   None
   122 //
   123 VOID SvcInstall() {
   124 	SC_HANDLE schSCManager;
   125 	SC_HANDLE schService;
   126 	TCHAR szPath[MAX_PATH];
   127 
   128 	if (!GetModuleFileName(NULL, szPath, MAX_PATH)) {
   129 		printf("Cannot install service (%d)\n", GetLastError());
   130 		return;
   131 	}
   132 
   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());
   137 		return;
   138 	}
   139 
   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 
   155 
   156 	if (schService == NULL) {
   157 		printf("CreateService failed (%d)\n", GetLastError());
   158 		CloseServiceHandle(schSCManager);
   159 		return;
   160 	}
   161 	else printf("Service installed successfully\n");
   162 
   163 	CloseServiceHandle(schService);
   164 	CloseServiceHandle(schSCManager);
   165 }
   166 
   167 //
   168 // Purpose: 
   169 //   Entry point for the service
   170 //
   171 // Parameters:
   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.
   176 // 
   177 // Return value:
   178 //   None.
   179 //
   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"));
   185 		return;
   186 	}
   187 
   188 	// These SERVICE_STATUS members remain as set here
   189 	gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
   190 	gSvcStatus.dwServiceSpecificExitCode = 0;
   191 
   192 	// Report initial status to the SCM
   193 	ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
   194 
   195 	if (!DoRegisterDeviceInterfaceToHwnd()) {
   196 		// Terminate on failure.
   197 		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("DoRegisterDeviceInterfaceToHwnd"));
   198 		ExitProcess(1);
   199 	}
   200 	
   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);
   205 		return;
   206 	}
   207 
   208 	// Report running status when initialization is complete.
   209 	ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
   210 	SvcReportEvent(EVENTLOG_INFORMATION_TYPE, TEXT("OpenSecUSBEventSvc is running"));
   211 
   212 	// Wait until our worker thread exits signaling that the service needs to stop
   213 	WaitForSingleObject(ghSvcStopEvent, INFINITE);
   214 	
   215 	SvcReportEvent(EVENTLOG_INFORMATION_TYPE, TEXT("OpenSecUSBEventSvc is exiting"));
   216 	// Perform any cleanup tasks
   217 	CloseHandle(ghSvcStopEvent);
   218 
   219 	// Report running status when initialization is complete.
   220 	ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
   221 }
   222 
   223 void NotifyOpenSecManager (void) {
   224 	HINTERNET	hSession = NULL,
   225 				hConnect = NULL,
   226 				hRequest = NULL;
   227 	BOOL		bResults = FALSE;
   228 
   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);
   232 	if (!hSession) {
   233 		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpOpen failed! "));
   234 		return;
   235 	}
   236 	// Specify an HTTP server.
   237 	hConnect = WinHttpConnect(hSession, L"localhost", 8080, 0);
   238 	if (!hConnect) {
   239 		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpConnect failed! "));
   240 		return;
   241 	}
   242 
   243 	// Create an HTTP request handle.
   244 	hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/device_change", NULL, WINHTTP_NO_REFERER, NULL, NULL);
   245 	if(!hRequest) {
   246 		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpOpenRequest failed! "));
   247 		return;
   248 	}
   249 
   250 	// Send a request.
   251 	bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
   252 	if (!bResults) {
   253 		SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpSendRequest failed! "));
   254 		return;
   255 	}
   256 
   257 	// End the request.
   258 	//if (bResults)
   259 	//	bResults = WinHttpReceiveResponse(hRequest, NULL);
   260 
   261 	//DWORD dwSize = 0;
   262 	//LPVOID lpOutBuffer = NULL;
   263 	//if (bResults) {
   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);
   270 	//	}
   271 	//}
   272 	//// Print the header contents.
   273 	//if (bResults)
   274 	//	printf("Header contents: \n%S", lpOutBuffer);
   275 	//// Free the allocated memory.
   276 	//delete [] lpOutBuffer;
   277 
   278 }
   279 
   280 //
   281 // Purpose: 
   282 //   Sets the current service status and reports it to the SCM.
   283 //
   284 // Parameters:
   285 //   dwCurrentState - The current state (see SERVICE_STATUS)
   286 //   dwWin32ExitCode - The system error code
   287 //   dwWaitHint - Estimated time for pending operation, 
   288 //     in milliseconds
   289 // 
   290 // Return value:
   291 //   None
   292 //
   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;
   299 
   300 	if (dwCurrentState == SERVICE_START_PENDING)
   301 		gSvcStatus.dwControlsAccepted = 0;
   302 	else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
   303 
   304 	if ((dwCurrentState == SERVICE_RUNNING) ||
   305 		(dwCurrentState == SERVICE_STOPPED))
   306 		gSvcStatus.dwCheckPoint = 0;
   307 	else gSvcStatus.dwCheckPoint = dwCheckPoint++;
   308 
   309 	// Report the status of the service to the SCM.
   310 	SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
   311 }
   312 
   313 // Purpose: 
   314 //   Called by SCM whenever a control code is sent to the service
   315 //   using the ControlService function.
   316 //
   317 // Parameters:
   318 //   dwCtrl - control code
   319 // 
   320 // Return value:
   321 //   None
   322 //
   323 VOID WINAPI SvcCtrlHandler(DWORD dwCtrl) {
   324 	// Handle the requested control code. 
   325 	switch (dwCtrl) {
   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);
   332 			return;
   333 
   334 		case SERVICE_CONTROL_INTERROGATE:
   335 			break;
   336 
   337 		case SERVICE_CONTROL_DEVICEEVENT:
   338 			SvcReportEvent(EVENTLOG_INFORMATION_TYPE, _T("Received SERVICE_CONTROL_DEVICEEVENT"));
   339 			//NotifyOpenSecManager();
   340 			break;
   341 
   342 		default:
   343 			break;
   344 	}
   345 }
   346 
   347 //
   348 // Purpose: 
   349 //   Logs messages to the event log
   350 //
   351 // Parameters:
   352 //   szFunction - name of function that failed
   353 // 
   354 // Return value:
   355 //   None
   356 //
   357 // Remarks:
   358 //   The service must have an entry in the Application event log.
   359 //
   360 VOID SvcReportEvent(WORD type, LPTSTR szFunction) {
   361 	HANDLE hEventSource;
   362 	LPCTSTR lpszStrings[2];
   363 	TCHAR Buffer[80];
   364 
   365 	hEventSource = RegisterEventSource(NULL, SVCNAME);
   366 
   367 	if (NULL != hEventSource) {
   368 		if (type == EVENTLOG_ERROR_TYPE)
   369 			StringCchPrintf(Buffer, 80, TEXT("Error has occured. %s failed with %d"), szFunction, GetLastError());
   370 		else
   371 			StringCchPrintf(Buffer, 80, TEXT("%s"), szFunction);
   372 
   373 		lpszStrings[0] = SVCNAME;
   374 		lpszStrings[1] = Buffer;
   375 
   376 		if (type == EVENTLOG_ERROR_TYPE)
   377 			ReportEvent(hEventSource,       
   378 				type, // event type
   379 				0,                   // event category
   380 				SVC_ERROR,           // event identifier
   381 				NULL,                // no security identifier
   382 				2,                   // size of lpszStrings array
   383 				0,                   // no binary data
   384 				lpszStrings,         // array of strings
   385 				NULL);               // no binary data
   386 		else
   387 			ReportEvent(hEventSource,
   388 				type, // event type
   389 				0,                   // event category
   390 				SVC_ERROR,		     // event identifier
   391 				NULL,                // no security identifier
   392 				2,                   // size of lpszStrings array
   393 				0,                   // no binary data
   394 				lpszStrings,         // array of strings
   395 				NULL);               // no binary data
   396 
   397 		DeregisterEventSource(hEventSource);
   398 	}
   399 }