/////////////////////////////////////////////////////////////// // local.cpp - server for outprocMT // // // // Platform: Dell Dimension 9150, WinXP, SP2 // // Application: Demonstration for CSE775 - Distrib. Objs // // Authors: Eddon & Eddon, Inside Distributed COM, // // Microsoft Press, 1998 // // Modified: Jim Fawcett, Syracuse Univ, CST 2-187 // // (315) 443-3948, fawcett@ecs.syr.edu // /////////////////////////////////////////////////////////////// #define _WIN32_DCOM #include #include // For cout #include "registry.h" // For registry functions #include "Component\component.h" // Generated by MIDL using namespace std; long g_cComponents = 0; long g_cServerLocks = 0; HANDLE g_hEvent; //----< component declaration >-------------------------------- class CInsideDCOM : public ISum { public: // IUnknown HRESULT __stdcall QueryInterface(REFIID riid, void** ppv); ULONG __stdcall AddRef(); ULONG __stdcall Release(); // ISum HRESULT __stdcall Sum(int x, int y, int* retval); CInsideDCOM() : m_cRef(1) { InitializeCriticalSection(&cs); InterlockedIncrement(&g_cComponents); } ~CInsideDCOM() { lock(); cout << "Component: CInsideDCOM::~CInsideDCOM()" << '\n' << endl; unlock(); InterlockedDecrement(&g_cComponents); DeleteCriticalSection(&cs); } void lock() { EnterCriticalSection(&cs); } void unlock() { LeaveCriticalSection(&cs); } private: CRITICAL_SECTION cs; ULONG m_cRef; }; // //----< component AddRef >------------------------------------- ULONG CInsideDCOM::AddRef() { lock(); cout << "Component: CInsideDCOM::AddRef() m_cRef = " << m_cRef + 1 << endl; unlock(); return InterlockedIncrement((long*)&m_cRef); } //----< component Release >------------------------------------ ULONG CInsideDCOM::Release() { lock(); cout << "Component: CInsideDCOM::Release() m_cRef = " << m_cRef - 1 << endl; unlock(); if(InterlockedDecrement((long*)&m_cRef) != 0) return m_cRef; SetEvent(g_hEvent); // Server main is waiting on this event lock(); delete this; unlock(); return 0; } //----< component QueryInterface >----------------------------- HRESULT CInsideDCOM::QueryInterface(REFIID riid, void** ppv) { if(riid == IID_IUnknown) { lock(); cout << "Component: CInsideDCOM::QueryInterface() for IUnknown returning " << this << endl; *ppv = reinterpret_cast(this); unlock(); } else if(riid == IID_ISum) { lock(); cout << "Component: CInsideDCOM::QueryInterface() for ISum returning " << this << endl; *ppv = (ISum*)this; unlock(); } else { lock(); *ppv = NULL; unlock(); return E_NOINTERFACE; } AddRef(); return S_OK; } // //----< implementation of component interface >---------------- HRESULT CInsideDCOM::Sum(int x, int y, int* retval) { lock(); DWORD ID = GetCurrentThreadId(); cout << "\n thread ID in CInsideDCOM::Sum is: " << ID << "\n\n"; cout << "Component: CInsideDCOM::Sum() " << x << " + " << y << " = " << x + y << '\n' << endl; *retval = x + y; unlock(); return S_OK; } //----< class factory declaration >---------------------------- class CFactory : public IClassFactory { public: // IUnknown ULONG __stdcall AddRef(); ULONG __stdcall Release(); HRESULT __stdcall QueryInterface(REFIID riid, void** ppv); // IClassFactory HRESULT __stdcall CreateInstance( IUnknown *pUnknownOuter, REFIID riid, void** ppv ); HRESULT __stdcall LockServer(BOOL bLock); CFactory() : m_cRef(1) { InitializeCriticalSection(&cs); } ~CFactory() { DeleteCriticalSection(&cs); } void lock() { EnterCriticalSection(&cs); } void unlock() { LeaveCriticalSection(&cs); } private: CRITICAL_SECTION cs; ULONG m_cRef; }; // //----< class factory AddRef >--------------------------------- ULONG CFactory::AddRef() { lock(); cout << "Component: CFactory::AddRef() m_cRef = " << m_cRef + 1 << endl; unlock(); return InterlockedIncrement((long*)&m_cRef); } //----< class factory Release >-------------------------------- ULONG CFactory::Release() { lock(); cout << "Component: CFactory::Release() m_cRef = " << m_cRef - 1 << endl; unlock(); if(InterlockedDecrement((long*)&m_cRef) != 0) return m_cRef; delete this; return 0; } //----< class factory QueryInterface >------------------------- HRESULT CFactory::QueryInterface(REFIID riid, void** ppv) { if((riid == IID_IUnknown) || (riid == IID_IClassFactory)) { lock(); cout << "Component: CFactory::QueryInteface() " << "for IUnknown or IClassFactory " << this << endl; *ppv = (IClassFactory*)this; unlock(); } else { lock(); *ppv = NULL; unlock(); return E_NOINTERFACE; } AddRef(); return S_OK; } // //----< create instance of component >------------------------- HRESULT CFactory:: CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv) { if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION; lock(); CInsideDCOM *pInsideDCOM = new CInsideDCOM; cout << "Component: CFactory::CreateInstance() " << pInsideDCOM << endl; unlock(); if(pInsideDCOM == NULL) return E_OUTOFMEMORY; // QueryInterface probably for IID_IUNKNOWN HRESULT hr = pInsideDCOM->QueryInterface(riid, ppv); pInsideDCOM->Release(); return hr; } //---< lock server process >----------------------------------- HRESULT CFactory::LockServer(BOOL bLock) { if(bLock) InterlockedIncrement(&g_cServerLocks); else InterlockedDecrement(&g_cServerLocks); return S_OK; } //----< register component >----------------------------------- // // - load type library // - place server entries in registry // void RegisterComponent() { ITypeLib* pTypeLib; LoadTypeLibEx(L"Component.exe", REGKIND_DEFAULT, &pTypeLib); pTypeLib->Release(); RegisterServer( "Component.exe", CLSID_InsideDCOM, "Inside DCOM Sample", "Component.InsideDCOM", "Component.InsideDCOM.1", NULL ); } // //----< check for designated command line parameters >--------- // // - RegServer: registers component as LocalServer32 // - UnregServer: removes entries from registry // - Embedding causes main to: // - create class factory // - register component with COM run-time // passing pointer to class factory // - wait for termination event // - then unregister component with COM run-time // void CommandLineParameters(int argc, char** argv) { RegisterComponent(); if(argc < 2) { cout << "No parameter, but registered anyway" << endl; exit(false); } char* szToken = strtok(argv[1], "-/"); if(_stricmp(szToken, "RegServer") == 0) { RegisterComponent(); cout << "RegServer" << endl; exit(true); } if(_stricmp(szToken, "UnregServer") == 0) { UnRegisterTypeLib(LIBID_Component, 1, 0, LANG_NEUTRAL, SYS_WIN32); UnregisterServer( CLSID_InsideDCOM, "Component.InsideDCOM", "Component.InsideDCOM.1" ); cout << "UnregServer" << endl; exit(true); } if(_stricmp(szToken, "Embedding") != 0) { cout << "Invalid parameter" << endl; exit(false); } } // //----< process start-up entry point >------------------------- void main(int argc, char** argv) { CommandLineParameters(argc, argv); cout << "Component: CoInitializeEx()" << endl; CoInitializeEx(NULL, COINIT_MULTITHREADED); DWORD ID = GetCurrentThreadId(); cout << "\n thread ID in server MTA is: " << ID << "\n\n"; IClassFactory *pClassFactory = new CFactory(); cout << "Component: CoRegisterClassObject()" << endl; DWORD dwRegister; CoRegisterClassObject( CLSID_InsideDCOM, pClassFactory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegister ); g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); WaitForSingleObject(g_hEvent, INFINITE); char ch; // don't collide with output in component destructor Sleep(100); cout << " strike any key to exit: "; cin.read(&ch,1); CoRevokeClassObject(dwRegister); pClassFactory->Release(); CoUninitialize(); }