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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
|
//+------------------------------------------------------------------------
//
// File: ipidtbl.hxx
//
// Contents: MID (machine identifier) table.
// OXID (object exporter identifier) table.
// IPID (interface pointer identifier) table.
//
// Classes: CMIDTable
// COXIDTable
// CIPIDTable
//
// History: 02-Feb-95 Rickhi Created
//
//-------------------------------------------------------------------------
#ifndef _IPIDTBL_HXX_
#define _IPIDTBL_HXX_
#include <pgalloc.hxx> // CPageAllocator
#include <lclor.h> // local OXID resolver interface
#include <remoteu.hxx> // CRemoteUnknown
#include <locks.hxx> // ASSERT_LOCK_HELD
#include <hash.hxx> // CStringHashTable
// forward declarations
class CRpcChannelBuffer;
//+------------------------------------------------------------------------
//
// This structure defines an Entry in the MID table. There is one MID
// table for the entire process. There is one MIDEntry per machine that
// the current process is talking to (including one for the local machine).
//
//-------------------------------------------------------------------------
typedef struct tagMIDEntry
{
SStringHashNode Node; // hash chain and key
MID mid; // machine identifier
LONG cRefs; // count of IPIDs using this OXIDEntry
DWORD dwFlags; // state flags
} MIDEntry;
// MID Table constants. MIDS_PER_PAGE is the number of MIDEntries
// in one page of the page allocator.
#define MIDS_PER_PAGE 5
//+------------------------------------------------------------------------
//
// class: CMIDTable
//
// Synopsis: Table of Machine IDs (MIDs) and associated information.
//
// History: 05-Jan-96 Rickhi Created
//
//-------------------------------------------------------------------------
class CMIDTable
{
public:
void Initialize(); // initialize table
void Cleanup(); // cleanup table
HRESULT FindOrCreateMIDEntry(REFMID rmid,
DUALSTRINGARRAY *psaResolver,
MIDEntry **ppMIDEntry);
MIDEntry *LookupMID(DUALSTRINGARRAY *psaResolver, DWORD *pdwHash);
void ReleaseEntry(MIDEntry *pMIDEntry);
private:
HRESULT AddMIDEntry(REFMID rmid,
DWORD dwHash,
DUALSTRINGARRAY *psaResolver,
MIDEntry **ppMIDEntry);
static CStringHashTable _HashTbl; // hash table for MIDEntries
static CPageAllocator _palloc; // page based allocator
};
//+------------------------------------------------------------------------
//
// This structure defines an Entry in the OXID table. There is one OXID
// table for the entire process. There is one OXIDEntry per apartment.
//
//-------------------------------------------------------------------------
typedef struct tagOXIDEntry
{
struct tagOXIDEntry *pPrev; // previous entry on inuse list
struct tagOXIDEntry *pNext; // next entry on free/inuse list
DWORD dwPid; // process id of server
DWORD dwTid; // thread id of server
MOXID moxid; // object exporter identifier + machine id
IPID ipidRundown;// IPID of IRundown and Remote Unknown
DWORD dwFlags; // state flags
handle_t hServerSTA; // rpc binding handle of server
handle_t hServerMTA; // rpc binding handle of server
MIDEntry *pMIDEntry; // MIDEntry for machine where server lives
IRemUnknown *pRUSTA; // STA model proxy for Remote Unknown
IRemUnknown *pRUMTA; // MTA model proxy for Remote Unknown
LONG cRefs; // count of IPIDs using this OXIDEntry
LONG cWaiters; // count of threads waiting for OIDs
HANDLE hComplete; // set when last outstanding call completes
LONG cCalls; // number of calls dispatched
LONG cResolverRef;//References to resolver
DWORD dwPad; // keep structure 16 byte aligned
} OXIDEntry;
// bit flags for dwFlags of OXIDEntry
typedef enum tagOXIDFLAGS
{
OXIDF_REGISTERED = 0x1, // oxid is registered with Resolver
OXIDF_MACHINE_LOCAL = 0x2, // oxid is local to this machine
OXIDF_STOPPED = 0x4, // thread can no longer receive calls
OXIDF_PENDINGRELEASE = 0x8, // oxid entry is already being released
OXIDF_MSWMSG = 0x10, // use mswmsg transport
OXIDF_REGISTERINGOIDS= 0x20, // a thread is busy registering OIDs
OXIDF_MTASERVER = 0x40 // the server is an MTA apartment.
} OXIDFLAGS;
// Parameter to FindOrCreateOXIDEntry
typedef enum tagFOCOXID
{
FOCOXID_REF = 1, // Got reference from resolver
FOCOXID_NOREF = 2 // No reference from resolver
} FOCOXID;
// OXID Table constants.
#define OXIDS_PER_PAGE 10
#define OXIDTBL_MAXEXPIRED 5 // max number of expired entries to keep
//+------------------------------------------------------------------------
//
// class: COXIDTable
//
// Synopsis: Maintains a table of OXIDs and associated information
//
// History: 02-Feb-95 Rickhi Created
//
//-------------------------------------------------------------------------
class COXIDTable
{
public:
HRESULT AddEntry(REFOXID roxid, OXID_INFO *poxidInfo,
MIDEntry *pMIDEntry, OXIDEntry **ppEntry);
void ReleaseEntry(OXIDEntry *pEntry);
HRESULT GetLocalEntry(OXIDEntry **ppEntry);
void ReleaseLocalSTAEntry(void);
void ReleaseLocalMTAEntry(void);
OXIDEntry *LookupOXID(REFOXID roxid, REFMID rmid);
HRESULT GetRemUnk(OXIDEntry *pOXIDEntry, IRemUnknown **ppRemUnk);
void Initialize(); // initialize table
void Cleanup(); // cleanup table
void FreeExpiredEntries(DWORD dwTime);
void ValidateOXID();
void FreeCleanupEntries();
DWORD NumOxidsToRemove();
void GetOxidsToRemove( OXID_REF *pRef, DWORD *pNum );
private:
void ExpireEntry(OXIDEntry *pEntry);
OXIDEntry *SearchList(REFMOXID rmoxid, OXIDEntry *pStart);
HRESULT MakeRemUnk(OXIDEntry *pOXIDEntry);
void AssertListsEmpty(void);
static DWORD _cExpired; // count of expired entries
static OXIDEntry _InUseHead; // head of InUse list.
static OXIDEntry _ExpireHead; // head of Expire list.
static OXIDEntry _CleanupHead; // head of Cleanup list.
static CPageAllocator _palloc; // page alloctor
// PERFWORK: could save space since only the first two entries of
// the InUseHead and ExpireHead are used (the list ptrs) and hence
// dont need whole OXIDEntries here.
};
//+------------------------------------------------------------------------
//
// Member: COXIDTbl::ValidateOXID, public
//
// Synopsis: Asserts that no OXIDEntries have trashed window handles.
//
//-------------------------------------------------------------------------
inline void COXIDTable::ValidateOXID()
{
#if DBG==1
LOCK
// Check all entries in use.
OXIDEntry *pCurr = _InUseHead.pNext;
while (pCurr != &_InUseHead)
{
Win4Assert( pCurr->hServerSTA != (void *) 0xC000001C );
Win4Assert( pCurr->hServerMTA != (void *) 0xC000001C );
pCurr = pCurr->pNext;
}
UNLOCK
#endif
}
//+------------------------------------------------------------------------
//
// Member: COXIDTbl::AssertListsEmpty, public
//
// Synopsis: Asserts that no OXIDEntries are in use
//
// History: 19-Apr-96 Rickhi Created
//
//-------------------------------------------------------------------------
inline void COXIDTable::AssertListsEmpty(void)
{
// Assert that there are no entries in the InUse or Expired lists.
Win4Assert(_InUseHead.pNext == &_InUseHead);
Win4Assert(_InUseHead.pPrev == &_InUseHead);
Win4Assert(_ExpireHead.pNext == &_ExpireHead);
Win4Assert(_ExpireHead.pPrev == &_ExpireHead);
}
//+------------------------------------------------------------------------
//
// This structure defines an Entry in the IPID table. There is one
// IPID table for the entire process. It holds IPIDs from local objects
// as well as remote objects.
//
//-------------------------------------------------------------------------
typedef struct tagIPIDEntry
{
struct tagIPIDEntry *pNextOID; // next IPIDEntry for same object
DWORD dwFlags; // flags (see IPIDFLAGS)
ULONG cStrongRefs; // strong reference count
ULONG cWeakRefs; // weak reference count
ULONG cPrivateRefs;// private reference count
CRpcChannelBuffer *pChnl; // channel pointer
IUnknown *pStub; // proxy or stub pointer
OXIDEntry *pOXIDEntry; // ptr to OXIDEntry in OXID Table
IPID ipid; // interface pointer identifier
IID iid; // interface iid
void *pv; // real interface pointer
DWORD pad[3]; // round size to modulus 16
} IPIDEntry;
// bit flags for dwFlags of IPIDEntry
typedef enum tagIPIDFLAGS
{
IPIDF_CONNECTING = 0x1, // ipid is being connected
IPIDF_DISCONNECTED = 0x2, // ipid is disconnected
IPIDF_SERVERENTRY = 0x4, // SERVER IPID vs CLIENT IPID
IPIDF_NOPING = 0x8, // dont need to ping the server or release
IPIDF_COPY = 0x10, // copy for security only
IPIDF_VACANT = 0x80, // entry is vacant (ie available to reuse)
IPIDF_NONNDRSTUB = 0x100, // stub does not use NDR marshaling
IPIDF_NONNDRPROXY = 0x200, // proxy does not use NDR marshaling
IPIDF_NOTIFYACT = 0x400 // notify activation on marshal/release
} IPIDFLAGS;
// IPID Table constants. IPIDS_PER_PAGE is the number of IPIDEntries
// in one page of the page allocator.
#define IPIDS_PER_PAGE 50
//+------------------------------------------------------------------------
//
// class: CIPIDTbl
//
// Synopsis: Maintains a table of IPIDs and associated information
//
// History: 02-Feb-95 Rickhi Created
//
//-------------------------------------------------------------------------
class CIPIDTable
{
public:
IPIDEntry *LookupIPID(REFIPID ripid); // find entry in the table with
// the matching ipid
IPIDEntry *FirstFree(void);
void ReleaseEntryList(IPIDEntry *pFirst, IPIDEntry *pLast);
IPIDEntry *GetEntryPtr(LONG iEntry);
LONG GetEntryIndex(IPIDEntry *pEntry);
#if DBG==1
void AssertValid(void) {;}
void ValidateIPIDEntry(IPIDEntry *pEntry, BOOL fServerSide,
CRpcChannelBuffer *pChnl);
#else
void AssertValid(void) {;}
void ValidateIPIDEntry(IPIDEntry *pEntry, BOOL fServerSide,
CRpcChannelBuffer *pChnl) {;}
#endif
void Initialize(); // initialize table
void Cleanup(); // cleanup table
private:
static CPageAllocator _palloc; // page alloctor
};
//+------------------------------------------------------------------------
//
// Global Externals
//
//+------------------------------------------------------------------------
extern CMIDTable gMIDTbl; // global table, defined in ipidtbl.cxx
extern COXIDTable gOXIDTbl; // global table, defined in ipidtbl.cxx
extern CIPIDTable gIPIDTbl; // global table, defined in ipidtbl.cxx
extern MIDEntry *gpLocalMIDEntry; // ptr to MIDEntry for current process
extern OXIDEntry *gpMTAOXIDEntry; // ptr to local OXIDEntry in MTA
extern DUALSTRINGARRAY *gpsaLocalResolver; // bindings for local OXID resolver.
//+------------------------------------------------------------------------
//
// Function Prototypes
//
//+------------------------------------------------------------------------
HRESULT GetLocalMIDEntry(MIDEntry **ppMIDEntry);
OXIDEntry *GetLocalOXIDEntry();
void SetLocalOXIDEntry(OXIDEntry *pOXIDEntry);
void DecOXIDRefCnt(OXIDEntry *pEntry);
void DecMIDRefCnt(MIDEntry *pEntry);
HRESULT FindOrCreateOXIDEntry(REFOXID roxid,
OXID_INFO &oxidInfo,
FOCOXID eReferenced,
DUALSTRINGARRAY *psaResolver,
REFMID rmid,
MIDEntry *pMIDEntry,
OXIDEntry **ppOXIDEntry);
//+------------------------------------------------------------------------
//
// Member: CIPIDTbl::FirstFree, public
//
// Synopsis: Finds the first available entry in the table and returns
// its index. Returns -1 if no space is available and it
// cant grow the list.
//
// History: 02-Feb-95 Rickhi Created
//
//-------------------------------------------------------------------------
inline IPIDEntry *CIPIDTable::FirstFree()
{
return (IPIDEntry *) _palloc.AllocEntry();
}
//+------------------------------------------------------------------------
//
// Member: CIPIDTbl::GetEntryIndex, public
//
// Synopsis: Converts an entry ptr into an entry index
//
// History: 02-Feb-95 Rickhi Created
//
//-------------------------------------------------------------------------
inline LONG CIPIDTable::GetEntryIndex(IPIDEntry *pIPIDEntry)
{
return _palloc.GetEntryIndex((PageEntry *)pIPIDEntry);
}
//+------------------------------------------------------------------------
//
// Member: CIPIDTbl::GetEntryPtr, public
//
// Synopsis: Converts an entry index into an entry pointer
//
// History: 02-Feb-95 Rickhi Created
//
//-------------------------------------------------------------------------
inline IPIDEntry *CIPIDTable::GetEntryPtr(LONG index)
{
return (IPIDEntry *) _palloc.GetEntryPtr(index);
}
//+------------------------------------------------------------------------
//
// Function: IncOXIDRefCnt, public
//
// Synopsis: increment the number of references to the OXIDEntry
//
// History: 02-Feb-95 Rickhi Created
//
//-------------------------------------------------------------------------
inline void IncOXIDRefCnt(OXIDEntry *pEntry)
{
Win4Assert(pEntry);
ASSERT_LOCK_HELD
ComDebOut((DEB_OXID,
"IncOXIDRefCnt pEntry:%x cRefs[%x]\n", pEntry, pEntry->cRefs+1));
pEntry->cRefs++;
}
//+------------------------------------------------------------------------
//
// Function: IncMIDRefCnt, public
//
// Synopsis: increment the number of references to the MIDEntry
//
// History: 05-Janb-96 Rickhi Created
//
//-------------------------------------------------------------------------
inline void IncMIDRefCnt(MIDEntry *pEntry)
{
Win4Assert(pEntry);
ASSERT_LOCK_HELD
ComDebOut((DEB_OXID,
"IncMIDRefCnt pEntry:%x cRefs[%x]\n", pEntry, pEntry->cRefs+1));
pEntry->cRefs++;
}
//+------------------------------------------------------------------------
//
// Function: MOXIDFromOXIDAndMID, public
//
// Synopsis: creates a MOXID (machine and object exporter ID) from
// the individual OXID and MID components
//
// History: 05-Janb-96 Rickhi Created
//
//-------------------------------------------------------------------------
inline void MOXIDFromOXIDAndMID(REFOXID roxid, REFMID rmid, MOXID *pmoxid)
{
BYTE *pb = (BYTE *)pmoxid;
memcpy(pb, &roxid, sizeof(OXID));
memcpy(pb+8, &rmid, sizeof(MID));
}
//+------------------------------------------------------------------------
//
// Function: OXIDFromMOXID, public
//
// Synopsis: extracts the OXID from a MOXID (machine and OXID)
//
// History: 05-Jan-96 Rickhi Created
//
//-------------------------------------------------------------------------
inline void OXIDFromMOXID(REFMOXID rmoxid, OXID *poxid)
{
memcpy(poxid, (BYTE *)&rmoxid, sizeof(OXID));
}
//+------------------------------------------------------------------------
//
// Function: MIDFromMOXID, public
//
// Synopsis: extracts the MID from a MOXID (machine and OXID)
//
// History: 05-Jan-96 Rickhi Created
//
//-------------------------------------------------------------------------
inline void MIDFromMOXID(REFMOXID rmoxid, OXID *pmid)
{
memcpy(pmid, ((BYTE *)&rmoxid)+8, sizeof(MID));
}
// OID + MID versions of the above routines.
#define MOIDFromOIDAndMID MOXIDFromOXIDAndMID
#define OIDFromMOID OXIDFromMOXID
#define MIDFromMOID MIDFromMOXID
#endif // _IPIDTBL_HXX_
|