summaryrefslogtreecommitdiffstats
path: root/private/ole32/com/dcomrem/ipidtbl.hxx
blob: 04962ea7995e56e59acc5851a6f2d6aa37289cc3 (plain) (blame)
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_