windows-nt/Source/XPSP1/NT/net/upnp/host/upnphost/dll/svcmain.cpp
2020-09-26 16:20:57 +08:00

267 lines
7.2 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000.
//
// File: S V C M A I N . C P P
//
// Contents: Service main for upnphost.dll
//
// Notes:
//
// Author: mbend 8 Aug 2000
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include <dbt.h>
#include "uhbase.h"
#include "uhinit.h"
#include "uhres.h"
#include "hostp.h"
// Includes for COM objects needed in the following object map.
#include "DynamicContentSource.h"
#include "DescriptionManager.h"
#include "DevicePersistenceManager.h"
#include "ContainerManager.h"
#include "Registrar.h"
#include "AutomationProxy.h"
#include "evtobj.h"
#include "ValidationManager.h"
#include "udhhttp.h"
#include "uhcommon.h"
CServiceModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_UPnPDynamicContentSource, CDynamicContentSource)
OBJECT_ENTRY(CLSID_UPnPDescriptionManager, CDescriptionManager)
OBJECT_ENTRY(CLSID_UPnPDevicePersistenceManager, CDevicePersistenceManager)
OBJECT_ENTRY(CLSID_UPnPContainerManager, CContainerManager)
OBJECT_ENTRY(CLSID_UPnPRegistrar, CRegistrar)
OBJECT_ENTRY(CLSID_UPnPAutomationProxy, CUPnPAutomationProxy)
OBJECT_ENTRY(CLSID_UPnPEventingManager, CUPnPEventingManager)
OBJECT_ENTRY(CLSID_UPnPValidationManager, CValidationManager)
END_OBJECT_MAP()
VOID
CServiceModule::DllProcessAttach (
HINSTANCE hinst)
{
CComModule::Init (ObjectMap, hinst);
}
VOID
CServiceModule::DllProcessDetach (
VOID)
{
CComModule::Term ();
}
DWORD
CServiceModule::DwHandler (
DWORD dwControl,
DWORD dwEventType,
PVOID pEventData,
PVOID pContext)
{
if ((SERVICE_CONTROL_STOP == dwControl) ||
(SERVICE_CONTROL_SHUTDOWN == dwControl))
{
TraceTag (ttidUPnPHost, "Received SERVICE_CONTROL_STOP request");
SetServiceStatus (SERVICE_STOP_PENDING);
// Post the quit message.
//
PostThreadMessage (m_dwThreadID, WM_QUIT, 0, 0);
}
else if (SERVICE_CONTROL_INTERROGATE == dwControl)
{
TraceTag (ttidUPnPHost, "Received SERVICE_CONTROL_INTERROGATE request");
UpdateServiceStatus (FALSE);
}
return 1;
}
VOID
CServiceModule::SetServiceStatus(DWORD dwState)
{
m_status.dwCurrentState = dwState;
m_status.dwCheckPoint = 0;
if (!::SetServiceStatus (m_hStatus, &m_status))
{
TraceHr (ttidError, FAL, HrFromLastWin32Error(), FALSE,
"CServiceModule::SetServiceStatus");
}
}
VOID CServiceModule::UpdateServiceStatus (
BOOL fUpdateCheckpoint /* = TRUE */)
{
if (fUpdateCheckpoint)
{
m_status.dwCheckPoint++;
}
if (!::SetServiceStatus (m_hStatus, &m_status))
{
TraceHr (ttidError, FAL, HrFromLastWin32Error(), FALSE,
"CServiceModule::UpdateServiceStatus");
}
}
VOID
CServiceModule::Run()
{
HRESULT hr = S_OK;
hr = CoInitializeEx (NULL,
COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
TraceHr (ttidError, FAL, hr, FALSE, "CServiceModule::Run: "
"CoInitializeEx failed");
if (SUCCEEDED(hr))
{
hr = HrCreateNetworkSID();
TraceHr(ttidError, FAL, hr, FALSE,"HrCreateNetworkSID");
}
if (SUCCEEDED(hr))
{
TraceTag (ttidUPnPHost, "Calling RegisterClassObjects...");
// Create the event to sychronize registering our class objects
// with the connection manager which attempts to CoCreate
// objects which are also registered here. I've seen cases
// where the connection manager will be off and running before
// this completes causing CoCreateInstance to fail.
// The connection manager will wait on this event before
// executing CoCreateInstance.
//
HANDLE hEvent;
hr = HrNmCreateClassObjectRegistrationEvent (&hEvent);
if (SUCCEEDED(hr))
{
hr = _Module.RegisterClassObjects (
CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
REGCLS_MULTIPLEUSE);
TraceHr (ttidError, FAL, hr, FALSE, "CServiceModule::Run: "
"_Module.RegisterClassObjects failed");
if(SUCCEEDED(hr))
{
IUPnPRegistrarPrivate * pPriv = NULL;
hr = HrCoCreateInstanceInproc(CLSID_UPnPRegistrar, &pPriv);
if(SUCCEEDED(hr))
{
hr = pPriv->Initialize();
ReleaseObj(pPriv);
}
}
// Signal the event and close it. If this delete's the
// event, so be it. It's purpose is served as all
// class objects have been registered.
//
SetEvent (hEvent);
CloseHandle (hEvent);
}
if (SUCCEEDED(hr))
{
hr = HrHttpInitialize();
}
if (SUCCEEDED(hr))
{
SetServiceStatus (SERVICE_RUNNING);
TraceTag (ttidUPnPHost, "upnphost is now running...");
MSG msg;
while (GetMessage (&msg, 0, 0, 0))
{
DispatchMessage (&msg);
}
// // We must synchronize with the install queue's thread otherwise
// // RevokeClassObjects will kill the InstallQueue object and
// // CoUninitialize will free the NetCfg module before the thread
// // is finished.
// //
// WaitForInstallQueueToExit();
if (SUCCEEDED(hr))
{
hr = HrHttpShutdown();
}
IUPnPRegistrarPrivate * pPriv = NULL;
hr = HrCoCreateInstanceInproc(CLSID_UPnPRegistrar, &pPriv);
if(SUCCEEDED(hr))
{
CoSuspendClassObjects();
hr = pPriv->Shutdown();
ReleaseObj(pPriv);
}
_Module.RevokeClassObjects ();
}
CoUninitialize();
}
CleanupNetworkSID();
}
VOID
CServiceModule::ServiceMain (
DWORD argc,
PWSTR argv[])
{
m_dwThreadID = GetCurrentThreadId ();
ZeroMemory (&m_status, sizeof(m_status));
m_status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
// Register the service control handler.
//
m_hStatus = RegisterServiceCtrlHandlerEx (
L"upnphost",
_DwHandler,
NULL);
if (m_hStatus)
{
SetServiceStatus (SERVICE_START_PENDING);
// When the Run function returns, the service has stopped.
//
Run ();
SetServiceStatus (SERVICE_STOPPED);
}
else
{
TraceHr (ttidError, FAL, HrFromLastWin32Error(), FALSE,
"CServiceModule::ServiceMain - RegisterServiceCtrlHandler failed");
}
}
// static
DWORD
WINAPI
CServiceModule::_DwHandler (
DWORD dwControl,
DWORD dwEventType,
PVOID pEventData,
PVOID pContext)
{
return _Module.DwHandler (dwControl, dwEventType, pEventData, pContext);
}