421 lines
12 KiB
C++
421 lines
12 KiB
C++
|
/**********************************************************************/
|
||
|
/** Microsoft Windows NT **/
|
||
|
/** Copyright(c) Microsoft Corp., 1992 **/
|
||
|
/**********************************************************************/
|
||
|
|
||
|
/*
|
||
|
usrcache.hxx
|
||
|
|
||
|
This file contains the class declarations for the abstract
|
||
|
USER_LBI_CACHE class. This class implements a cache of LBIs
|
||
|
used when dealing with very large user databases. This class's
|
||
|
primary purpose is to be the "backing store" for a LAZY_LISTBOX.
|
||
|
As such, its interface is very similar to the BLT_LISTBOX
|
||
|
interface.
|
||
|
|
||
|
|
||
|
FILE HISTORY:
|
||
|
KeithMo 15-Dec-1992 Created.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#ifndef _USRCACHE_HXX_
|
||
|
#define _USRCACHE_HXX_
|
||
|
|
||
|
|
||
|
#include "base.hxx"
|
||
|
#include "slist.hxx"
|
||
|
|
||
|
DLL_CLASS ADMIN_AUTHORITY;
|
||
|
|
||
|
|
||
|
//
|
||
|
// These manifests are the default parameters for the
|
||
|
// USER_LBI_CACHE constructor.
|
||
|
//
|
||
|
|
||
|
#define ULC_INITIAL_GROWTH_DEFAULT 0
|
||
|
#define ULC_REQUEST_COUNT_DEFAULT 0
|
||
|
#define ULC_REMOTE_USERS_DEFAULT FALSE
|
||
|
|
||
|
|
||
|
//
|
||
|
// This is the "growth delta" applied to the cache whenever
|
||
|
// the structure array needs to be resized as a result of
|
||
|
// adding items to the cache.
|
||
|
//
|
||
|
// NOTE: This MUST be a power of two!
|
||
|
//
|
||
|
|
||
|
#define ULC_CACHE_GROWTH_DELTA 32
|
||
|
|
||
|
|
||
|
// Error codes returned by the AddItem method.
|
||
|
//
|
||
|
|
||
|
#define ULC_ERR (-1)
|
||
|
|
||
|
|
||
|
//
|
||
|
// An array of these simple structures is used as the
|
||
|
// actual cache. The following relationships are always
|
||
|
// in effect for pddu and plbi:
|
||
|
//
|
||
|
// +-------+-------+------------------------------+
|
||
|
// | | | |
|
||
|
// | pddu | plbi | cache entry |
|
||
|
// | | | |
|
||
|
// +-------+-------+------------------------------+
|
||
|
// | | | |
|
||
|
// | NULL | NULL | unused or unavailable |
|
||
|
// | | | |
|
||
|
// | NULL | !NULL | LBI created with AddItem |
|
||
|
// | | | |
|
||
|
// | !NULL | NULL | needs LBI (no QueryItem yet) |
|
||
|
// | | | |
|
||
|
// | !NULL | !NULL | LBI created during QueryItem |
|
||
|
// | | | |
|
||
|
// +-------+-------+------------------------------+
|
||
|
//
|
||
|
// The array elements actually consist of ULC_ENTRY_BASE structures
|
||
|
// plus _cbExtraBytes of extra space.
|
||
|
//
|
||
|
|
||
|
typedef struct _ULC_ENTRY
|
||
|
{
|
||
|
DOMAIN_DISPLAY_USER * pddu;
|
||
|
LBI * plbi;
|
||
|
BYTE bExtraBytes;
|
||
|
|
||
|
} ULC_ENTRY;
|
||
|
|
||
|
typedef struct _ULC_ENTRY_BASE
|
||
|
{
|
||
|
DOMAIN_DISPLAY_USER * pddu;
|
||
|
LBI * plbi;
|
||
|
|
||
|
} ULC_ENTRY_BASE;
|
||
|
|
||
|
|
||
|
//
|
||
|
// This is the "type" of the compare method required by qsort().
|
||
|
//
|
||
|
|
||
|
typedef int (__cdecl * PQSORT_COMPARE)( const void * p0, const void * p1 );
|
||
|
|
||
|
|
||
|
/*************************************************************************
|
||
|
|
||
|
NAME: ULC_API_BUFFER
|
||
|
|
||
|
SYNOPSIS: ULC_API_BUFFER is used to keep track of the buffers
|
||
|
allocated by the the SamQueryDisplayInformation
|
||
|
API. An SLIST of these nodes is maintained by
|
||
|
USER_LBI_CACHE.
|
||
|
|
||
|
INTERFACE: ULC_API_BUFFER - Class constructor.
|
||
|
|
||
|
~ULC_API_BUFFER - Class destructor.
|
||
|
|
||
|
QueryItemCount - Returns the number of items
|
||
|
stored in the buffer associated
|
||
|
with this node.
|
||
|
|
||
|
QueryBufferPtr - Returns the buffer pointer
|
||
|
associated with this node.
|
||
|
|
||
|
HISTORY:
|
||
|
KeithMo 15-Dec-1992 Created.
|
||
|
|
||
|
**************************************************************************/
|
||
|
DLL_CLASS ULC_API_BUFFER
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
//
|
||
|
// Pointer to the actual buffer.
|
||
|
//
|
||
|
|
||
|
DOMAIN_DISPLAY_USER * _pddu;
|
||
|
|
||
|
//
|
||
|
// The number of items in this buffer.
|
||
|
//
|
||
|
|
||
|
ULONG _cItems;
|
||
|
|
||
|
public:
|
||
|
|
||
|
//
|
||
|
// Usual constructor/destructor goodies.
|
||
|
//
|
||
|
|
||
|
ULC_API_BUFFER( DOMAIN_DISPLAY_USER * pddu,
|
||
|
ULONG cItems );
|
||
|
|
||
|
~ULC_API_BUFFER( VOID );
|
||
|
|
||
|
//
|
||
|
// Public accessors.
|
||
|
//
|
||
|
|
||
|
ULONG QueryCount( VOID ) const
|
||
|
{ return _cItems; }
|
||
|
|
||
|
DOMAIN_DISPLAY_USER * QueryBuffer( VOID ) const
|
||
|
{ return _pddu; }
|
||
|
|
||
|
}; // class ULC_API_BUFFER
|
||
|
|
||
|
|
||
|
DECL_SLIST_OF( ULC_API_BUFFER, DLL_BASED );
|
||
|
|
||
|
|
||
|
/*************************************************************************
|
||
|
|
||
|
NAME: USER_LBI_CACHE
|
||
|
|
||
|
SYNOPSIS: This abstract class implements the guts of an LBI
|
||
|
cache used to manipulate very large user databases.
|
||
|
|
||
|
INTERFACE: USER_LBI_CACHE - Class constructor.
|
||
|
|
||
|
~USER_LBI_CACHE - Class destructor.
|
||
|
|
||
|
ReadUsers - Read user accounts from a server
|
||
|
into the cache. pfQuitEnum
|
||
|
optionally points to a location
|
||
|
where another thread may request
|
||
|
that enumeration stop.
|
||
|
|
||
|
AddItem - Add an item to the cache
|
||
|
|
||
|
RemoveItem - Remove an item from the cache
|
||
|
w/o deleting the corresponding
|
||
|
LBI. Strangely, this may call
|
||
|
through to CreateLBI to create
|
||
|
a new LBI.
|
||
|
|
||
|
QueryItem - Query a cache item. This may
|
||
|
call through to the CreateLBI
|
||
|
virtual to create a new LBI.
|
||
|
Therefore, it may fail.
|
||
|
|
||
|
QueryCount - Returns the number of entries
|
||
|
in the cache.
|
||
|
|
||
|
IsItemAvailable - Returns TRUE if the given item
|
||
|
is available in the cache. Note
|
||
|
that this does *not* mean that
|
||
|
an associated LBI has been
|
||
|
created, only that the necessary
|
||
|
data is available.
|
||
|
|
||
|
Sort - Sort the cache items. Note that
|
||
|
an initial sort is performed at
|
||
|
object construction.
|
||
|
|
||
|
PARENT: BASE
|
||
|
|
||
|
HISTORY:
|
||
|
KeithMo 15-Dec-1992 Created.
|
||
|
|
||
|
**************************************************************************/
|
||
|
DLL_CLASS USER_LBI_CACHE : public BASE
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
//
|
||
|
// Our cache.
|
||
|
//
|
||
|
|
||
|
VOID * _pCache;
|
||
|
|
||
|
//
|
||
|
// A list of buffers as returned by SamQueryDisplayInformation.
|
||
|
//
|
||
|
|
||
|
SLIST_OF( ULC_API_BUFFER ) _slBuffers;
|
||
|
|
||
|
//
|
||
|
// The number of "slots" in the cache. These slots
|
||
|
// are not necessarily in use. See _cEntries;
|
||
|
//
|
||
|
|
||
|
INT _cSlots;
|
||
|
|
||
|
//
|
||
|
// The number of entries in the cache. Note that the
|
||
|
// cache may "grow" (the array will be resized) as new
|
||
|
// entries are added. _cEntries is always <= _cSlots.
|
||
|
//
|
||
|
|
||
|
INT _cEntries;
|
||
|
|
||
|
//
|
||
|
// Number of extra bytes at the end of each ULC_ENTRY. Note that
|
||
|
// this is rounded up from the construction parameter to the
|
||
|
// next multiple of sizeof(DWORD).
|
||
|
//
|
||
|
|
||
|
INT _cbExtraBytes;
|
||
|
|
||
|
//
|
||
|
// This worker method is responsible for "lazy LBI" creation.
|
||
|
// It is invoked by QueryItem & RemoveItem to ensure that a
|
||
|
// particular cache entry contains a valid LBI.
|
||
|
//
|
||
|
|
||
|
LBI * W_GetLBI( INT i );
|
||
|
|
||
|
//
|
||
|
// This worker method is responsible for growing the
|
||
|
// cache array as needed.
|
||
|
//
|
||
|
|
||
|
BOOL W_GrowCache( INT cTotalCacheEntries );
|
||
|
|
||
|
protected:
|
||
|
|
||
|
//
|
||
|
// This callback is invoked during QueryItem() cache misses.
|
||
|
//
|
||
|
|
||
|
virtual LBI * CreateLBI( const DOMAIN_DISPLAY_USER * pddu ) = 0;
|
||
|
|
||
|
//
|
||
|
// These callbacks are invoked during the binary search
|
||
|
// invoked while processing AddItem.
|
||
|
//
|
||
|
|
||
|
virtual INT Compare( const LBI * plbi,
|
||
|
const DOMAIN_DISPLAY_USER * pddu ) const = 0;
|
||
|
|
||
|
virtual INT Compare( const LBI * plbi0,
|
||
|
const LBI * plbi1 ) const = 0;
|
||
|
|
||
|
//
|
||
|
// This virtual callback returns the appropriate compare
|
||
|
// method to be used by qsort() while sorting the cache entries.
|
||
|
// The default compare method is USER_LBI_CACHE::CompareLogonNames().
|
||
|
//
|
||
|
|
||
|
virtual PQSORT_COMPARE QueryCompareMethod( VOID ) const;
|
||
|
|
||
|
//
|
||
|
// These virtual callbacks are invoked to lock & unlock
|
||
|
// the cache. These may be redefined by a subclass to
|
||
|
// provide multithread safety. The default implementation
|
||
|
// is a NOP for each callback.
|
||
|
//
|
||
|
|
||
|
virtual VOID LockCache( VOID );
|
||
|
|
||
|
virtual VOID UnlockCache( VOID );
|
||
|
|
||
|
//
|
||
|
// This static method will do a case insensitive compare
|
||
|
// of two UNICODE_STRINGs. Might be useful for derived
|
||
|
// subclasses.
|
||
|
//
|
||
|
|
||
|
static int CmpUniStrs( const UNICODE_STRING * punicode0,
|
||
|
const UNICODE_STRING * punicode1 );
|
||
|
|
||
|
//
|
||
|
// This is the default compare routine to be used by
|
||
|
// qsort() while sorting the cache entries.
|
||
|
//
|
||
|
|
||
|
static int __cdecl CompareLogonNames( const void * p0,
|
||
|
const void * p1 );
|
||
|
|
||
|
inline INT QueryULCEntrySize( VOID )
|
||
|
{ return sizeof(ULC_ENTRY_BASE) + _cbExtraBytes; }
|
||
|
|
||
|
inline ULC_ENTRY * QueryULCEntryPtr( INT i )
|
||
|
{
|
||
|
ASSERT( i >= 0 && i < _cSlots && _pCache != NULL );
|
||
|
return (ULC_ENTRY *) ( ((BYTE *)_pCache) + ( i * QueryULCEntrySize() ) );
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
//
|
||
|
// Usual constructor/destructor goodies.
|
||
|
//
|
||
|
// Note that padminauth must be NULL for downlevel machines.
|
||
|
//
|
||
|
|
||
|
USER_LBI_CACHE( INT cbExtraBytes = 0 );
|
||
|
|
||
|
virtual ~USER_LBI_CACHE( VOID );
|
||
|
|
||
|
//
|
||
|
// Read the API data & initialize the cache. New items are appended
|
||
|
// to the end of the cache, and are not in sorted order.
|
||
|
//
|
||
|
|
||
|
APIERR ReadUsers( ADMIN_AUTHORITY * padminauth,
|
||
|
UINT nInitialGrowthSpace = ULC_INITIAL_GROWTH_DEFAULT,
|
||
|
UINT cUsersPerRequest = ULC_REQUEST_COUNT_DEFAULT,
|
||
|
BOOL fIncludeRemoteUsers = ULC_REMOTE_USERS_DEFAULT,
|
||
|
BOOL * pfQuitEnum = NULL );
|
||
|
|
||
|
//
|
||
|
// Add a new LBI to the cache. Will return the index of
|
||
|
// the newly added item if successful, ULC_ERR otherwise.
|
||
|
//
|
||
|
|
||
|
virtual INT AddItem( LBI * plbi );
|
||
|
|
||
|
//
|
||
|
// Remove the item at index i from the cache, but don't
|
||
|
// delete the LBI. Will return a pointer to the LBI if
|
||
|
// successful, NULL otherwise.
|
||
|
//
|
||
|
|
||
|
virtual LBI * RemoveItem( INT i );
|
||
|
|
||
|
//
|
||
|
// Query the item at index i in the cache. Will return
|
||
|
// a pointer to the LBI if successful, NULL otherwise.
|
||
|
//
|
||
|
|
||
|
virtual LBI * QueryItem( INT i );
|
||
|
|
||
|
//
|
||
|
// Determines if the necessary data for a given item is
|
||
|
// available.
|
||
|
//
|
||
|
|
||
|
virtual BOOL IsItemAvailable( INT i );
|
||
|
|
||
|
//
|
||
|
// Returns the number of entries in the cache.
|
||
|
//
|
||
|
|
||
|
INT QueryCount( VOID ) const
|
||
|
{ return _cEntries; }
|
||
|
|
||
|
//
|
||
|
// Sort the cache entries.
|
||
|
//
|
||
|
|
||
|
VOID Sort( VOID );
|
||
|
|
||
|
//
|
||
|
// Perform a binary search on the cache, finding the
|
||
|
// appropriate index for the new LBI (or a potential LBI for the
|
||
|
// provided DOMAIN_DISPLAY_USER).
|
||
|
//
|
||
|
|
||
|
INT BinarySearch( LBI * plbiNew );
|
||
|
INT BinarySearch( DOMAIN_DISPLAY_USER * pddu );
|
||
|
|
||
|
}; // class USER_LBI_CACHE
|
||
|
|
||
|
|
||
|
#endif // _USRCACHE_HXX_
|
||
|
|