Figure 1 CDevice
Device.h
// Device.h : Declaration of the CDevice
#ifndef __DEVICE_H_
#define __DEVICE_H_
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CDevice
class ATL_NO_VTABLE CDevice :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CDevice, &CLSID_Device>,
public IDeviceStatus,
public IDeviceControl,
public IStdMarshalInfo
{
public:
CDevice()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_DEVICE)
DECLARE_NOT_AGGREGATABLE(CDevice)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CDevice)
COM_INTERFACE_ENTRY(IDeviceStatus)
COM_INTERFACE_ENTRY(IDeviceControl)
COM_INTERFACE_ENTRY(IStdMarshalInfo)
END_COM_MAP()
// IDeviceStatus
public:
STDMETHOD(GetCurrentPosition)(/*[out]*/ DWORD* pdwPos);
STDMETHOD(GetLastPosition)(/*[out]*/ DWORD* pdwPos);
// IDeviceControl
STDMETHOD(SetPosition)(/*[in]*/ DWORD dwPos, /*[out]*/ DWORD*
pdwOldPos);
// IStdMarshalInfo
STDMETHOD(GetClassForHandler)(ULONG dwDestContext,
VOID * pvDestContext, GUID * pClsid);
};
#endif //__DEVICE_H_
Device.cpp
// Device.cpp : Implementation of CDevice
#include "stdafx.h"
#include "DeviceServer.h"
#include "Device.h"
const CLSID CLSID_DeviceHandler =
{0xE5B12275,0xDBF9,0x4F4D,{0xB3,0xA0,0x3E,0xFA,0xD4,0xA3,0x9D,0x1D}};
/////////////////////////////////////////////////////////////////////////////
// CDevice
STDMETHODIMP CDevice::GetLastPosition(DWORD *pdwPos)
{
*pdwPos = GetCurrentProcessId ();
return S_OK;
}
STDMETHODIMP CDevice::GetCurrentPosition(DWORD *pdwPos)
{
*pdwPos = GetCurrentProcessId ();
return S_OK;
}
STDMETHODIMP CDevice::SetPosition(DWORD dwPos, DWORD* pdwOldPos)
{
*pdwOldPos = GetCurrentProcessId ();
return S_OK;
}
STDMETHODIMP CDevice::GetClassForHandler(ULONG dwDestContext,
VOID * pvDestContext, GUID * pClsid)
{
*pClsid = CLSID_DeviceHandler;
return S_OK;
}
Figure 3 CDeviceHandler
DeviceHandler.h
// DeviceHandler.h : Declaration of the CDeviceHandler
#ifndef __DEVICEHANDLER_H_
#define __DEVICEHANDLER_H_
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CDeviceHandler
class ATL_NO_VTABLE CDeviceHandler :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CDeviceHandler, &CLSID_DeviceHandler>,
public IDeviceStatus
{
public:
CDeviceHandler()
{
}
HRESULT FinalConstruct ();
DECLARE_GET_CONTROLLING_UNKNOWN()
DECLARE_REGISTRY_RESOURCEID(IDR_DEVICEHANDLER)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CDeviceHandler)
COM_INTERFACE_ENTRY(IDeviceStatus)
COM_INTERFACE_ENTRY_AGGREGATE_BLIND (m_spUnkInner.p)
END_COM_MAP()
// IDeviceStatus
public:
STDMETHOD(GetCurrentPosition)(/*[out]*/ DWORD* pdwPos);
STDMETHOD(GetLastPosition)(/*[out]*/ DWORD* pdwPos);
CComPtr<IUnknown> m_spUnkInner;
};
#endif //__DEVICEHANDLER_H_
DeviceHandler.cpp
// DeviceHandler.cpp : Implementation of CDeviceHandler
#include "stdafx.h"
#include "DeviceHandlerServer.h"
#include "DeviceHandler.h"
/////////////////////////////////////////////////////////////////////////////
// CDeviceHandler
STDMETHODIMP CDeviceHandler::GetLastPosition(DWORD *pdwPos)
{
//
// Handle this call locally.
//
*pdwPos = GetCurrentProcessId ();
return S_OK;
}
STDMETHODIMP CDeviceHandler::GetCurrentPosition(DWORD *pdwPos)
{
//
// Delegate this call to the device object.
//
HRESULT hr;
IDeviceStatus* pDeviceStatus;
hr = m_spUnkInner->QueryInterface (IID_IDeviceStatus, (void**)
&pDeviceStatus);
if (FAILED (hr))
return hr;
hr = pDeviceStatus->GetCurrentPosition (pdwPos);
pDeviceStatus->Release ();
return hr;
}
HRESULT CDeviceHandler::FinalConstruct ()
{
//
// Aggregate COM's proxy manager.
//
return CoGetStdMarshalEx (GetControllingUnknown (), SMEXF_HANDLER,
&m_spUnkInner);
}
DeviceHandler.rgs
HKCR
{
DeviceHandlerServer.DeviceHandler.1 = s 'DeviceHandler Class'
{
CLSID = s '{E5B12275-DBF9-4F4D-B3A0-3EFAD4A39D1D}'
}
DeviceHandlerServer.DeviceHandler = s 'DeviceHandler Class'
{
CLSID = s '{E5B12275-DBF9-4F4D-B3A0-3EFAD4A39D1D}'
CurVer = s 'DeviceHandlerServer.DeviceHandler.1'
}
NoRemove CLSID
{
ForceRemove {E5B12275-DBF9-4F4D-B3A0-3EFAD4A39D1D} =
s'DeviceHandler Class'
{
ProgID = s 'DeviceHandlerServer.DeviceHandler.1'
VersionIndependentProgID =
s'DeviceHandlerServer.DeviceHandler'
InprocHandler32 = s '%MODULE%'
{
val ThreadingModel = s 'Both'
}
'TypeLib' = s '{2DC1B111-F396-44CB-88C7-4FE8DF8FC331}'
}
}
}
Figure 5 CDeviceClientDlg
DeviceClientDlg.h
// DeviceClientDlg.h : header file
//
#if !defined(AFX_DEVICECLIENTDLG_H__BE6BB82F_1D6E_4D76_948C_C829534E00F3__INCLUDED_)
#define AFX_DEVICECLIENTDLG_H__BE6BB82F_1D6E_4D76_948C_C829534E00F3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
// CDeviceClientDlg dialog
class CDeviceClientDlg : public CDialog
{
// Construction
public:
CDeviceClientDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CDeviceClientDlg)
enum { IDD = IDD_DEVICECLIENT_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDeviceClientDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
void ReportError (HRESULT hr);
IDeviceStatus* m_pDeviceStatus;
IDeviceControl* m_pDeviceControl;
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CDeviceClientDlg)
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnGetLastPosition();
afx_msg void OnGetCurrentPosition();
afx_msg void OnSetPosition();
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately
// before the previous line.
#endif // !defined(AFX_DEVICECLIENTDLG_H__BE6BB82F_1D6E_4D76_948C_C829534E00F3__INCLUDED_)
DeviceClientDlg.cpp
// DeviceClientDlg.cpp : implementation file
//
#include "stdafx.h"
#include "DeviceServer.h"
#include "DeviceServer_i.c"
#include "DeviceClient.h"
#include "DeviceClientDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDeviceClientDlg dialog
CDeviceClientDlg::CDeviceClientDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDeviceClientDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CDeviceClientDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in
// Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pDeviceStatus = NULL;
m_pDeviceControl = NULL;
}
void CDeviceClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDeviceClientDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDeviceClientDlg, CDialog)
//{{AFX_MSG_MAP(CDeviceClientDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_GETLASTPOS, OnGetLastPosition)
ON_BN_CLICKED(IDC_GETCURPOS, OnGetCurrentPosition)
ON_BN_CLICKED(IDC_SETPOS, OnSetPosition)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDeviceClientDlg message handlers
BOOL CDeviceClientDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//
// Display the process ID in the dialog.
//
DWORD dwPID = ::GetCurrentProcessId ();
CString string;
string.Format (_T ("Process ID = %lu"), dwPID);
SetDlgItemText (IDC_PID, string);
//
// Create a device object and cache an IDeviceStatus interface pointer.
//
HRESULT hr = ::CoCreateInstance (CLSID_Device, NULL, CLSCTX_SERVER,
IID_IDeviceStatus, (void**) &m_pDeviceStatus);
if (FAILED (hr)) {
ReportError (hr);
GetDlgItem (IDC_GETLASTPOS)->EnableWindow (FALSE);
GetDlgItem (IDC_GETCURPOS)->EnableWindow (FALSE);
GetDlgItem (IDC_SETPOS)->EnableWindow (FALSE);
return TRUE;
}
//
// Cache an IDeviceControl interface pointer, too.
//
hr = m_pDeviceStatus->QueryInterface (IID_IDeviceControl,
(void**) &m_pDeviceControl);
if (FAILED (hr)) {
ReportError (hr);
GetDlgItem (IDC_GETLASTPOS)->EnableWindow (FALSE);
GetDlgItem (IDC_GETCURPOS)->EnableWindow (FALSE);
GetDlgItem (IDC_SETPOS)->EnableWindow (FALSE);
m_pDeviceStatus->Release ();
return TRUE;
}
return TRUE;
}
void CDeviceClientDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CDeviceClientDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CDeviceClientDlg::OnDestroy()
{
//
// Release interface pointers before shutting down.
//
if (m_pDeviceStatus != NULL) {
m_pDeviceStatus->Release ();
m_pDeviceStatus = NULL;
}
if (m_pDeviceControl != NULL) {
m_pDeviceControl->Release ();
m_pDeviceControl = NULL;
}
CDialog::OnDestroy();
}
void CDeviceClientDlg::OnGetLastPosition()
{
ASSERT (m_pDeviceStatus != NULL);
//
// Call IDeviceStatus::GetLastPosition.
//
DWORD dwPos;
HRESULT hr = m_pDeviceStatus->GetLastPosition (&dwPos);
if (FAILED (hr)) {
ReportError (hr);
return;
}
//
// Display the last device position (actually the process ID).
//
CString string;
string.Format (_T ("Process ID = %lu"), dwPos);
MessageBox (string);
}
void CDeviceClientDlg::OnGetCurrentPosition()
{
ASSERT (m_pDeviceStatus != NULL);
//
// Call IDeviceStatus::GetCurrentPosition.
//
DWORD dwPos;
HRESULT hr = m_pDeviceStatus->GetCurrentPosition (&dwPos);
if (FAILED (hr)) {
ReportError (hr);
return;
}
//
// Display the current device position (actually the process ID).
//
CString string;
string.Format (_T ("Process ID = %lu"), dwPos);
MessageBox (string);
}
void CDeviceClientDlg::OnSetPosition()
{
ASSERT (m_pDeviceControl != NULL);
//
// Call IDeviceControl::SetPosition.
//
DWORD dwOldPos;
HRESULT hr = m_pDeviceControl->SetPosition (1234, &dwOldPos);
if (FAILED (hr)) {
ReportError (hr);
return;
}
//
// Display the old device position (actually the process ID).
//
CString string;
string.Format (_T ("Process ID = %lu"), dwOldPos);
MessageBox (string);
}
/////////////////////////////////////////////////////////////////////////////
// Helper function for error reporting
void CDeviceClientDlg::ReportError(HRESULT hr)
{
LPTSTR pszMessage;
if (::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, (LPTSTR) &pszMessage,
0, NULL)) {
MessageBox (pszMessage, _T ("Error"));
::LocalFree (pszMessage);
}
}