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.
 
 
 
 
 
 

788 lines
17 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
binding.cxx
Abstract:
This file contains the code to implement the remoted API functions.
This implements the NSI binding object APIs.
Author:
Steven Zeck (stevez) 04/01/92
--*/
#include "core.hxx"
extern NSI_INTERFACE_ID_T NilNsiIfIdOnWire;
CDEF
#include "nsisvr.h"
void
nsi_binding_export(
IN UNSIGNED32 EntryNameSyntax,
IN STRING_T EntryName,
IN NSI_INTERFACE_ID_T * Interface,
IN NSI_SERVER_BINDING_VECTOR_T *BindingVector,
IN NSI_UUID_VECTOR_P_T ObjectVector, OPT
IN UNSIGNED16 * status
)
/*++
Routine Description:
Export interfaces and objects to a server entry.
Arguments:
EntryNameSyntax - Name syntax
EntryName - Name string of the entry to export
Interface - Interface unexport
BindingVector - Vector of string bindings to export.
ObjectVector - Objects to add to the entry
status - Status is returned here
Returns:
NSI_S_OK, NSI_S_UNSUPPORTED_NAME_SYNTAX, NSI_S_INCOMPLETE_NAME,
NSI_OUT_OF_MEMORY, NSI_S_INVALID_OBJECT, NSI_S_NOTHING_TO_EXPORT,
NSI_S_ENTRY_ALREADY_EXISTS
--*/
{
UUID_ARRAY ObjectDA;
DLIST(3, "binding_export\n");
// We only accept the default with with a name.
if (EntryNameSyntax != RPC_C_NS_SYNTAX_DCE) {
*status = NSI_S_UNSUPPORTED_NAME_SYNTAX;
return;
}
if (EntryName == NIL) {
*status = NSI_S_INCOMPLETE_NAME;
return;
}
if (ObjectVector && ObjectVector->count > MAX_OBJECT_SIZE) {
*status = NSI_S_INVALID_OBJECT;
return;
}
if (memcmp(Interface, &NilNsiIfIdOnWire, sizeof(NSI_INTERFACE_ID_T)) == 0)
{
Interface = (NSI_INTERFACE_ID_T *)NULL;
}
ENTRY_KEY Entry(EntryName, FALSE, status);
if (*status)
return;
// If there is a object vector, Copy it to an array of objects.
if (ObjectVector && ObjectVector->count) {
unsigned int i, j, NewCount = 1;
//First weed out any duplicates found
for (i = 1; i < ObjectVector->count; i++)
{
for (j=0; j < NewCount; j++)
{
if (!memcmp(ObjectVector->uuid[i], ObjectVector->uuid[j],
sizeof(NSI_UUID_T) ) )
break;
}
if (j == NewCount)
{
if (i > NewCount)
ObjectVector->uuid[NewCount] = ObjectVector->uuid[i];
NewCount++;
}
}
ObjectVector->count = NewCount;
ObjectDA = UUID_ARRAY(ObjectVector->count);
NS_UUID ** pGID = (NS_UUID **) ObjectVector->uuid;
for (UUID_ARRAY_ITER ODi(ObjectDA); ODi; ++ODi, ++pGID)
*ODi = **pGID;
}
if (!Interface || !BindingVector) {
// Update an Entry just with the object vectors.
if (!ObjectVector) {
*status = NSI_S_NOTHING_TO_EXPORT;
return;
}
/*
If Interface or bindingvector ar null, the call is just adding
Object Uuid vectors and we should ignore both If and BVs in that case
ENTRY_SERVER_ITEM *ServerItem = new ENTRY_SERVER_ITEM(LocalItemType,
NIL, NIL, NIL, status);
if (!ServerItem)
*status = NSI_S_OUT_OF_MEMORY;
*/
if (!*status)
*status = InsertServerEntry(&Entry, (ENTRY_SERVER_ITEM *)NULL,
&ObjectDA);
ObjectDA.Free();
return;
}
// create a new interface node in the DICT tree if there is none
for (unsigned int Index = 0;
Index < BindingVector->count && *status == NSI_S_OK;
Index++) {
ENTRY_SERVER_ITEM *ServerItem = new ENTRY_SERVER_ITEM(LocalItemType,
(NS_SYNTAX_ID *) &Interface->Interface,
(NS_SYNTAX_ID *) &Interface->TransferSyntax,
BindingVector->string[Index], status);
if (!ServerItem)
*status = NSI_S_OUT_OF_MEMORY;
if (*status)
break;
*status = InsertServerEntry(&Entry, ServerItem, &ObjectDA);
}
ObjectDA.Free();
}
void
I_nsi_binding_update_local(
IN UNSIGNED32 EntryNameSyntax,
IN STRING_T EntryName,
IN NSI_INTERFACE_ID_T * Interface,
IN NSI_SERVER_BINDING_VECTOR_T *BindingVector,
IN NSI_UUID_VECTOR_P_T ObjectVector, OPT
IN UNSIGNED16 * status
)
{
nsi_binding_export(
EntryNameSyntax,
EntryName,
Interface,
BindingVector,
ObjectVector,
status
);
}
void
nsi_mgmt_binding_unexport(
UNSIGNED32 EntryNameSyntax,
STRING_T EntryName,
NSI_IF_ID_P_T Interface,
UNSIGNED32 VersOption,
NSI_UUID_VECTOR_P_T ObjectVector,
UNSIGNED16 * status
)
/*++
Routine Description:
unExport a information from a server entry finer control then nsi_binding
counter part.
Arguments:
EntryNameSyntax - Name syntax
EntryName - Name string of the entry to unexport
Interface - Interface to unexport
VersOption - controls in fine detail which interfaces to remove.
ObjectVector - Objects to remove from the entry
status - Status is returned here
Returns:
NSI_S_OK, NSI_S_UNSUPPORTED_NAME_SYNTAX, NSI_S_INCOMPLETE_NAME,
NSI_S_INVALID_VERS_OPTION, NSI_S_ENTRY_NOT_FOUND.
NSI_S_NOTHING_TO_UNEXPORT, NSI_S_NOT_ALL_OBJS_UNEXPORTED,
NSI_S_INTERFACE_NOT_FOUND
--*/
{
ENTRY_SERVER_NODE *pEntry;
USED(ObjectVector);
DLIST(3, "binding_unexport\n");
// We only accept the default with with a name.
if (EntryNameSyntax != RPC_C_NS_SYNTAX_DCE) {
*status = NSI_S_UNSUPPORTED_NAME_SYNTAX;
return;
}
if (EntryName == NIL) {
*status = NSI_S_INCOMPLETE_NAME;
return;
}
if (VersOption > RPC_C_VERS_UPTO) {
*status = NSI_S_INVALID_VERS_OPTION;
return;
}
if (!Interface && !ObjectVector) {
*status = NSI_S_NOTHING_TO_UNEXPORT;
return;
}
CLAIM_MUTEX Update(pESaccess);
ENTRY_KEY Entry(EntryName, FALSE, status);
if (*status)
return;
if (EntryName)
DLIST(4, " On Entry: " << Entry << nl);
pEntry = (ENTRY_SERVER_NODE *)EntryDict->Find(&Entry);
if (!pEntry) {
*status = NSI_S_ENTRY_NOT_FOUND;
return;
}
if (!pEntry->IsType(ServerEntryType)) {
*status = NSI_S_NOTHING_TO_UNEXPORT;
return;
}
if (Interface && !*status) {
*status = NSI_S_INTERFACE_NOT_FOUND;
// Do a linear search for a Server entry that matches
ENTRY_SERVER_ITEM *ServerItem, *ServerItemNext;
for (ServerItem = pEntry->First(); ServerItem;
ServerItem = ServerItemNext) {
ServerItemNext = ServerItem->Next();
// Match the interface depending on the options.
if (ServerItem->TheInterfaceGID() != *(NS_UUID *)Interface)
continue;
switch (VersOption) {
case RPC_C_VERS_ALL:
break;
case RPC_C_VERS_COMPATIBLE:
if (ServerItem->TheInterface().CompatibleInterface(
*(NS_SYNTAX_ID *)Interface))
break;
continue;
case RPC_C_VERS_EXACT:
if (ServerItem->TheInterface() == *(NS_SYNTAX_ID *)Interface)
break;
continue;
case RPC_C_VERS_MAJOR_ONLY:
if (ServerItem->TheInterface().TheVersion().Major() !=
Interface->version >> 16)
break;
continue;
case RPC_C_VERS_UPTO:
if ((*(SYNTAX_VERSION *) &Interface->version) -
ServerItem->TheInterface().TheVersion() >= 0)
break;
continue;
}
// If you got here then the inteface matched, so its history.
*status = NSI_S_OK;
delete (ServerItem);
}
}
// Remove the any objects from the entry last.
if (ObjectVector && (ObjectVector->count != 0)
&& *status == NSI_S_OK
&& (pEntry = (ENTRY_SERVER_NODE *)EntryDict->Find(&Entry)))
{
unsigned int i, j, NewCount = 1;
//First weed out any duplicates found
for (i = 1; i < ObjectVector->count; i++)
{
for (j=0; j < NewCount; j++)
{
if (!memcmp(ObjectVector->uuid[i], ObjectVector->uuid[j],
sizeof(NSI_UUID_T) ) )
break;
}
if (j == NewCount)
{
if (i > NewCount)
ObjectVector->uuid[NewCount] = ObjectVector->uuid[i];
NewCount++;
}
}
ObjectVector->count = NewCount;
for (ULONG Index = 0; Index < ObjectVector->count; Index++)
if (!pEntry->DeleteObject((NS_UUID *)ObjectVector->uuid[Index]))
*status = NSI_S_NOT_ALL_OBJS_UNEXPORTED;
}
ASSERT(AssertHeap());
}
void
nsi_binding_unexport(
IN UNSIGNED32 EntryNameSyntax,
IN STRING_T EntryName,
IN NSI_INTERFACE_ID_T * Interface,
IN NSI_UUID_VECTOR_P_T ObjectVector, OPT
IN UNSIGNED16 * status
)
/*++
Routine Description:
unExport a information from a server entry..
Arguments:
EntryNameSyntax - Name syntax
EntryName - Name string of the entry to unexport
Interface - Interface to unexport
ObjectVector - Objects to remove from the entry
status - Status is returned here
Returns:
See: nsi_mgmt_binding_unexport()
--*/
{
if (memcmp(Interface, &NilNsiIfIdOnWire, sizeof(NSI_INTERFACE_ID_T)) == 0)
{
Interface = (NSI_INTERFACE_ID_T *)NULL;
}
nsi_mgmt_binding_unexport(EntryNameSyntax, EntryName,
(Interface)? &Interface->Interface: NIL,
RPC_C_VERS_EXACT, ObjectVector, status);
}
void
nsi_binding_lookup_begin(
IN UNSIGNED32 EntryNameSyntax,
IN STRING_T EntryName,
IN NSI_INTERFACE_ID_T * Interface, OPT
IN NSI_UUID_P_T Object, OPT
IN UNSIGNED32 VectorSize,
IN UNSIGNED32 Ignore,
OUT NSI_NS_HANDLE_T * InqContext,
IN UNSIGNED16 * status
)
/*++
Routine Description:
Start a lookup operation. Just save all the input params in the
newly created lookup context. Perform the initial query.
Arguments:
EntryNameSyntax - Name syntax
EntryName - Name string to lookup on.
Interface - Interface to search for
Object - Object to search for
VectorSize- Size of return vector
InqContext - Context to continue with for use with "Next"
status - Status is returned here
Returns:
NSI_S_OK, NSI_S_UNSUPPORTED_NAME_SYNTAX, NSI_S_ENTRY_NOT_FOUND,
NSI_OUT_OF_MEMORY
--*/
{
DLIST(3, "binding_lookup_begin\n");
// We only accept the default with NO name.
if (memcmp(Interface, &NilNsiIfIdOnWire, sizeof(NSI_INTERFACE_ID_T)) == 0)
{
Interface = (NSI_INTERFACE_ID_T *)NULL;
}
if (EntryNameSyntax != RPC_C_NS_SYNTAX_DCE) {
*status = NSI_S_UNSUPPORTED_NAME_SYNTAX;
return;
}
CLAIM_MUTEX Update(pESaccess);
// Allocate a search handle which is returned as the context handle.
ENTRY_KEY Entry(EntryName, TRUE, status);
if (*status)
return;
QUERY_SERVER * TheQuery = new QUERY_SERVER(&Entry,
(Interface)? (NS_SYNTAX_ID *) &Interface->Interface: &NilSyntaxID,
(Interface)? (NS_SYNTAX_ID *) &Interface->TransferSyntax: &NilSyntaxID,
(Object)? (NS_UUID *) Object: &NilGlobalID,
NS_PUBLIC_INTERFACE, status);
if (!TheQuery)
*status = NSI_S_OUT_OF_MEMORY;
if (*status)
return;
// Set the default lookup size if none is given.
if (VectorSize == 0)
VectorSize = 10;
REPLY_SERVER_ITEM *ReplyServer = new
REPLY_SERVER_ITEM(TheQuery, Object == NIL, VectorSize);
if (!ReplyServer) {
delete TheQuery;
*status = NSI_S_OUT_OF_MEMORY;
return;
}
DLIST(4, "Allocating search handle " << hex(long(ReplyServer)) << nl);
if (EntryName)
DLIST(4, " On Entry: " << Entry << nl);
if (Interface)
DLIST(4, " On Interface: " << *((NS_SYNTAX_ID *) &Interface->Interface) << nl);
if (Object)
DLIST(4, " On Object: " << *((NS_UUID *) Object) << nl);
perf.cLookUp++;
*InqContext = (NSI_NS_HANDLE_T) ReplyServer;
*status = ReplyServer->PerformQueryIfNeeded(TRUE);
// Can't return nothing found just yet...
if (*status == NSI_S_NO_MORE_MEMBERS)
*status = NSI_S_OK;
ASSERT(AssertHeap());
}
void
nsi_binding_lookup_next(
OUT NSI_NS_HANDLE_T InqContext,
OUT NSI_BINDING_VECTOR_T ** BindingVectorOut,
IN UNSIGNED16 * status
)
/*++
Routine Description:
Continue a lookup operation.
Arguments:
InqContext - Context to continue with.
BindingVectorOut - Pointer to return new vector of bindings
status - Status is returned here
Returns:
NSI_S_OK, NSI_OUT_OF_MEMORY, NSI_S_NO_MORE_BINDINGS,
NSI_S_INVALID_NS_HANDLE
--*/
{
DLIST(3, "binding_lookup_next\n");
REPLY_SERVER_ITEM *ReplyServer = (REPLY_SERVER_ITEM *) InqContext;
NSI_BINDING_VECTOR_T * BindingVector;
ENTRY_SERVER_ITEM *EntryServer;
NS_UUID *Object;
*status = NSI_S_OK;
ASSERT(AssertHeap());
CLAIM_MUTEX Update(pESaccess);
if (! ReplyServer->AssertHandle()) {
*status = NSI_S_INVALID_NS_HANDLE;
return;
}
// Search the entire list, assembling a reply into a QUERY_REF list.
if (*status = ReplyServer->PerformQueryIfNeeded(FALSE)) {
DLIST(4, " No interfaces found\n");
if (*status == NSI_S_NO_MORE_MEMBERS ||
*status == NSI_S_ENTRY_NOT_FOUND)
*status = NSI_S_NO_MORE_BINDINGS;
return;
}
BindingVector = (NSI_BINDING_VECTOR_T *) new char [
sizeof(NSI_BINDING_VECTOR_T) +
(ReplyServer->TheVectorSize() * sizeof(NSI_BINDING_T))];
if (!BindingVector){
*status = NSI_S_OUT_OF_MEMORY;
return;
}
BindingVector->count = 0;
*BindingVectorOut = BindingVector;
ASSERT(AssertHeap());
while ( BindingVector->count < ReplyServer->TheVectorSize()
&& (EntryServer = ReplyServer->NextBindingAndObject(&Object)) )
{
// Copy the transport field to the string binding
ASSERT(AssertHeap());
LONG SizeBinding;
UICHAR ObjectBuffer[UUID_STRING_SIZE+1];
SizeBinding = EntryServer->TheStringBinding().cCur();
if (Object) {
CatUZ(Object->ToString(ObjectBuffer), (PUZ)"@\0\0");
SizeBinding += UUID_STRING_SIZE+1;
}
ASSERT(AssertHeap());
BindingVector->binding[BindingVector->count].string =
new UICHAR [SizeBinding];
ASSERT(AssertHeap());
if (!BindingVector->binding[BindingVector->count].string) {
*status = NSI_S_OUT_OF_MEMORY;
return;
}
ASSERT(AssertHeap());
BindingVector->binding[BindingVector->count].string[0] = NIL;
CatUZ( CatUZ(BindingVector->binding[BindingVector->count].string,
(Object)? ObjectBuffer: NIL),
EntryServer->TheStringBinding().pCur());
BindingVector->binding[BindingVector->count].entry_name =
EntryServer->TheEntry().CopyName();
if (!BindingVector->binding[BindingVector->count].entry_name) {
delete BindingVector->binding[BindingVector->count].string;
*status = NSI_S_OUT_OF_MEMORY;
return;
}
BindingVector->binding[BindingVector->count].entry_name_syntax =
RPC_C_NS_SYNTAX_DCE;
DLIST(4, " Return: " <<
BindingVector->binding[BindingVector->count].string << nl);
BindingVector->count++;
}
if (BindingVector->count == 0)
*status = NSI_S_NO_MORE_BINDINGS;
ASSERT(AssertHeap());
}
void
nsi_binding_lookup_done(
IN OUT NSI_NS_HANDLE_T * InqContext,
IN UNSIGNED16 * status
)
/*++
Routine Description:
Finish up a lookup operation.
Arguments:
InqContext - Context to close
status - Status is returned here
Returns:
See: CloseContextHandle()
--*/
{
DLIST(3, "lookup_next_done\n");
CloseContextHandle(InqContext, status);
}
void
CloseContextHandle(
IN OUT void ** InqContext,
IN unsigned short* status
)
/*++
Routine Description:
Close an open context handle. This one function closes all context
handles for all the APIs. This is nicely handled via a C++ virtual
destructor.
Arguments:
InqContext - Context to close
status - Status is returned here
Returns:
NSI_S_OK, NSI_S_INVALID_NS_HANDLE
--*/
{
REPLY_BASE_ITEM * ReplyBase = *( REPLY_BASE_ITEM **) InqContext;
*status = NSI_S_OK;
CLAIM_MUTEX Update(pESaccess);
if (ReplyBase->AssertHandle())
delete ReplyBase;
else
*status = NSI_S_INVALID_NS_HANDLE;
*InqContext = NIL;
ASSERT(AssertHeap());
}
void __RPC_API
NSI_NS_HANDLE_T_rundown(
IN NSI_NS_HANDLE_T InqContext
)
/*++
Routine Description:
Cleanup and abort a lookup operation.
Arguments:
InqContext - Context to cleanup
--*/
{
UNSIGNED16 status;
DLIST(3, "lookup_next_rundown\n");
CloseContextHandle(&InqContext, &status);
}
ENDDEF