Figure 2   CDeviceMonitor

DeviceMonitor.h


// DeviceMonitor.h : Declaration of the CDeviceMonitor

#ifndef __DEVICEMONITOR_H_
#define __DEVICEMONITOR_H_

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// CDeviceMonitor
class ATL_NO_VTABLE CDeviceMonitor : 
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CDeviceMonitor, &CLSID_DeviceMonitor>,
    public IDeviceMonitor
{
public:
    CDeviceMonitor()
    {
        m_dwDeviceID = 0;
    }

    void FinalRelease ();

DECLARE_REGISTRY_RESOURCEID(IDR_DEVICEMONITOR)
DECLARE_NOT_AGGREGATABLE(CDeviceMonitor)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CDeviceMonitor)
    COM_INTERFACE_ENTRY(IDeviceMonitor)
END_COM_MAP()

// IDeviceMonitor
public:
    STDMETHOD(GetDeviceID)(/*[out]*/ DWORD* pID);
    STDMETHOD(StartMonitoring)(/*[in, string]*/ LPCOLESTR pszDeviceName);
protected:
    DWORD m_dwDeviceID;
    DWORD m_dwROTID;
};

#endif //__DEVICEMONITOR_H_
DeviceMonitor.cpp

// DeviceMonitor.cpp : Implementation of CDeviceMonitor

#define ATL_DEBUG_INTERFACES

#include "stdafx.h"
#include "DevMonServer.h"
#include "DeviceMonitor.h"

/////////////////////////////////////////////////////////////////////////////
// CDeviceMonitor

STDMETHODIMP CDeviceMonitor::StartMonitoring(LPCOLESTR pszDeviceName)
{
    //
    // Fail the call if this object is already monitoring a device.
    //
    if (m_dwDeviceID)
        return E_FAIL;

    //
    // Create a display name of the form "Instance:devicename."
    //
    int nLen = wcslen (pszDeviceName);

    LPOLESTR pszDisplayName =
        (LPOLESTR) CoTaskMemAlloc ((nLen + 10) * sizeof (OLECHAR));

    if (pszDisplayName == NULL)
        return E_OUTOFMEMORY;

    wcscpy (pszDisplayName, OLESTR ("Instance:"));
    wcscat (pszDisplayName, pszDeviceName);

    //
    // Create an instance moniker from the display name.
    //
    IBindCtx* pBindCtx;
    HRESULT hr = CreateBindCtx (0, &pBindCtx);

    if (SUCCEEDED (hr)) {
        ULONG ulEaten;
        IMoniker* pMoniker;
        hr = MkParseDisplayName (pBindCtx, pszDisplayName, &ulEaten,
            &pMoniker);

        if (SUCCEEDED (hr)) {
            //
            // Register the moniker in the running object table.
            //
            IRunningObjectTable* prot;
            hr = pBindCtx->GetRunningObjectTable (&prot);

            if (SUCCEEDED (hr)) {
                hr = prot->Register (0, (IUnknown*) this, pMoniker,
                    &m_dwROTID);
                prot->Release ();
            }
            pMoniker->Release ();
        }
        pBindCtx->Release ();
    }

    //
    // Initialize the device ID, clean up, and return.
    //
    if (SUCCEEDED (hr))
        m_dwDeviceID = GetTickCount ();

    CoTaskMemFree (pszDisplayName);
    return hr;
}

void CDeviceMonitor::FinalRelease ()
{
    if (m_dwDeviceID) {
        //
        // Remove the moniker from the running object table.
        //
        IRunningObjectTable* prot;
        HRESULT hr = GetRunningObjectTable (0, &prot);

        if (SUCCEEDED (hr)) {
            prot->Revoke (m_dwROTID);
            prot->Release ();
        }
    }
}

STDMETHODIMP CDeviceMonitor::GetDeviceID(DWORD *pID)
{
    if (!m_dwDeviceID)
        return E_FAIL;

    *pID = m_dwDeviceID;
    return S_OK;
}