You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
6.2 KiB
225 lines
6.2 KiB
/*++
|
|
|
|
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();
|
|
}
|
|
|
|
MsgConfigurationLock(MSG_GET_SHARED, "MsgrCtrlHandler");
|
|
|
|
//
|
|
// If a message or LANA addition/removal message came in at the same time
|
|
// as the stop/shutdown control, it's possible that MsgNetEventCompletion
|
|
// has already run with the state set to STOPPING, in which case it's already
|
|
// done cleanup, so we don't need to (and shouldn't) set the wakeupEvent.
|
|
//
|
|
|
|
if (wakeupEvent != NULL)
|
|
{
|
|
SetEvent( wakeupEvent );
|
|
}
|
|
|
|
MsgConfigurationLock(MSG_RELEASE, "MsgrCtrlHandler");
|
|
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);
|
|
|
|
MsgConfigurationLock(MSG_GET_SHARED, "MsgrCtrlHandler");
|
|
SetEvent(wakeupEvent);
|
|
MsgConfigurationLock(MSG_GET_SHARED, "MsgrCtrlHandler");
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|