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.
 
 
 
 
 
 

2122 lines
44 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
worker.c
Abstract:
This file contains the real stuff for the EP Mapper.
Author:
Bharat Shah (barat) 17-2-92
Revision History:
--*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sysinc.h>
#include <rpc.h>
#include <rpcndr.h>
#include "epmp.h"
#include "eptypes.h"
#include "local.h"
#include "twrproto.h"
#define EP_S_DUPLICATE_ENTRY 0x16c9a0d8
UUID MgmtIf = {0xafa8bd80, 0x7d8a, 0x11c9,
{ 0xbe, 0xf4, 0x08, 0x00, 0x2b, 0x10, 0x29, 0x89}};
void
DeletePSEP(
PIFOBJNode Node,
char * Protseq,
char * Endpoint
);
void
PurgeOldEntries(
PIFOBJNode Node,
PPSEPNode List,
BOOL StrictMatch
);
RPC_STATUS
MatchPSAndEP (
PPSEPNode Node,
void *Pseq,
void * Endpoint,
unsigned long Version
);
PPSEPNode
FindPSEP (
register PPSEPNode List,
char * Pseq,
char * Endpoint,
unsigned long Version,
PFNPointer2 Compare
);
PIFOBJNode
FindIFOBJNode(
register PIFOBJNode List,
UUID * Obj,
UUID * IF,
unsigned long Version,
unsigned long Inq,
unsigned long VersOpts,
PFNPointer Compare
);
PIENTRY
MatchByKey(
register PIENTRY pList,
unsigned long key
)
/*++
Routine Description:
This routine Seqrches the Link-list of IF-OBJ nodes based on
key supplied.
Arguments:
List - The Linked list [head] - to be searched
key - The Id
Return Value:
Returns a pointer to the matching IFObj node in the list or returns NULL.
--*/
{
CheckInSem();
for (; pList && pList->Id < key; pList = pList->Next)
{
;
}
return(pList);
}
//#ifdef CONNIE_ONLY
RPC_STATUS RPC_ENTRY
GetForwardEp(
UUID *IfId,
RPC_VERSION * IFVersion,
UUID *Object,
unsigned char * Protseq,
void * * EpString
)
/*++
Routine Description:
Server rutime has received a pkt destined for a dynamically
declared endpoint. Epmapper must return the servers endpoint
to enable the runtime to correctly forward the pkt.
Arguments:
IF - Server Interface UUID
IFVersion - Version of the Interface
Obj - UUID of the Object
Protseq - Ptotocol sequence the interface is using.
EpString - Place to store the endpoint structure.
Return Value:
Returns a pointer to a string containing the server's endpoint.
RPC_S_OUT_OF_MEMORY
EPT_S_NOT_REGISTERED
---*/
{
PIFOBJNode pNode;
PPSEPNode pPSEPNode;
unsigned short len;
char * String;
PFNPointer Match;
unsigned long Version = VERSION(IFVersion->MajorVersion,
IFVersion->MinorVersion);
unsigned long InqType;
if (memcmp((char *)IfId, (char *)&MgmtIf, sizeof(UUID)) == 0)
{
InqType = RPC_C_EP_MATCH_BY_OBJ;
Match = SearchIFObjNode;
}
else
{
InqType = 0;
Match = WildCardMatch;
}
*EpString = 0;
EnterSem();
pNode = IFObjList;
if (pNode == 0)
{
LeaveSem();
return(EPT_S_NOT_REGISTERED);
}
while (pNode != 0)
{
pNode = FindIFOBJNode(pNode, Object, IfId, Version,
InqType, 0, Match);
if (pNode == 0)
{
LeaveSem();
return(EPT_S_NOT_REGISTERED);
}
pPSEPNode = pNode->PSEPlist;
pPSEPNode = FindPSEP(pPSEPNode, Protseq, NULL, 0L, MatchPSAndEP);
if (pPSEPNode == 0)
{
pNode = pNode->Next;
if (pNode == 0)
{
LeaveSem();
return(EPT_S_NOT_REGISTERED);
}
continue;
}
//Ok We have a PSEPNode
//We just ought to return the first one!
//Use I_RpcAllocate To Allocate because runtime will free this!
String = I_RpcAllocate( len = (strlen(pPSEPNode->EP) + 1) );
if (String == 0)
{
LeaveSem();
return(RPC_S_OUT_OF_MEMORY);
}
memset(String, len, 0);
memcpy(String, pPSEPNode->EP, len);
*EpString = String;
LeaveSem();
return(RPC_S_OK);
}
}
//#endif
RPC_STATUS
SearchIFObjNode(
PIFOBJNode pNode,
UUID *Object,
UUID *IfUuid,
unsigned long Version,
unsigned long InqType,
unsigned long VersOption
)
/*++
Routine Description:
This routine Seqrches the Link-list of IF-OBJ nodes based on
Obj, IFUuid, IFVersion, Inqtype [Ignore OBJ, IgnoreIF, etc],
and VersOption [Identical Ver, Compatible Vers. etc]
Arguments:
List - The Linked list head - to be searched
Obj - UUID of the Object
IF - Interface UUID
Version - Version of the Interface
InqType - Type of Inquiry [Filter options based on IF/Obj/Both
VersOpts - Filter options based on Version
Return Value:
Returns a pointer to the matching IFObj node in the list or returns NULL.
--*/
{
switch (InqType)
{
case RPC_C_EP_ALL_ELTS :
return 0;
case RPC_C_EP_MATCH_BY_BOTH:
if ( memcmp((char *)&pNode->ObjUuid,
(char *)Object, sizeof(UUID)) )
return(1);
//Intentionally Fall through ..
case RPC_C_EP_MATCH_BY_IF:
return(!
((!memcmp((char *)&pNode->IFUuid,
(char *)IfUuid, sizeof(UUID)))
&&(
( (VersOption == RPC_C_VERS_UPTO)
&& pNode->IFVersion <= Version )
|| ( (VersOption == RPC_C_VERS_COMPATIBLE)
&&((pNode->IFVersion & 0xFFFF0000) ==
(Version & 0xFFFF0000))
&& (pNode->IFVersion >= Version) )
|| ( (VersOption == RPC_C_VERS_EXACT)
&& (pNode->IFVersion == Version) )
|| (VersOption == RPC_C_VERS_ALL)
|| ( (VersOption == RPC_C_VERS_MAJOR_ONLY)
&&((pNode->IFVersion & 0xFFFF0000L)
== (Version & 0xFFFF0000L)) )
|| ( (VersOption ==
I_RPC_C_VERS_UPTO_AND_COMPATIBLE)
&&((pNode->IFVersion & 0xFFFF0000L)
== (Version & 0xFFFF0000L))
&& (pNode->IFVersion <= Version) )
)
)
);
case RPC_C_EP_MATCH_BY_OBJ:
return(
memcmp((char *)&pNode->ObjUuid,
(char *)Object, sizeof(UUID))
);
}
}
PIFOBJNode
FindIFOBJNode(
register PIFOBJNode List,
UUID * Obj,
UUID * IF,
unsigned long Version,
unsigned long Inq,
unsigned long VersOpts,
PFNPointer Compare
)
/*++
Routine Description:
This routine Seqrches the Link-list of IF-OBJ nodes based on
Obj and IF specified.
Arguments:
List - The Linked list head - to be searched
Obj - UUID of the Object
IF - Interface UUID
Version - Version of the Interface
Inq - Type of Inquiry [Filter based on IF/OB/Both]
VersOpt - Filter based on version [<=, >=, == etc]
Compare() - A pointer to function used for searching.
WildCardMatch or ExactMatch.
Return Value:
Returns a pointer to the matching IFObj node in the list or returns NULL.
--*/
{
CheckInSem();
for (; (List !=NULL) && (*Compare)(List, Obj, IF, Version, Inq, VersOpts);
List = List->Next)
{
;
}
return (List);
}
PPSEPNode
FindPSEP (
register PPSEPNode List,
char * Pseq,
char * Endpoint,
unsigned long Version,
PFNPointer2 Compare
)
/*++
Routine Description:
This routine Seqrches the Link-list of PSEP nodes based on
Protocol sequence and Endpoint specified.
Arguments:
List - The Linked list head - to be searched
Pseq - Protocol sequence string specified
Endpoint - Endpoint string specified
Version - Version of the Interface
Compare() - A pointer to function used for searching.
Return Value:
Returns a pointer to the matching PSEP node in the list or returns NULL.
--*/
{
CheckInSem();
for (; List && (*Compare)(List, Pseq, Endpoint, Version); List = List->Next)
{
;
}
return (List);
if (Version) ; // May need this if we overload FindNode and collapese
//FindPSEP and FindIFOBJ
}
RPC_STATUS
ExactMatch(
PIFOBJNode Node,
UUID *Obj,
UUID *IF,
unsigned long Version,
unsigned long InqType,
unsigned long VersOptions
)
/*++
Routine Description:
This routine compares a Node in the IFOBJList to [Obj, IF, Version] triple
and returns 0 if there is an exact match else returns 1
Arguments:
Node - An IFOBJ node
Obj - UUID of the Object
IF - Interface UUID
Version - Version of the Interface
Return Value:
Returns 0 if there is an exact match; 1 otherwise
--*/
{
return((memcmp(&Node->ObjUuid, Obj,sizeof(UUID))
|| memcmp(&Node->IFUuid, IF, sizeof(UUID))
|| (Node->IFVersion != Version)));
}
RPC_STATUS
WildCardMatch (
PIFOBJNode Node,
UUID *Obj,
UUID *IF,
unsigned long Version,
unsigned long InqType,
unsigned long VersOptions
)
/*++
Routine Description:
This routine compares a Node in the IFOBJList to [Obj, IF, Version] triple
and returns 0 if there is an exact match or if registered IF-Obj node
has a NULL Obj UUid and version of the registed IF_Obj is >= that
supplied
Arguments:
Node - An IFOBJ node
Obj - UUID of the Object
IF - Interface UUID
Version - Version of the Interface
Return Value:
Returns 0 if there is a wild card match ; 1 otherwise
--*/
{
if ( (!memcmp(&Node->IFUuid, IF, sizeof(UUID)))
&& ( (Node->IFVersion & 0xFFFF0000L) == (Version & 0xFFFF0000L))
&& (Node->IFVersion >= Version)
&& ( (!memcmp(&Node->ObjUuid, Obj, sizeof(UUID)))
|| (IsNullUuid(&Node->ObjUuid)) ) )
{
return(0);
}
return(1);
}
RPC_STATUS
MatchPSAndEP (
PPSEPNode Node,
void *Pseq,
void * Endpoint,
unsigned long Version
)
/*++
Routine Description:
This routine Matches A Node on PSEP list with given Protseq and Endpoint
If Pseq is given pseqs are matched, if Endpoint is given Endpoints
are matched, if neither is given returns true, if both are given
both are matched.
Arguments:
Node - A PSEP node on PSEP list.
Pseq - Protocol Sequence string
Endpoint - Endpoint string
Return Value:
Returns 0 if Matched successfully, 1 otherwise.
--*/
{
// These hacks were needed to get this file to build for Chicago
// without using CRTDLL.
// BUGBUG: Add a new Macro to sysinc.h for StringCompare
#ifdef NTENV
return ( (Pseq && stricmp(Node->Protseq, Pseq))
|| (Endpoint && stricmp(Node->EP, Endpoint)) );
#endif
#ifdef DOSWIN32RPC
return ( (Pseq && lstrcmpi(Node->Protseq, Pseq))
|| (Endpoint && lstrcmpi(Node->EP, Endpoint)) );
#endif
}
/*
More Dead Code
void
DeleteAll(
UUID *Object,
UUID *Interface,
unsigned long IFVersion
)
/*
/*++
Routine Description:
This routine finds an IFOBJ Node that exactly matches ObjUuid,
IfUuid and IFVersion supplied. It then deletes the entire PSEPlist
of that IFOBJNode.
Arguments:
Obj - UUID of the Object
IF - Interface UUID
Version - Version of the Interface
Return Value:
Nothing
--*/
/*
{
PPSEPNode list, node;
PIFOBJNode pNode;
pNode = FindIFOBJNode(IFObjList, Object, Interface,
IFVersion, 0L, 0L, ExactMatch);
if ((pNode == NULL) || ((list = pNode->PSEPlist) == NULL))
{
return;
}
while (node = list)
{
list = list->Next;
node->Signature = FREE;
FreeMem(node, node->Cb);
}
pNode->PSEPlist = NULL;
}
*/
void
PurgeOldEntries(
PIFOBJNode Node,
PPSEPNode List,
BOOL StrictMatch
)
{
PPSEPNode Tmp, X;
char * Endpoint = 0;
CheckInSem();
Tmp = Node->PSEPlist;
while (Tmp != 0)
{
if (StrictMatch == TRUE)
Endpoint = Tmp->EP;
if (X = FindPSEP(List, Tmp->Protseq, Endpoint, 0L, MatchPSAndEP))
{
X = Tmp;
Tmp = Tmp->Next;
UnLinkFromPSEPList(&Node->PSEPlist, X);
X->Signature = FREE;
FreeMem(X, X->Cb);
}
else
{
Tmp = Tmp->Next;
}
}
}
RPC_STATUS
IsNullUuid (
UUID * Uuid
)
/*++
Routine Description:
This routine checks if a UUID is Nil
Arguments:
Uuid - UUID to be tested
Return Value:
Returns 1 if it is a Nil UUID
0 otherwise.
--*/
{
unsigned long PAPI * Vector;
Vector = (unsigned long PAPI *) Uuid;
if ( (Vector[0] == 0)
&& (Vector[1] == 0)
&& (Vector[2] == 0)
&& (Vector[3] == 0))
return(1);
return(0);
}
twr_p_t
NewTower(
twr_p_t Tower
)
/*++
Routine Description:
This routine returns a New, Duplicated tower
Arguments:
Tower - The tower that needs to be duplicated.
Return Value:
Retunes a pointer to a new tower if successful else returns
NULL
--*/
{
unsigned short len;
twr_p_t NewTower;
len = sizeof(Tower->tower_length) + Tower->tower_length;
if ( (NewTower = MIDL_user_allocate(len)) != NULL )
{
memcpy((char *)NewTower, (char *)Tower, len);
}
return(NewTower);
}
PSAVEDCONTEXT
GetNewContext(
unsigned long Type
)
/*++
Routine Description
++*/
{
PSAVEDCONTEXT Context;
if ( ((Context = AllocMem(sizeof(SAVEDCONTEXT))) == 0) )
return 0;
memset(Context, 0, sizeof(SAVEDCONTEXT));
Context->Cb = sizeof(SAVEDCONTEXT);
Context->Type = Type;
EnLinkContext(Context);
return(Context);
}
RPC_STATUS
AddToSavedContext(
PSAVEDCONTEXT Context,
PIFOBJNode Node,
PPSEPNode Psep,
unsigned long Calltype
)
{
void * NewNode;
unsigned long Size;
unsigned long TowerSize;
ASSERT(Calltype == Context->Type);
switch (Calltype)
{
case EP_MAP:
Size = sizeof(SAVEDTOWER) ;
if ( (NewNode = AllocMem(Size)) == 0 )
return(RPC_S_OUT_OF_MEMORY);
memset(NewNode, 0, Size);
((PSAVEDTOWER)NewNode)->Cb = Size;
((PSAVEDTOWER)NewNode)->Signature = 0xCBBCCBBC;
((PSAVEDTOWER)NewNode)->Tower = NewTower(Psep->Tower);
break;
case EP_LOOKUP:
Size = sizeof(SAVED_EPT) + strlen(Node->Annotation) + 1;
if ( (NewNode = AllocMem(Size)) == 0 )
return(RPC_S_OUT_OF_MEMORY);
memset(NewNode, 0, Size);
((PSAVED_EPT)NewNode)->Cb = Size;
((PSAVED_EPT)NewNode)->Signature = 0xABBAABBA;
((PSAVED_EPT)NewNode)->Tower = NewTower(Psep->Tower);
((PSAVED_EPT)NewNode)->Annotation = (char *)NewNode + sizeof(SAVED_EPT);
memcpy( (char *) &((PSAVED_EPT)NewNode)->Object,
(char *)&Node->ObjUuid,
sizeof(UUID)
);
strcpy(((PSAVED_EPT)NewNode)->Annotation, Node->Annotation);
break;
default:
ASSERT(!"Unknwon lookup type\n");
break;
}
Link((PIENTRY *)(&Context->List), NewNode);
return(RPC_S_OK);
}
RPC_STATUS
GetEntriesFromSavedContext(
PSAVEDCONTEXT Context,
char * Buffer,
unsigned long Requested,
unsigned long *Returned
)
{
PIENTRY SavedEntry = (PIENTRY)Context->List;
PIENTRY TmpEntry;
unsigned long Type = Context->Type;
while ( (*Returned < Requested) && (SavedEntry != 0) )
{
switch (Type)
{
case EP_MAP:
((I_Tower *)Buffer)->Tower = ((PSAVEDTOWER)SavedEntry)->Tower;
Buffer = Buffer + sizeof(I_Tower);
break;
case EP_LOOKUP:
((ept_entry_t *)Buffer)->tower = ((PSAVED_EPT)SavedEntry)->Tower;
strcpy(((ept_entry_t *)Buffer)->annotation,
((PSAVED_EPT)SavedEntry)->Annotation);
memcpy(Buffer,(char *)&((PSAVED_EPT)SavedEntry)->Object,
sizeof(UUID));
Buffer = Buffer + sizeof(ept_entry_t);
break;
default:
ASSERT(!"Unknown Inquiry Type");
break;
}
(*Returned)++;
TmpEntry = SavedEntry;
SavedEntry = SavedEntry->Next;
UnLink((PIENTRY *)&Context->List, TmpEntry);
FreeMem(TmpEntry, TmpEntry->Cb);
}
return(RPC_S_OK);
}
RPC_STATUS
GetEntries(
UUID *ObjUuid,
UUID *IFUuid,
unsigned long Version,
char * Pseq,
unsigned long *key,
char * Buffer,
unsigned long Calltype,
unsigned long Requested,
unsigned long *Returned,
unsigned long InqType,
unsigned long VersOptions,
PFNPointer Match
)
/*++
Routine Description:
This is a generic routine for retreiving a series [as spec. by Requested]
of Towers (in case of Map) or ept_entry_t's in case of Lookup.
Arguments:
ObjUuid - Object Uuid
IfUuid - Interface Uuid
Version - InterfaceVersion [hi ushort = VerMajor, lo ushort VerMinor]
Protseq - An ascii string specifying the protocol seq.
key - A resume key - If NULL, search is started from the beginning
if non-null, represents an encoding from where the epmapper
is supposed to start searching. It is an opaque value
as far as the client is concerned.
Buffer - A buffer of entries returned
Calltype - A flag to indicate whether Ep_entries or string bindings
are to be returned.
Requested - Max no. of entries requested
Returned - Actual no of entroes returned
Return Value:
RPC_S_OUT_OF_MEMORY
RPC_S_OK
EP_S_NOT_REGISTERED
--*/
{
PIFOBJNode pNode=NULL, pList = IFObjList;
unsigned long err=0, fResumeNodeFound=0;
PPSEPNode pPSEPNode;
char * buffer = Buffer;
PSAVEDCONTEXT Context = (PSAVEDCONTEXT) *key;
*Returned = 0;
EnterSem();
if (*key)
{
if (*key == 0xFFFFFFFFL)
{
*key = 0;
LeaveSem();
return(EP_S_NOT_REGISTERED);
}
err = GetEntriesFromSavedContext(Context, Buffer, Requested, Returned);
if (Context->List == 0)
{
UnLink((PIENTRY *)&GlobalContextList, (PIENTRY)Context);
FreeMem(Context, Context->Cb);
//Setting the Key To FFFFFFFFL is a hack for down level
//Version 1.0 Ep Clients who never expected getting a key 0
//and Success!
if (Requested <= 1)
*key = 0xFFFFFFFFL;
else
*key = 0L;
LeaveSem();
return(err);
}
LeaveSem();
return(err);
}
*key = 0;
while ( (!err) )
{
if ( (pNode = FindIFOBJNode(pList, ObjUuid, IFUuid,
Version, InqType, VersOptions, Match)) == 0)
{
break;
}
pPSEPNode = pNode->PSEPlist;
while (pPSEPNode != 0)
{
if ( (pPSEPNode=FindPSEP(pPSEPNode, Pseq, NULL, 0L, MatchPSAndEP))
== 0)
break;
if (*Returned < Requested)
{
PackDataIntoBuffer(&buffer, pNode, pPSEPNode, Calltype);
(*Returned)++;
}
else
{
if (Context == 0)
{
*key = (unsigned long) (Context = GetNewContext(Calltype));
if (Context == 0)
{
err == RPC_S_OUT_OF_MEMORY;
break;
}
}
AddToSavedContext(Context, pNode, pPSEPNode, Calltype);
}
pPSEPNode = pPSEPNode->Next;
} //While - over PSEPList
pList = pNode->Next;
} //While - over IFOBJList
LeaveSem();
if ( (*Returned == 0) && Requested && (!err) )
{
err = EP_S_NOT_REGISTERED;
}
if ( (*Returned <= Requested) && (Context == 0) )
{
if (Requested <= 1)
*key = 0xFFFFFFFFL;
else
*key = 0L;
}
return(err);
}
void
PackDataIntoBuffer(
char * * Buffer,
PIFOBJNode Node,
PPSEPNode PSEP,
unsigned long Type)
{
/*++
Routine Description:
This routine copies 1 entry [Either a Tower or ept_entry]
in the Buffer, increments buffer appropriately.
Arguments:
BindingHandle - An explicit binding handle to the EP.
Node - IFOBJNode
PSEP - PSEPNode
Type - Type of entry to be copied
Return Value:
Nothing
--*/
I_Tower * Twr;
ept_entry_t *p;
switch (Type)
{
case EP_MAP:
Twr = (I_Tower *)(* Buffer);
Twr->Tower = NewTower(PSEP->Tower);
* Buffer += sizeof(I_Tower);
break;
case EP_LOOKUP:
p = (ept_entry_t *)(*Buffer);
memcpy( *Buffer, (char *)&Node->ObjUuid, sizeof(UUID) );
strcpy(p->annotation, Node->Annotation);
p->tower = NewTower(PSEP->Tower);
*Buffer += sizeof(ept_entry_t);
break;
default:
break;
}
}
/*
DeadCode
RPC_STATUS
ep_insert_x(
UUID *Object,
UUID *Interface,
unsigned long IFVersion,
twr_t * Tower,
char PAPI * Protseq,
char PAPI * Endpoint,
char PAPI * Annotation
)
*/
/*++
Routine Description:
This routine adds an endpoint to the epmapper database.
Arguments:
BindingHandle - An explicit binding handle to the EP.
Object - Object Uuid.
Interface - If Uuid
IFVersion - Version of the IF [Hi ushort=Major, Lo ushort=Minor]
Tower - A Tower representation of the Endpoint/Protseq which is stored
Protseq - Protocol Sequence
Endpooint - Endpoint string
Annotation - Annotation.
Return Value:
RPC_S_OUT_OF_MEMORY
RPC_S_OK - Endpoint was successfully added.
EPT_S_INVALID_ENTRY - This endpoint already exists in the database,
or an incorrect endpoint was added
EPT_S_CANT_PERFORM_OP - MaxRequested value exceed ep_max_lookup_results
--*/
/*
{
PIFOBJNode pNode;
PPSEPNode pPSEPNode = NULL;
unsigned long cb, err =0;
PEP_T p;
if (!Protseq || !Endpoint)
{
return(EPT_S_INVALID_ENTRY);
}
CheckInSem();
if ( (pNode = FindIFOBJNode(IFObjList, Object, Interface,
IFVersion, 0L, 0L, ExactMatch)) == NULL )
{
cb = sizeof(IFOBJNode);
cb += strlen(Annotation) + 1;
if ( (pNode = AllocMem(cb)) == NULL )
{
return(RPC_S_OUT_OF_MEMORY);
}
memset(pNode, 0, cb);
pNode->Cb = cb;
pNode->Signature = IFOBJSIGN;
memcpy((char *)&pNode->ObjUuid, (char *)Object, sizeof(UUID));
memcpy((char *)&pNode->IFUuid, (char *)Interface, sizeof(UUID));
pNode->IFVersion = IFVersion;
strcpy((pNode->Annotation=(char *)(pNode+1)), Annotation);
if (IsNullUuid(Object))
pNode->IFOBJid = MAKEGLOBALIFOBJID(MAXIFOBJID);
else
pNode->IFOBJid = MAKEGLOBALIFOBJID(GlobalIFOBJid--);
if (pNode->IFOBJid == 0xFF000000L)
LinkAtEnd(&IFObjList, pNode);
else
EnLinkOnIFOBJList(pNode);
}
if (pNode->PSEPlist != NULL)
{
pPSEPNode=FindPSEP(pNode->PSEPlist, Protseq, Endpoint,0L,MatchPSAndEP);
}
if (pPSEPNode != NULL)
{
err = EP_S_DUPLICATE_ENTRY;
}
else
{
cb = sizeof(PSEPNode) +
strlen(Protseq) +
strlen(Endpoint) +
2 + //for the 2 null terminators
Tower->tower_length +
sizeof(Tower->tower_length) +
4; //We need to align tower on DWORD
if ( (pPSEPNode = AllocMem(cb)) == NULL )
{
return (RPC_S_OUT_OF_MEMORY);
}
memset(pPSEPNode, 0, cb);
pPSEPNode->Signature = PSEPSIGN;
pPSEPNode->Cb = cb;
strcpy(pPSEPNode->Protseq=((char *) (pPSEPNode+1)), Protseq);
pPSEPNode->EP = pPSEPNode->Protseq + strlen(pPSEPNode->Protseq)+1;
strcpy(pPSEPNode->EP, Endpoint);
pPSEPNode->Tower =
(twr_t PAPI *)(pPSEPNode->EP + strlen(pPSEPNode->EP) + 1);
(char PAPI *)(pPSEPNode->Tower)
+= 4 - ((unsigned long)(pPSEPNode->Tower) & 3);
memcpy((char PAPI *)pPSEPNode->Tower, Tower,
Tower->tower_length + sizeof(Tower->tower_length));
pPSEPNode->PSEPid = MAKEGLOBALEPID(pNode->IFOBJid, GlobalEPid--);
EnLinkOnPSEPList(&pNode->PSEPlist, pPSEPNode);
}
return(err);
}
*/
RPC_STATUS
ep_delete_x(
UUID *Object,
UUID *Interface,
unsigned long IFVersion,
char PAPI * Protseq,
char PAPI * Endpoint
)
/*++
Routine Description:
This routine deletes an Endpoint registered with the epmapper
Arguments:
BindingHandle - An explicit binding handle to the EP.
Object - Object Uuid.
Interface - If Uuid
IFVersion - Version of the IF [Hi ushort=Major, Lo ushort=Minor]
Protseq - Protocol Sequence
Endpooint - Endpoint string
Return Value:
RPC_S_OK - The endpoint was successfully deleted
EPT_S_NOT_REGISTERED - No matching entries were found
--*/
{
PIFOBJNode pNode;
PPSEPNode pPSEPNode = NULL;
unsigned long cb, err = 0;
PEP_T p;
if (!Protseq || !Endpoint)
{
return(EPT_S_NOT_REGISTERED);
}
CheckInSem();
pNode = FindIFOBJNode(IFObjList, Object, Interface, IFVersion,
0L, 0L, ExactMatch);
if ((pNode != NULL) && (pNode->PSEPlist != NULL))
{
pPSEPNode=FindPSEP(pNode->PSEPlist, Protseq, Endpoint,
0L,MatchPSAndEP);
}
if (pPSEPNode != NULL)
{
UnLinkFromPSEPList(&pNode->PSEPlist, pPSEPNode);
pPSEPNode->Signature = FREE;
FreeMem(pPSEPNode, pPSEPNode->Cb);
if (pNode->PSEPlist == NULL)
{
UnLinkFromIFOBJList(pNode);
pNode->Signature = FREE;
FreeMem(pNode, pNode->Cb);
}
}
else
{
err = EPT_S_NOT_REGISTERED;
}
return(err);
}
void
ept_insert(
handle_t h,
unsigned32 NumEntries,
ept_entry_t Entries[],
unsigned long Replace,
error_status *Status
)
/*++
Routine Description:
This is the exposed rpc interface routine that adds a series of
Endpoins to the Map.
Arguments:
BindingHandle - An explicit binding handle to the EP.
NumEntries - Number of Entries to be added
Entries - An array of ept_entry_t entries
Replace - TRUE => Replace existing entries.
FALSE=> Just add
Return Value:
RPC_S_OK - The endpoint was successfully deleted
RPC_S_OUT_OF_MEMORY - There is no memory to perform the op.
EPT_S_CANT_PERFORM - Invalid entry
--*/
{
ept_entry_t * Ep;
unsigned short i, j;
unsigned long err = 0;
unsigned long Version;
char *Protseq, *Endpoint;
RPC_IF_ID IfId;
PPSEPNode List = 0;
PPSEPNode pPSEPNode, TmpPsep;
unsigned long cb;
twr_t * Tower;
BOOL IFNodeFound = FALSE;
PIFOBJNode Node, NewNode, Tmp;
UUID * Object;
char * Annotation;
RPC_STATUS Err;
SECURITY_DESCRIPTOR SecurityDescriptor, * PSecurityDesc;
BOOL Bool;
EnterCriticalSection(&TableMutex);
EnterSem();
for (Ep = &Entries[0], i = 0; i < NumEntries; Ep++,i++)
{
err = TowerExplode(Ep->tower, &IfId, NULL, &Protseq, &Endpoint, 0);
if (err == RPC_S_OUT_OF_MEMORY)
break;
if (err)
{
err = RPC_S_OK;
continue;
}
Object = &Ep->object;
Annotation = (char *)&Ep->annotation;
Tower = Ep->tower;
cb = sizeof(PSEPNode) +
strlen(Protseq) +
strlen(Endpoint) +
2 + //for the 2 null terminators
Tower->tower_length +
sizeof(Tower->tower_length) +
4; //We need to align tower on DWORD
if ( (pPSEPNode = AllocMem(cb)) == NULL )
{
err = RPC_S_OUT_OF_MEMORY;
break;
}
for (j = 0; j < sizeof(EpMapperTable)/sizeof(EpMapperTable[0]); j++)
{
#ifdef NTENV
if (stricmp(EpMapperTable[j].Protseq, Protseq) == 0)
#endif
#ifdef DOSWIN32RPC
if (lstrcmpi(EpMapperTable[j].Protseq, Protseq) == 0)
#endif
{
if (EpMapperTable[j].State == NOTSTARTED)
EpMapperTable[j].State = STARTINGTOLISTEN;
break;
}
}
memset(pPSEPNode, 0, cb);
pPSEPNode->Signature = PSEPSIGN;
pPSEPNode->Cb = cb;
strcpy(pPSEPNode->Protseq=((char *) (pPSEPNode+1)), Protseq);
pPSEPNode->EP = pPSEPNode->Protseq + strlen(pPSEPNode->Protseq)+1;
strcpy(pPSEPNode->EP, Endpoint);
pPSEPNode->Tower =
(twr_t PAPI *)(pPSEPNode->EP + strlen(pPSEPNode->EP) + 1);
(char PAPI *)(pPSEPNode->Tower)
+= 4 - ((unsigned long)(pPSEPNode->Tower) & 3);
memcpy((char PAPI *)pPSEPNode->Tower, Tower,
Tower->tower_length + sizeof(Tower->tower_length));
EnLinkOnPSEPList(&List, pPSEPNode);
I_RpcFree(Protseq);
I_RpcFree(Endpoint);
}
if ( (err == RPC_S_OUT_OF_MEMORY) || (List == 0) )
{
*Status = err;
LeaveSem();
LeaveCriticalSection(&TableMutex);
return;
}
//Leave Main Sem - so lookups can proceed - keep TableMutex Locked
//So database updates are serialized
LeaveSem();
for (j = 0; j < sizeof(EpMapperTable)/sizeof(EpMapperTable[0]); j++)
{
if (EpMapperTable[j].State == STARTINGTOLISTEN)
{
#ifdef NTENV
if (stricmp(EpMapperTable[j].Protseq, "ncalrpc") == 0)
#endif
#ifdef DOSWIN32RPC
if (lstrcmpi(EpMapperTable[j].Protseq, "ncalrpc") == 0)
#endif
{
//for ncalrpc - croft up a Security Descriptor
Bool = InitializeSecurityDescriptor(
&SecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION
);
if (Bool == FALSE)
{
#if DBG
DbgPrint("RPCSS: Starting on LRPC.. \
Initialize SecDesc ret. (%d) \n", GetLastError());
#endif
continue;
}
Bool = SetSecurityDescriptorDacl (
&SecurityDescriptor,
TRUE, // Dacl present
NULL, // NULL Dacl
FALSE // Not defaulted
);
if (Bool == FALSE)
{
#if DBG
DbgPrint("RPCSS: Starting on LRPC.. \
Initialize SetSecDescDacl ret. (%d)\n",GetLastError());
#endif
continue;
}
PSecurityDesc = &SecurityDescriptor;
}
else
{
PSecurityDesc = 0;
}
Err = RpcServerUseProtseqEp(
EpMapperTable[j].Protseq,
5,
EpMapperTable[j].Endpoint,
PSecurityDesc
);
if (Err != RPC_S_OK)
{
#if DBG
DbgPrint("RPCSS: UseProtseq returned %d\n", Err);
DbgPrint("RPCSS: Couldnt Start Listening on %s\n",
EpMapperTable[j].Protseq);
#endif
EpMapperTable[j].State = NOTSTARTED;
}
else
{
EpMapperTable[j].State = STARTED;
}
}
}
EnterSem();
Version = VERSION(IfId.VersMajor, IfId.VersMinor);
if (Replace == TRUE)
{
Node = IFObjList;
while (Node != 0)
{
Node = FindIFOBJNode(
Node,
Object,
&IfId.Uuid,
Version,
RPC_C_EP_MATCH_BY_BOTH,
I_RPC_C_VERS_UPTO_AND_COMPATIBLE,
SearchIFObjNode
);
if (Node == 0)
break;
PurgeOldEntries(Node, List, FALSE);
if (Node->IFVersion == Version)
{
IFNodeFound = TRUE;
//Seek to the end of Tmp and then Link
TmpPsep = List;
while (TmpPsep->Next != 0)
TmpPsep = TmpPsep->Next;
TmpPsep->Next = Node->PSEPlist;
Node->PSEPlist = List;
}
if (Node->PSEPlist == 0)
{
Tmp = Node;
Node = Node->Next;
UnLinkFromIFOBJList(Tmp);
Tmp->Signature = FREE;
FreeMem(Tmp, Tmp->Cb);
}
else
{
Node = Node->Next;
}
} //.. while loop
} //..if Replace == TRUE
if (Replace != TRUE)
{
NewNode = FindIFOBJNode(IFObjList, Object, &IfId.Uuid,
Version, 0, 0, ExactMatch);
if (NewNode)
{
PurgeOldEntries(NewNode, List, TRUE);
//Seek to the end of Tmp and then Link
TmpPsep = List;
while (TmpPsep->Next != 0)
TmpPsep = TmpPsep->Next;
TmpPsep->Next = NewNode->PSEPlist;
NewNode->PSEPlist = List;
}
}
if ( ((Replace != TRUE) && (NewNode == 0))
||((Replace == TRUE) && (IFNodeFound == FALSE)) )
{
cb = sizeof(IFOBJNode);
cb += strlen(Annotation) + 1;
if ( (NewNode = AllocMem(cb)) == NULL )
{
LeaveSem();
LeaveCriticalSection(&TableMutex);
*Status = RPC_S_OUT_OF_MEMORY;
return;
}
memset(NewNode, 0, cb);
NewNode->Cb = cb;
NewNode->Signature = IFOBJSIGN;
memcpy((char *)&NewNode->ObjUuid, (char *)Object, sizeof(UUID));
memcpy((char *)&NewNode->IFUuid, (char *)&IfId.Uuid, sizeof(UUID));
NewNode->IFVersion = Version;
strcpy((NewNode->Annotation=(char *)(NewNode+1)), Annotation);
if (IsNullUuid(Object))
NewNode->IFOBJid = MAKEGLOBALIFOBJID(MAXIFOBJID);
else
NewNode->IFOBJid = MAKEGLOBALIFOBJID(GlobalIFOBJid--);
if (NewNode->IFOBJid == 0xFF000000L)
LinkAtEnd(&IFObjList, NewNode);
else
EnLinkOnIFOBJList(NewNode);
NewNode->PSEPlist = List;
}
LeaveSem();
LeaveCriticalSection(&TableMutex);
*Status = err;
}
void
ept_delete(
handle_t h,
unsigned32 NumEntries,
ept_entry_t Entries[],
error_status *Status
)
/*++
Routine Description:
This routine deletes the specified Endpoints
Arguments:
BindingHandle - An explicit binding handle to the EP.
NumEntries - #of entries in the Bunffer that need to be deleted.
Entries[] - Buffer of #NumEntries of ept_entry_t structures
Return Value:
RPC_S_OK - The endpoint was successfully deleted
EPT_S_NOT_REGISTERED - No matching entries were found
--*/
{
ept_entry_t * Ep;
unsigned short i;
RPC_STATUS err=0;
unsigned long Version;
char *Protseq, *Endpoint;
RPC_IF_ID IfId;
RPC_TRANSFER_SYNTAX XferId;
EnterSem();
for (Ep = &Entries[0], i = 0; i < NumEntries; Ep++,i++)
{
err = TowerExplode(Ep->tower, &IfId, &XferId, &Protseq, &Endpoint, 0);
if (err == RPC_S_OUT_OF_MEMORY)
break;
if (err)
continue;
Version = VERSION(IfId.VersMajor, IfId.VersMinor);
//ep_delete_x can only return ept_s_not_registered
//but dce doesnt like such errors- if an item was not registered
//and you say unregister that is success i.e.implying after api called
//item isnt registered - hence ignore the error here
ep_delete_x(&Ep->object, &IfId.Uuid, Version,
Protseq, Endpoint);
if (Protseq)
I_RpcFree(Protseq);
if (Endpoint)
I_RpcFree(Endpoint);
}
LeaveSem();
*Status = err;
}
void
ept_lookup (
handle_t hEpMapper,
unsigned32 InquiryType,
UUID * Object,
RPC_IF_ID * Ifid,
unsigned32 VersOptions,
ept_lookup_handle_t *LookupHandle,
unsigned32 MaxRequested,
unsigned32 *NumEntries,
ept_entry_t Entries[],
error_status *Status
)
/*++
Routine Description:
This routine returns upto MaxRequested, ept_entryis currently
registered with the Endpoint mapper based on the
Obj, Interface, Protocol sequence and filters VersOptions and
InqType
Arguments:
BindingHandle - An explicit binding handle to the EP.
InquiryType - Search Filter [Seach based on IF, Obj or Both]
Obj - Object Uuid. specified by the client
ObjInterface - Interface Uuid spec. by the client.
InId - The If Specification [IF Uuid+IfVersion]
VersOpts- Search Filter based on Versions [Versins <, >, ==]
MapHandle - A resume key - If NULL, search is started from the beginning
if non-null, represents an encoding from where the epmapper
is supposed to start searching. It is an opaque value
as far as the client is concerned.
MaxRequested - Max number of entries requested by the client.
Returned - The actual number of entries returned by the mapper.
Entries - Buffer of ept_entries returned,
Return Value:
RPC_S_OUT_OF_MEMORY
RPC_S_OK - At least one matching entry is being returned.
EP_S_NOT_REGISTERED - No matching entries were found
EP_S_CANT_PERFORM_OP - MaxRequested value exceed ep_max_lookup_results
--*/
{
unsigned long Version;
switch (VersOptions)
{
case RPC_C_VERS_ALL:
Version = 0;
break;
case RPC_C_VERS_COMPATIBLE:
case RPC_C_VERS_EXACT:
case RPC_C_VERS_UPTO:
Version = VERSION(Ifid->VersMajor, Ifid->VersMinor);
break;
case RPC_C_VERS_MAJOR_ONLY:
Version = VERSION(Ifid->VersMajor, 0);
break;
default:
break;
}
*Status =
GetEntries(
Object, &Ifid->Uuid, Version, NULL,
(unsigned long *)LookupHandle,
(char *)Entries, EP_LOOKUP,
MaxRequested, NumEntries,
InquiryType, VersOptions,
SearchIFObjNode
);
}
void
ept_map (
handle_t h,
UUID *Obj OPTIONAL,
twr_p_t MapTower,
ept_lookup_handle_t *MapHandle,
unsigned32 MaxTowers,
unsigned32 *NumTowers,
twr_p_t *ITowers,
error_status *Status
)
/*++
Routine Description:
This routine returns a fully-resolved string binding, for a given
Obj, Interface, and Protocol sequence if an appropriate entry is
found. Else returns EP_S_NOT_REGISTERED.
Arguments:
BindingHandle - An explicit binding handle to the EP.
Obj - Object Uuid. specified by the client
ObjInterface - Interface Uuid spec. by the client.
Interfacever - InterfaceVersion [hi ushort = VerMajor, lo ushort VerMinor]
Protseq - An ascii string specifying the protocol seq.
MapHandle - A resume key - If NULL, search is started from the beginning
if non-null, represents an encoding from where the epmapper
is supposed to start searching. It is an opaque value
as far as the client is concerned.
Binding - The fully resolved string binding returned if the call is
successful.
Return Value:
RPC_S_OUT_OF_MEMORY
RPC_S_OK
EP_S_NOT_REGISTERED
--*/
{
RPC_IF_ID Ifid;
RPC_TRANSFER_SYNTAX Xferid;
char *Protseq;
unsigned long Version;
char * String = 0;
*Status = TowerExplode(MapTower, &Ifid, &Xferid, &Protseq, NULL, 0);
Version = VERSION(Ifid.VersMajor,Ifid.VersMinor);
if (memcmp((char *)&Ifid.Uuid, (char *)&MgmtIf, sizeof(UUID)) == 0)
{
if ((Obj == 0) || IsNullUuid(Obj))
{
*NumTowers = 0;
*Status = RPC_S_BINDING_INCOMPLETE;
}
else
{
*Status = GetEntries(
Obj, &Ifid.Uuid, Version, Protseq,
(unsigned long *)MapHandle,
(char *)ITowers, EP_MAP,
MaxTowers, NumTowers,
RPC_C_EP_MATCH_BY_OBJ,
RPC_C_VERS_ALL,
SearchIFObjNode
);
}
}
else
{
*Status = GetEntries(
Obj, &Ifid.Uuid, Version, Protseq,
(unsigned long *)MapHandle,
(char *)ITowers, EP_MAP,
MaxTowers, NumTowers,
0L, 0L,
WildCardMatch
);
}
if (Protseq)
I_RpcFree(Protseq);
}
void
ept_inq_object(
handle_t BindingHandle,
UUID *Object,
error_status *status
)
/*++
Routine Description:
Not supported
Arguments:
BindingHandle - An explicit binding handle to the EP.
Object _ No idea whose UUID this is.
Return Value:
EP_S_CANT_PERFORM_OP
--*/
{
*status = EP_S_CANT_PERFORM_OP;
}
void
DeletePSEP(
PIFOBJNode Node,
char * Protseq,
char * Endpoint
)
{
PSEPNode * Psep , * Tmp;
if (Node == 0)
return;
Psep = Node->PSEPlist;
while (Psep != 0)
{
Psep = FindPSEP( Psep, Protseq, Endpoint, 0L, MatchPSAndEP );
if (Psep != 0)
{
Tmp = Psep;
Psep = Psep->Next;
UnLinkFromPSEPList(&Node->PSEPlist, Tmp);
Tmp->Signature = FREE;
FreeMem(Tmp, Tmp->Cb);
}
}
}
void
ept_mgmt_delete(
handle_t BindingHandle,
boolean32 ObjectSpecd,
UUID * Object,
twr_p_t Tower,
error_status *Error
)
/*++
Routine Description:
Not supported
Arguments:
BindingHandle - An explicit binding handle to the EP.
Object _ ObjUUid
Tower - Tower specifying the Endpoints to be deleted.
Return Value:
EP_S_CANT_PERFORM_OP
--*/
{
RPC_IF_ID IfId;
RPC_TRANSFER_SYNTAX XferId;
PIFOBJNode List, Tmp;
unsigned long Version;
char * Protseq, * Endpoint;
RPC_STATUS Status;
unsigned long InqType;
*Error = EP_S_NOT_REGISTERED;
EnterSem();
Status = TowerExplode(Tower, &IfId, &XferId, &Protseq, &Endpoint, 0);
if (Status != RPC_S_OK)
{
LeaveSem();
return;
}
Version = VERSION(IfId.VersMajor, IfId.VersMinor);
if (!ObjectSpecd)
{
Object = &NilUuid;
InqType = RPC_C_EP_MATCH_BY_IF;
}
else
{
InqType = RPC_C_EP_MATCH_BY_BOTH;
}
List = IFObjList;
while (List != 0)
{
if ( (List = FindIFOBJNode(List , Object, &IfId.Uuid,
Version, InqType, RPC_C_VERS_EXACT,
SearchIFObjNode) ) == 0 )
{
break;
}
DeletePSEP(List, Protseq, Endpoint);
*Error = RPC_S_OK;
if (List->PSEPlist == 0)
{
Tmp = List;
List = List->Next;
UnLinkFromIFOBJList(Tmp);
Tmp->Signature = FREE;
FreeMem(Tmp, Tmp->Cb);
}
else
{
List = List->Next;
}
}
I_RpcFree(Protseq);
I_RpcFree(Endpoint);
LeaveSem();
}
void ept_lookup_handle_t_rundown (ept_lookup_handle_t h)
{
PSAVEDCONTEXT Context = (PSAVEDCONTEXT) h;
PIENTRY Entry ;
unsigned long Type;
PIENTRY Tmp;
twr_t * Tower;
ASSERT (Context != 0);
if ( ((unsigned long )Context) == 0xFFFFFFFF)
return;
Type = Context->Type;
EnterSem();
Entry = (PIENTRY)Context->List;
while (Entry != 0)
{
switch (Type)
{
case EP_MAP:
Tower = ((PSAVEDTOWER)Entry)->Tower;
break;
case EP_LOOKUP:
Tower = ((PSAVED_EPT)Entry)->Tower;
break;
default:
ASSERT(!"Unknown Inquiry Type");
break;
}
FreeMem( Tower, Tower->tower_length + sizeof(Tower->tower_length ));
Tmp = Entry;
Entry = Entry->Next;
FreeMem(Tmp, Tmp->Cb);
}
//Now free The Context
UnLink((PIENTRY *)&GlobalContextList, (PIENTRY)Context);
FreeMem( (PIENTRY)Context, ((PIENTRY)Context)->Cb );
LeaveSem();
}
void
ept_lookup_handle_free(
handle_t h,
ept_lookup_handle_t * ept_context_handle,
error_status * status
)
{
if (ept_context_handle != 0)
{
ept_lookup_handle_t_rundown( *ept_context_handle );
*ept_context_handle = 0;
}
*status = 0;
}