267 lines
7.2 KiB
C++
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);
|
||
|
}
|
||
|
|