MzCOM: avoid the ATL framework

Building MzCOM without ATL means that Visual Studio Express --- or
other free compilers, in principle --- can build MzCOM. It also cleans
up and simplifies the build.

The non-ATL implementation is based on "Com in Plain C" by
Jeff Glatt, and uses a lot of his code (with instructive
comments intact).
This commit is contained in:
Matthew Flatt 2014-05-20 18:01:17 +01:00
parent 165bae6c2c
commit dfeba12997
17 changed files with 1032 additions and 753 deletions

704
racket/src/mzcom/com_glue.c Normal file
View File

@ -0,0 +1,704 @@
/* Much of this code is from "COM in Plain C" by Jeff Gatt on Code
Project. That code is licensed under the Code Project Open License
(CPOL). */
#include <windows.h>
#include <objbase.h>
#include <activscp.h>
#include <olectl.h>
#include <stddef.h>
#define FOR_GLUE
#include "com_glue.h"
// A count of how many objects our DLL has created (by some
// app calling our IClassFactory object's CreateInstance())
// which have not yet been Release()'d by the app
static DWORD OutstandingObjects;
// A count of how many apps have locked our DLL via calling our
// IClassFactory object's LockServer()
static DWORD LockCount;
// Where I store a pointer to my type library's TYPEINFO
static ITypeInfo *MyTypeInfo;
// The MzObj object ////////////////////////////////////////////////////////////
// In our .H file, we use a macro which defines our MzObj struct
// as so:
//
// typedef struct {
// IMzObjVtbl *lpVtbl;
// } MzObj;
//
// In other words, the .H file defines our MzObj to have nothing
// but a pointer to its VTable. And of course, every COM object must
// start with a pointer to its VTable.
//
// But we actually want to add some more members to our MzObj.
// We just don't want any app to be able to know about, and directly
// access, those members. So here we'll define a MyRealMzObj that
// contains those extra members. The app doesn't know that we're
// really allocating and giving it a MyRealMzObj object. We'll
// lie and tell it we're giving a plain old MzObj. That's ok
// because a MyRealMzObj starts with the same VTable pointer.
//
// We add a DWORD reference count so that this MzObj
// can be allocated (which we do in our IClassFactory object's
// CreateInstance()) and later freed. And, we have an extra
// BSTR (pointer) string, which is used by some of the functions we'll
// add to MzObj
typedef struct {
IMzObjVtbl *lpVtbl;
DWORD count;
void *obj;
IConnectionPointContainer container;
IConnectionPoint point;
IMzObjEvents *evts;
} MyRealMzObj;
// Here are MzObj's functions.
//
// Every COM object's interface must have the 3 functions QueryInterface(),
// AddRef(), and Release().
//
// I also chose to add 2, extra functions to MzObj, which a program
// will call with the names GetString and SetString.
// MzObj's QueryInterface()
static HRESULT STDMETHODCALLTYPE QueryInterface(IMzObj *com_obj, REFIID vTableGuid, void **ppv)
{
// Because our IMzObj sources events, we must return an
// IConnectionPointContainer sub-object if the app asks for one. Because we've
// embedded our IConnectionPointContainer object inside of our MyRealIMzObj,
// we can get that sub-object very easily using pointer arithmetic
if (IsEqualIID(vTableGuid, &IID_IConnectionPointContainer))
*ppv = ((unsigned char *)com_obj + offsetof(MyRealMzObj, container));
else if (IsEqualIID(vTableGuid, &IID_IConnectionPoint))
*ppv = ((unsigned char *)com_obj + offsetof(MyRealMzObj, point));
// Check if the GUID matches MzObj VTable's GUID. We gave the C variable name
// IID_MzObj to our VTable GUID. We can use an OLE function called
// IsEqualIID to do the comparison for us. Also, if the caller passed a
// IUnknown GUID, then we'll likewise return the MzObj, since it can
// masquerade as an IUnknown object too. Finally, if the called passed a
// IDispatch GUID, then we'll return the MzObj, since it can masquerade
// as an IDispatch too
else if (!IsEqualIID(vTableGuid, &IID_IUnknown) && !IsEqualIID(vTableGuid, &IID_IMzObj) && !IsEqualIID(vTableGuid, &IID_IDispatch))
{
// We don't recognize the GUID passed to us. Let the caller know this,
// by clearing his handle, and returning E_NOINTERFACE.
*ppv = 0;
return(E_NOINTERFACE);
}
else
// Fill in the caller's handle
*ppv = com_obj;
// Increment the count of callers who have an outstanding pointer to this object
com_obj->lpVtbl->AddRef(com_obj);
return(NOERROR);
}
// MzObj's AddRef()
static ULONG STDMETHODCALLTYPE AddRef(IMzObj *com_obj)
{
// Increment MzObj's reference count, and return the updated value.
// NOTE: We have to typecast to gain access to any data members. These
// members are not defined in our .H file (so that an app can't directly
// access them). Rather they are defined only above in our MyRealMzObj
// struct. So typecast to that in order to access those data members
return(++((MyRealMzObj *)com_obj)->count);
}
// MzObj's Release()
static ULONG STDMETHODCALLTYPE Release(IMzObj *com_obj)
{
// Decrement MzObj's reference count. If 0, then we can safely free
// this MzObj now
if (--((MyRealMzObj *)com_obj)->count == 0)
{
delete_mzobj(((MyRealMzObj *)com_obj)->obj);
GlobalFree(com_obj);
InterlockedDecrement(&OutstandingObjects);
if (com_can_unregister()) {
/* Only allowed object is released... */
PostMessage(NULL, WM_QUIT, 0, 0);
}
return(0);
}
return(((MyRealMzObj *)com_obj)->count);
}
// ================== The standard IDispatch functions
// This is just a helper function for the IDispatch functions below
static HRESULT loadMyTypeInfo(void)
{
register HRESULT hr;
LPTYPELIB pTypeLib;
// Load our type library and get a ptr to its TYPELIB. Note: This does an
// implicit pTypeLib->lpVtbl->AddRef(pTypeLib)
if (!(hr = LoadRegTypeLib(&CLSID_TypeLib, 1, 0, 0, &pTypeLib)))
{
// Get Microsoft's generic ITypeInfo, giving it our loaded type library. We only
// need one of these, and we'll store it in a global Tell Microsoft this is for
// our MzObj's VTable, by passing that VTable's GUID
if (!(hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib, &IID_IMzObj, &MyTypeInfo)))
{
// We no longer need the ptr to the TYPELIB now that we've given it
// to Microsoft's generic ITypeInfo. Note: The generic ITypeInfo has done
// a pTypeLib->lpVtbl->AddRef(pTypeLib), so this TYPELIB ain't going away
// until the generic ITypeInfo does a pTypeLib->lpVtbl->Release too
pTypeLib->lpVtbl->Release(pTypeLib);
// Since caller wants us to return our ITypeInfo pointer,
// we need to increment its reference count. Caller is
// expected to Release() it when done
MyTypeInfo->lpVtbl->AddRef(MyTypeInfo);
}
}
return(hr);
}
// MzObj's GetTypeInfoCount()
static ULONG STDMETHODCALLTYPE GetTypeInfoCount(IMzObj *com_obj, UINT *pCount)
{
*pCount = 1;
return(S_OK);
}
// MzObj's GetTypeInfo()
static ULONG STDMETHODCALLTYPE GetTypeInfo(IMzObj *com_obj, UINT itinfo, LCID lcid, ITypeInfo **pTypeInfo)
{
register HRESULT hr;
// Assume an error
*pTypeInfo = 0;
if (itinfo)
hr = ResultFromScode(DISP_E_BADINDEX);
// If our ITypeInfo is already created, just increment its ref count. NOTE: We really should
// store the LCID of the currently created TYPEINFO and compare it to what the caller wants.
// If no match, unloaded the currently created TYPEINFO, and create the correct one. But since
// we support only one language in our IDL file anyway, we'll ignore this
else if (MyTypeInfo)
{
MyTypeInfo->lpVtbl->AddRef(MyTypeInfo);
hr = 0;
}
else
{
// Load our type library and get Microsoft's generic ITypeInfo object. NOTE: We really
// should pass the LCID to match, but since we support only one language in our IDL
// file anyway, we'll ignore this
hr = loadMyTypeInfo();
}
if (!hr) *pTypeInfo = MyTypeInfo;
return(hr);
}
// MzObj's GetIDsOfNames()
static ULONG STDMETHODCALLTYPE GetIDsOfNames(IMzObj *com_obj, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid)
{
if (!MyTypeInfo)
{
register HRESULT hr;
if ((hr = loadMyTypeInfo())) return(hr);
}
// Let OLE32.DLL's DispGetIDsOfNames() do all the real work of using our type
// library to look up the DISPID of the requested function in our object
return(DispGetIDsOfNames(MyTypeInfo, rgszNames, cNames, rgdispid));
}
// MzObj's Invoke()
static ULONG STDMETHODCALLTYPE Invoke(IMzObj *com_obj, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS *params, VARIANT *result, EXCEPINFO *pexcepinfo,
UINT *puArgErr)
{
// We implement only a "default" interface
if (!IsEqualIID(riid, &IID_NULL))
return(DISP_E_UNKNOWNINTERFACE);
// We need our type lib's TYPEINFO (to pass to DispInvoke)
if (!MyTypeInfo)
{
register HRESULT hr;
if ((hr = loadMyTypeInfo())) return(hr);
}
// Let OLE32.DLL's DispInvoke() do all the real work of calling the appropriate
// function in our object, and massaging the passed args into the correct format
return(DispInvoke(com_obj, MyTypeInfo, dispid, wFlags, params, result, pexcepinfo, puArgErr));
}
// ================== The following are my own extra functions added to MzObj
static HRESULT STDMETHODCALLTYPE Eval(IMzObj *com_obj, BSTR str, BSTR *res)
{
if (!str) return(E_POINTER);
return mzobj_eval(((MyRealMzObj*)com_obj)->obj, str, res);
}
static HRESULT STDMETHODCALLTYPE About(IMzObj *com_obj)
{
return mzobj_about(((MyRealMzObj*)com_obj)->obj);
}
static HRESULT STDMETHODCALLTYPE Reset(IMzObj *com_obj)
{
return mzobj_reset(((MyRealMzObj*)com_obj)->obj);
}
// Here's MzObj's VTable. It never changes so we can declare it
// static
static const IMzObjVtbl IMzObj_Vtbl = {QueryInterface,
AddRef,
Release,
GetTypeInfoCount,
GetTypeInfo,
GetIDsOfNames,
Invoke,
Eval,
About,
Reset};
VOID Fire_SchemeError(IMzObj *com_obj, BSTR description)
{
if (((MyRealMzObj*)com_obj)->evts) {
VARIANTARG pvars[1];
DISPPARAMS disp = { pvars, NULL, 1, 0 };
memset(pvars, 0, sizeof(pvars));
pvars[0].vt = VT_BSTR;
pvars[0].bstrVal = description;
((MyRealMzObj*)com_obj)->evts->lpVtbl->Invoke(((MyRealMzObj*)com_obj)->evts, 0x1, &IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp,
NULL, NULL, NULL);
}
}
// Our IConnectionPointContainer sub-object (for IMzObj) ////////////////////////
static STDMETHODIMP QueryInterface_Connect(IConnectionPointContainer *com_obj, REFIID vTableGuid, void **ppv)
{
// Because this is a sub-object of our IMzObj (ie, MyRealMzObj) object,
// we delegate to IMzObj's QueryInterface. And because we embedded the
// IConnectionPointContainer directly inside of MyRealMzObj, all we need
// is a little pointer arithmetic to get our IMzObj
return(QueryInterface((IMzObj *)((char *)com_obj - offsetof(MyRealMzObj, container)), vTableGuid, ppv));
}
static STDMETHODIMP_(ULONG) AddRef_Connect(IConnectionPointContainer *com_obj)
{
// Because we're a sub-object of IMzObj, delegate to its AddRef()
// in order to increment IMzObj's reference count
return(AddRef((IMzObj *)((char *)com_obj - offsetof(MyRealMzObj, container))));
}
static STDMETHODIMP_(ULONG) Release_Connect(IConnectionPointContainer *com_obj)
{
// Because we're a sub-object of IMzObj, delegate to its Release()
// in order to decrement IMzObj's reference count
return(Release((IMzObj *)((char *)com_obj - offsetof(MyRealMzObj, container))));
}
static STDMETHODIMP EnumConnectionPoints(IConnectionPointContainer *com_obj, IEnumConnectionPoints **enumPoints)
{
// The app had better know the GUIDs of whatever objects our
// IMzObj supports for callbacks (ie, an IMzObjEvents), because
// we're not going to bother providing him with an object to
// enumerate the VTable GUIDs of all those supported objects
*enumPoints = 0;
return(E_NOTIMPL);
}
static STDMETHODIMP FindConnectionPoint(IConnectionPointContainer *com_obj, REFIID vTableGuid, IConnectionPoint **ppv)
{
// Is the app asking us to return an IConnectionPoint object it can use
// to give us its IMzObjEvents object? The app asks this by passing us
// IMzObjEvents VTable's GUID (which we defined in IMzObj.h)
if (IsEqualIID(vTableGuid, &DIID_IMzObjEvents))
{
MyRealMzObj *iExample;
// The app obviously wants to connect its IMzObjEvents object
// to IMzObj. In order to do that, we need to give the app a
// standard IConnectionPoint, so the app can call its Advise function
// to give us its IMzObjEvents. This is easy to do since we embedded both
// our IConnectionPointContainer and IConnectionPoint inside of our
// IMzObj. All we need is a little pointer arithmetic
iExample = (MyRealMzObj *)((char *)com_obj - offsetof(MyRealMzObj, container));
*ppv = &iExample->point;
// Because we're giving the app a pointer to our IConnectionPoint, and
// our IConnectionPoint is a sub-object of IMzObj, we need to
// increment IMzObj's reference count. The easiest way to do this is to call
// our IConnectionPointContainer's AddRef, because all we do there is delegate
// to our IMzObj's AddRef
AddRef_Connect(com_obj);
return(S_OK);
}
// We don't support any other app objects connecting to IMzObj
// events. All we've defined, and support, is an IMzObjEvents object. Tell
// the app we don't know anything about the GUID he passed to us, and
// do not give him any IConnectPoint object
*ppv = 0;
return(E_NOINTERFACE);
}
static const IConnectionPointContainerVtbl IConnectionPointContainer_Vtbl = {QueryInterface_Connect,
AddRef_Connect,
Release_Connect,
EnumConnectionPoints,
FindConnectionPoint};
// Our IConnectionPoint sub-object (for IMzObj) ////////////////////////////
static STDMETHODIMP QueryInterface_Point(IConnectionPoint *com_obj, REFIID vTableGuid, void **ppv)
{
// Because this is a sub-object of our IMzObj (ie, MyRealMzObj) object,
// we delegate to IMzObj's QueryInterface. And because we embedded the
// IConnectionPoint directly inside of MyRealMzObj, all we need
// is a little pointer arithmetic to get our IMzObj
return(QueryInterface((IMzObj *)((char *)com_obj - offsetof(MyRealMzObj, point)), vTableGuid, ppv));
}
static STDMETHODIMP_(ULONG) AddRef_Point(IConnectionPoint *com_obj)
{
// Because we're a sub-object of IMzObj, delegate to its AddRef()
// in order to increment IMzObj's reference count
return(AddRef((IMzObj *)((char *)com_obj - offsetof(MyRealMzObj, point))));
}
static STDMETHODIMP_(ULONG) Release_Point(IConnectionPoint *com_obj)
{
// Because we're a sub-object of IMzObj, delegate to its Release()
// in order to decrement IMzObj's reference count
return(Release((IMzObj *)((char *)com_obj - offsetof(MyRealMzObj, point))));
}
// Called by the app to get our IMzObjEvents VTable's GUID (which we defined in IMzObj.h).
// The app would call GetConnectionInterface() if it didn't link with IMzObj.h, and
// therefore doesn't know our IMzObjEvents VTable's GUID. The app needs to know this GUID
// because our Advise function below is going to pass this same GUID to some app object's
// QueryInterface. The app's QueryInterface had better recognize this GUID if it intends
// to honor our request to give us its IMzObjEvents object
static STDMETHODIMP GetConnectionInterface(IConnectionPoint *com_obj, IID *vTableGuid)
{
// Tell the app to recognize our IMzObjEvents VTable GUID (defined as
// DIID_IFeedback in IMzObj.h) when our Advise function calls
// some app QueryInterface function
CopyMemory(vTableGuid, &DIID_IMzObjEvents, sizeof(GUID));
return(S_OK);
}
// Called by the app to get the IConnectionPointContainer sub-object for our
// IMzObj object.
static STDMETHODIMP GetConnectionPointContainer(IConnectionPoint *com_obj, IConnectionPointContainer **ppv)
{
MyRealMzObj *iExample;
// Get the MyRealMzObj that this IConnectionPoint sub-object belongs
// to. Because this IConnectPoint sub-object is embedded directly inside its
// MyRealMzObj, all we need is a little pointer arithmetic
iExample = (MyRealMzObj *)((char *)com_obj - offsetof(MyRealMzObj, point));
// Because the IConnectionPointContainer sub-object is also embedded right inside
// the same MyRealMzObj, we can get a pointer to it easily as so
*ppv = &iExample->container;
// Because we're giving the app a pointer to our IConnectionPointContainer, and
// our IConnectionPointContainer is a sub-object of IMzObj, we need to
// increment IMzObj's reference count. The easiest way to do this is to call
// our IConnectionPoint's AddRef, because all we do there is delegate
// to our IMzObj's AddRef
AddRef_Point(com_obj);
return(S_OK);
}
// Called by the app to give us its IMzObjEvents object. Actually, the app doesn't
// just give us its IMzObjEvents. Rather, the app calls our Advise, passing us some
// app object from which we can request the app to give us its IMzObjEvents. All of
// this convoluted stuff is a combination of poor pre-planning by Microsoft
// programmers when they designed this stuff, as well as the colossal blunder of
// designing COM to accomodate the limitations of early, primitive editions of
// Visual Basic.
//
// The second arg passed here is some app object whose QueryInterface function
// we call to request the app's IMzObjEvents. We pass the GUID DIID_IMzObjEvents to
// this QueryInterface in order to tell the app to give us its IMzObjEvents
static STDMETHODIMP Advise(IConnectionPoint *com_obj, IUnknown *obj, DWORD *cookie)
{
HRESULT hr;
MyRealMzObj *iExample;
// Get the MyRealMzObj that this IConnectionPoint sub-object belongs
// to. Because this IConnectPoint sub-object is embedded directly inside its
// MyRealMzObj, all we need is a little pointer arithmetic
iExample = (MyRealMzObj *)((char *)com_obj - offsetof(MyRealMzObj, point));
// We allow only one IMzObjEvents for our IMzObj, so see if the app already
// called our Advise(), and we got one. If so, let the app know that it is trying
// to give us more IFeedbacks2 than we allow
if (iExample->evts) return(CONNECT_E_ADVISELIMIT);
// Ok, we haven't yet gotten the one IMzObjEvents we allow from the app. Get the app's
// IMzObjEvents object. We do this by calling the QueryInterface function of the
// app object passed to us. We pass IMzObjEvents VTable's GUID (which we defined
// in IMzObj.h).
//
// Save the app's IMzObjEvents pointer in our IMzObj feedback member, so we
// can get it when we need it
hr = obj->lpVtbl->QueryInterface(obj, &DIID_IMzObjEvents, (void **)&iExample->evts);
// We need to return (to the app) some value that will clue our Unadvise() function
// below how to locate this app IMzObjEvents. The simpliest thing is to just use the
// app's IMzObjEvents pointer as that returned value
*cookie = (DWORD)iExample->evts;
return(hr);
}
// Called by the app to tell us to stop using, and Release(), its IMzObjEvents object.
// The second arg passed here is the value our Advise() function above returned when
// we got the IMzObjEvents from the app. This value should help us locate wherever we
// stored that IMzObjEvents pointer we got in Advise()
static STDMETHODIMP Unadvise(IConnectionPoint *com_obj, DWORD cookie)
{
MyRealMzObj *iExample;
// Get the MyRealMzObj that this IConnectionPoint sub-object belongs
// to. Because this IConnectPoint sub-object is embedded directly inside its
// MyRealMzObj, all we need is a little pointer arithmetic
iExample = (MyRealMzObj *)((char *)com_obj - offsetof(MyRealMzObj, point));
// Use the passed value to find wherever we stored his IMzObjEvents pointer.
// Well, since we allow only one IMzObjEvents for our IMzObj, we already
// know we stored it in our IMzObj->feedback member. And Advise()
// returned that pointer as the "cookie" value. So we already got the
// IMzObjEvents right now.
//
// Let's just make sure the cookie he passed is really the pointer we expect
if (cookie && (IMzObjEvents *)cookie == iExample->evts)
{
// Release the app's IMzObjEvents
((IMzObjEvents *)cookie)->lpVtbl->Release((IMzObjEvents *)cookie);
// We no longer have the app's IMzObjEvents, so clear the IMzObj
// feedback member
iExample->evts = 0;
return(S_OK);
}
return(CONNECT_E_NOCONNECTION);
}
static STDMETHODIMP EnumConnections(IConnectionPoint *com_obj, IEnumConnections **enumConnects)
{
*enumConnects = 0;
return(E_NOTIMPL);
}
static const IConnectionPointVtbl IConnectionPoint_Vtbl = {
QueryInterface_Point,
AddRef_Point,
Release_Point,
GetConnectionInterface,
GetConnectionPointContainer,
Advise,
Unadvise,
EnumConnections};
// The IClassFactory object ///////////////////////////////////////////////////////
// Since we only ever need one IClassFactory object, we declare
// it static. The only requirement is that we ensure any
// access to its members is thread-safe
static IClassFactory MyIClassFactoryObj;
// IClassFactory's AddRef()
static ULONG STDMETHODCALLTYPE classAddRef(IClassFactory *com_obj)
{
// Someone is obtaining my IClassFactory, so inc the count of
// pointers that I've returned which some app needs to Release()
InterlockedIncrement(&OutstandingObjects);
// Since we never actually allocate/free an IClassFactory (ie, we
// use just 1 static one), we don't need to maintain a separate
// reference count for our IClassFactory. We'll just tell the caller
// that there's at least one of our IClassFactory objects in existance
return(1);
}
// IClassFactory's QueryInterface()
static HRESULT STDMETHODCALLTYPE classQueryInterface(IClassFactory *com_obj, REFIID factoryGuid, void **ppv)
{
// Make sure the caller wants either an IUnknown or an IClassFactory.
// In either case, we return the same IClassFactory pointer passed to
// us since it can also masquerade as an IUnknown
if (IsEqualIID(factoryGuid, &IID_IUnknown) || IsEqualIID(factoryGuid, &IID_IClassFactory))
{
// Call my IClassFactory's AddRef
com_obj->lpVtbl->AddRef(com_obj);
// Return (to the caller) a ptr to my IClassFactory
*ppv = com_obj;
return(NOERROR);
}
// We don't know about any other GUIDs
*ppv = 0;
return(E_NOINTERFACE);
}
// IClassFactory's Release()
static ULONG STDMETHODCALLTYPE classRelease(IClassFactory *com_obj)
{
// One less object that an app has not yet Release()'ed
return(InterlockedDecrement(&OutstandingObjects));
}
// IClassFactory's CreateInstance() function. It is called by
// someone who has a pointer to our IClassFactory object and now
// wants to create and retrieve a pointer to our MzObj
static HRESULT STDMETHODCALLTYPE classCreateInstance(IClassFactory *com_obj, IUnknown *punkOuter, REFIID vTableGuid, void **objHandle)
{
HRESULT hr;
IMzObj *thisobj;
// Assume an error by clearing caller's handle
*objHandle = 0;
// We don't support aggregation in this example
if (punkOuter)
hr = CLASS_E_NOAGGREGATION;
else
{
// Allocate our MzObj object (actually a MyRealMzObj)
if (!(thisobj = (IMzObj *)GlobalAlloc(GMEM_FIXED, sizeof(MyRealMzObj))))
hr = E_OUTOFMEMORY;
else
{
// Store MzObj's VTable in the object
thisobj->lpVtbl = (IMzObjVtbl *)&IMzObj_Vtbl;
// Our MyRealIMzObj is a multiple interface object. It has an
// IConnectionPointContainer sub-object embedded directly inside of
// it. And we just allocated it when we allocated the MyRealIMzObj
// above. Now we need to set its VTable into its lpVtbl member and
// we're done initializing this sub-object
((MyRealMzObj *)thisobj)->container.lpVtbl = (IConnectionPointContainerVtbl *)&IConnectionPointContainer_Vtbl;
// Our MyRealIMzObj also has an IConnectionPoint sub-object
// embedded directly inside of it. And we just allocated it when we
// allocated the MyRealIMzObj above. Now we need to set its
// VTable into its lpVtbl member and we're done initializing this sub-object
((MyRealMzObj *)thisobj)->point.lpVtbl = (IConnectionPointVtbl *)&IConnectionPoint_Vtbl;
// Increment the reference count so we can call Release() below and
// it will deallocate only if there is an error with QueryInterface()
((MyRealMzObj *)thisobj)->count = 1;
// Initialize any other members we added to the MzObj. We added
// a string member
((MyRealMzObj *)thisobj)->obj = new_mzobj(thisobj);
((MyRealMzObj *)thisobj)->evts = NULL;
// Fill in the caller's handle with a pointer to the MzObj we just
// allocated above. We'll let MzObj's QueryInterface do that, because
// it also checks the GUID the caller passed, and also increments the
// reference count (to 2) if all goes well
hr = IMzObj_Vtbl.QueryInterface(thisobj, vTableGuid, objHandle);
// Decrement reference count. NOTE: If there was an error in QueryInterface()
// then Release() will be decrementing the count back to 0 and will free the
// MzObj for us. One error that may occur is that the caller is asking for
// some sort of object that we don't support (ie, it's a GUID we don't recognize)
IMzObj_Vtbl.Release(thisobj);
// If success, inc static object count to keep this DLL loaded
if (!hr) InterlockedIncrement(&OutstandingObjects);
}
}
return(hr);
}
// IClassFactory's LockServer(). It is called by someone
// who wants to lock this DLL in memory
static HRESULT STDMETHODCALLTYPE classLockServer(IClassFactory *com_obj, BOOL flock)
{
if (flock) InterlockedIncrement(&LockCount);
else InterlockedDecrement(&LockCount);
return(NOERROR);
}
// IClassFactory's VTable
static const IClassFactoryVtbl IClassFactory_Vtbl = {classQueryInterface,
classAddRef,
classRelease,
classCreateInstance,
classLockServer};
// Miscellaneous functions ///////////////////////////////////////////////////////
static DWORD reg_cookie;
HRESULT com_register()
{
// Initialize my IClassFactory with the pointer to its vtable
MyIClassFactoryObj.lpVtbl = (IClassFactoryVtbl *)&IClassFactory_Vtbl;
return CoRegisterClassObject(&CLSID_IMzObj, &MyIClassFactoryObj,
CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &reg_cookie);
}
int com_can_unregister()
/* called from multiple threads */
{
/* Note that OutstandingObjects will stay at least 1 after the class is registered. */
return !((OutstandingObjects > 1) || (LockCount > 0));
}
int com_unregister()
{
// If someone has retrieved pointers to any of our objects, and
// not yet Release()'ed them, then we return S_FALSE to indicate
// not to unload this DLL. Also, if someone has us locked, return
// S_FALSE
if (!com_can_unregister())
return 0;
else {
if (MyTypeInfo) MyTypeInfo->lpVtbl->Release(MyTypeInfo);
CoRevokeClassObject(reg_cookie);
return 1;
}
}
const GUID com_get_class_iid()
{
return IID_IMzObj;
}

View File

@ -0,0 +1,75 @@
#ifndef _COM_GLUE_H_
#define _COM_GLUE_H_
#ifdef FOR_GLUE
#include <initguid.h>
// {A604CB9C-2AB5-11D4-B6D3-0060089002FE}
DEFINE_GUID(CLSID_TypeLib, 0xA604CB9C, 0x2ab5, 0x11d4, 0xb6, 0xd3, 0x00, 0x60, 0x08, 0x90, 0x02, 0xfe);
// {A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}
DEFINE_GUID(CLSID_IMzObj, 0xA3B0AF9E, 0x2ab0, 0x11d4, 0xb6, 0xd2, 0x00, 0x60, 0x08, 0x90, 0x02, 0xfe);
// {A604CBA8-2AB5-11D4-B6D3-0060089002FE}
DEFINE_GUID(IID_IMzObj, 0xA604CBA8, 0x2ab5, 0x11d4, 0xb6, 0xd3, 0x00, 0x60, 0x08, 0x90, 0x02, 0xfe);
#undef INTERFACE
#define INTERFACE IMzObj
DECLARE_INTERFACE_ (INTERFACE, IDispatch)
{
// IUnknown functions
STDMETHOD (QueryInterface) (THIS_ REFIID, void **) PURE;
STDMETHOD_ (ULONG, AddRef) (THIS) PURE;
STDMETHOD_ (ULONG, Release) (THIS) PURE;
// IDispatch functions
STDMETHOD_ (ULONG, GetTypeInfoCount)(THIS_ UINT *) PURE;
STDMETHOD_ (ULONG, GetTypeInfo) (THIS_ UINT, LCID, ITypeInfo **) PURE;
STDMETHOD_ (ULONG, GetIDsOfNames) (THIS_ REFIID, LPOLESTR *, UINT, LCID, DISPID *) PURE;
STDMETHOD_ (ULONG, Invoke) (THIS_ DISPID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *) PURE;
// Extra functions
STDMETHOD (Eval) (THIS_ BSTR, BSTR *) PURE;
STDMETHOD (About) (THIS) PURE;
STDMETHOD (Reset) (THIS) PURE;
};
// {A604CBA9-2AB5-11D4-B6D3-0060089002FE}
DEFINE_GUID(DIID_IMzObjEvents, 0xA604CBA9, 0x2ab5, 0x11d4, 0xb6, 0xd3, 0x00, 0x60, 0x08, 0x90, 0x02, 0xfe);
#undef INTERFACE
#define INTERFACE IMzObjEvents
DECLARE_INTERFACE_ (INTERFACE, IDispatch)
{
// IUnknown functions
STDMETHOD (QueryInterface) (THIS_ REFIID, void **) PURE;
STDMETHOD_ (ULONG, AddRef) (THIS) PURE;
STDMETHOD_ (ULONG, Release) (THIS) PURE;
// IDispatch functions
STDMETHOD_ (ULONG, GetTypeInfoCount)(THIS_ UINT *) PURE;
STDMETHOD_ (ULONG, GetTypeInfo) (THIS_ UINT, LCID, ITypeInfo **) PURE;
STDMETHOD_ (ULONG, GetIDsOfNames) (THIS_ REFIID, LPOLESTR *, UINT, LCID, DISPID *) PURE;
STDMETHOD_ (ULONG, Invoke) (THIS_ DISPID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *) PURE;
// Extra functions
STDMETHOD (SchemeError) (THIS_ BSTR *) PURE;
};
#else
typedef struct IMzObj { int dummy; } IMzObj;
#endif
extern HRESULT com_register();
extern int com_unregister();
extern int com_can_unregister();
extern const GUID com_get_class_iid();
extern void *new_mzobj(IMzObj*);
extern void delete_mzobj(void*);
extern HRESULT mzobj_about(void*);
extern HRESULT mzobj_reset(void*);
extern HRESULT mzobj_eval(void*, BSTR, BSTR*);
extern VOID Fire_SchemeError(IMzObj *com_obj, BSTR description);
#endif // _COM_GLUE_H_

View File

@ -3,96 +3,101 @@
// This file is not xformed for 3m. There's just one
// bit of conditional compilation on MZCOM_3M.
#include "stdafx.h"
#include "../racket/src/schvers.h"
#include "resource.h"
#include <initguid.h>
#include "mzcom.h"
#include "mzcom_i.c"
#include "mzobj.h"
#include <objbase.h>
extern "C" {
#include "com_glue.h"
};
// time for EXE to be idle before shutting down
#define dwTimeOut (5000)
// time to wait for threads to finish up
#define dwPause (1000)
HINSTANCE globHinst;
// Passed to CreateThread to monitor the shutdown event
/* A monitor thread might be a good idea to make sure the process
terminates if it's somehow started and not used. It also creates
a race condition, though, so it's disabled for now. */
#if 0
// time for EXE to be idle before shutting down
#define dwTimeOut (5000)
static HANDLE hEventShutdown;
static DWORD dwThreadID;
// Polls for idle state
static DWORD WINAPI MonitorProc(void* pv)
{
CExeModule* p = (CExeModule*)pv;
p->MonitorShutdown();
return 0;
while (1) {
DWORD dwWait=0;
do
{
dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
} while (dwWait == WAIT_OBJECT_0);
if (com_can_unregister())
break;
}
CloseHandle(hEventShutdown);
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
return 0;
}
LONG CExeModule::Unlock()
static bool StartMonitor()
{
LONG l = CComModule::Unlock();
if (l == 0)
{
bActivity = true;
SetEvent(hEventShutdown);
}
return l;
dwThreadID = GetCurrentThreadId();
hEventShutdown = CreateEvent(NULL, false, false, NULL);
if (hEventShutdown == NULL)
return false;
DWORD subThreadID;
HANDLE h = CreateThread(NULL, 0, MonitorProc, NULL, 0, &subThreadID);
return (h != NULL);
}
// Monitors the shutdown event
void CExeModule::MonitorShutdown()
{
while (1)
{
WaitForSingleObject(hEventShutdown, INFINITE);
DWORD dwWait=0;
do
{
bActivity = false;
dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
} while (dwWait == WAIT_OBJECT_0);
// timed out
if (!bActivity && m_nLockCnt == 0) // if no activity let's really bail
{
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
CoSuspendClassObjects();
if (!bActivity && m_nLockCnt == 0)
#else
static bool StartMonitor() { return TRUE; }
#endif
break;
}
}
CloseHandle(hEventShutdown);
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
}
bool CExeModule::StartMonitor()
static int set_reg_string(HKEY sub, char *name, char *s)
{
hEventShutdown = CreateEvent(NULL, false, false, NULL);
if (hEventShutdown == NULL)
return false;
DWORD dwThreadID;
HANDLE h = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
return (h != NULL);
return RegSetValueExA(sub, name, 0, REG_SZ, (const BYTE *)s, strlen(s));
}
CExeModule _Module;
static int set_reg_sub_string(HKEY sub, char *name, char *s)
{
HKEY sub2;
int nRet;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_MzObj, CMzObj)
END_OBJECT_MAP()
nRet = RegCreateKeyExA(sub, name, 0, NULL, 0, KEY_SET_VALUE, NULL, &sub2, NULL);
if (!nRet) {
nRet |= set_reg_string(sub2, NULL, s);
nRet |= RegCloseKey(sub2);
}
return nRet;
}
LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
{
while (p1 != NULL && *p1 != NULL)
while (p1 != NULL && *p1 != NULL)
{
LPCTSTR p = p2;
while (p != NULL && *p != NULL)
LPCTSTR p = p2;
while (p != NULL && *p != NULL)
{
if (*p1 == *p)
return CharNext(p1);
p = CharNext(p);
if (*p1 == *p)
return CharNext(p1);
p = CharNext(p);
}
p1 = CharNext(p1);
p1 = CharNext(p1);
}
return NULL;
return NULL;
}
int IsFlag(LPCTSTR cmd, LPCTSTR flag)
@ -122,8 +127,8 @@ int IsFlag(LPCTSTR cmd, LPCTSTR flag)
/////////////////////////////////////////////////////////////////////////////
//
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/) {
extern "C" int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/) {
globHinst = hInstance;
@ -136,98 +141,160 @@ extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
load_delayed_dll(hInstance, "libracketxxxxxxx.dll");
#endif
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
#else
HRESULT hRes = CoInitialize(NULL);
#endif
_ASSERTE(SUCCEEDED(hRes));
_Module.Init(ObjectMap, hInstance, &LIBID_MZCOMLib);
_Module.dwThreadID = GetCurrentThreadId();
HRESULT nRet = CoInitialize(NULL);
int argc, i;
char **argv, *normalized_path;
argv = cmdline_to_argv(&argc, &normalized_path);
int nRet = 0, verbose = 0;
int verbose = 0;
BOOL bRun = TRUE;
LPCTSTR lpszToken;
for (i = 1; i < argc; i++)
{
lpszToken = argv[i];
if (IsFlag(lpszToken, _T("UnregServer")))
if (IsFlag(lpszToken, "UnregServer"))
{
if (!nRet) {
_Module.UpdateRegistryFromResource(IDR_MZCOM, FALSE);
nRet = _Module.UnregisterServer(TRUE);
HKEY sub;
nRet |= RegDeleteKeyA(HKEY_CLASSES_ROOT, "MzCOM.MzObj");
nRet |= RegDeleteKeyA(HKEY_CLASSES_ROOT, "MzCOM.MzObj." MZSCHEME_VERSION);
if (!nRet) {
nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
if (!nRet) {
nRet |= RegDeleteKeyA(sub, "{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}");
nRet |= RegCloseKey(sub);
}
}
if (!nRet) {
nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "AppID", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
if (!nRet) {
nRet |= RegDeleteKeyA(sub, "{A604CB9D-2AB5-11D4-B6D3-0060089002FE}");
nRet |= RegCloseKey(sub);
}
}
bRun = FALSE;
}
}
else if (IsFlag(lpszToken, _T("RegServer")))
else if (IsFlag(lpszToken, "RegServer"))
{
if (!nRet) {
_Module.UpdateRegistryFromResource(IDR_MZCOM, TRUE);
nRet = _Module.RegisterServer(TRUE);
HKEY sub, sub2;
nRet |= RegCreateKeyExA(HKEY_CLASSES_ROOT, "MzCOM.MzObj", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
if (!nRet) {
nRet |= set_reg_string(sub, NULL, "MzObj Class");
nRet |= set_reg_sub_string(sub, "CLSID", "{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}");
nRet |= set_reg_sub_string(sub, "CurVer", "MzCOM.MzObj." MZSCHEME_VERSION);
nRet |= RegCloseKey(sub);
}
if (!nRet) {
nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "MzCOM.MzObj." MZSCHEME_VERSION, 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
if (!nRet) {
nRet |= set_reg_string(sub, NULL, "MzObj Class");
nRet |= set_reg_sub_string(sub, "CLSID", "{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}");
nRet |= RegCloseKey(sub);
}
}
if (!nRet) {
nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
if (!nRet) {
nRet = RegCreateKeyExA(sub, "{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub2, NULL);
if (!nRet) {
nRet |= set_reg_string(sub2, NULL, "MzObj Class");
nRet |= set_reg_string(sub2, "AppId", "{A604CB9D-2AB5-11D4-B6D3-0060089002FE}");
nRet |= set_reg_sub_string(sub2, "ProgID", "MzCOM.MzObj." MZSCHEME_VERSION);
nRet |= set_reg_sub_string(sub2, "VersionIndependentProgID", "MzCOM.MzObj");
nRet |= set_reg_sub_string(sub2, "Programmable", "");
char *path;
path = (char *)malloc(1024 * sizeof(wchar_t));
GetModuleFileNameA(NULL, path, 1024);
nRet |= set_reg_sub_string(sub2, "LocalServer32", path);
free(path);
nRet |= set_reg_sub_string(sub2, "TypeLib", "{A604CB9C-2AB5-11D4-B6D3-0060089002FE}");
nRet |= RegCloseKey(sub2);
}
nRet |= RegCloseKey(sub);
}
}
if (!nRet) {
nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "AppID", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
if (!nRet) {
nRet = RegCreateKeyExA(sub, "{A604CB9D-2AB5-11D4-B6D3-0060089002FE}", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub2, NULL);
if (!nRet) {
nRet |= set_reg_string(sub2, NULL, "MzCOM");
nRet |= RegCloseKey(sub2);
}
}
if (!nRet) {
nRet = RegCreateKeyExA(sub, "MzCOM.EXE", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub2, NULL);
if (!nRet) {
nRet |= set_reg_string(sub2, "AppID", "{A604CB9D-2AB5-11D4-B6D3-0060089002FE}");
nRet |= RegCloseKey(sub2);
}
}
nRet |= RegCloseKey(sub);
}
bRun = FALSE;
}
}
else if (IsFlag(lpszToken, _T("v")))
else if (IsFlag(lpszToken, "v"))
{
verbose = 1;
}
else if (IsFlag(lpszToken, _T("?")))
else if (IsFlag(lpszToken, "?"))
{
MessageBox(NULL,
_T("/RegServer - register\n"
"/UnregServer - unregister\n"
"/Embedding - ignored\n"
"/v - report failures\n"
"/? - show this help"),
_T("Help"),
"/RegServer - register\n"
"/UnregServer - unregister\n"
"/Embedding - ignored\n"
"/v - report failures\n"
"/? - show this help",
"Help",
MB_OK);
bRun = FALSE;
}
else if (IsFlag(lpszToken, _T("Embedding")))
else if (IsFlag(lpszToken, "Embedding"))
{
/* ??? */
}
else
{
if (verbose)
MessageBox(NULL, lpszToken, _T("Unknown Flag"), MB_OK);
MessageBox(NULL, lpszToken, "Unknown Flag", MB_OK);
bRun = FALSE;
break;
}
}
if (bRun)
{
_Module.StartMonitor();
if (bRun) {
StartMonitor();
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
REGCLS_SINGLEUSE | REGCLS_SUSPENDED);
// was: REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
nRet = com_register();
_ASSERTE(SUCCEEDED(hRes));
hRes = CoResumeClassObjects();
#else
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
// was REGCLS_MULTIPLEUSE);
REGCLS_SINGLEUSE);
#endif
_ASSERTE(SUCCEEDED(hRes));
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
_Module.RevokeClassObjects();
Sleep(dwPause); //wait for any threads to finish
if (!nRet) {
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
while (!com_unregister()) {
Sleep(dwPause); // wait for any objects to finish
}
}
}
if (verbose && (nRet != 0)) {
wchar_t *res;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
@ -241,7 +308,7 @@ extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
MessageBoxW(NULL, res, L"Registration Failed", MB_OK);
}
_Module.Term();
CoUninitialize();
return nRet;
CoUninitialize();
return nRet;
}

View File

@ -12,10 +12,14 @@
START_XFORM_SKIP;
#endif
#include "stdafx.h"
#include "resource.h"
#include "mzcom.h"
#include <process.h>
#include <objbase.h>
extern "C" {
#include "com_glue.h"
};
#ifdef MZ_PRECISE_GC
END_XFORM_SKIP;
@ -332,7 +336,10 @@ void CMzObj::startMzThread(void) {
}
CMzObj::CMzObj(void) {
CMzObj::CMzObj(void *_com_obj) {
com_obj = _com_obj;
inputMutex = NULL;
readSem = NULL;
threadHandle = NULL;
@ -433,7 +440,7 @@ void CMzObj::RaiseError(const OLECHAR *msg) {
if (CreateErrorInfo(&pICreateErrorInfo) == S_OK &&
pICreateErrorInfo != NULL) {
pICreateErrorInfo->SetGUID(IID_IMzObj);
pICreateErrorInfo->SetGUID(com_get_class_iid());
pICreateErrorInfo->SetDescription((LPOLESTR)msg);
pICreateErrorInfo->SetSource((LPOLESTR)L"MzCOM.MzObj");
if (pICreateErrorInfo->QueryInterface(IID_IErrorInfo,
@ -443,7 +450,7 @@ void CMzObj::RaiseError(const OLECHAR *msg) {
}
}
Fire_SchemeError(bstr);
Fire_SchemeError((IMzObj *)com_obj, bstr);
SysFreeString(bstr);
}
@ -470,7 +477,7 @@ BOOL CMzObj::testThread(void) {
/////////////////////////////////////////////////////////////////////////////
// CMzObj
STDMETHODIMP CMzObj::Eval(BSTR input, BSTR *output) {
HRESULT CMzObj::Eval(BSTR input, BSTR *output) {
if (!testThread()) {
return E_ABORT;
}
@ -515,12 +522,12 @@ INT_PTR WINAPI dlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM) {
}
}
STDMETHODIMP CMzObj::About() {
HRESULT CMzObj::About() {
DialogBox(globHinst,MAKEINTRESOURCE(ABOUTBOX),NULL,dlgProc);
return S_OK;
}
STDMETHODIMP CMzObj::Reset() {
HRESULT CMzObj::Reset() {
if (!testThread()) {
return E_ABORT;
}
@ -530,6 +537,31 @@ STDMETHODIMP CMzObj::Reset() {
return S_OK;
}
void *new_mzobj(IMzObj *com_obj)
{
return new CMzObj(com_obj);
}
void delete_mzobj(void *o)
{
delete (CMzObj *)o;
}
HRESULT mzobj_about(void *o)
{
return ((CMzObj *)o)->About();
}
HRESULT mzobj_reset(void *o)
{
return ((CMzObj *)o)->Reset();
}
HRESULT mzobj_eval(void *o, BSTR s, BSTR *r)
{
return ((CMzObj *)o)->Eval(s, r);
}
#ifdef MZ_PRECISE_GC
END_XFORM_SKIP;
#endif

View File

@ -4,7 +4,6 @@
#define __MZOBJ_H_
#include "resource.h" // main symbols
#include "MzCOMCP.h"
typedef struct {
BSTR **ppInput;
@ -27,16 +26,13 @@ extern HINSTANCE globHinst;
START_XFORM_SKIP;
#endif
class ATL_NO_VTABLE CMzObj :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMzObj, &CLSID_MzObj>,
public IConnectionPointContainerImpl<CMzObj>,
public IDispatchImpl<IMzObj, &IID_IMzObj, &LIBID_MZCOMLib>,
public CProxy_IMzObjEvents< CMzObj >
class CMzObj
{
private:
void *com_obj;
HRESULT hr;
HANDLE inputMutex;
HANDLE readSem;
@ -56,29 +52,14 @@ class ATL_NO_VTABLE CMzObj :
public:
CMzObj(void);
CMzObj(void* com_obj);
~CMzObj(void);
DECLARE_REGISTRY_RESOURCEID(IDR_MZOBJ)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CMzObj)
COM_INTERFACE_ENTRY(IMzObj)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CMzObj)
CONNECTION_POINT_ENTRY(DIID__IMzObjEvents)
END_CONNECTION_POINT_MAP()
// IMzObj
public:
STDMETHOD(Reset)(void);
STDMETHOD(About)(void);
STDMETHOD(Eval)(BSTR input,/*[out,retval]*/BSTR *output);
HRESULT Reset(void);
HRESULT About(void);
HRESULT Eval(BSTR input,/*[out,retval]*/BSTR *output);
};
#ifdef MZ_XFORM

View File

@ -1,38 +0,0 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#if !defined(AFX_STDAFX_H__A604CB9F_2AB5_11D4_B6D3_0060089002FE__INCLUDED_)
#define AFX_STDAFX_H__A604CB9F_2AB5_11D4_B6D3_0060089002FE__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define STRICT
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#define _ATL_APARTMENT_THREADED
#include <atlbase.h>
//You may derive a class from CComModule and use it if you want to override
//something, but do not change the name of _Module
class CExeModule : public CComModule
{
public:
LONG Unlock();
DWORD dwThreadID;
HANDLE hEventShutdown;
void MonitorShutdown();
bool StartMonitor();
bool bActivity;
};
extern CExeModule _Module;
#include <atlcom.h>
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__A604CB9F_2AB5_11D4_B6D3_0060089002FE__INCLUDED)

View File

@ -1,8 +1,9 @@
This directory contains
- solution files and project files for building minimal Racket (and
GRacket) with Microsoft Visual Studio 2008 (a.k.a. version 9.0)
and up, which work with the Express version of Visual Studio;
- solution files and project files for building minimal Racket and
related executables with Microsoft Visual Studio 2008
(a.k.a. version 9.0) and up, which work with the Express version
of Visual Studio;
- mzconfig.h which is a manual version of information that is gathered
automatically when using the "configure" script;
@ -10,16 +11,11 @@ This directory contains
- scripts for building 3m variants of Racket and GRacket using Visual
Studio command-line tools;
- solution files and project files for building MzCOM with
Microsoft Visual Studio 2008 (not Express, which doesn't support ATL
and MFC);
- solution files and project files for building "myssink.dll" with
Microsoft Visual Studio 2008, although the DLL is normally
downloaded along with other pre-built DLLs.
Microsoft Visual Studio 2008 (not Express), although the DLL is
normally downloaded along with other pre-built DLLs.
Visual Studio Express is available for free from Microsoft; it can be
used to build Racket and GRacket, but not MzCOM.
Visual Studio Express is available for free from Microsoft.
Racket and GRacket also compile with MinGW. To compile with MinGW,
follow the instructions in racket\src\README (which contains a short
@ -192,9 +188,8 @@ updated to replace "xxxxxxxx" with a specific version number.
Building MzCOM
--------------
Beware that MzCOM does not build with Express versions of Visual
Studio. Otherwise, building MzCOMCGC is similar to building
RacketCGC. Building the 3m variant is a little different.
Building MzCOMCGC is similar to building RacketCGC. Building the 3m
variant is a little different.
To build MzCOMCGC, make the MzCOM solution in
racket\src\worksp\mzcom - makes racket\MzCOMCGC.exe

View File

@ -24,14 +24,9 @@
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
UseOfATL="1"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="..\..\..\racket -c mzobj_rgs.rkt"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName="$(OutDir)\$(ProjectName).tlb"
@ -64,6 +59,7 @@
GenerateDebugInformation="true"
ProgramDatabaseFile="..\..\..\lib\$(ProjectName)CGC.pdb"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
@ -75,14 +71,9 @@
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
UseOfATL="1"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="..\..\..\racket -c mzobj_rgs.rkt"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
@ -116,6 +107,7 @@
GenerateDebugInformation="true"
ProgramDatabaseFile="..\..\..\lib\$(ProjectName)CGC.pdb"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
@ -128,14 +120,9 @@
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
UseOfATL="1"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="..\..\..\racket -c mzobj_rgs.rkt"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName="$(OutDir)\$(ProjectName).tlb"
@ -172,6 +159,7 @@
GenerateDebugInformation="true"
ProgramDatabaseFile="..\..\..\lib\$(ProjectName)CGC.pdb"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
@ -183,14 +171,9 @@
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
UseOfATL="1"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="..\..\..\racket -c mzobj_rgs.rkt"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
@ -228,6 +211,7 @@
GenerateDebugInformation="true"
ProgramDatabaseFile="..\..\..\lib\$(ProjectName)CGC.pdb"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
@ -240,14 +224,9 @@
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
UseOfATL="1"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="..\..\..\racket -c mzobj_rgs.rkt"
/>
<Tool
Name="VCMIDLTool"
TypeLibraryName="$(OutDir)\$(ProjectName).tlb"
@ -285,6 +264,7 @@
GenerateDebugInformation="true"
ProgramDatabaseFile="..\..\..\lib\$(ProjectName).pdb"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
@ -296,14 +276,9 @@
ConfigurationType="1"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
UseOfMFC="0"
UseOfATL="1"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="..\..\..\racket -c mzobj_rgs.rkt"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
@ -342,6 +317,7 @@
GenerateDebugInformation="true"
ProgramDatabaseFile="..\..\..\lib\$(ProjectName).pdb"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
@ -359,6 +335,10 @@
RelativePath="..\..\mzcom\mzcom.cxx"
>
</File>
<File
RelativePath="..\..\mzcom\com_glue.c"
>
</File>
<File
RelativePath="..\..\mzcom\mzcom.idl"
>
@ -367,27 +347,19 @@
RelativePath="..\..\mzcom\mzobj.cxx"
>
</File>
<File
RelativePath="..\..\mzcom\stdafx.h"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath=".\mzcom.h"
>
</File>
<File
RelativePath=".\MzCOMCP.h"
>
</File>
<File
RelativePath="..\..\mzcom\mzobj.h"
>
</File>
<File
RelativePath="..\..\mzcom\com_glue.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
@ -401,14 +373,6 @@
RelativePath=".\mzcom.rc"
>
</File>
<File
RelativePath=".\MzCOM.rgs"
>
</File>
<File
RelativePath=".\MzObj.rgs"
>
</File>
</Filter>
</Files>
<Globals>

View File

@ -1,32 +0,0 @@
#ifndef _MZCOMCP_H_
#define _MZCOMCP_H_
template <class T>
class CProxy_IMzObjEvents : public IConnectionPointImpl<T, &DIID__IMzObjEvents, CComDynamicUnkArray>
{
//Warning this class may be recreated by the wizard.
public:
VOID Fire_SchemeError(BSTR description)
{
T* pT = static_cast<T*>(this);
int nConnectionIndex;
CComVariant* pvars = new CComVariant[1];
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
pvars[0] = description;
DISPPARAMS disp = { pvars, NULL, 1, 0 };
pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
}
}
delete[] pvars;
}
};
#endif

View File

@ -6,5 +6,3 @@ The MzCOM source files are in plt/src/mzcom/.
You'll also need the Racket sources to compile
MzCOM. See plt/src/worksp/README for more information
on compiling Racket.
Send questions to Paul Steckler, steck@racket-lang.org.

View File

@ -1,9 +0,0 @@
; MzCOM.def : Declares the module parameters.
LIBRARY "MzCOM.DLL"
EXPORTS
DllCanUnloadNow @1 PRIVATE
DllGetClassObject @2 PRIVATE
DllRegisterServer @3 PRIVATE
DllUnregisterServer @4 PRIVATE

View File

@ -1,382 +0,0 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 5.01.0164 */
/* at Thu Jul 25 15:25:42 2002
*/
/* Compiler settings for F:\plt\src\mzcom\mzcom.idl:
Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
error checks: allocation ref bounds_check enum stub_data
*/
//@@MIDL_FILE_HEADING( )
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 440
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/
#ifndef __mzcom_h__
#define __mzcom_h__
#ifdef __cplusplus
extern "C"{
#endif
/* Forward Declarations */
#ifndef __IMzObj_FWD_DEFINED__
#define __IMzObj_FWD_DEFINED__
typedef interface IMzObj IMzObj;
#endif /* __IMzObj_FWD_DEFINED__ */
#ifndef ___IMzObjEvents_FWD_DEFINED__
#define ___IMzObjEvents_FWD_DEFINED__
typedef interface _IMzObjEvents _IMzObjEvents;
#endif /* ___IMzObjEvents_FWD_DEFINED__ */
#ifndef __MzObj_FWD_DEFINED__
#define __MzObj_FWD_DEFINED__
#ifdef __cplusplus
typedef class MzObj MzObj;
#else
typedef struct MzObj MzObj;
#endif /* __cplusplus */
#endif /* __MzObj_FWD_DEFINED__ */
/* header files for imported files */
#include "oaidl.h"
#include "ocidl.h"
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void __RPC_FAR * );
#ifndef __IMzObj_INTERFACE_DEFINED__
#define __IMzObj_INTERFACE_DEFINED__
/* interface IMzObj */
/* [unique][helpstring][dual][uuid][object] */
EXTERN_C const IID IID_IMzObj;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("A604CBA8-2AB5-11D4-B6D3-0060089002FE")
IMzObj : public IDispatch
{
public:
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Eval(
BSTR input,
/* [retval][out] */ BSTR __RPC_FAR *output) = 0;
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE About( void) = 0;
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Reset( void) = 0;
};
#else /* C style interface */
typedef struct IMzObjVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
IMzObj __RPC_FAR * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
IMzObj __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
IMzObj __RPC_FAR * This);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )(
IMzObj __RPC_FAR * This,
/* [out] */ UINT __RPC_FAR *pctinfo);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )(
IMzObj __RPC_FAR * This,
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )(
IMzObj __RPC_FAR * This,
/* [in] */ REFIID riid,
/* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
/* [in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )(
IMzObj __RPC_FAR * This,
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
/* [out] */ VARIANT __RPC_FAR *pVarResult,
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
/* [out] */ UINT __RPC_FAR *puArgErr);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Eval )(
IMzObj __RPC_FAR * This,
BSTR input,
/* [retval][out] */ BSTR __RPC_FAR *output);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *About )(
IMzObj __RPC_FAR * This);
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Reset )(
IMzObj __RPC_FAR * This);
END_INTERFACE
} IMzObjVtbl;
interface IMzObj
{
CONST_VTBL struct IMzObjVtbl __RPC_FAR *lpVtbl;
};
#ifdef COBJMACROS
#define IMzObj_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IMzObj_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IMzObj_Release(This) \
(This)->lpVtbl -> Release(This)
#define IMzObj_GetTypeInfoCount(This,pctinfo) \
(This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
#define IMzObj_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
(This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
#define IMzObj_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
(This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
#define IMzObj_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
(This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
#define IMzObj_Eval(This,input,output) \
(This)->lpVtbl -> Eval(This,input,output)
#define IMzObj_About(This) \
(This)->lpVtbl -> About(This)
#define IMzObj_Reset(This) \
(This)->lpVtbl -> Reset(This)
#endif /* COBJMACROS */
#endif /* C style interface */
/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IMzObj_Eval_Proxy(
IMzObj __RPC_FAR * This,
BSTR input,
/* [retval][out] */ BSTR __RPC_FAR *output);
void __RPC_STUB IMzObj_Eval_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IMzObj_About_Proxy(
IMzObj __RPC_FAR * This);
void __RPC_STUB IMzObj_About_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IMzObj_Reset_Proxy(
IMzObj __RPC_FAR * This);
void __RPC_STUB IMzObj_Reset_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __IMzObj_INTERFACE_DEFINED__ */
#ifndef __MZCOMLib_LIBRARY_DEFINED__
#define __MZCOMLib_LIBRARY_DEFINED__
/* library MZCOMLib */
/* [helpstring][version][uuid] */
EXTERN_C const IID LIBID_MZCOMLib;
#ifndef ___IMzObjEvents_DISPINTERFACE_DEFINED__
#define ___IMzObjEvents_DISPINTERFACE_DEFINED__
/* dispinterface _IMzObjEvents */
/* [helpstring][uuid] */
EXTERN_C const IID DIID__IMzObjEvents;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("A604CBA9-2AB5-11D4-B6D3-0060089002FE")
_IMzObjEvents : public IDispatch
{
};
#else /* C style interface */
typedef struct _IMzObjEventsVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
_IMzObjEvents __RPC_FAR * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
_IMzObjEvents __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
_IMzObjEvents __RPC_FAR * This);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )(
_IMzObjEvents __RPC_FAR * This,
/* [out] */ UINT __RPC_FAR *pctinfo);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )(
_IMzObjEvents __RPC_FAR * This,
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )(
_IMzObjEvents __RPC_FAR * This,
/* [in] */ REFIID riid,
/* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
/* [in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )(
_IMzObjEvents __RPC_FAR * This,
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
/* [out] */ VARIANT __RPC_FAR *pVarResult,
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
/* [out] */ UINT __RPC_FAR *puArgErr);
END_INTERFACE
} _IMzObjEventsVtbl;
interface _IMzObjEvents
{
CONST_VTBL struct _IMzObjEventsVtbl __RPC_FAR *lpVtbl;
};
#ifdef COBJMACROS
#define _IMzObjEvents_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define _IMzObjEvents_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define _IMzObjEvents_Release(This) \
(This)->lpVtbl -> Release(This)
#define _IMzObjEvents_GetTypeInfoCount(This,pctinfo) \
(This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
#define _IMzObjEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
(This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
#define _IMzObjEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
(This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
#define _IMzObjEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
(This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* ___IMzObjEvents_DISPINTERFACE_DEFINED__ */
EXTERN_C const CLSID CLSID_MzObj;
#ifdef __cplusplus
class DECLSPEC_UUID("A3B0AF9E-2AB0-11D4-B6D2-0060089002FE")
MzObj;
#endif
#endif /* __MZCOMLib_LIBRARY_DEFINED__ */
/* Additional Prototypes for ALL interfaces */
unsigned long __RPC_USER BSTR_UserSize( unsigned long __RPC_FAR *, unsigned long , BSTR __RPC_FAR * );
unsigned char __RPC_FAR * __RPC_USER BSTR_UserMarshal( unsigned long __RPC_FAR *, unsigned char __RPC_FAR *, BSTR __RPC_FAR * );
unsigned char __RPC_FAR * __RPC_USER BSTR_UserUnmarshal(unsigned long __RPC_FAR *, unsigned char __RPC_FAR *, BSTR __RPC_FAR * );
void __RPC_USER BSTR_UserFree( unsigned long __RPC_FAR *, BSTR __RPC_FAR * );
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif

Binary file not shown.

View File

@ -87,14 +87,6 @@ BEGIN
END
/////////////////////////////////////////////////////////////////////////////
//
// REGISTRY
//
IDR_MZCOM REGISTRY "MzCOM.rgs"
IDR_MZOBJ REGISTRY "MzObj.rgs"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog

View File

@ -1,11 +0,0 @@
HKCR
{
NoRemove AppID
{
{A604CB9D-2AB5-11D4-B6D3-0060089002FE} = s 'MzCOM'
'MzCOM.EXE'
{
val AppID = s {A604CB9D-2AB5-11D4-B6D3-0060089002FE}
}
}
}

View File

@ -1,11 +0,0 @@
LIBRARY "MzCOMPS"
DESCRIPTION 'Proxy/Stub DLL'
EXPORTS
DllGetClassObject @1 PRIVATE
DllCanUnloadNow @2 PRIVATE
GetProxyDllInfo @3 PRIVATE
DllRegisterServer @4 PRIVATE
DllUnregisterServer @5 PRIVATE

View File

@ -1,46 +0,0 @@
#lang racket/base
(define template #<<EOS
HKCR
{
MzCOM.MzObj.@|VERSION| = s 'MzObj Class'
{
CLSID = s '{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}'
}
MzCOM.MzObj = s 'MzObj Class'
{
CLSID = s '{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}'
CurVer = s 'MzCOM.MzObj.@|VERSION|'
}
NoRemove CLSID
{
ForceRemove {A3B0AF9E-2AB0-11D4-B6D2-0060089002FE} = s 'MzObj Class'
{
ProgID = s 'MzCOM.MzObj.@|VERSION|'
VersionIndependentProgID = s 'MzCOM.MzObj'
ForceRemove 'Programmable'
LocalServer32 = s '%MODULE%'
val AppID = s '{A604CB9D-2AB5-11D4-B6D3-0060089002FE}'
'TypeLib' = s '{A604CB9C-2AB5-11D4-B6D3-0060089002FE}'
}
}
}
EOS
)
(define content (regexp-replace* #rx"@[|]VERSION[|]" template (version)))
(define file "mzobj.rgs")
(unless (and (file-exists? file)
(equal? content
(call-with-input-file*
file
(lambda (i)
(read-string (add1 (string-length content)) i)))))
(call-with-output-file*
file
#:exists 'truncate
(lambda (o)
(display content o))))