RegisterServiceCtrlHandlerEx LPHANDLER_FUNCTION_EX register callback call twice when i insert or remove USB device

  • Thread starter Thread starter bhoomilc
  • Start date Start date
B

bhoomilc

Guest
Hi All,

I'm trying to develop USB detect windows service for my custom use in one of the project.

The behavior of detect insert/remove device works perfect with good sense.

The only weired behaviour I have seen is the Log messages is printed twice for device insert/remove.


here is the code for the same,

#include <stdio.h>
#include <windows.h>
#include <dbt.h>
#include <initguid.h>
#include <usbiodef.h>

#define SERVICE_NAME L"USBDetectService"
#define SLEEP_TIME 5000

SERVICE_STATUS Status;
SERVICE_STATUS_HANDLE hStatus;
HDEVNOTIFY hDeviceNotify;
FILE* Log;

void ServiceMain();
DWORD ControlHandler(DWORD, DWORD, LPVOID, LPVOID);

void main()
{
Log = fopen("C:\\SampleUSBEventService.log", "w");
fprintf(Log, "Logging started...\n");

fprintf(Log, "Service executable started...\n");
SERVICE_TABLE_ENTRY ServiceTable[1];
ServiceTable[0].lpServiceName = SERVICE_NAME;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

fprintf(Log, "Invoking StartServiceCtrlDispatcher...\n");
StartServiceCtrlDispatcher(ServiceTable);

fprintf(Log, "Logging finished!\n");
fclose(Log);
}

void ServiceMain()
{
fprintf(Log, "Entering ServiceMain function...\n");
Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
Status.dwCurrentState = SERVICE_START_PENDING;
Status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_SHUTDOWN;
Status.dwWin32ExitCode = 0;
Status.dwServiceSpecificExitCode = 0;
Status.dwCheckPoint = 0;
Status.dwWaitHint = 0;

hStatus =
RegisterServiceCtrlHandlerEx(SERVICE_NAME,
(LPHANDLER_FUNCTION_EX)ControlHandler,
0);
fprintf(Log, "RegisterServiceCtrlHandlerEx returned %p\n", hStatus);

if (hStatus == (SERVICE_STATUS_HANDLE)0)
fprintf(Log, "Error : RegisterServiceCtrlHandlerEx returned %d\n", GetLastError());; // Error

SetServiceStatus(hStatus, &Status);

// Some initialization
fprintf(Log, "Registering device notification...\n");
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
hDeviceNotify = NULL;

// static const GUID GuidDevInterfaceDisk =
// { 0x53F56307, 0xB6BF, 0x11D0,
// { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } };

static const GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72,
0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 };

//static const GUID guidForModemDevices = { 0x2c7089aa, 0x2e0e, 0x11d1,
//{ 0xb1, 0x14, 0x00, 0xc0, 0x4f, 0xc2, 0xaa, 0xe4 } };

ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));

NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
//NotificationFilter.dbcc_classguid = WceusbshGUID;

hDeviceNotify =
RegisterDeviceNotification((HANDLE)hStatus,
&NotificationFilter,
DEVICE_NOTIFY_SERVICE_HANDLE |
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);

fprintf(Log, "RegisterDeviceNotification returned %p\n", hDeviceNotify);

if (hDeviceNotify == NULL)
fprintf(Log, "Error : RegisterDeviceNotification returned %d\n", GetLastError());; // Error


Status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &Status);

fprintf(Log, "Running...\n");
while (Status.dwCurrentState == SERVICE_RUNNING)
{
Sleep(SLEEP_TIME);
}
}

DWORD ControlHandler(DWORD dwControl, DWORD dwEventType,
LPVOID lpEventData, LPVOID lpContext)
{
fprintf(Log, "ControlHandler call with %d:%d\n", dwControl, dwEventType);
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
UnregisterDeviceNotification(hDeviceNotify);
Status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &Status);
return NO_ERROR;
case SERVICE_CONTROL_SHUTDOWN:
UnregisterDeviceNotification(hDeviceNotify);
Status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &Status);
return NO_ERROR;
//case SERVICE_CONTROL_PAUSE:
// fprintf(Log, "SERVICE_CONTROL_PAUSE! ");
// Status.dwCurrentState = SERVICE_PAUSED;
// SetServiceStatus(hStatus, &Status);
// return NO_ERROR;
//case SERVICE_CONTROL_CONTINUE:
// Status.dwCurrentState = SERVICE_RUNNING;
// fprintf(Log, "SERVICE_CONTROL_CONTINUE! ");
// SetServiceStatus(hStatus, &Status);
// return NO_ERROR;
case SERVICE_CONTROL_DEVICEEVENT:
fprintf(Log, "SERVICE_CONTROL_DEVICEEVENT! ");
switch (dwEventType)
{
case DBT_DEVICEARRIVAL:
// Handle
fprintf(Log, "DBT_DEVICEARRIVAL\n");
break;
case DBT_DEVICEREMOVECOMPLETE:
fprintf(Log, "DBT_DEVICEREMOVECOMPLETE\n");
// Handle
break;
}
break;
default:
fprintf(Log, "Unknown dwControl: %d\n", dwControl);
SetServiceStatus(hStatus, &Status);
break;
}
return NO_ERROR;
}

/////////////////////////////////////////LOG-FILE view/////////////////////////////

Logging started...
Service executable started...
Invoking StartServiceCtrlDispatcher...
Entering ServiceMain function...
RegisterServiceCtrlHandlerEx returned 00E371E0
Registering device notification...
RegisterDeviceNotification returned 00E25F00
Running...
ControlHandler call with 11:32768
SERVICE_CONTROL_DEVICEEVENT! DBT_DEVICEARRIVAL
ControlHandler call with 11:32768
SERVICE_CONTROL_DEVICEEVENT! DBT_DEVICEARRIVAL
ControlHandler call with 11:32772
SERVICE_CONTROL_DEVICEEVENT! DBT_DEVICEREMOVECOMPLETE
ControlHandler call with 11:32772
SERVICE_CONTROL_DEVICEEVENT! DBT_DEVICEREMOVECOMPLETE
ControlHandler call with 1:0
Logging finished!
///////////////////////////////////////////////////////////////////////////////////////////////



why the ControlHandler callback execute twice?

thanks in advance.


BhoomilC

Continue reading...
 
Back
Top