Listing 6: server.cpp Simple console-mode server app
// COM Marshalling Sample Server // Author : Fran Heeran #define INC_OLE2 #include <stdio.h> #include <conio.h> #include <windows.h> #include <initguid.h> #include "marsamp.h" extern "C" BOOL RegisterServer(LPSTR pszExeName); extern "C" void UnregisterServer(); HANDLE hevtDone; // Standard Class Factory class CClassFactory : public IClassFactory { protected: ULONG m_cRef; public: CClassFactory() { m_cRef = 1; } STDMETHODIMP QueryInterface (REFIID riid, void** ppv); STDMETHODIMP_(ULONG) AddRef(void) { return ++m_cRef; } STDMETHODIMP_(ULONG) Release(void); STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR*); STDMETHODIMP LockServer(BOOL) { return E_FAIL; } }; // ISimpleObject Interface class CSimpleObject : public IUnknown { private: LONG m_cRef; public: CSimpleObject() { m_cRef = 1; } ~CSimpleObject() { SetEvent(hevtDone); } IUNKNOWN_METHODS(IMPL); ISIMPLEOBJECT_METHODS(IMPL); }; CClassFactory g_ClassFactory; int __cdecl main(int argc, char *argv[], char *envp[]) { HRESULT hr; DWORD dwRegister; // Handle register/unregister commands if (argc > 1) { if (!strcmp(argv[1], "-register")) { if (argc != 3) { printf("Useage is server -register [path to server \ & proxy/stub]"); return 0; } if (!RegisterServer(argv[2])) printf("Failed to register Server & Proxy/Stub"); else printf("Successfully registered Server & Proxy/Stub"); return 0; } else if (!strcmp(argv[1], "-unregister")) { UnregisterServer(); printf("Unregistered Server & Proxy/Stub"); return 0; } } // Create the thread which is signaled when the // instance is deleted hevtDone = CreateEvent(NULL, FALSE, FALSE, NULL); if (!hevtDone) return 1; // Initialize COM hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); RETURNONFAILURE(hr, "CoInitializeEx() failed"); // Register class-object hr = CoRegisterClassObject(CLSID_SimpleObject, &g_ClassFactory, CLSCTX_SERVER, REGCLS_SINGLEUSE, &dwRegister); RETURNONFAILURE(hr,"Failed to register class object"); printf("Waiting...\n"); // Wait until we have been called to display the array WaitForSingleObject(hevtDone, INFINITE); CloseHandle(hevtDone); CoUninitialize(); // Wait for a key so the user can view the output printf("\nPress Any Key to Exit\n"); char ch = _getch(); return 0; } STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppvObject) { *ppvObject = NULL; if(IsEqualIID(riid, IID_IUnknown)) *ppvObject = (LPUNKNOWN) (LPCLASSFACTORY) this; else if(IsEqualIID(riid, IID_IClassFactory)) *ppvObject = (LPCLASSFACTORY) this; else return E_NOINTERFACE; ((LPUNKNOWN)*ppvObject)->AddRef(); return NOERROR; } STDMETHODIMP_(ULONG) CClassFactory::Release() { if (--m_cRef) return m_cRef; delete this; return 0; } STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID FAR *ppvObject) { HRESULT hr; CSimpleObject *pObj; *ppvObject = NULL; hr = ResultFromScode(E_OUTOFMEMORY); // Verify that a controlling unknown asks for IUnknown if (NULL != pUnkOuter) return ResultFromScode(CLASS_E_NOAGGREGATION); // Create the object telling us to notify us when it's gone. pObj = new CSimpleObject(); if (NULL == pObj) return hr; hr = pObj->QueryInterface(riid, ppvObject); if (FAILED(hr)) delete pObj; pObj->Release(); return hr; } STDMETHODIMP_(ULONG) CSimpleObject::Release() { if (!InterlockedDecrement(&m_cRef)) { delete this; return 0; } return m_cRef; } STDMETHODIMP_(ULONG) CSimpleObject::AddRef() { return InterlockedIncrement(&m_cRef); } STDMETHODIMP CSimpleObject::QueryInterface(REFIID riid, void** ppv) { if (ppv == NULL) return E_INVALIDARG; if (riid == IID_IUnknown || riid == IID_ISimpleObject) { *ppv = (IUnknown *) this; AddRef(); return S_OK; } *ppv = NULL; return E_NOINTERFACE; } STDMETHODIMP CSimpleObject::DisplayArray(BOOL *pArr) { printf("Array Length = %d Bytes\r\nCompressed Length = %d \ Bytes\r\n", FLAG_ARRAY_SIZE * sizeof(BOOL), FLAG_ARRAY_SIZE / 8); for (int i = 0;i < FLAG_ARRAY_SIZE;i++) printf("%d ", *(pArr + i)); return S_OK; } //End of File