March 01, 1998
Control How COM Marshals Your Data
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
| |||||||||