Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1089 lines
19 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
protocol.hxx
Abstract:
This module deals with objects that make up the server and group
entry items. This includes creatation/destruction and searching
of the entries.
Author:
Steven Zeck (stevez) 07/01/90
--*/
#ifndef _PROTOCOL_
#define _PROTOCOL_
class QUERY_SERVER;
class ENTRY_BASE_NODE;
class ENTRY_BASE_ITEM;
class ENTRY_SERVER_ITEM;
class ENTRY_SERVER_NODE;
class ENTRY_GROUP_ITEM;
class ENTRY_GROUP_NODE;
DYN_ARRAY_TYPE(UUID_ARRAY, NS_UUID, LONG)
// The following enumeration is the the type of entry the object is.
typedef enum {
ServerEntryType = 1,
GroupEntryType,
ProfileEntryType,
AnyEntryType,
LastEntryType
} TYPE_ENTRY_NODE ;
// The following are the type of base member entry the object is.
typedef enum {
LocalItemType = 1, // local item
CacheItemType, // cached item, ie - remote
DeleteItemType, // delayed delete due
LastItemType // end marker
} TYPE_ENTRY_ITEM;
// The follwing is the return values by MatchItem virtual functions.
typedef enum {
NoMatch, // Item didn't match
ItemMatch, // This item matched
SubItemMatch, // or a subitem under this object matched
}MATCH_RETURN;
// The following is the format for a query on the net with mailslots.
typedef struct {
NS_SYNTAX_ID Interface; // inteface that we are looking for
NS_UUID Object; // Object that we are interested in
UICHAR WkstaName[DOMAIN_MAX]; // buffer for machine name
UICHAR EntryName[ENTRY_MAX]; // buffer for entry name
} QueryPacket;
/*++
Class Definition:
ENTRY_KEY
Abstract:
This is the EntryName object. It is the name of the entries in
the in memory object data base.
--*/
class ENTRY_KEY {
private:
UNICODE_ARRAY EntryName; // and the string value of the entry
public:
ENTRY_KEY(
IN PUZ Name,
IN PUZ DomainName,
OUT STATUS *Status
);
ENTRY_KEY(
IN PUZ Name,
IN int fAllowGlobal,
OUT STATUS *Status
);
// Construct a new object by copying an existing one.
ENTRY_KEY(
IN ENTRY_KEY *KeyNew,
OUT STATUS *Status
)
{
EntryName = KeyNew->EntryName.Dup();
*Status = (!KeyNew->EntryName.pCur() || EntryName.pCur())?
NSI_S_OK: NSI_S_OUT_OF_MEMORY;
}
ACCESSOR(UNICODE_ARRAY, EntryName);
// Free the allocated objects referenced.
void
Free(
)
{
EntryName.Free();
}
// Set the value of the EntryName
void
SetEntryName(
IN UNICODE_ARRAY &New,
OUT UNICODE_ARRAY &Previous
)
{
Previous = EntryName;
EntryName = New;
}
int
Equal(
UNICODE_ARRAY& Entry1
);
// Compare two objects for identity
int
Equal (
IN ENTRY_KEY &Entry1
)
{
return(Equal(Entry1.EntryName));
}
// Determine if an entry name is empty.
int
IsNil(
)
{
return(EntryName.cCur() == 0);
}
// Return a Copy of the entry name.
UICHAR *
CopyName(
)
{
return((UICHAR *)NewCopy(EntryName.pCur(), (int) EntryName.Size()));
}
// Return the size to marshall this object.
int
MarshallSize(
)
{
return(sizeof(ENTRY_KEY) + EntryName.Size());
}
char *
Marshall(
OUT char *Buffer
);
PUZ
MakeLocalName(
OUT PUZ Buffer,
OUT PUZ DomainBuffer,
IN PUZ DefDomain
);
friend char *
KeyEntryUnMarshall(
OUT ENTRY_KEY **Key,
IN UICHAR * Domain,
IN char *Buffer,
OUT STATUS *Status
);
friend ostream& operator << (ostream&, ENTRY_KEY&);
};
/*++
Class Definition:
QUERY_REF_ITEM
Abstract:
This linked list is how replies are stored. Each found EntryItem
is referenced by a pointer to the base case for EntryItems.
--*/
NEW_LINK_LIST(QUERY_REF,
ENTRY_BASE_ITEM *EntryItem; /* Reference to matched item */
QUERY_REF_ITEM (
IN ENTRY_BASE_ITEM *EntryItemNew
)
{
EntryItem = EntryItemNew;
}
QUERY_REF_ITEM *
Free(
IN OUT QUERY_REF_LIST &ML
);
friend ostream& operator << (ostream&, QUERY_REF_ITEM&);
friend class QUERY;
)
/*++
Class Definition:
QUERY
Abstract:
Base class for a query into the object data base. It contains the
specification for the query and the resulting replay.
--*/
class QUERY {
protected:
QUERY_REF_LIST ReplyList; // List which gets the reply from the query.
ENTRY_KEY Entry; // The entry, that we are searching on.
TYPE_ENTRY_NODE Type; // Type of entry we are interested in.
long ExpirationTime; // Cut off point for cached entries.
long Scope; // Flags which limit query.
int RecursionCount; // Keeps track of the recursion in searchs.
public:
QUERY(
IN TYPE_ENTRY_NODE TypeNew,
IN ENTRY_KEY *KeyNew,
IN long ScopeNew,
OUT STATUS *Status
) :
Entry(KeyNew, Status)
{
Type = TypeNew;
ExpirationTime = maxCacheAge;
Scope = ScopeNew;
RecursionCount = 0;
}
~QUERY() {
Entry.Free();
}
ENTRY_BASE_ITEM *
NextReply(
);
QUERY_REF_ITEM *
First(
)
{
return(ReplyList.First());
}
void FreeReply(
IN QUERY_REF_ITEM * Item
)
{
Item->Free(ReplyList);
}
ACCESSOR(long, ExpirationTime);
STATUS
Search(
);
STATUS
SearchEntry(
IN ENTRY_SERVER_NODE * &ENTRY_SERVER
);
virtual STATUS
QueryNet(
);
STATUS BroadCast(
IN QueryPacket& NetRequest,
IN ENTRY_KEY &Entry
);
virtual STATUS
GetUpdatesFromMasterLocator(
);
char * DetectMasterLocator(
);
};
/*++
Class Definition:
QUERY_SERVER
Abstract:
Dervived class when searching only for a server entry object.
--*/
class QUERY_SERVER: public QUERY {
private:
// The following optional members are used to filter the search.
NS_SYNTAX_ID Interface; // Interface of interest.
NS_SYNTAX_ID TransferSyntax; // Stub transfer syntax of interest.
NS_UUID Object; // Object of interest
public:
QUERY_SERVER(
IN ENTRY_KEY *KeyNew,
IN NS_SYNTAX_ID *InterfaceNew,
IN NS_SYNTAX_ID * TransferSyntaxNew,
IN NS_UUID *ObjectNew,
IN long ScopeNew,
OUT STATUS *Status
) : QUERY (ServerEntryType, KeyNew, ScopeNew, Status)
{
Interface = *InterfaceNew;
TransferSyntax = *TransferSyntaxNew;
Object = *ObjectNew;
}
ACCESSOR(NS_UUID, Object);
virtual STATUS
QueryNet(
);
virtual STATUS
GetUpdatesFromMasterLocator(
);
friend class ENTRY_SERVER_ITEM;
};
/*++
Class Definition:
QUERY_GROUP
Abstract:
Dervived class when searching only for a group entry object.
--*/
class QUERY_GROUP: public QUERY {
private:
public:
QUERY_GROUP(
IN ENTRY_KEY *KeyNew,
IN long ScopeNew,
OUT STATUS *Status
) : QUERY (GroupEntryType, KeyNew, ScopeNew, Status)
{
}
virtual STATUS
QueryNet(
);
virtual STATUS
GetUpdatesFromMasterLocator(
);
friend class ENTRY_GROUP_ITEM;
};
/*++
Class Definition:
ENTRY_BASE_ITEM
Abstract:
Each type of entry object has a linked list of these objects. These items
make up the member objects that belong to the entry. This is the
base class for all member objects of a EntryNode (see next class).
--*/
NEW_LINK_LIST(ENTRY_BASE,
protected:
TYPE_ENTRY_ITEM Type; /* type of list item */
ENTRY_BASE_NODE *EntryNode; /* reference to which node I'm in */
ULONG Time; /* time arrived for cached PS */
ULONG UseCount; /* number of references to object */
public:
ENTRY_BASE_ITEM(
IN TYPE_ENTRY_ITEM TypeNew
)
{
Type = TypeNew;
Time = CurrentTime();
EntryNode = NIL;
UseCount = 1;
}
ACCESSOR(ENTRY_BASE_NODE *, EntryNode)
// See if a this object is a queried type.
BOOL
IsType(
IN TYPE_ENTRY_ITEM qType
)
{
return(qType == Type);
}
// Determine if a cached entry is stale and should be discarded.
BOOL
IsStaleEntry(
IN long Age
)
{
return(Type == CacheItemType && CurrentTime() > Time+Age);
}
// Threads must Reserve and Release an node item to use it.
void
MultiThreadReserve(
)
{
UseCount++;
}
void
MultiThreadRelease(
)
{
UseCount--;
if (Type == DeleteItemType && UseCount == 0)
delete this;
}
virtual
~ENTRY_BASE_ITEM(
);
virtual MATCH_RETURN
MatchItem(
IN QUERY *SearchSpec
);
virtual int
Marshall(
OUT PB Buffer,
IN OUT long UNALIGNED *cbBuffer
);
virtual ostream&
Format(
IN OUT ostream&
);
friend ostream& operator << (ostream&, ENTRY_BASE_ITEM&);
)
/*++
Class Definition:
ENTRY_BASE_NODE
Abstract:
This is the base class for all entry objects. It contains the name
of the entry and the type. All ENTRY_BASE_ITEM are belong to one
of this objects. This object is the one keep in the dictionary
for fast access.
--*/
class ENTRY_BASE_NODE {
protected:
ENTRY_KEY Entry; // The entry name, must be first member.
TYPE_ENTRY_NODE Type; // Type of entry object.
ENTRY_BASE_LIST ItemList; // List of member objects of this node.
public:
unsigned long LastUpdateTime;
ENTRY_BASE_NODE(
IN TYPE_ENTRY_NODE TypeNew,
IN ENTRY_KEY *KeyNew,
OUT STATUS *Status
):
Entry (KeyNew, Status)
{
Type = TypeNew;
LastUpdateTime = 0;
}
ACCESSOR(ENTRY_KEY, Entry)
ACCESSOR(ENTRY_BASE_LIST, ItemList)
// See if a this object is a queried type.
BOOL
IsType(
IN TYPE_ENTRY_NODE qType
)
{
return(qType == Type);
}
virtual void DeleteAllObjects()
{
//do nothing - just keep compiler happy
}
friend int ENTRY_BASE_NODECompare(ENTRY_KEY &E1, ENTRY_BASE_NODE &E2);
friend ENTRY_KEY& ENTRY_BASE_NODEMyKey(ENTRY_BASE_NODE &E1);
friend ostream& operator << (ostream&, ENTRY_BASE_NODE&);
};
/*++
Class Definition:
ENTRY_SERVER_NODE
Abstract:
The is a server entry node. This class addes the object vector
which all members of a server entry share.
--*/
class ENTRY_SERVER_NODE:public ENTRY_BASE_NODE {
private:
UUID_ARRAY ObjectDA; // Commaon object vector.
public:
ENTRY_SERVER_NODE(
IN ENTRY_KEY *KeyNew,
OUT STATUS *Status
): ENTRY_BASE_NODE (ServerEntryType, KeyNew, Status)
{
}
ACCESSOR(UUID_ARRAY, ObjectDA)
STATUS
MergeObjects(
IN UUID_ARRAY *NewObject
);
int
DeleteObject(
IN NS_UUID *Objects
);
virtual void DeleteAllObjects(
);
int
SearchObject(
IN NS_UUID *Object
);
ENTRY_SERVER_ITEM *
First(
)
{
return((ENTRY_SERVER_ITEM * ) TheItemList().First());
}
friend ostream& operator << (ostream&, ENTRY_SERVER_NODE&);
friend class ENTRY_SERVER_ITEM;
};
/*++
Class Definition:
ENTRY_SERVER_ITEM
Abstract:
This instance of a sever entry member object. It adds members which
describe the interface the the binding.
--*/
class ENTRY_SERVER_ITEM: public ENTRY_BASE_ITEM {
private:
NS_SYNTAX_ID Interface; // The interface of the member.
NS_SYNTAX_ID TransferSyntax; // The stub transfer syntax of the member.
UNICODE_ARRAY StringBinding; // DCE string binding.
public:
ASSERT_CLASS;
ENTRY_SERVER_ITEM (
IN TYPE_ENTRY_ITEM TypeNew,
IN NS_SYNTAX_ID *InterfaceNew,
IN NS_SYNTAX_ID * Transfer,
IN PUZ StringBinding,
OUT STATUS *Status);
virtual
~ENTRY_SERVER_ITEM(
);
int
Compare(
IN ENTRY_SERVER_ITEM * ServerItem
);
// Memeber access/update functions
NS_UUID &
TheInterfaceGID(
)
{
return(Interface.ThesyntaxGID());
}
ENTRY_KEY &
TheEntry(
)
{
return(EntryNode->TheEntry());
}
UUID_ARRAY &
TheObjectDA(
)
{
return(((ENTRY_SERVER_NODE *)EntryNode)->TheObjectDA());
}
ACCESSOR(NS_SYNTAX_ID, Interface);
ACCESSOR(NS_SYNTAX_ID, TransferSyntax);
ACCESSOR(UNICODE_ARRAY, StringBinding);
virtual MATCH_RETURN
MatchItem(
IN QUERY *SearchSpec
);
virtual int
Marshall(
OUT PB Buffer,
IN OUT long UNALIGNED *cbBuffer
);
virtual ostream&
Format(
ostream&
);
ENTRY_SERVER_ITEM *
Next(
)
{
return((ENTRY_SERVER_ITEM * ) ENTRY_BASE_ITEM::Next());
}
friend ostream& operator << (ostream&, QUERY_REF_ITEM&);
friend ostream& operator << (ostream&, ENTRY_SERVER_ITEM&);
};
STATUS
InsertServerEntry(
IN ENTRY_KEY *Entry,
IN ENTRY_SERVER_ITEM *ServerItem,
IN UUID_ARRAY * ObjectDA
);
/*++
Class Definition:
ENTRY_GROUP_NODE
Abstract:
This is a group entry node. No additional data members are added.
--*/
class ENTRY_GROUP_NODE:public ENTRY_BASE_NODE {
private:
public:
ENTRY_GROUP_NODE(
IN ENTRY_KEY *KeyNew,
OUT STATUS *Status
): ENTRY_BASE_NODE (GroupEntryType, KeyNew, Status)
{
}
ENTRY_GROUP_ITEM *
First(
)
{
return((ENTRY_GROUP_ITEM * ) TheItemList().First());
}
friend ostream& operator << (ostream&, ENTRY_GROUP_NODE&);
friend class EnteryGroupItem;
};
/*++
Class Definition:
ENTRY_GROUP_ITEM
Abstract:
This is a group entry member item. Group are simply a list of entry
names that reference other entry objects. The links are symbolic
references, not pointer values.
--*/
class ENTRY_GROUP_ITEM: public ENTRY_BASE_ITEM {
private:
UNICODE_ARRAY Member; // Entry Name of the member.
public:
ASSERT_CLASS;
ENTRY_GROUP_ITEM (
IN TYPE_ENTRY_ITEM TypeNew,
IN PUZ MemberBinding,
OUT STATUS *Status
);
virtual ~ENTRY_GROUP_ITEM(
);
// Compare this item with an other group member.
int
Compare (
IN ENTRY_GROUP_ITEM * GroupItem
)
{
return (CmpUZ(Member.pCur(), GroupItem->Member.pCur()));
}
// Compare this item with a unicode string for identity.
int
Compare (
IN PUZ Name
)
{
return (CmpUZ(Member.pCur(), Name));
}
ACCESSOR(UNICODE_ARRAY, Member);
virtual MATCH_RETURN
MatchItem(
IN OUT QUERY *SearchSpec
);
virtual int
Marshall(
OUT PB Buffer,
IN OUT long UNALIGNED *cbBuffer
);
virtual ostream&
Format(
IN OUT ostream&
);
ENTRY_GROUP_ITEM *
Next(
)
{
return((ENTRY_GROUP_ITEM * ) ENTRY_BASE_ITEM::Next());
}
friend ostream& operator << (ostream&, ENTRY_GROUP_ITEM&);
};
STATUS
InsertGroupEntry(
IN ENTRY_KEY *Entry,
IN ENTRY_GROUP_ITEM *GroupItem
);
/*++
Class Definition:
REPLY_BASE_ITEM
Abstract:
All replies are kept in a LinkList. There is a base reply type
which is used to derive several different kinds of replies in progress.
Each derived REPLY_BASE must implement the virtual functions Free and Discard.
--*/
/* State of the Query in a lookup operation. */
typedef enum {
InitialQuery, /* First query has been made */
FinialQuery, /* Finial query made, no more allowed */
ReRunQuery /* Rerun the query */
}REPLY_STATE;
NEW_LINK_LIST(REPLY_BASE,
protected:
long pidOwner; /* owner of the resource */
QUERY * aQuery; /* QUERY for lookup */
REPLY_STATE QueryMade; /* QUERY has been made */
public:
REPLY_BASE_ITEM();
~REPLY_BASE_ITEM();
BOOL
AssertHandle(
);
/* Set the cache discard age for a query. */
void SetExpiration(
IN unsigned long Time
)
{
aQuery->TheExpirationTime() = Time;
/* If the "Next" operation hasn't been called, rerun the query. */
if (QueryMade == InitialQuery) {
FreeQueryResult();
QueryMade = ReRunQuery;
}
}
/* Get the next item in the query reply. */
ENTRY_BASE_ITEM *
NextBaseItem(
)
{
return(aQuery->NextReply());
}
STATUS
PerformQueryIfNeeded(
BOOL fFirstTime
);
void
FreeQueryResult(
);
virtual BOOL
Discard(
IN ENTRY_BASE_ITEM *BaseItem
);
virtual BOOL
UpdateObject(
IN ENTRY_SERVER_NODE *Entry,
IN int Index
);
)
extern REPLY_BASE_LIST RPRoot; // Global list of replies from this root.
inline
REPLY_BASE_ITEM::REPLY_BASE_ITEM(
)
/*++
Routine Description:
Construct a base REPLY_BASE_ITEM object. Link this object into the
global list of replies.
--*/
{
QueryMade = InitialQuery;
aQuery = NIL;
pidOwner = (long) this;
RPRoot.Append(this);
}
/*++
Class Definition:
REPLY_SERVER_ITEM
Abstract:
This a reply object for a server entry based query. It contains
additional state to interate through the replies formain the
cross product of the reply list and object vector.
--*/
NEW_LINK_LIST_CLASS(REPLY_SERVER, REPLY_BASE,
private:
unsigned int VectorSize; /* Vector size to return */
unsigned int fAllObjects; /* Include all objects in response */
UUID_ARRAY_ITER ObjectCur; /* Iterator for current object */
public:
REPLY_SERVER_ITEM(
IN QUERY_SERVER * aQueryNew,
IN BOOL fAllObjectsNew = FALSE,
IN int VectorSizeNew = 0
)
{
aQuery = aQueryNew; /* BUGBUG glock c++: base should require this */
VectorSize = VectorSizeNew;
fAllObjects = fAllObjectsNew;
}
STATUS
PerformQueryIfNeeded(
BOOL fFirstTime
);
ENTRY_SERVER_ITEM *
NextBindingAndObject(
OUT NS_UUID ** Object
);
BOOL
NextObject(
OUT NS_UUID ** Object
)
{
return((!ObjectCur)? FALSE:
(*Object = &*ObjectCur, ++ObjectCur, TRUE));
}
ACCESSOR(unsigned int, VectorSize);
virtual BOOL
Discard(
IN ENTRY_BASE_ITEM *BaseItem
);
virtual BOOL
UpdateObject(
IN ENTRY_SERVER_NODE *Entry,
IN int Index
);
)
/*++
Class Definition:
REPLY_GROUP_ITEM
Abstract:
This a reply object for a group entry based query. Only group
items will be in the reply list.
--*/
NEW_LINK_LIST_CLASS(REPLY_GROUP, REPLY_BASE,
public:
REPLY_GROUP_ITEM(
IN QUERY_GROUP * aQueryNew
)
{
aQuery = aQueryNew; /* BUGBUG glock c++: base should require this */
}
)
#endif // _PROTOCOL_