You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
446 lines
9.8 KiB
446 lines
9.8 KiB
#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;
|
|
}
|
|
|