Windows Service and Device notification

192 views
Skip to first unread message

abraham louis

unread,
Feb 27, 2003, 3:02:46 PM2/27/03
to
I am using the follwing code to recieve
SERVICE_CONTROL_DEVICEEVENT in my windows service.

//In my service_main function I have used this code to
register the control handler.
sshStatusHandle = RegisterServiceCtrlHandlerEx(TEXT
(SZSERVICENAME), (LPHANDLER_FUNCTION_EX)service_ctrl,
NULL);


DEV_BROADCAST_DEVICEINTERFACE header = {0};
header.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
header.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
hDevNotify = RegisterDeviceNotification(sshStatusHandle,
&header, DEVICE_NOTIFY_SERVICE_HANDLE);

//hDevNotify is successful, returns no error.

//This is my service_ctrl function
DWORD WINAPI service_ctrl(DWORD dwCtrlCode, DWORD
dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
switch (dwCtrlCode)
{
case SERVICE_CONTROL_DEVICEEVENT:
//Never gets this event when any kind of device (USB
or CDs) is plugged or unplugged to the PC.
WriteToLog();
break;
.....
}
If I run the same code in a windows application, I get the
WM_DEVICECHANGE event.

Can someone please tell me if I have to do anything else
for a service?

Thanks in advance,
Abraham Louis

Jim Cavalaris [MS]

unread,
Feb 27, 2003, 4:34:56 PM2/27/03
to
you are registering for device interface notification events, but
haven't specified a device interface class GUID to indicate which
class of devices you want to be notified about.

Device Interface Classes:
http://msdn.microsoft.com/library/en-us/install/hh/install/setup-cls_54kn.asp

Registering for Device Notification:
http://msdn.microsoft.com/library/en-us/devio/base/registering_for_device_notification.asp

you need to set the dbcc_classguid field of the
DEV_BROADCAST_DEVICEINTERFACE structure (with the code below, you
have actually supplied a 'null' GUID; all fields initialized to
zero).

you will have the same problem with this code even when run from
a windows application. the only WM_DEVICECHANGE messages you're
receiving in your windows application are probably the ones that
are broadcast to all top level windows, not any of the WM_DEVICECHANGE
messages that correspond to DBT_DEVTYP_DEVICEINTERFACE
notification events (DBT_DEVICEARRIVAL / DBT_DEVICEREMOVECOMPLETE).
for WM_DEVICECHANGE or SERVICE_CONTROL_DEVICEEVENT messages with
DBT_DEVICE* events, always check the type of the associated data
structure (i.e. check the DEV_BROADCAST_HDR dbcd_devicetype field
to determine if it is DBT_DEVTYP_DEVICEINTERFACE, etc.)

hope this helps,
jim.

--
This posting is provided "AS IS" with no warranties, and confers no rights.


"abraham louis" <abraha...@roche.com> wrote in message news:009401c2de9b$3224e0d0$a601...@phx.gbl...

Abraham Louis

unread,
Feb 28, 2003, 10:17:03 AM2/28/03
to
Thanks for your response, Jim.
I tried both ways by specifying a class GUID for USB and
without the class GUID. In the standalone application if I
specify the USB GUID, I am getting notification for USB
device otherwise I get notified for every device like
loading CD, connecting a floppy drive to my laptop and so
on.

Even if I specify the USB Class GUID in the service, I am
not getting any notification. Also, I tried by removing
the registration code (RegisterDeviceNotification) to
recieve the default messages like CD open/close. I am not
recieving this either.

Whatever code that works in User application doesn't work
in service.

Here is the code I am using.

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <Dbt.h>
#include <Setupapi.h>
#include <initguid.h>

#include "service.h"

#ifdef DEFINE_GUID
DEFINE_GUID(GUID_CLASS_USB_DEVICE, 0xA5DCBF10L, 0x6530,
0x11D2, 0x90,
0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
#endif

// internal variables
SERVICE_STATUS ssStatus; // current status
of the service
SERVICE_STATUS_HANDLE sshStatusHandle;
DWORD dwErr = 0;
BOOL bDebug = FALSE;
TCHAR szErr[256];
// this event is signalled when the
// service should end
//
HANDLE hServerStopEvent = NULL;
HDEVNOTIFY hDevNotify;

// internal function prototypes


DWORD WINAPI service_ctrl(DWORD dwCtrlCode, DWORD

dwEventType, LPVOID lpEventData, LPVOID lpContext);
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);

void __cdecl main(int argc, char **argv)
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)
service_main},
{ NULL, NULL}
};

if (!StartServiceCtrlDispatcher(dispatchTable))
AddToMessageLog(TEXT("StartServiceCtrlDispatcher
failed."));
}


void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
{

// register our service control handler:
//
sshStatusHandle = RegisterServiceCtrlHandlerEx( TEXT
(SZSERVICENAME), (LPHANDLER_FUNCTION_EX)service_ctrl,
NULL);

if (!sshStatusHandle)
goto cleanup;

// SERVICE_STATUS members that don't change in example
//
ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode = 0;


// report the status to the service control manager.
//
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, //
service state
NO_ERROR, // exit
code
3000)) // wait
hint
goto cleanup;


ServiceStart( dwArgc, lpszArgv );

cleanup:

// try to report the stopped status to the service
control manager.
//
if (sshStatusHandle)
(VOID)ReportStatusToSCMgr(
SERVICE_STOPPED,
dwErr,
0);

return;
}

DWORD WINAPI service_ctrl(DWORD dwCtrlCode,
DWORD
dwEventType,
LPVOID
lpEventData,
LPVOID
lpContext)
{

// Handle the requested control code.
//

switch (dwCtrlCode)
{
case SERVICE_CONTROL_DEVICEEVENT:
AddToMessageLog(TEXT("SERVICE_CONTROL_DEVICEEVENT"));
break;

case SERVICE_CONTROL_STOP:
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR,
0);
ServiceStop();
return NO_ERROR;

// Update the service status.
//
case SERVICE_CONTROL_INTERROGATE:
break;

// invalid control code
//
default:
break;

}

ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR,
0);

return NO_ERROR;
}

BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
BOOL fResult = TRUE;


if ( !bDebug ) // when debugging we don't report to the
SCM
{
if (dwCurrentState == SERVICE_START_PENDING)
ssStatus.dwControlsAccepted = 0;
else
ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

ssStatus.dwCurrentState = dwCurrentState;
ssStatus.dwWin32ExitCode = dwWin32ExitCode;
ssStatus.dwWaitHint = dwWaitHint;

if ( ( dwCurrentState == SERVICE_RUNNING ) ||
( dwCurrentState == SERVICE_STOPPED ) )
ssStatus.dwCheckPoint = 0;
else
ssStatus.dwCheckPoint = dwCheckPoint++;


// Report the status of the service to the service
control manager.
//
if (!(fResult = SetServiceStatus( sshStatusHandle,
&ssStatus)))
{
AddToMessageLog(TEXT("SetServiceStatus"));
}
}
return fResult;
}

VOID AddToMessageLog(LPTSTR lpszMsg)
{
TCHAR szMsg [(sizeof(SZSERVICENAME) / sizeof(TCHAR)) +
100 ];
HANDLE hEventSource;
LPTSTR lpszStrings[2];

if ( !bDebug )
{
dwErr = GetLastError();

// Use event logging to log the error.
//
hEventSource = RegisterEventSource(NULL, TEXT
(SZSERVICENAME));

_stprintf(szMsg, TEXT("%s error: %d"), TEXT
(SZSERVICENAME), dwErr);
lpszStrings[0] = szMsg;
lpszStrings[1] = lpszMsg;

if (hEventSource != NULL)
{
ReportEvent(hEventSource, // handle of event
source
EVENTLOG_ERROR_TYPE, // event type
0, // event
category
0, // event ID
NULL, // current
user's SID
2, // strings in
lpszStrings
0, // no bytes of
raw data
lpszStrings, // array of
error strings
NULL); // no raw data

(VOID) DeregisterEventSource(hEventSource);
}
}
}

VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
{
//MEMORYSTATUS memory;
DEV_BROADCAST_DEVICEINTERFACE header = {0};

if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, //
service state
NO_ERROR, // exit
code
3000)) // wait
hint
goto cleanup;

hServerStopEvent = CreateEvent(
NULL, // no security
attributes
TRUE, // manual reset
event
FALSE, // not-signalled
NULL); // no name

if ( hServerStopEvent == NULL)
goto cleanup;


if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, //
service state
NO_ERROR, // exit
code
3000)) // wait
hint
goto cleanup;

// Register for Device Notification.
//

header.dbcc_size = sizeof
(DEV_BROADCAST_DEVICEINTERFACE);
header.dbcc_devicetype =
DBT_DEVTYP_DEVICEINTERFACE;
memcpy(&header.dbcc_classguid, &GUID_CLASS_USB_DEVICE,
sizeof(GUID_CLASS_USB_DEVICE));
hDevNotify = RegisterDeviceNotification
(sshStatusHandle, &header, DEVICE_NOTIFY_SERVICE_HANDLE);

if(!hDevNotify)
{
AddToMessageLog(TEXT
("RegisterDeviceNotification"));
goto cleanup;
}

// report the status to the service control manager.
//
if (!ReportStatusToSCMgr(
SERVICE_RUNNING, //
service state
NO_ERROR, // exit
code
0)) // wait
hint
goto cleanup;


WaitForSingleObject(hServerStopEvent, INFINITE);

cleanup:

if (hServerStopEvent)
CloseHandle(hServerStopEvent);

return;
}


VOID ServiceStop()
{
UnregisterDeviceNotification(hDevNotify);

if ( hServerStopEvent )
SetEvent(hServerStopEvent);
}

Thanks again,
Abraham Louis

Abraham Louis

unread,
Mar 4, 2003, 10:22:09 AM3/4/03
to
Please ignore my previous post. I have resolved the
problem.

>.
>

sujayup...@gmail.com

unread,
Jun 21, 2018, 6:27:00 AM6/21/18
to
Hi Abraham,

Can you please share your changes. I am facing a similar issue in the service.

Thanks in advance.
Reply all
Reply to author
Forward
0 new messages