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.
475 lines
9.9 KiB
475 lines
9.9 KiB
/*++
|
|
|
|
Microsoft Windows NT RPC Name Service
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
master.cxx
|
|
|
|
Abstract:
|
|
|
|
This file contains the implementations for non inline member functions
|
|
of CMasterLookupHandle and CMasterObjectInqHandle, which are classes used for
|
|
interaction with a master locator for looking up binding handles and objects.
|
|
|
|
Things to improve in future revisions:
|
|
|
|
1. The structure of the locator-to-locator RPC interface needs a complete redesign.
|
|
The query to a master locator should be for a complete entry, not piecemeal
|
|
and painfully repetitive as it is now.
|
|
|
|
2. There is a suspicion that client locators don't release all the lookup handles
|
|
they get from a master locator (about 1 in 200 in a random test), probably in
|
|
exceptional circumstances. This needs to be fixed if true.
|
|
|
|
Author:
|
|
|
|
Satish Thatte (SatishT) 10/1/95 Created all the code below except where
|
|
otherwise indicated.
|
|
|
|
--*/
|
|
|
|
#include <master.hxx>
|
|
#include <api.hxx>
|
|
#include <var.hxx>
|
|
#include <loctoloc.h>
|
|
|
|
|
|
#if DBG
|
|
ULONG CMasterLookupHandle::ulMasterLookupHandleCount = 0;
|
|
ULONG CMasterLookupHandle::ulMasterLookupHandleNo = 0;
|
|
#endif
|
|
|
|
NSI_UUID_VECTOR_P_T
|
|
getObjectVector(
|
|
IN RPC_BINDING_HANDLE hCurrentMaster,
|
|
IN UNSIGNED32 EntryNameSyntax,
|
|
IN STRING_T EntryName,
|
|
OUT ULONG& StatusCode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Broadcasts for the requested binding handles.
|
|
|
|
Arguments:
|
|
|
|
hCurrentMaster - the binding handle for the master locator
|
|
|
|
EntryNameSyntax - syntax of entry name
|
|
|
|
EntryName - entry name for object query
|
|
|
|
StatusCode - status of query returned here
|
|
|
|
Returns:
|
|
|
|
A standard UUID vector containing the object UUIDs returned by the
|
|
master locator.
|
|
|
|
--*/
|
|
{
|
|
STATUS Status;
|
|
|
|
NSI_UUID_VECTOR_P_T pUuidVector = NULL;
|
|
|
|
HANDLE hObjectHandle = NULL;
|
|
|
|
RpcImpersonateClient(0);
|
|
|
|
RpcTryExcept {
|
|
|
|
CLIENT_I_nsi_entry_object_inq_begin(
|
|
hCurrentMaster,
|
|
EntryNameSyntax,
|
|
EntryName,
|
|
&hObjectHandle,
|
|
&Status
|
|
);
|
|
}
|
|
RpcExcept (EXCEPTION_EXECUTE_HANDLER) {
|
|
RpcBindingFree(&hCurrentMaster);
|
|
hCurrentMaster = NULL;
|
|
|
|
StatusCode = RpcExceptionCode();
|
|
|
|
if (StatusCode == RPC_S_ACCESS_DENIED)
|
|
StatusCode = NSI_S_NO_NS_PRIVILEGE;
|
|
|
|
RpcRevertToSelf();
|
|
return NULL;
|
|
}
|
|
RpcEndExcept;
|
|
|
|
if ((StatusCode = Status) != NSI_S_OK) return NULL;
|
|
|
|
CLIENT_I_nsi_entry_object_inq_next(
|
|
hCurrentMaster,
|
|
hObjectHandle,
|
|
&pUuidVector,
|
|
&Status
|
|
);
|
|
|
|
StatusCode = Status;
|
|
|
|
CLIENT_I_nsi_entry_object_inq_done(
|
|
&hObjectHandle,
|
|
&Status
|
|
);
|
|
|
|
StatusCode = Status;
|
|
|
|
RpcRevertToSelf();
|
|
|
|
return pUuidVector;
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
CMasterLookupHandle::initialize()
|
|
/*++
|
|
|
|
Method Description:
|
|
|
|
Establishes contact with the master locator and acquires a context handle
|
|
for the lookup parameters stored as members in this object.
|
|
|
|
Remarks:
|
|
|
|
The reason for separating initialization as a method separate from the
|
|
constructor is that "lookupIfNecessary" may force reinitialization if
|
|
the information is too stale. This can happen if the user resets the
|
|
expiration age for a specific context handle.
|
|
|
|
--*/
|
|
{
|
|
DBGOUT(TRACE,"CMasterLookupHandle::initialize called for Handle#" << ulHandleNo << "\n\n");
|
|
|
|
StatusCode = NSI_S_OK;
|
|
|
|
RPC_SYNTAX_IDENTIFIER interfaceID;
|
|
|
|
if (pgvInterface) interfaceID = *pgvInterface;
|
|
|
|
RPC_SYNTAX_IDENTIFIER xferSyntaxID;
|
|
|
|
if (pgvTransferSyntax) xferSyntaxID = *pgvTransferSyntax;
|
|
|
|
NSI_UUID_T objID;
|
|
|
|
if (pidObject) objID = pidObject->myGUID();
|
|
|
|
UNSIGNED16 status = 0;
|
|
|
|
RpcMgmtSetCancelTimeout(CONNECTION_TIMEOUT);
|
|
|
|
hCurrentMaster = ConnectToMasterLocator(
|
|
StatusCode
|
|
);
|
|
|
|
if (!hCurrentMaster || StatusCode) {
|
|
StatusCode = NSI_S_NAME_SERVICE_UNAVAILABLE;
|
|
myRpcLocator->SetDCsDown();
|
|
return;
|
|
}
|
|
else myRpcLocator->SetDCsUp();
|
|
|
|
RpcImpersonateClient(0);
|
|
|
|
lookupHandle = NULL;
|
|
|
|
/* The following is a work around, because the compiler refuses to accept
|
|
|
|
penEntryName ? (*penEntryName) : NULL
|
|
|
|
*/
|
|
|
|
STRING_T szEntryName = NULL;
|
|
if (penEntryName) szEntryName = *penEntryName;
|
|
|
|
RpcTryExcept {
|
|
CLIENT_I_nsi_lookup_begin(
|
|
hCurrentMaster,
|
|
u32EntryNameSyntax,
|
|
szEntryName,
|
|
pgvInterface? &interfaceID : NULL,
|
|
pgvTransferSyntax? &xferSyntaxID : NULL,
|
|
pidObject? &objID : NULL,
|
|
ulVS,
|
|
ulCacheMax? ulCacheMax: ulCacheMax+CACHE_GRACE, // ensures that it is nonzero
|
|
&lookupHandle, // the above is wierd but necessary because ulCacheAge is frequently -1
|
|
&status
|
|
);
|
|
}
|
|
RpcExcept (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
RpcBindingFree(&hCurrentMaster);
|
|
hCurrentMaster = NULL;
|
|
|
|
StatusCode = RpcExceptionCode();
|
|
|
|
if (StatusCode == RPC_S_ACCESS_DENIED)
|
|
StatusCode = NSI_S_NO_NS_PRIVILEGE;
|
|
|
|
// this is a copout to take care of NT vs NSI code conflicts
|
|
|
|
else if (StatusCode < NSI_S_STATUS_MAX)
|
|
StatusCode = NSI_S_NAME_SERVICE_UNAVAILABLE;
|
|
|
|
RpcRevertToSelf();
|
|
return;
|
|
}
|
|
RpcEndExcept;
|
|
|
|
RpcRevertToSelf();
|
|
|
|
StatusCode = status; // hopefully, RPC_S_OK;
|
|
|
|
fFinished = FALSE;
|
|
|
|
ulCreationTime = CurrentTime();
|
|
fNotInitialized = FALSE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CMasterLookupHandle::fetchNext()
|
|
/*++
|
|
|
|
Method Description:
|
|
|
|
Fetches the next vector of binding handles from the master locator, along
|
|
with associated object UUIDs.
|
|
|
|
Remarks:
|
|
|
|
The process is inefficient in that each binding handle returned has an
|
|
entry name associated with it and we must make a full fledged object query
|
|
for every binding handle. This is extremely expensive but the current structure
|
|
of the locator-to-locator interface forces it upon us.
|
|
|
|
--*/
|
|
{
|
|
DBGOUT(TRACE,"CMasterLookupHandle::fetchNext called for Handle#" << ulHandleNo << "\n\n");
|
|
|
|
STATUS status;
|
|
|
|
/* We only want to run down the info acquired in the last fetchNext.
|
|
A full-scale rundown of the handle would also give up the context
|
|
handle and binding to the master locator, which would ruin us.
|
|
The only thing we have to fix is to reset the fNotInitialzed flag,
|
|
so that we don't call initialize() again on this handle.
|
|
*/
|
|
|
|
CRemoteLookupHandle::rundown();
|
|
fNotInitialized = FALSE;
|
|
|
|
psslNewCache = new TSSLEntryList;
|
|
|
|
NSI_BINDING_VECTOR_T * pNextVector = NULL;
|
|
|
|
RpcImpersonateClient(0);
|
|
|
|
RpcTryExcept {
|
|
|
|
CLIENT_I_nsi_lookup_next(
|
|
hCurrentMaster,
|
|
lookupHandle,
|
|
&pNextVector,
|
|
&status
|
|
);
|
|
}
|
|
RpcExcept (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
RpcBindingFree(&hCurrentMaster);
|
|
hCurrentMaster = NULL;
|
|
|
|
StatusCode = RpcExceptionCode();
|
|
|
|
if (StatusCode == RPC_S_ACCESS_DENIED)
|
|
StatusCode = NSI_S_NO_NS_PRIVILEGE;
|
|
|
|
RpcRevertToSelf();
|
|
return FALSE;
|
|
}
|
|
RpcEndExcept;
|
|
|
|
RpcRevertToSelf();
|
|
|
|
StatusCode = status;
|
|
|
|
if (status == NSI_S_NO_MORE_BINDINGS) return FALSE;
|
|
|
|
else if (status != NSI_S_OK) Raise(status);
|
|
|
|
else {
|
|
|
|
NSI_UUID_VECTOR_P_T pUuidVector;
|
|
|
|
for (unsigned int i = 0; i < pNextVector->count; i++)
|
|
{
|
|
|
|
pUuidVector = getObjectVector(
|
|
hCurrentMaster,
|
|
pNextVector->binding[i].entry_name_syntax,
|
|
pNextVector->binding[i].entry_name,
|
|
StatusCode
|
|
);
|
|
|
|
/* first update the central cache and, if there is anything new,
|
|
also update the temporary cache in psslNewCache
|
|
*/
|
|
|
|
CGUIDVersion nullGV; // standard initialization to null
|
|
|
|
|
|
myRpcLocator->UpdateCache(
|
|
pNextVector->binding[i].entry_name,
|
|
pNextVector->binding[i].entry_name_syntax,
|
|
pgvInterface ? *pgvInterface : nullGV,
|
|
pgvTransferSyntax ? *pgvTransferSyntax : nullGV,
|
|
pNextVector->binding[i].string,
|
|
pUuidVector,
|
|
psslNewCache
|
|
);
|
|
|
|
midl_user_free(pNextVector->binding[i].entry_name);
|
|
midl_user_free(pNextVector->binding[i].string);
|
|
|
|
if (pUuidVector) {
|
|
for (unsigned int j = 0; j < pUuidVector->count; j++)
|
|
midl_user_free(pUuidVector->uuid[j]);
|
|
|
|
midl_user_free(pUuidVector);
|
|
}
|
|
|
|
pUuidVector = NULL;
|
|
}
|
|
|
|
midl_user_free(pNextVector);
|
|
}
|
|
|
|
TEntryIterator *pCacheIter = new TSSLEntryListIterator(*psslNewCache);
|
|
|
|
plhFetched = new CGroupLookupHandle(
|
|
pCacheIter,
|
|
pgvInterface,
|
|
pgvTransferSyntax,
|
|
pidObject,
|
|
ulVS,
|
|
ulCacheMax
|
|
);
|
|
|
|
/* do not delete psslNewCache -- it is done by the constructor above */
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
CMasterLookupHandle::rundown()
|
|
/*++
|
|
|
|
Method Description:
|
|
|
|
Release the binding to the master and the context handle received from the master.
|
|
|
|
Remarks:
|
|
|
|
The reason to separate this from the destructor is similar to the case of
|
|
initialize(), i.e., finalization may happen due to reinitialization rather than
|
|
destruction.
|
|
|
|
--*/{
|
|
|
|
DBGOUT(TRACE,"CMasterLookupHandle::rundown called for Handle#" << ulHandleNo << "\n\n");
|
|
|
|
STATUS status;
|
|
|
|
// First do the standard rundown for remote handles
|
|
|
|
CRemoteLookupHandle::rundown();
|
|
|
|
// Then try closing lookupHandle in master locator
|
|
|
|
if (hCurrentMaster) {
|
|
|
|
RpcImpersonateClient(0);
|
|
|
|
RpcTryExcept {
|
|
|
|
CLIENT_I_nsi_lookup_done(
|
|
hCurrentMaster,
|
|
&lookupHandle,
|
|
&status
|
|
);
|
|
|
|
}
|
|
RpcExcept (EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGOUT(MEM1,"Could not close lookup handle in master\n\n");
|
|
}
|
|
RpcEndExcept;
|
|
|
|
RpcBindingFree(&hCurrentMaster);
|
|
hCurrentMaster = NULL;
|
|
RpcRevertToSelf();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CMasterObjectInqHandle::CMasterObjectInqHandle(
|
|
STRING_T szEntryName,
|
|
ULONG ulCacheAge
|
|
)
|
|
: CRemoteObjectInqHandle(szEntryName,ulCacheAge)
|
|
{
|
|
}
|
|
|
|
void
|
|
CMasterObjectInqHandle::initialize() {
|
|
|
|
ulIndex = 0;
|
|
|
|
StatusCode = NSI_S_OK;
|
|
|
|
RpcMgmtSetCancelTimeout(CONNECTION_TIMEOUT);
|
|
|
|
RPC_BINDING_HANDLE hCurrentMaster =
|
|
ConnectToMasterLocator(
|
|
StatusCode
|
|
);
|
|
|
|
if (!hCurrentMaster || StatusCode) {
|
|
myRpcLocator->SetDCsDown();
|
|
return;
|
|
}
|
|
else myRpcLocator->SetDCsUp();
|
|
|
|
/* The following is a work around, because the compiler refuses to accept
|
|
|
|
penEntryName ? (*penEntryName) : NULL
|
|
|
|
*/
|
|
|
|
STRING_T szEntryName = NULL;
|
|
if (penEntryName) szEntryName = *penEntryName;
|
|
|
|
pUuidVector = getObjectVector(
|
|
hCurrentMaster,
|
|
RPC_C_NS_SYNTAX_DCE,
|
|
szEntryName,
|
|
StatusCode
|
|
);
|
|
|
|
ulCreationTime = CurrentTime();
|
|
fNotInitialized = FALSE;
|
|
}
|
|
|