446 lines
9.4 KiB
C++
446 lines
9.4 KiB
C++
#define INIT_MY_GUIDS
|
||
#include <ole2ver.h>
|
||
#include "edataobj.h"
|
||
|
||
|
||
// Count of the number of objects and number of locks.
|
||
ULONG g_cObj=0;
|
||
ULONG g_cLock=0;
|
||
|
||
//Make window handle global so other code can cause a shutdown
|
||
HWND g_hWnd=NULL;
|
||
HINSTANCE g_hInst=NULL;
|
||
|
||
|
||
/*
|
||
* WinMain
|
||
*
|
||
* Purpose:
|
||
* Main entry point of application.
|
||
*/
|
||
|
||
int PASCAL
|
||
WinMain(
|
||
HINSTANCE hInst,
|
||
HINSTANCE hInstPrev,
|
||
LPSTR pszCmdLine,
|
||
int nCmdShow)
|
||
{
|
||
MSG msg;
|
||
PAPPVARS pAV;
|
||
|
||
#ifndef WIN32
|
||
int cMsg = 96;
|
||
while (!SetMessageQueue(cMsg) && (cMsg -= 9))
|
||
;
|
||
#endif
|
||
g_hInst=hInst;
|
||
|
||
pAV=new CAppVars(hInst, hInstPrev, pszCmdLine, nCmdShow);
|
||
|
||
if (NULL==pAV)
|
||
return -1;
|
||
|
||
if (pAV->FInit())
|
||
{
|
||
while (GetMessage(&msg, NULL, 0,0 ))
|
||
{
|
||
TranslateMessage(&msg);
|
||
DispatchMessage(&msg);
|
||
}
|
||
}
|
||
|
||
delete pAV;
|
||
return msg.wParam;
|
||
}
|
||
|
||
|
||
LRESULT WINAPI
|
||
DataObjectWndProc(
|
||
HWND hWnd,
|
||
UINT iMsg,
|
||
WPARAM wParam,
|
||
LPARAM lParam)
|
||
{
|
||
switch (iMsg)
|
||
{
|
||
case WM_DESTROY:
|
||
PostQuitMessage(0);
|
||
break;
|
||
|
||
default:
|
||
return (DefWindowProc(hWnd, iMsg, wParam, lParam));
|
||
}
|
||
|
||
return 0L;
|
||
}
|
||
|
||
|
||
void PASCAL
|
||
ObjectDestroyed(void)
|
||
{
|
||
g_cObj--;
|
||
|
||
//No more objects and no locks, shut the app down.
|
||
if (0L==g_cObj && 0L==g_cLock && IsWindow(g_hWnd))
|
||
PostMessage(g_hWnd, WM_CLOSE, 0, 0L);
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
CAppVars::CAppVars(
|
||
HINSTANCE hInst,
|
||
HINSTANCE hInstPrev,
|
||
LPSTR pszCmdLine,
|
||
UINT nCmdShow)
|
||
{
|
||
m_hInst =hInst;
|
||
m_hInstPrev =hInstPrev;
|
||
m_pszCmdLine=pszCmdLine;
|
||
|
||
m_nCmdShow = nCmdShow;
|
||
|
||
m_hWnd=NULL;
|
||
|
||
#if 0
|
||
for (i=0; i < DOSIZE_CSIZES; i++)
|
||
{
|
||
m_rgdwRegCO[i]=0;
|
||
m_rgpIClassFactory[i]=NULL;
|
||
}
|
||
#else
|
||
m_dwRegCO = 0;
|
||
m_pIClassFactory = NULL;
|
||
#endif
|
||
|
||
m_fInitialized=FALSE;
|
||
return;
|
||
}
|
||
|
||
|
||
CAppVars::~CAppVars(void)
|
||
{
|
||
#if 0
|
||
UINT i;
|
||
|
||
//Revoke and destroy the class factories of all sizes
|
||
for (i=0; i < DOSIZE_CSIZES; i++)
|
||
{
|
||
if (0L!=m_rgdwRegCO[i])
|
||
CoRevokeClassObject(m_rgdwRegCO[i]);
|
||
|
||
if (NULL!=m_rgpIClassFactory[i])
|
||
m_rgpIClassFactory[i]->Release();
|
||
}
|
||
#else
|
||
if (0L != m_dwRegCO)
|
||
CoRevokeClassObject(m_dwRegCO);
|
||
|
||
if (NULL != m_pIClassFactory)
|
||
m_pIClassFactory->Release();
|
||
#endif
|
||
|
||
if (m_fInitialized)
|
||
CoUninitialize();
|
||
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* CAppVars::FInit
|
||
*
|
||
* Purpose:
|
||
* Initializes an CAppVars object by registering window classes,
|
||
* etc... If this function fails the caller should guarantee
|
||
* that the destructor is called.
|
||
*
|
||
* Return Value:
|
||
* BOOL TRUE if successful, FALSE otherwise.
|
||
*/
|
||
|
||
BOOL
|
||
CAppVars::FInit(void)
|
||
{
|
||
WNDCLASS wc;
|
||
HRESULT hr;
|
||
DWORD dwVer;
|
||
#ifdef WIN32
|
||
static TCHAR szClass[] = TEXT("IdataSvr32");
|
||
#else
|
||
static TCHAR szClass[] = TEXT("IdataSvr16");
|
||
#endif
|
||
|
||
//Check command line for -Embedding
|
||
if (lstrcmpiA(m_pszCmdLine, "-Embedding"))
|
||
return FALSE;
|
||
|
||
dwVer=CoBuildVersion();
|
||
|
||
if (rmm!=HIWORD(dwVer))
|
||
return FALSE;
|
||
|
||
if (FAILED(CoInitialize(NULL)))
|
||
return FALSE;
|
||
|
||
m_fInitialized=TRUE;
|
||
|
||
if (!m_hInstPrev)
|
||
{
|
||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||
wc.lpfnWndProc = DataObjectWndProc;
|
||
wc.cbClsExtra = 0;
|
||
wc.cbWndExtra = 0;
|
||
wc.hInstance = m_hInst;
|
||
wc.hIcon = NULL;
|
||
wc.hCursor = NULL;
|
||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||
wc.lpszMenuName = NULL;
|
||
wc.lpszClassName = szClass;
|
||
|
||
if (!RegisterClass(&wc))
|
||
return FALSE;
|
||
}
|
||
|
||
m_hWnd=CreateWindow(szClass,
|
||
szClass,
|
||
WS_OVERLAPPEDWINDOW,
|
||
135, 135, 350, 250,
|
||
NULL, NULL, m_hInst, NULL);
|
||
|
||
if (NULL==m_hWnd)
|
||
return FALSE;
|
||
|
||
g_hWnd=m_hWnd;
|
||
|
||
//ShowWindow(m_hWnd, m_nCmdShow);
|
||
//UpdateWindow(m_hWnd);
|
||
|
||
|
||
#if 0
|
||
/*
|
||
* This code supplies three different classes, one for each type
|
||
* of data object that handles a different size of data. All the
|
||
* class factories share the same implementation, but their
|
||
* instantiations differ by the type passed in the constructor.
|
||
* When the class factories create objects, they pass that size
|
||
* to the CDataObject contstructor as well.
|
||
*/
|
||
|
||
UINT i;
|
||
HRESULT hr2, hr3;
|
||
|
||
for (i=0; i < DOSIZE_CSIZES; i++)
|
||
{
|
||
m_rgpIClassFactory[i]=new CDataObjectClassFactory(i);
|
||
|
||
if (NULL==m_rgpIClassFactory[i])
|
||
return FALSE;
|
||
|
||
m_rgpIClassFactory[i]->AddRef();
|
||
}
|
||
|
||
hr=CoRegisterClassObject(CLSID_DataObjectSmall
|
||
, m_rgpIClassFactory[0], CLSCTX_LOCAL_SERVER
|
||
, REGCLS_MULTIPLEUSE, &m_rgdwRegCO[0]);
|
||
|
||
hr2=CoRegisterClassObject(CLSID_DataObjectMedium
|
||
, m_rgpIClassFactory[1], CLSCTX_LOCAL_SERVER
|
||
, REGCLS_MULTIPLEUSE, &m_rgdwRegCO[1]);
|
||
|
||
hr3=CoRegisterClassObject(CLSID_DataObjectLarge
|
||
, m_rgpIClassFactory[2], CLSCTX_LOCAL_SERVER
|
||
, REGCLS_MULTIPLEUSE, &m_rgdwRegCO[2]);
|
||
|
||
if (FAILED(hr) || FAILED(hr2) || FAILED(hr3))
|
||
return FALSE;
|
||
#else
|
||
m_pIClassFactory = new CDataObjectClassFactory();
|
||
if (NULL == m_pIClassFactory)
|
||
return FALSE;
|
||
m_pIClassFactory->AddRef();
|
||
#ifdef WIN32
|
||
hr = CoRegisterClassObject( CLSID_DataObjectTest32,
|
||
m_pIClassFactory,
|
||
CLSCTX_LOCAL_SERVER,
|
||
REGCLS_MULTIPLEUSE,
|
||
&m_dwRegCO );
|
||
#else
|
||
hr = CoRegisterClassObject( CLSID_DataObjectTest16,
|
||
m_pIClassFactory,
|
||
CLSCTX_LOCAL_SERVER,
|
||
REGCLS_MULTIPLEUSE,
|
||
&m_dwRegCO );
|
||
#endif // WIN32
|
||
if (FAILED(hr))
|
||
return FALSE;
|
||
#endif
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/*
|
||
* CDataObjectClassFactory::CDataObjectClassFactory
|
||
* CDataObjectClassFactory::~CDataObjectClassFactory
|
||
*
|
||
* Constructor Parameters:
|
||
* iSize UINT specifying the data size for this class.
|
||
*/
|
||
|
||
CDataObjectClassFactory::CDataObjectClassFactory()
|
||
{
|
||
m_cRef=0L;
|
||
return;
|
||
}
|
||
|
||
|
||
CDataObjectClassFactory::~CDataObjectClassFactory(void)
|
||
{
|
||
return;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CDataObjectClassFactory::QueryInterface(
|
||
REFIID riid,
|
||
PPVOID ppv)
|
||
{
|
||
*ppv=NULL;
|
||
|
||
//Any interface on this object is the object pointer.
|
||
#ifdef ORIGINAL_CODE_LOOKS_WRONG
|
||
if (IID_IUnknown==riid || IID_IClassFactory==riid)
|
||
#else
|
||
if (IsEqualIID(IID_IUnknown, riid)|| IsEqualIID(IID_IClassFactory, riid))
|
||
#endif
|
||
*ppv = this;
|
||
|
||
if (NULL!=*ppv)
|
||
{
|
||
((LPUNKNOWN)*ppv)->AddRef();
|
||
return NOERROR;
|
||
}
|
||
|
||
return ResultFromScode(E_NOINTERFACE);
|
||
}
|
||
|
||
|
||
STDMETHODIMP_(ULONG)
|
||
CDataObjectClassFactory::AddRef(void)
|
||
{
|
||
return ++m_cRef;
|
||
}
|
||
|
||
|
||
STDMETHODIMP_(ULONG)
|
||
CDataObjectClassFactory::Release(void)
|
||
{
|
||
ULONG cRefT;
|
||
|
||
cRefT=--m_cRef;
|
||
|
||
if (0L==m_cRef)
|
||
delete this;
|
||
|
||
return cRefT;
|
||
}
|
||
|
||
|
||
/*
|
||
* CDataObjectClassFactory::CreateInstance
|
||
*
|
||
* Purpose:
|
||
* Instantiates a CDataObject object that supports the IDataObject
|
||
* and IUnknown interfaces. If the caller asks for a different
|
||
* interface than these two then we fail.
|
||
*
|
||
* Parameters:
|
||
* pUnkOuter LPUNKNOWN to the controlling IUnknown if we are
|
||
* being used in an aggregation.
|
||
* riid REFIID identifying the interface the caller
|
||
* desires to have for the new object.
|
||
* ppvObj PPVOID in which to store the desired interface
|
||
* pointer for the new object.
|
||
*
|
||
* Return Value:
|
||
* HRESULT NOERROR if successful, otherwise contains
|
||
* E_NOINTERFACE if we cannot support the
|
||
* requested interface.
|
||
*/
|
||
|
||
STDMETHODIMP
|
||
CDataObjectClassFactory::CreateInstance(
|
||
LPUNKNOWN pUnkOuter,
|
||
REFIID riid,
|
||
PPVOID ppvObj)
|
||
{
|
||
PCDataObject pObj;
|
||
HRESULT hr;
|
||
|
||
*ppvObj=NULL;
|
||
hr=ResultFromScode(E_OUTOFMEMORY);
|
||
|
||
#ifdef ORIGINAL_CODE_LOOKS_WRONG
|
||
if (NULL!=pUnkOuter && IID_IUnknown!=riid)
|
||
#else
|
||
if (NULL!=pUnkOuter && (! IsEqualIID(IID_IUnknown, riid) ) )
|
||
#endif
|
||
return ResultFromScode(E_NOINTERFACE);
|
||
|
||
//Create the object telling it the data size to work with
|
||
pObj=new CDataObject(pUnkOuter, ObjectDestroyed);
|
||
|
||
if (NULL==pObj)
|
||
return hr;
|
||
|
||
if (pObj->FInit())
|
||
hr=pObj->QueryInterface(riid, ppvObj);
|
||
|
||
g_cObj++;
|
||
|
||
if (FAILED(hr))
|
||
{
|
||
delete pObj;
|
||
ObjectDestroyed(); //Decrements g_cObj
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
/*
|
||
* CDataObjectClassFactory::LockServer
|
||
*
|
||
* Purpose:
|
||
* Increments or decrements the lock count of the serving
|
||
* IClassFactory object. When the number of locks goes to
|
||
* zero and the number of objects is zero, we shut down the
|
||
* application.
|
||
*
|
||
* Parameters:
|
||
* fLock BOOL specifying whether to increment or
|
||
* decrement the lock count.
|
||
*
|
||
* Return Value:
|
||
* HRESULT NOERROR always.
|
||
*/
|
||
|
||
STDMETHODIMP
|
||
CDataObjectClassFactory::LockServer(
|
||
BOOL fLock)
|
||
{
|
||
if (fLock)
|
||
g_cLock++;
|
||
else
|
||
{
|
||
g_cLock--;
|
||
|
||
//No more objects and no locks, shut the app down.
|
||
if (0L==g_cObj && 0L==g_cLock && IsWindow(g_hWnd))
|
||
PostMessage(g_hWnd, WM_CLOSE, 0, 0L);
|
||
}
|
||
|
||
return NOERROR;
|
||
}
|
||
|