-
Notifications
You must be signed in to change notification settings - Fork 1
/
giplip.h
181 lines (163 loc) · 5.31 KB
/
giplip.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
////////////////////////////////////////////////////////
//
// giplip.h - Copyright 1997, Don Box
//
// IGlobalInterfaceTable Management Classes
//
// This file provides two classes that simplify sharing interface
// pointers across intra-process apartment boundaries (such as when
// using the FreeThreadedMarshaler):
//
// GlobalInterfacePointer<Itf, &IID_Itf> - a wrapper around IGIT cookies
// LocalInterfacePointer<Itf, &IID_Itf> - wraps imported IGIT cookies
//
// Usage:
//
// class Bar : public IBar {
// GlobalInterfacePointer<IFoo, &IID_IFoo> m_gipFoo;
// STDMETHODIMP put_Foo(IFoo *pFoo) {
// if (m_gipFoo.IsOK())
// m_gipFoo.Unglobalize();
// return m_gipFoo.Globalize(pFoo);
// }
// STDMETHODIMP BarMethod(void) {
// HRESULT hr;
// LIP(IFoo) lipFoo(m_gipFoo, hr);
// if (SUCCEEDED(hr))
// hr = lipFoo->FooMethod();
// return hr;
// }
// };
//
// define this symbol in exactly one translation unit per target (a la INITGUID)
#ifdef _INIT_GIPLIP
IGlobalInterfaceTable *g_pGIT = 0;
#endif
#ifndef _GIPLIP_H
#define _GIPLIP_H
#include <assert.h>
#ifndef __IGlobalInterfaceTable_FWD_DEFINED__
#error "You need NT4/SP3 SDK headers and libs from http:/www.microsoft.com/msdn"
#endif
// this is where the template class gets its pointer to the GIT
extern IGlobalInterfaceTable *g_pGIT;
// this is a wrapper that grabs the GIT when needed
class GIT {
public:
// initialize module-wide GIT pointer
static HRESULT Init(void) {
HRESULT hr = S_OK;
if (g_pGIT == 0)
hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, 0, CLSCTX_ALL,
IID_IGlobalInterfaceTable, (void**)&g_pGIT);
return hr;
}
// release module-wide GIT pointer
static void Term(void) {
if (g_pGIT != 0)
g_pGIT->Release();
}
// autoinit module-wide GIT pointer
GIT(void) {
HRESULT hr = Init();
assert(SUCCEEDED(hr) && "Couldn't initialize GlobalInterfaceTable");
}
// autoterm module-wide GIT pointer
~GIT(void) { Term(); }
};
// wrapper around a GIT cookie
template <class Itf, const IID* piid>
class GlobalInterfacePointer
{
// prevent missuse
GlobalInterfacePointer(const GlobalInterfacePointer&);
void operator =(const GlobalInterfacePointer&);
DWORD m_dwCookie; // the GIT cookie
public:
// start as invalid cookie
GlobalInterfacePointer(void) : m_dwCookie(0) { }
// auto-globalize local pointer
GlobalInterfacePointer(Itf *pItf, HRESULT& hr)
: m_dwCookie(0) {
hr = Globalize(pItf);
}
// auto-unglobalize
~GlobalInterfacePointer(void) {
if (m_dwCookie)
Unglobalize();
}
// register an interface pointer in GIT
HRESULT Globalize(Itf *pItf) {
assert(g_pGIT != 0 && "GIT::Init not called");
assert(m_dwCookie == 0 && "Attempt to Globalize invalidCookie");
return g_pGIT->RegisterInterfaceInGlobal(pItf, *piid, &m_dwCookie);
}
// revoke an interface pointer in GIT
HRESULT Unglobalize(void) {
assert(g_pGIT != 0 && "GIT::Init not called");
assert(m_dwCookie != 0 && "Attempt to Unglobalize invalid cookie");
HRESULT hr = g_pGIT->RevokeInterfaceFromGlobal(m_dwCookie);
m_dwCookie = 0;
return hr;
}
// get a local interface pointer from GIT
HRESULT Localize(Itf **ppItf) const {
assert(g_pGIT != 0 && "GIT::Init not called");
assert(m_dwCookie != 0 && "Attempt to Localize invalid cookie");
return g_pGIT->GetInterfaceFromGlobal(m_dwCookie, *piid,(void**)ppItf);
}
// convenience methods
bool IsOK(void) const {
return m_dwCookie != 0;
}
DWORD GetCookie(void) const {
return m_dwCookie;
}
};
// convenience macro
#define GIP(Itf) GlobalInterfacePointer<Itf, &IID_##Itf>
// wrapper around locally imported pointer
template <class Itf, const IID* piid>
class LocalInterfacePointer
{
// prevent missuse
LocalInterfacePointer(const LocalInterfacePointer&);
void operator = (const LocalInterfacePointer&);
// temp imported pointer
Itf *m_pItf;
public:
// import from GIP
LocalInterfacePointer(const GlobalInterfacePointer<Itf, piid>& rhs,
HRESULT& hr) {
hr = rhs.Localize(&m_pItf);
}
// import from raw cookie
LocalInterfacePointer(DWORD dwCookie, HRESULT& hr)
{
assert(g_pGIT != 0 && "GIT::Init not called");
hr = g_pGIT->GetInterfaceFromGlobal(dwCookie, *piid, (void**)&m_pItf);
}
// release temp local pointer
~LocalInterfacePointer(void)
{
if (m_pItf)
m_pItf->Release();
}
// declare new Itf class with private AddRef/Release
class SafeItf : public Itf {
STDMETHOD_(ULONG, AddRef)(void) = 0;
STDMETHOD_(ULONG, Release)(void) = 0;
};
// provide an arrow operator
SafeItf *operator ->(void) const {
assert(m_pItf && "Null LocalInterfacePointer Used");
return GetInterface();
}
// provide use of temp pointer
SafeItf *GetInterface(void) const {
return (SafeItf*)m_pItf;
}
};
// convenience macro
#define LIP(Itf) LocalInterfacePointer<Itf,&IID_##Itf>
#endif