Figure 1 UnlockCookie
// secondary object that releases lock at final release
class UnlockCookie : public IUnknown {
HANDLE m_hsem;
UnlockCookie(HANDLE h) : m_hsem(h) {}
~UnlockCookie() {
// release lock back to OS at final release
ReleaseSemaphore(m_hsem, 1, 0);
}
// heap-based IUnknown implementation deleted
};
// primary object that holds lock until released
class SharedObject : public ISharedObject2 {
HANDLE m_hsem; // init'ed in constructor
STDMETHODIMP LockExclusive(IUnknown **ppUnkLock) {
// acquire lock from OS
WaitForSingleObject(m_hsem, INFINITE);
// create and return an intermediate object that
// will unlock at its final release
(*ppUnkLock = new UnlockCookie(m_hsem))->AddRef();
return S_OK;
}
: : :
};
Layer | COM | Sockets | Description |
Application | Your code | ||
Presentation | NDR: Presents data in host's native format | ||
Session | DCE: Manages state for an association | ||
Transport | UDP/TCP: Exposes multiple endpoints on host | ||
Network | IP: Exposes hosts across subnets | ||
Data Link | ENET: Exposes hosts within a single subnet | ||
Physical | COAX/UTP: Transmits bits |
Figure 3 Displaying Jukebox Titles
#include <jukebox.h>
const UINT CF_JUKEBOX_TITLE_INFO =
RegisterClipboardFormat( "JukeboxTitleInfo" );
void DisplayItems(IJukeBox* pjb, ostream& os) {
IDataObject* pdo = 0;
for ( long i = 0;
SUCCEEDED(pjb->GetDiskInfo(i, &pdo));
i++ ) {
FORMATETC fe = {CF_JUKEBOX_TITLE_INFO, 0,
DVASPECT_CONTENT, -1,
TYMED_HGLOBAL};
STGMEDIUM stgm; ZeroMemory(&stgm, sizeof stgm);
if (SUCCEEDED(pdo->GetData(&fe, &stgm))) {
JUKEBOX_TITLE_INFO* pInfo =
GlobalLock(stgm.hGlobal);
os << pInfo->Author << ": "
<< pInfo->Title << endl;
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
pdo->Release();
}
}
Figure 4 IWorker Interface
// We're not supporting late-binding clients
// (which tend to require connection points)
// so this doesn't need to be a dispinterface
interface IWorkerEvents : IUnknown {
HRESULT OnWorkCompleted([in] IWorker *pWorker);
HRESULT OnWorkDelayed([in] IWorker *pWorker);
}
interface IWorker : IUnknown {
enum WorkerAdviseFlags {
WAF_COMPLETED = 0x1,
WAF_DELAYED = 0x2,
WAF_ALL = 0x3
};
HRESULT StartWork();
HRESULT WorkerAdvise(
[in] IWorkerEvents* pEvents,
[in] enum WorkerAdviseFlags flags,
[out] long * pnCookie);
HRESULT WorkerUnadvise([in] long dwCookie);
}
Figure 5 Implementing IworkerEvents
' Event interface implementation
Implements IWorkerEvents
Dim g_worker As IWorker
Dim g_cookie As Long
Private Sub Form_Load()
Set g_worker = New Worker
' Set up communication for a subset of events
g_cookie = g_worker.WorkerAdvise(Me, WE_COMPLETED)
End Sub
' Handle the events we're interested in
Private Sub IWorkerEvents_OnWorkCompleted(IWorker src)
MsgBox "Work Completed"
g_worker.WorkerUnadvise g_cookie
End Sub
Private Sub IWorkerEvents_OnWorkDelayed(IWorker src)
' this will never be called since WorkerAdvise
' was called with WE_COMPLETED only
End Sub
Figure 6 IDL for Typeless Languages
[object,dual,uuid(92284211-9221-2412-11d1-552124391232)]
interface ICat : IDispatch {
[id(1)] HRESULT Meow([in] long nVolume);
[id(2),propget] HRESULT AsDog([out, retval] IDog **p);
}
[object,dual,uuid(92284212-9221-2412-11d1-552124391232)]
interface IDog : IDispatch {
[id(1)] HRESULT Bark([in] long nVolume);
[id(2),propget] HRESULT AsCat([out, retval] ICat **p);
}
In the Ory, this allows the typeless client to write the following:
Sub MeowAndBark( )
Dim cat ' typeless language, so everything is variant
Dim dog ' typeless language, so everything is variant
Set dog = CreateObject("DogCat")
Set cat = dog.AsCat ' pseudo QueryInterface
dog.Bark 100
cat.Meow 200
End Sub
Figure 7 Automation-style Model
[ uuid(E4244920-3DA0-11d1-A84F-0080C7667ABF) ]
library AnimalLib {
dispinterface _PetStore; dispinterface _Animal;
dispinterface _Dog; dispinterface _Cat;
// Top-level object
[ uuid(E4244921-3DA0-11d1-A84F-0080C7667ABF) ]
dispinterface _PetStore {
properties:
[id(1), readonly] _Animal Youngest;
[id(2), readonly] _Animal Cutest;
methods:
[id(3)] _Animal GetAnimal([in] BSTR bstrName);
[id(4)] void PutAnimal([in] _Animal a);
}
[ uuid(E4244922-3DA0-11d1-A84F-0080C7667ABF) ]
dispinterface _Animal {
properties:
[id(1), readonly] _PetStore PetStore;
[id(2), readonly] _Dog Dogness;
[id(3), readonly] _Cat Catness;
methods:
[id(4)] void Eat();
}
[ uuid(E4244923-3DA0-11d1-A84F-0080C7667ABF) ]
dispinterface _Dog {
properties:
[id(1), readonly] _Animal Animalness;
methods:
[id(2)] void Bark();
}
[ uuid(E4244924-3DA0-11d1-A84F-0080C7667ABF) ]
dispinterface _Cat {
properties:
[id(1), readonly] _Animal Animalness;
methods:
[id(2)] void Meow();
}
[uuid(E4244925-3DA0-11d1-A84F-0080C7667ABF),appobject]
coclass PetStore {
[hidden, default] dispinterface _PetStore;
}
[uuid(E4244926-3DA0-11d1-A84F-0080C7667ABF)]
coclass Animal {
[hidden, default] dispinterface _Animal;
}
[uuid(E4244927-3DA0-11d1-A84F-0080C7667ABF),
noncreatable]
coclass Dog {
[hidden, default] dispinterface _Dog;
}
[uuid(E4244927-3DA0-11d1-A84F-0080C7667ABF),
noncreatable]
coclass Cat {
[hidden, default] dispinterface _Cat;
}
}