Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Windows Service and Device notification

324 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.
0 new messages