//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
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...
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
>.
>