mirror of https://github.com/lianthony/NT4.0
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
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
|