1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/server/windows/USBEventSvc/OpenSecUSBEventSvc/OpenSecUSBEventSvc.cpp Tue Dec 03 18:04:46 2013 +0100
1.3 @@ -0,0 +1,399 @@
1.4 +#include <InitGuid.h>
1.5 +#include <Windows.h>
1.6 +#include <SetupApi.h>
1.7 +
1.8 +#include <tchar.h>
1.9 +#include <strsafe.h>
1.10 +#include <dbt.h>
1.11 +#include <usbiodef.h>
1.12 +#include <Winhttp.h>
1.13 +#include "OpenSecUSBEventSvcLog.h"
1.14 +
1.15 +#pragma comment(lib, "advapi32.lib")
1.16 +
1.17 +#define SVCNAME TEXT("OpenSecUSBEventSvc")
1.18 +
1.19 +//sc create "USBEventSvc" binPath= "C:\Users\BarthaM\Documents\Visual Studio 2010\Projects\USBEventSvc\Debug\USBEventSvc.exe"
1.20 +//sc delete "USBEventSvc"
1.21 +
1.22 +// USB Raw Device Interface Class GUID
1.23 +//{ 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51,0xed } }
1.24 +// Disk Device Interface Class GUID
1.25 +//{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } }
1.26 +
1.27 +// This GUID is for all USB serial host PnP drivers
1.28 +//GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72, 0x8a, 0x6d, 0xb5, 0x4c, 0x2b, 0x4f, 0xc8, 0x35 };
1.29 +
1.30 +GUID WceusbshGUID = { 0x88bae032, 0x5a81, 0x49f0, 0xbc, 0x3d, 0xa4, 0xff, 0x13, 0x82, 0x16, 0xd6 };
1.31 +//DEFINE_GUID(GUID_CLASS_STORAGE_VOLUME, 0x53F5630DL, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B);
1.32 +
1.33 +
1.34 +SERVICE_STATUS gSvcStatus;
1.35 +SERVICE_STATUS_HANDLE gSvcStatusHandle = NULL;
1.36 +HANDLE ghSvcStopEvent = NULL;
1.37 +HDEVNOTIFY ghDeviceNotify;
1.38 +
1.39 +DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
1.40 +
1.41 +VOID SvcInstall(void);
1.42 +VOID WINAPI SvcCtrlHandler(DWORD);
1.43 +VOID WINAPI SvcMain(DWORD, LPTSTR *);
1.44 +
1.45 +VOID ReportSvcStatus(DWORD, DWORD, DWORD);
1.46 +VOID SvcInit(DWORD, LPTSTR *);
1.47 +VOID SvcReportEvent(WORD, LPTSTR);
1.48 +
1.49 +
1.50 +// DoRegisterDeviceInterfaceToHwnd
1.51 +// Registers an HWND for notification of changes in the device interfaces
1.52 +// for the specified interface class GUID.
1.53 +// Parameters:
1.54 +// InterfaceClassGuid - The interface class GUID for the device
1.55 +// interfaces.
1.56 +// hWnd - Window handle to receive notifications.
1.57 +// hDeviceNotify - Receives the device notification handle. On failure,
1.58 +// this value is NULL.
1.59 +// Return Value:
1.60 +// If the function succeeds, the return value is TRUE.
1.61 +// If the function fails, the return value is FALSE.
1.62 +// Note:
1.63 +// RegisterDeviceNotification also allows a service handle be used,
1.64 +// so a similar wrapper function to this one supporting that scenario
1.65 +// could be made from this template.
1.66 +
1.67 +BOOL DoRegisterDeviceInterfaceToHwnd(void) {
1.68 + DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
1.69 + ZeroMemory(&NotificationFilter, sizeof (NotificationFilter));
1.70 + NotificationFilter.dbcc_size = sizeof (DEV_BROADCAST_DEVICEINTERFACE);
1.71 + NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
1.72 + NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
1.73 + memcpy(&(NotificationFilter.dbcc_classguid), &(GUID_DEVINTERFACE_USB_DEVICE), sizeof(struct _GUID));
1.74 +
1.75 + ghDeviceNotify = RegisterDeviceNotification(gSvcStatusHandle,
1.76 + &NotificationFilter,
1.77 + DEVICE_NOTIFY_SERVICE_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
1.78 +
1.79 + if (NULL == ghDeviceNotify) {
1.80 + SvcReportEvent(EVENTLOG_ERROR_TYPE, _T("RegisterDeviceNotification failed!"));
1.81 + return FALSE;
1.82 + }
1.83 + return TRUE;
1.84 +}
1.85 +
1.86 +//
1.87 +// Purpose:
1.88 +// Entry point for the process
1.89 +//
1.90 +// Parameters:
1.91 +// None
1.92 +//
1.93 +// Return value:
1.94 +// None
1.95 +//
1.96 +void __cdecl _tmain(int argc, TCHAR *argv[]) {
1.97 + // If command-line parameter is "install", install the service.
1.98 + // Otherwise, the service is probably being started by the SCM.
1.99 + if (lstrcmpi(argv[1], TEXT("install")) == 0){
1.100 + SvcInstall();
1.101 + return;
1.102 + }
1.103 +
1.104 + // TO_DO: Add any additional services for the process to this table.
1.105 + SERVICE_TABLE_ENTRY DispatchTable[] = {
1.106 + { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
1.107 + { NULL, NULL }
1.108 + };
1.109 +
1.110 + // This call returns when the service has stopped.
1.111 + // The process should simply terminate when the call returns.
1.112 + if (!StartServiceCtrlDispatcher(DispatchTable)) {
1.113 + SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("StartServiceCtrlDispatcher"));
1.114 + }
1.115 +}
1.116 +
1.117 +// Purpose:
1.118 +// Installs a service in the SCM database
1.119 +//
1.120 +// Parameters:
1.121 +// None
1.122 +//
1.123 +// Return value:
1.124 +// None
1.125 +//
1.126 +VOID SvcInstall() {
1.127 + SC_HANDLE schSCManager;
1.128 + SC_HANDLE schService;
1.129 + TCHAR szPath[MAX_PATH];
1.130 +
1.131 + if (!GetModuleFileName(NULL, szPath, MAX_PATH)) {
1.132 + printf("Cannot install service (%d)\n", GetLastError());
1.133 + return;
1.134 + }
1.135 +
1.136 + // Get a handle to the SCM database. local computer, ServicesActive database, full access rights
1.137 + schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1.138 + if (NULL == schSCManager) {
1.139 + printf("Open SCManager failed (%d)\n", GetLastError());
1.140 + return;
1.141 + }
1.142 +
1.143 + // Create the service
1.144 + schService = CreateService(
1.145 + schSCManager, // SCM database
1.146 + SVCNAME, // name of service
1.147 + SVCNAME, // service name to display
1.148 + SERVICE_ALL_ACCESS, // desired access
1.149 + SERVICE_WIN32_OWN_PROCESS, // service type
1.150 + SERVICE_DEMAND_START, // start type
1.151 + SERVICE_ERROR_NORMAL, // error control type
1.152 + szPath, // path to service's binary
1.153 + NULL, // no load ordering group
1.154 + NULL, // no tag identifier
1.155 + NULL, // no dependencies
1.156 + NULL, // LocalSystem account
1.157 + NULL); // no password
1.158 +
1.159 + if (schService == NULL) {
1.160 + printf("CreateService failed (%d)\n", GetLastError());
1.161 + CloseServiceHandle(schSCManager);
1.162 + return;
1.163 + }
1.164 + else printf("Service installed successfully\n");
1.165 +
1.166 + CloseServiceHandle(schService);
1.167 + CloseServiceHandle(schSCManager);
1.168 +}
1.169 +
1.170 +//
1.171 +// Purpose:
1.172 +// Entry point for the service
1.173 +//
1.174 +// Parameters:
1.175 +// dwArgc - Number of arguments in the lpszArgv array
1.176 +// lpszArgv - Array of strings. The first string is the name of
1.177 +// the service and subsequent strings are passed by the process
1.178 +// that called the StartService function to start the service.
1.179 +//
1.180 +// Return value:
1.181 +// None.
1.182 +//
1.183 +VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv) {
1.184 + // Register the handler function for the service
1.185 + gSvcStatusHandle = RegisterServiceCtrlHandlerEx(SVCNAME, (LPHANDLER_FUNCTION_EX)SvcCtrlHandler, 0);
1.186 + if (!gSvcStatusHandle) {
1.187 + SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("RegisterServiceCtrlHandler"));
1.188 + return;
1.189 + }
1.190 +
1.191 + // These SERVICE_STATUS members remain as set here
1.192 + gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1.193 + gSvcStatus.dwServiceSpecificExitCode = 0;
1.194 +
1.195 + // Report initial status to the SCM
1.196 + ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
1.197 +
1.198 + if (!DoRegisterDeviceInterfaceToHwnd()) {
1.199 + // Terminate on failure.
1.200 + SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("DoRegisterDeviceInterfaceToHwnd"));
1.201 + ExitProcess(1);
1.202 + }
1.203 +
1.204 + // default security attributes, manual reset, not signaled, no name
1.205 + ghSvcStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1.206 + if (ghSvcStopEvent == NULL) {
1.207 + ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
1.208 + return;
1.209 + }
1.210 +
1.211 + // Report running status when initialization is complete.
1.212 + ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
1.213 + SvcReportEvent(EVENTLOG_INFORMATION_TYPE, TEXT("OpenSecUSBEventSvc is running"));
1.214 +
1.215 + // Wait until our worker thread exits signaling that the service needs to stop
1.216 + WaitForSingleObject(ghSvcStopEvent, INFINITE);
1.217 +
1.218 + SvcReportEvent(EVENTLOG_INFORMATION_TYPE, TEXT("OpenSecUSBEventSvc is exiting"));
1.219 + // Perform any cleanup tasks
1.220 + CloseHandle(ghSvcStopEvent);
1.221 +
1.222 + // Report running status when initialization is complete.
1.223 + ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
1.224 +}
1.225 +
1.226 +void NotifyOpenSecManager (void) {
1.227 + HINTERNET hSession = NULL,
1.228 + hConnect = NULL,
1.229 + hRequest = NULL;
1.230 + BOOL bResults = FALSE;
1.231 +
1.232 + //devices_json = url_encode(devices_json);
1.233 + // Use WinHttpOpen to obtain a session handle.
1.234 + hSession = WinHttpOpen(L"OpenSecUSBEventSvc", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
1.235 + if (!hSession) {
1.236 + SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpOpen failed! "));
1.237 + return;
1.238 + }
1.239 + // Specify an HTTP server.
1.240 + hConnect = WinHttpConnect(hSession, L"localhost", 8080, 0);
1.241 + if (!hConnect) {
1.242 + SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpConnect failed! "));
1.243 + return;
1.244 + }
1.245 +
1.246 + // Create an HTTP request handle.
1.247 + hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/device_change", NULL, WINHTTP_NO_REFERER, NULL, NULL);
1.248 + if(!hRequest) {
1.249 + SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpOpenRequest failed! "));
1.250 + return;
1.251 + }
1.252 +
1.253 + // Send a request.
1.254 + bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
1.255 + if (!bResults) {
1.256 + SvcReportEvent(EVENTLOG_ERROR_TYPE, TEXT("Error notifying the OpenSec manager. WinHttpSendRequest failed! "));
1.257 + return;
1.258 + }
1.259 +
1.260 + // End the request.
1.261 + //if (bResults)
1.262 + // bResults = WinHttpReceiveResponse(hRequest, NULL);
1.263 +
1.264 + //DWORD dwSize = 0;
1.265 + //LPVOID lpOutBuffer = NULL;
1.266 + //if (bResults) {
1.267 + // WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
1.268 + // // Allocate memory for the buffer.
1.269 + // if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
1.270 + // lpOutBuffer = new WCHAR[dwSize / sizeof(WCHAR)];
1.271 + // // Now, use WinHttpQueryHeaders to retrieve the header.
1.272 + // bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, lpOutBuffer, &dwSize, WINHTTP_NO_HEADER_INDEX);
1.273 + // }
1.274 + //}
1.275 + //// Print the header contents.
1.276 + //if (bResults)
1.277 + // printf("Header contents: \n%S", lpOutBuffer);
1.278 + //// Free the allocated memory.
1.279 + //delete [] lpOutBuffer;
1.280 +
1.281 +}
1.282 +
1.283 +//
1.284 +// Purpose:
1.285 +// Sets the current service status and reports it to the SCM.
1.286 +//
1.287 +// Parameters:
1.288 +// dwCurrentState - The current state (see SERVICE_STATUS)
1.289 +// dwWin32ExitCode - The system error code
1.290 +// dwWaitHint - Estimated time for pending operation,
1.291 +// in milliseconds
1.292 +//
1.293 +// Return value:
1.294 +// None
1.295 +//
1.296 +VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) {
1.297 + static DWORD dwCheckPoint = 1;
1.298 + // Fill in the SERVICE_STATUS structure.
1.299 + gSvcStatus.dwCurrentState = dwCurrentState;
1.300 + gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
1.301 + gSvcStatus.dwWaitHint = dwWaitHint;
1.302 +
1.303 + if (dwCurrentState == SERVICE_START_PENDING)
1.304 + gSvcStatus.dwControlsAccepted = 0;
1.305 + else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
1.306 +
1.307 + if ((dwCurrentState == SERVICE_RUNNING) ||
1.308 + (dwCurrentState == SERVICE_STOPPED))
1.309 + gSvcStatus.dwCheckPoint = 0;
1.310 + else gSvcStatus.dwCheckPoint = dwCheckPoint++;
1.311 +
1.312 + // Report the status of the service to the SCM.
1.313 + SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
1.314 +}
1.315 +
1.316 +// Purpose:
1.317 +// Called by SCM whenever a control code is sent to the service
1.318 +// using the ControlService function.
1.319 +//
1.320 +// Parameters:
1.321 +// dwCtrl - control code
1.322 +//
1.323 +// Return value:
1.324 +// None
1.325 +//
1.326 +VOID WINAPI SvcCtrlHandler(DWORD dwCtrl) {
1.327 + // Handle the requested control code.
1.328 + switch (dwCtrl) {
1.329 + case SERVICE_CONTROL_STOP:
1.330 + UnregisterDeviceNotification(ghDeviceNotify);
1.331 + ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
1.332 + // Signal the service to stop.
1.333 + SetEvent(ghSvcStopEvent);
1.334 + ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
1.335 + return;
1.336 +
1.337 + case SERVICE_CONTROL_INTERROGATE:
1.338 + break;
1.339 +
1.340 + case SERVICE_CONTROL_DEVICEEVENT:
1.341 + SvcReportEvent(EVENTLOG_INFORMATION_TYPE, _T("Received SERVICE_CONTROL_DEVICEEVENT"));
1.342 + //NotifyOpenSecManager();
1.343 + break;
1.344 +
1.345 + default:
1.346 + break;
1.347 + }
1.348 +}
1.349 +
1.350 +//
1.351 +// Purpose:
1.352 +// Logs messages to the event log
1.353 +//
1.354 +// Parameters:
1.355 +// szFunction - name of function that failed
1.356 +//
1.357 +// Return value:
1.358 +// None
1.359 +//
1.360 +// Remarks:
1.361 +// The service must have an entry in the Application event log.
1.362 +//
1.363 +VOID SvcReportEvent(WORD type, LPTSTR szFunction) {
1.364 + HANDLE hEventSource;
1.365 + LPCTSTR lpszStrings[2];
1.366 + TCHAR Buffer[80];
1.367 +
1.368 + hEventSource = RegisterEventSource(NULL, SVCNAME);
1.369 +
1.370 + if (NULL != hEventSource) {
1.371 + if (type == EVENTLOG_ERROR_TYPE)
1.372 + StringCchPrintf(Buffer, 80, TEXT("Error has occured. %s failed with %d"), szFunction, GetLastError());
1.373 + else
1.374 + StringCchPrintf(Buffer, 80, TEXT("%s"), szFunction);
1.375 +
1.376 + lpszStrings[0] = SVCNAME;
1.377 + lpszStrings[1] = Buffer;
1.378 +
1.379 + if (type == EVENTLOG_ERROR_TYPE)
1.380 + ReportEvent(hEventSource,
1.381 + type, // event type
1.382 + 0, // event category
1.383 + SVC_ERROR, // event identifier
1.384 + NULL, // no security identifier
1.385 + 2, // size of lpszStrings array
1.386 + 0, // no binary data
1.387 + lpszStrings, // array of strings
1.388 + NULL); // no binary data
1.389 + else
1.390 + ReportEvent(hEventSource,
1.391 + type, // event type
1.392 + 0, // event category
1.393 + SVC_ERROR, // event identifier
1.394 + NULL, // no security identifier
1.395 + 2, // size of lpszStrings array
1.396 + 0, // no binary data
1.397 + lpszStrings, // array of strings
1.398 + NULL); // no binary data
1.399 +
1.400 + DeregisterEventSource(hEventSource);
1.401 + }
1.402 +}