/////////////////////////////////////////////////////////////////////
// Client.cs - Demonstate COM+ with ATL project, using C# client
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ATL_COMPlus
{
  class Client
  {
    private ATL_COMPLUSLib.ATLComponent comp;

    Client()
    {
      comp = new ATL_COMPLUSLib.ATLComponent();
    }
    //----< modify a shared string in child thread >-----------------

    void threadProc()
    {
      for (int i = 0; i < 1000; ++i)
        comp.modifyShared("child  ");
    }
    //----< modify a shared string in parent thread >----------------

    static void Main(string[] args)
    {
      Client client = new Client();
      client.comp.shout("Hi There");
      Console.Write("\n  {0}", client.comp.reply());
      Thread t = new Thread(new ThreadStart(client.threadProc));
      t.Priority = ThreadPriority.Lowest;
      t.Start();
      for (int i = 0; i < 200; ++i)
      {
        client.comp.modifyShared("parent ");
        Console.Write("\n  {0}", client.comp.reply());
      }
      t.Join();
      Console.Write("\n  {0}", client.comp.reply());
      Console.Write("\n\n");
    }
  }
}
/////////////////////////////////////////////////////////////////////
// ATL_COMPlus. idl - Demonstate COM+ with ATL project
//
// This file will be processed by the MIDL tool to
// produce the type library (ATL_COMPLUS.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";

[
  object,
  uuid(128D3285-7399-4F48-8E8B-72DE72A4EE4E),
  dual,
  nonextensible,
  helpstring("IATLComponent Interface"),
  pointer_default(unique)
]
interface IATLComponent : IDispatch{
  [id(1), helpstring("method shout")] HRESULT shout([in] BSTR phrase);
  [id(2), helpstring("method reply")] HRESULT reply([out,retval] BSTR* phrase);
  [id(3), helpstring("method modifyShared")] HRESULT modifyShared([in] BSTR addition);
};
[
  uuid(DA98EFFE-2F05-4A6C-97CA-0FA239A8A332),
  version(1.0),
  helpstring("ATL_COMPLUS 1.0 Type Library")
]
library ATL_COMPLUSLib
{
  importlib("stdole2.tlb");
  [
    uuid(92228E21-F2E2-44D3-9E1F-0DDABE7504AD),
    helpstring("ATLComponent Class")
  ]
  coclass ATLComponent
  {
    [default] interface IATLComponent;
  };
};
/////////////////////////////////////////////////////////////////////
// ATLComponent.h - Demonstate COM+ with ATL project
//
#pragma once
#include "ATL_COMPLUS.h"
#include "resource.h" 
#include <comsvcs.h>
#include <iostream>


class ATL_NO_VTABLE CATLComponent :
  public CComObjectRootEx<CComMultiThreadModel>,
  public IObjectControl,
  public CComCoClass<CATLComponent, &CLSID_ATLComponent>,
  public IDispatchImpl<IATLComponent, &IID_IATLComponent, &LIBID_ATL_COMPLUSLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
  CATLComponent() : shared_(L"")
  {
    std::wcout << "\n  ATL_COMPlus object constructed";
  }

  DECLARE_PROTECT_FINAL_CONSTRUCT()

  HRESULT FinalConstruct()
  {
    return S_OK;
  }

  void FinalRelease()
  {
  }

DECLARE_REGISTRY_RESOURCEID(IDR_ATLCOMPONENT)

BEGIN_COM_MAP(CATLComponent)
  COM_INTERFACE_ENTRY(IATLComponent)
  COM_INTERFACE_ENTRY(IObjectControl)
  COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// IObjectControl
public:
  STDMETHOD(Activate)();
  STDMETHOD_(BOOL, CanBePooled)();
  STDMETHOD_(void, Deactivate)();

  CComPtr<IObjectContext> m_spObjectContext;

// IATLComponent
public:
  STDMETHOD(shout)(BSTR phrase);
public:
  STDMETHOD(reply)(BSTR* phrase);
public:
  STDMETHOD(modifyShared)(BSTR added);
private:
  CComBSTR shared_;
};

OBJECT_ENTRY_AUTO(__uuidof(ATLComponent), CATLComponent)
/////////////////////////////////////////////////////////////////////
// ATLComponent.cpp - Demonstate COM+ with ATL project
//
#include "stdafx.h"
#include "ATLComponent.h"
#include <iostream>
#include <sstream>

// CATLComponent

HRESULT CATLComponent::Activate()
{
  HRESULT hr = GetObjectContext(&m_spObjectContext);
  if (SUCCEEDED(hr))
    return S_OK;
  return hr;
} 

BOOL CATLComponent::CanBePooled()
{
  return FALSE;
} 

void CATLComponent::Deactivate()
{
  m_spObjectContext.Release();
} 


STDMETHODIMP CATLComponent::shout(BSTR phrase)
{
  std::wcout << "\n  " << phrase;
  if(m_spObjectContext->IsSecurityEnabled())
    std::cout << "\n\n  security is enabled\n";
  else
    std::cout << "\n\n  security is disabled\n";
  return S_OK;
}

STDMETHODIMP CATLComponent::reply(BSTR* phrase)
{
  CComBSTR btemp("shared value is ");
  btemp += shared_;
  *phrase = btemp;
  return S_OK;
}

STDMETHODIMP CATLComponent::modifyShared(BSTR added)
{
  if(shared_.Length() > 60)
    shared_.Empty();
  shared_ += added;
  return S_OK;
}
