209 lines
5.3 KiB
C
209 lines
5.3 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
sighandl.c
|
||
|
||
Abstract:
|
||
|
||
The Messenger Service ControlHandling routines. This file contains
|
||
the following functions:
|
||
|
||
MsgrCtrlHandler
|
||
uninstall
|
||
|
||
Author:
|
||
|
||
Dan Lafferty (danl) 17-Jul-1991
|
||
|
||
Environment:
|
||
|
||
User Mode -Win32
|
||
|
||
Revision History:
|
||
|
||
17-Jul-1991 danl
|
||
Ported from LM2.0
|
||
|
||
--*/
|
||
|
||
//
|
||
// Includes
|
||
//
|
||
|
||
#include "msrv.h" // Message server declarations
|
||
#include <winsvc.h> // SERVICE_STOP
|
||
#include <dbt.h> // DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE
|
||
|
||
#include <netlib.h> // UNUSED macro
|
||
#include <msgdbg.h> // MSG_LOG
|
||
#include "msgdata.h"
|
||
|
||
|
||
|
||
DWORD
|
||
MsgrCtrlHandler(
|
||
IN DWORD dwControl,
|
||
IN DWORD dwEventType,
|
||
IN LPVOID lpEventData,
|
||
IN LPVOID lpContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function receives control requests that come in from the
|
||
Service Controller
|
||
|
||
Arguments:
|
||
|
||
dwControl - This is the control code.
|
||
dwEventType - In the case of a PnP control, the PNP event that occurred
|
||
lpEventData - Event-specific data for PnP controls
|
||
lpContext - Context data
|
||
|
||
Return Value:
|
||
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwRetVal = NO_ERROR;
|
||
static HANDLE s_hNeverSetEvent;
|
||
|
||
MSG_LOG(TRACE,"Control Request Received\n",0);
|
||
|
||
switch (dwControl) {
|
||
case SERVICE_CONTROL_SHUTDOWN:
|
||
|
||
MSG_LOG(TRACE,"Control Request = SHUTDOWN\n",0);
|
||
|
||
// Fall through
|
||
|
||
case SERVICE_CONTROL_STOP:
|
||
|
||
MSG_LOG(TRACE,"Control Request = STOP\n",0);
|
||
|
||
//
|
||
// Start the de-installation. This call includes the sending of
|
||
// the new status to the Service Controller.
|
||
//
|
||
|
||
//
|
||
// Update the Service Status to the pending state. And wake up
|
||
// the display thread (if running) so it will read it.
|
||
//
|
||
|
||
MsgStatusUpdate (STOPPING);
|
||
|
||
if (s_hNeverSetEvent != NULL)
|
||
{
|
||
CloseHandle(s_hNeverSetEvent);
|
||
s_hNeverSetEvent = NULL;
|
||
}
|
||
|
||
|
||
//
|
||
// In Hydra case, the display thread never goes asleep.
|
||
//
|
||
|
||
if (!g_IsTerminalServer)
|
||
{
|
||
MsgDisplayThreadWakeup();
|
||
}
|
||
|
||
SetEvent( wakeupEvent );
|
||
break;
|
||
|
||
case SERVICE_CONTROL_INTERROGATE:
|
||
MSG_LOG(TRACE,"Control Request = INTERROGATE\n",0);
|
||
MsgStatusUpdate (UPDATE_ONLY);
|
||
break;
|
||
|
||
case SERVICE_CONTROL_DEVICEEVENT:
|
||
MSG_LOG(TRACE,"Control Request = DEVICEEVENT\n",0);
|
||
|
||
if (dwEventType == DBT_DEVICEARRIVAL
|
||
||
|
||
dwEventType == DBT_DEVICEREMOVECOMPLETE)
|
||
{
|
||
NTSTATUS ntStatus;
|
||
|
||
if (s_hNeverSetEvent == NULL)
|
||
{
|
||
s_hNeverSetEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
||
if (s_hNeverSetEvent == NULL)
|
||
{
|
||
MsgStatusUpdate(UPDATE_ONLY);
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Assert that we're only getting the notifications we requested.
|
||
// If this fails, we'll do an extra rescan of the LANAs but find
|
||
// no changes and therefore do no extra work past that.
|
||
//
|
||
ASSERT(lpEventData
|
||
&&
|
||
((PDEV_BROADCAST_DEVICEINTERFACE) lpEventData)->dbcc_devicetype
|
||
== DBT_DEVTYP_DEVICEINTERFACE);
|
||
|
||
MSG_LOG1(TRACE," Device has been %s\n",
|
||
(dwEventType == DBT_DEVICEARRIVAL ? "added" : "removed"));
|
||
|
||
//
|
||
// We're currently waiting on LAN adapter install/removal, which does
|
||
// not directly coincide with NetBios binding/unbinding. We need to
|
||
// wait about 5 seconds to allow NetBios itself to process the event.
|
||
// Don't do this synchronously or else sleep/hibernate takes 5 seconds
|
||
// per LAN adapter to occur.
|
||
//
|
||
|
||
if (g_hNetTimeoutEvent == NULL)
|
||
{
|
||
ntStatus = RtlRegisterWait(&g_hNetTimeoutEvent, // Work item handle
|
||
s_hNeverSetEvent, // Waitable handle
|
||
MsgNetEventCompletion, // Callback
|
||
NULL, // pContext
|
||
5000, // Timeout
|
||
WT_EXECUTEONLYONCE | // One-shot and potentially lengthy
|
||
WT_EXECUTELONGFUNCTION);
|
||
|
||
if (!NT_SUCCESS(ntStatus))
|
||
{
|
||
MSG_LOG1(ERROR,
|
||
"MsgrCtrlHandler: RtlRegisterWait failed %x\n",
|
||
ntStatus);
|
||
|
||
//
|
||
// Asynchronous failed -- do it synchronously
|
||
//
|
||
|
||
Sleep(5000);
|
||
SetEvent(wakeupEvent);
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// As long as we're here...
|
||
//
|
||
MsgStatusUpdate (UPDATE_ONLY);
|
||
break;
|
||
|
||
default:
|
||
MSG_LOG(TRACE,"Control Request = OTHER (%#x)!!!\n", dwControl);
|
||
ASSERT(FALSE);
|
||
dwRetVal = ERROR_CALL_NOT_IMPLEMENTED;
|
||
}
|
||
|
||
return dwRetVal;
|
||
}
|
||
|