2025-11-28 00:35:46 +09:00

282 lines
7.2 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//
// DimmerService.cpp
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <objbase.h>
#include <atlbase.h>
#include "DeviceDll.h"
#include <atlcom.h>
#include <initguid.h>
#include <upnphost.h>
#include "resource.h"
#include "dimmerdevice.h"
#include "DimmerService.h"
UPNPDimmerService::UPNPDimmerService()
{
// Set the default values for the state table variables power and dimLevel
power = VARIANT_FALSE;
dimnessLevel = 0;
InitializeCriticalSection(&csSync);
// Make it NULL and this will be later set when the device host calls the Advise()
esEventingManager = NULL;
}
UPNPDimmerService::~UPNPDimmerService()
{
// Cleanup before the service exits
if (esEventingManager)
{
// we have to release the pointer to the Eventing Manager Interface on shutdown
esEventingManager->Release();
esEventingManager = NULL;
}
DeleteCriticalSection(&csSync);
}
HRESULT UPNPDimmerService::get_Power(_Out_ VARIANT_BOOL *pval)
{
// Return the value of the state table variable Power
EnterCriticalSection(&csSync);
*pval = power;
LeaveCriticalSection(&csSync);
return S_OK;
}
HRESULT UPNPDimmerService::get_dimLevel(_Out_ LONG *dLevel)
{
// Return the value of the state table variable dimLevel
EnterCriticalSection(&csSync);
*dLevel = dimnessLevel;
LeaveCriticalSection(&csSync);
return S_OK;
}
HRESULT UPNPDimmerService::PowerOn()
{
DISPID rgdispidChanges[1];
HRESULT hr = S_OK;
WCHAR cwszDebugString[DEBUG_STRING_LENGTH];
EnterCriticalSection(&csSync);
if (power != VARIANT_TRUE)
{
power = VARIANT_TRUE;
LeaveCriticalSection(&csSync);
// We have to send an event here indicating that the value of Power has changed
if(esEventingManager)
{
// Send the event that power = TRUE through OnStateChanged API exposed by IUPnPEventSource
rgdispidChanges[0]=DISPID_POWER;
hr = esEventingManager->OnStateChanged(1, rgdispidChanges);
if(FAILED(hr))
{
INT iLen = swprintf_s( cwszDebugString, 100, L"UPNPDimmerService: PowerOn failed. Call to IUPnPEventSink::OnStateChanged method failed. HRESULT: 0x%x\n", hr );
if(-1 != iLen)
{
OutputDebugString(cwszDebugString);
}
else
{
OutputDebugString(L"UPNPDimmerService: swprintf_s failed.");
}
}
}
}
else
{
LeaveCriticalSection(&csSync);
}
return hr;
}
HRESULT UPNPDimmerService::PowerOff()
{
DISPID rgdispidChanges[1];
HRESULT hr = S_OK;
WCHAR cwszDebugString[DEBUG_STRING_LENGTH];
EnterCriticalSection(&csSync);
if (power != VARIANT_FALSE)
{
power = VARIANT_FALSE;
// We have to send an event here since the value of a State table variable
// has changed
LeaveCriticalSection(&csSync);
if(esEventingManager)
{
// Send the event using the OnStateChanged API and indicate the the
// value of the state table variable Power has changed
rgdispidChanges[0]=DISPID_POWER;
hr = esEventingManager->OnStateChanged(1, rgdispidChanges);
if(FAILED(hr))
{
INT iLen = swprintf_s( cwszDebugString, 100, L"UPNPDimmerService: PowerOff failed. Call to IUPnPEventSink::OnStateChanged method failed. HRESULT: 0x%x\n", hr );
if(-1 != iLen)
{
OutputDebugString(cwszDebugString);
}
else
{
OutputDebugString(L"UPNPDimmerService: swprintf_s failed.");
}
}
}
}
else
{
LeaveCriticalSection(&csSync);
}
return hr;
}
HRESULT UPNPDimmerService::GetPowerValue(_Out_ VARIANT_BOOL*powerVal)
{
EnterCriticalSection(&csSync);
*powerVal = power;
LeaveCriticalSection(&csSync);
// We have no events to send for this action
return S_OK;
}
HRESULT UPNPDimmerService::SetDimLevel(_In_ LONG dLevel)
{
DISPID rgdispidChanges[1];
HRESULT hr = S_OK;
WCHAR cwszDebugString[DEBUG_STRING_LENGTH];
EnterCriticalSection(&csSync);
dimnessLevel = dLevel;
// The possible values for dimnessLevel are 0 - 100
if (dimnessLevel > 100) dimnessLevel = 100;
if (dimnessLevel < 0) dimnessLevel = 0;
LeaveCriticalSection(&csSync);
// We have to send an event here
if(esEventingManager)
{
// Send the event using the OnStateChanged API to indicate that value
// of State table varaible dimLevel has changed
rgdispidChanges[0]=DISPID_DIMLEVEL;
hr = esEventingManager->OnStateChanged(1, rgdispidChanges);
if(FAILED(hr))
{
INT iLen = swprintf_s( cwszDebugString, 100, L"UPNPDimmerService: SetDimLevel failed. Call to IUPnPEventSink::OnStateChanged method failed. HRESULT: 0x%x\n", hr );
if(-1 != iLen)
{
OutputDebugString(cwszDebugString);
}
else
{
OutputDebugString(L"UPNPDimmerService: swprintf_s failed.");
}
}
}
return hr;
}
HRESULT UPNPDimmerService::GetDimLevel(_Out_ LONG *dLevel)
{
EnterCriticalSection(&csSync);
*dLevel = dimnessLevel;
LeaveCriticalSection(&csSync);
// We have no events to send here as the state table has not changed
return S_OK;
}
HRESULT UPNPDimmerService::GetConfigDetails(_Out_ VARIANT_BOOL *powerVal, _Out_ LONG *dLevel)
{
EnterCriticalSection(&csSync);
*dLevel = dimnessLevel;
*powerVal = power;
LeaveCriticalSection(&csSync);
// We have no events to send here as the state table has not changed
return S_OK;
}
HRESULT UPNPDimmerService::Advise (_In_ IUPnPEventSink *punkSubscriber)
{
// We have to get query for the IUPnPEventSink Interface to send events
// later using the OnStateChanged API
HRESULT hr = S_OK;
WCHAR cwszDebugString[DEBUG_STRING_LENGTH];
// Query the pointer passed to the Advise function for the IUPnPEventSink Interface
hr = punkSubscriber->QueryInterface(IID_IUPnPEventSink, (void **)&esEventingManager);
if (FAILED(hr))
{
INT iLen = swprintf_s( cwszDebugString, 100, L"UPNPDimmerService: Query Interface failed. Could not get pointer to IUPnPEventSink. HRESULT: 0x%x\n", hr );
if(-1 != iLen)
{
OutputDebugString(cwszDebugString);
}
else
{
OutputDebugString(L"UPNPDimmerService: swprintf_s failed.");
}
esEventingManager = NULL;
return hr;
}
return hr;
}
HRESULT UPNPDimmerService::Unadvise(_In_ IUPnPEventSink *punkSubscriber)
{
UNREFERENCED_PARAMETER(punkSubscriber);
// Device Host is not interested in receiving more events and so set the
// pointer to the IUPnPEventSink interface to NULL
if (esEventingManager)
{
// esEventingManager is already set by the advise
esEventingManager->Release();
esEventingManager = NULL;
}
return S_OK;
}