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.
679 lines
14 KiB
679 lines
14 KiB
|
|
#include "core.hxx"
|
|
#include "locquery.h"
|
|
#include "locclass.hxx"
|
|
#include "mailslot.hxx"
|
|
|
|
#define PIPENAME ( (unsigned short *)L"\\PIPE\\LOCATOR" )
|
|
#define PROTSEQ ( (unsigned short *)L"ncacn_np" )
|
|
|
|
extern "C" {
|
|
void CLIENT_I_nsi_ping_locator(
|
|
handle_t hLocatortoPing,
|
|
error_status_t *status);
|
|
}
|
|
|
|
/*
|
|
|
|
Class __LOCATOR
|
|
|
|
*/
|
|
|
|
extern NATIVE_CLASS_LOCATOR *Locator;
|
|
|
|
handle_t
|
|
NATIVE_CLASS_LOCATOR::GetBindingToMasterLocator(
|
|
int * Status)
|
|
{
|
|
|
|
|
|
if ( Status ) ;
|
|
ASSERT(!"should never be triggered");
|
|
|
|
return((handle_t)0);
|
|
|
|
}
|
|
|
|
void
|
|
NATIVE_CLASS_LOCATOR::CacheThisServer(
|
|
PUZ ServerName)
|
|
{
|
|
|
|
//we really dont do much in the default case
|
|
}
|
|
|
|
/*
|
|
void
|
|
NATIVE_CLASS_LOCATOR::SetupHelperRoutine(
|
|
)
|
|
{
|
|
|
|
ASSERT(!"should never be triggered");
|
|
|
|
}
|
|
*/
|
|
|
|
/*
|
|
void
|
|
NATIVE_CLASS_LOCATOR::DestroyBindingToMasterLocator()
|
|
{
|
|
ASSERT(!"should never be triggered");
|
|
}
|
|
*/
|
|
|
|
void NATIVE_CLASS_LOCATOR::SetIamMasterLocator()
|
|
{
|
|
|
|
IamMasterLocatorFlag = TRUE;
|
|
}
|
|
|
|
handle_t
|
|
NATIVE_CLASS_LOCATOR::GetBindingToNamedLocator(
|
|
unsigned short * Server,
|
|
int * Status
|
|
)
|
|
{
|
|
|
|
RPC_BINDING_HANDLE hNewHandle = NULL;
|
|
unsigned short * StringBindingW = 0;
|
|
|
|
*Status = RpcStringBindingComposeW(
|
|
0,
|
|
PROTSEQ,
|
|
(unsigned short *)Server,
|
|
PIPENAME,
|
|
0,
|
|
&StringBindingW
|
|
);
|
|
|
|
if (*Status == RPC_S_OK)
|
|
{
|
|
*Status = RpcBindingFromStringBindingW(
|
|
StringBindingW,
|
|
&hNewHandle
|
|
);
|
|
}
|
|
|
|
|
|
if (*Status == RPC_S_OK)
|
|
{
|
|
CLIENT_I_nsi_ping_locator(
|
|
hNewHandle,
|
|
(error_status_t *)Status
|
|
);
|
|
}
|
|
|
|
if (*Status == RPC_S_OK)
|
|
{
|
|
//Now Update The DataStructure and Mark The State Etc
|
|
|
|
DataStructureMutex.Request();
|
|
if (State == BOUND)
|
|
{
|
|
//oops someone already bound to something while we getDCing
|
|
//lets try and use the same thing
|
|
|
|
*Status = RpcBindingFree(&hNewHandle);
|
|
RpcStringFreeW(&StringBindingW);
|
|
ASSERT(*Status == RPC_S_OK);
|
|
}
|
|
else
|
|
{
|
|
State = BOUND;
|
|
MasterLocatorStringBinding = StringBindingW;
|
|
MasterLocator = StrdupUZ((PUZ)Server);
|
|
}
|
|
|
|
DataStructureMutex.Clear();
|
|
}
|
|
|
|
return((handle_t) hNewHandle);
|
|
}
|
|
|
|
BOOL
|
|
NATIVE_CLASS_LOCATOR::IsReplyNeeded(
|
|
PQUERYLOCATOR Query)
|
|
{
|
|
|
|
|
|
|
|
switch (Query->MessageType)
|
|
|
|
{
|
|
|
|
case QUERY_MASTER_LOCATOR:
|
|
return (Locator->InqIfIamMasterLocator());
|
|
|
|
|
|
case QUERY_ANY_LOCATOR:
|
|
return(TRUE);
|
|
|
|
case QUERY_DC_LOCATOR:
|
|
return((SysType == ROLE_LMNT_BACKUPDC) ||
|
|
(SysType == ROLE_LMNT_PDC));
|
|
|
|
case QUERY_BOUND_LOCATOR:
|
|
return((State == BOUND) ||
|
|
(Locator->InqIfIamMasterLocator()));
|
|
|
|
default:
|
|
DLIST(3, "Bogus Query MsgType=" << Query->MessageType << nl);
|
|
};
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
handle_t
|
|
DOMAIN_MACHINE_LOCATOR::GetBindingToMasterLocator(
|
|
int * RetStatus)
|
|
{
|
|
/*
|
|
|
|
Routine Description:
|
|
|
|
Returns a binding handle to the master locator.
|
|
Returns RPC_S_SERVER_UNAVAILABLE if master is unavailable
|
|
|
|
*/
|
|
|
|
|
|
handle_t hNewHandle = 0;
|
|
unsigned long IState;
|
|
LPBYTE ServerNameBuffer = 0;
|
|
LPBYTE Buffer = 0;
|
|
DWORD ReturnedEntries, TotalEntries;
|
|
LPSERVER_INFO_100 LPServerInfo;
|
|
UICHAR UZServerName[UNCLEN+1];
|
|
|
|
DataStructureMutex.Request();
|
|
if ((IState = State) == BOUND)
|
|
{
|
|
*RetStatus =
|
|
RpcBindingFromStringBindingW(
|
|
MasterLocatorStringBinding,
|
|
&hNewHandle
|
|
);
|
|
}
|
|
DataStructureMutex.Clear();
|
|
|
|
if (IState == BOUND)
|
|
{
|
|
ASSERT(*RetStatus == RPC_S_OK);
|
|
return(hNewHandle);
|
|
}
|
|
|
|
//Now try Locators on PDC and then BDCs
|
|
|
|
*RetStatus = NetGetDCName(
|
|
0,
|
|
0,
|
|
&ServerNameBuffer
|
|
);
|
|
|
|
if (*RetStatus == NERR_Success)
|
|
{
|
|
|
|
DLIST(3, "PDC=> " << (PUZ) ServerNameBuffer << nl);
|
|
hNewHandle = GetBindingToNamedLocator (
|
|
(unsigned short *) ServerNameBuffer,
|
|
(int *)RetStatus
|
|
);
|
|
if (*RetStatus == RPC_S_OK)
|
|
{
|
|
IState = BOUND;
|
|
}
|
|
}
|
|
|
|
if (ServerNameBuffer != 0)
|
|
{
|
|
NetApiBufferFree(ServerNameBuffer);
|
|
}
|
|
|
|
if (IState == BOUND)
|
|
{
|
|
ASSERT(*RetStatus == RPC_S_OK);
|
|
return(hNewHandle);
|
|
}
|
|
|
|
//If we are here we need to try all the BDCs.
|
|
|
|
|
|
*RetStatus = NetServerEnum(
|
|
0,
|
|
100,
|
|
&Buffer,
|
|
0xffffffff,
|
|
&ReturnedEntries,
|
|
&TotalEntries,
|
|
SV_TYPE_DOMAIN_BAKCTRL,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if (*RetStatus != NERR_Success)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
LPServerInfo = (LPSERVER_INFO_100)Buffer;
|
|
|
|
while (ReturnedEntries != 0)
|
|
{
|
|
|
|
ServerNameBuffer = (LPBYTE)LPServerInfo->sv100_name;
|
|
UZServerName[0] = '\\';
|
|
UZServerName[1] = '\\';
|
|
UZServerName[2] = 0;
|
|
CatUZ(UZServerName, (PUZ)ServerNameBuffer);
|
|
|
|
DLIST(3, "now trying BDC [" << UZServerName << "] \n");
|
|
hNewHandle = GetBindingToNamedLocator (
|
|
(unsigned short *) UZServerName,
|
|
(int *)RetStatus
|
|
);
|
|
|
|
if (*RetStatus == RPC_S_OK)
|
|
break;
|
|
|
|
LPServerInfo++;
|
|
ReturnedEntries--;
|
|
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (Buffer != NULL)
|
|
NetApiBufferFree(Buffer);
|
|
|
|
if (*RetStatus != RPC_S_OK)
|
|
*RetStatus = RPC_S_SERVER_UNAVAILABLE;
|
|
|
|
return(hNewHandle);
|
|
}
|
|
|
|
|
|
void
|
|
WRKGRP_MACHINE_LOCATOR::TryBroadcastingForMasterLocator(
|
|
)
|
|
{
|
|
|
|
QUERYLOCATOR Query;
|
|
STATUS Status;
|
|
int MailStatus;
|
|
|
|
WRITE_MAIL_SLOT BSResponder(RESPONDERMSLOT_S, DomainName, &Status);
|
|
|
|
if (Status != NSI_S_OK)
|
|
{
|
|
//Log it but ignore it
|
|
DLIST(3, "Attempted Broadcast Failure Err=" << Status << nl);
|
|
return;
|
|
|
|
}
|
|
|
|
Query.SenderOsType = OS_NTWKGRP;
|
|
Query.MessageType = QUERY_MASTER_LOCATOR;
|
|
|
|
Query.RequesterName[0] = 0;
|
|
CatUZ(Query.RequesterName, SelfName);
|
|
|
|
MailStatus = BSResponder.Write((PB) &Query, sizeof(Query));
|
|
|
|
if (MailStatus != 0)
|
|
{
|
|
//Log it, but not much else we can do
|
|
|
|
DLIST(3, "Attempted Write to BroadcastMS Err=" << Status << nl);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
handle_t
|
|
WRKGRP_MACHINE_LOCATOR::GetBindingToMasterLocator(
|
|
int * RetStatus)
|
|
{
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
|
|
Returns a binding handle to the master locator.
|
|
Returns RPC_S_SERVER_UNAVAILABLE if master is unavailable
|
|
|
|
*/
|
|
|
|
|
|
handle_t hNewHandle;
|
|
unsigned long IState;
|
|
UICHAR ServerName[UNCLEN+1];
|
|
PCACHEDNODE pNode;
|
|
BOOL TriedBroadcasting = FALSE;
|
|
|
|
DataStructureMutex.Request();
|
|
if ((IState = State) == BOUND)
|
|
{
|
|
*RetStatus = RpcBindingFromStringBindingW(
|
|
MasterLocatorStringBinding,
|
|
&hNewHandle
|
|
);
|
|
}
|
|
DataStructureMutex.Clear();
|
|
|
|
if (IState == BOUND)
|
|
{
|
|
ASSERT(*RetStatus == RPC_S_OK);
|
|
return(hNewHandle);
|
|
}
|
|
|
|
//Now try all the cached locators, one after the other!
|
|
|
|
while (1)
|
|
{
|
|
|
|
DataStructureMutex.Request();
|
|
|
|
if (Head == NULL)
|
|
{
|
|
if (TriedBroadcasting == FALSE)
|
|
{
|
|
TryBroadcastingForMasterLocator();
|
|
TriedBroadcasting = TRUE;
|
|
DataStructureMutex.Clear();
|
|
continue;
|
|
}
|
|
|
|
*RetStatus = RPC_S_SERVER_UNAVAILABLE;
|
|
DataStructureMutex.Clear();
|
|
break;
|
|
}
|
|
|
|
ServerName[0] = NIL;
|
|
CatUZ((PUZ)ServerName, (PUZ)Head->ServerName);
|
|
|
|
DataStructureMutex.Clear();
|
|
|
|
hNewHandle = GetBindingToNamedLocator (
|
|
(unsigned short *) ServerName,
|
|
(int *)RetStatus
|
|
);
|
|
if (*RetStatus == RPC_S_OK)
|
|
{
|
|
return(hNewHandle);
|
|
}
|
|
else
|
|
{
|
|
DataStructureMutex.Request();
|
|
|
|
pNode = FindCachedEntry(ServerName);
|
|
pNode = DeleteCachedEntry(pNode);
|
|
delete pNode;
|
|
|
|
DataStructureMutex.Clear();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
NATIVE_CLASS_LOCATOR::DestroyBindingToMasterLocator()
|
|
{
|
|
DataStructureMutex.Request();
|
|
|
|
State = UNBOUND;
|
|
|
|
if (MasterLocator != 0)
|
|
{
|
|
delete MasterLocator;
|
|
}
|
|
|
|
if (MasterLocatorStringBinding != 0)
|
|
{
|
|
RpcStringFreeW(&MasterLocatorStringBinding);
|
|
}
|
|
|
|
MasterLocatorStringBinding = 0;
|
|
|
|
DataStructureMutex.Clear();
|
|
|
|
}
|
|
|
|
void
|
|
NATIVE_CLASS_LOCATOR::ProcessMessage(
|
|
PQUERYLOCATOR Query,
|
|
int * Status
|
|
)
|
|
{
|
|
|
|
QUERYLOCATORREPLY Reply;
|
|
int MailStatus;
|
|
STATUS Err;
|
|
|
|
*Status = NSI_S_OK;
|
|
if (IsReplyNeeded(Query) == FALSE)
|
|
return;
|
|
|
|
//Copy SelfName
|
|
|
|
Reply.SenderName[0] = Nil;
|
|
CatUZ(Reply.SenderName, SelfName);
|
|
Reply.Uptime = CurrentTimeMS() - LocatorStartTime;
|
|
|
|
if (((InqIfIamMasterLocator() == TRUE)) || (SysType == ROLE_LMNT_PDC))
|
|
{
|
|
Reply.Hint = REPLY_MASTER_LOCATOR;
|
|
}
|
|
else
|
|
if (State == BOUND)
|
|
{
|
|
Reply.Hint = REPLY_BOUND_LOCATOR;
|
|
}
|
|
else
|
|
{
|
|
Reply.Hint =
|
|
((SysType == ROLE_LMNT_BACKUPDC) ?
|
|
REPLY_DC_LOCATOR : REPLY_OTHER_LOCATOR);
|
|
}
|
|
|
|
//Now form the return Mailslot name
|
|
//
|
|
UICHAR ReplyMSName[sizeof(RESPONDERMSLOT_C) +
|
|
sizeof(Query->RequesterName)];
|
|
ReplyMSName[0] = '\\';
|
|
ReplyMSName[1] = '\\';
|
|
ReplyMSName[2] = Nil;
|
|
CatUZ(CatUZ(ReplyMSName, Query->RequesterName), RESPONDERMSLOT_C);
|
|
|
|
WRITE_MAIL_SLOT MSReply(ReplyMSName, NIL, &Err);
|
|
|
|
if (Err != NSI_S_OK)
|
|
{
|
|
DLIST( 3, "Error (" << *Status << ") creating a MSlot" << nl);
|
|
return;
|
|
}
|
|
|
|
MailStatus = MSReply.Write((char *) &Reply, sizeof(Reply));
|
|
|
|
if (MailStatus)
|
|
{
|
|
DLIST( 3, "Error (" << *Status << ") writting to MSlot" << nl);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
DomainLocatorResponder(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Each Locator has an additional thread that creates a mailslot
|
|
This thread replies to queries that seek to find the master locator.
|
|
|
|
This particular Responder runs on Domain locators only
|
|
|
|
--*/
|
|
{
|
|
int Status;
|
|
int MailStatus;
|
|
int LongStatus;
|
|
unsigned short LookupStatus;
|
|
QUERYLOCATOR Query;
|
|
QUERYLOCATORREPLY Reply;
|
|
int cbBytesRead;
|
|
|
|
READ_MAIL_SLOT hMSRead(RESPONDERMSLOT_S, sizeof(QUERYLOCATOR), &Status);
|
|
DLIST(2, "starting LocatorSearchResponder Thread..\n");
|
|
|
|
if (Status != NSI_S_OK)
|
|
{
|
|
AbortServer("Error in new mailslot", Status);
|
|
}
|
|
|
|
Reply.SenderName[0] = NIL;
|
|
CatUZ(Reply.SenderName, SelfName);
|
|
|
|
while (1)
|
|
{
|
|
ASSERT(AssertHeap());
|
|
MailStatus = hMSRead.Read((PB) &Query, cbBytesRead);
|
|
|
|
if (MailStatus)
|
|
AbortServer("Mailslot read error", MailStatus);
|
|
|
|
if (!CmpUZ(Query.RequesterName, SelfName))
|
|
continue;
|
|
|
|
DLIST(3, Query.RequesterName << " did query for locator" << nl);
|
|
|
|
if (cbBytesRead != sizeof(QUERYLOCATOR))
|
|
{
|
|
DLIST(3, "Bummer, Bad Message of size(" << cbBytesRead
|
|
<< ") recvd" << nl);
|
|
continue;
|
|
}
|
|
|
|
Locator->ProcessMessage(&Query, &LongStatus);
|
|
}
|
|
}
|
|
|
|
void
|
|
NATIVE_CLASS_LOCATOR::SetupHelperRoutine(
|
|
)
|
|
{
|
|
|
|
void * pThreadHandle;
|
|
DWORD ThreadId;
|
|
|
|
pThreadHandle = CreateThread(
|
|
0,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE)DomainLocatorResponder,
|
|
0,
|
|
0,
|
|
&ThreadId
|
|
);
|
|
|
|
}
|
|
|
|
PCACHEDNODE
|
|
WRKGRP_MACHINE_LOCATOR::FindCachedEntry(PUZ ServerName)
|
|
{
|
|
|
|
PCACHEDNODE pNode;
|
|
|
|
for(pNode = Head; pNode; pNode = pNode->Next)
|
|
{
|
|
if ( CmpUZ(pNode->ServerName, (PUZ)ServerName) == 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(pNode);
|
|
}
|
|
|
|
void
|
|
WRKGRP_MACHINE_LOCATOR::InsertCacheEntry(PCACHEDNODE pNode)
|
|
{
|
|
|
|
|
|
if (Tail == NULL)
|
|
{
|
|
ASSERT(Head == NULL);
|
|
Tail = pNode;
|
|
}
|
|
|
|
pNode->Previous = 0;
|
|
pNode->Next = Head;
|
|
if (Head != NULL)
|
|
Head->Previous = pNode;
|
|
Head = pNode;
|
|
CacheSize ++;
|
|
}
|
|
|
|
|
|
PCACHEDNODE
|
|
WRKGRP_MACHINE_LOCATOR::DeleteCachedEntry(PCACHEDNODE pNode)
|
|
{
|
|
|
|
|
|
if (pNode == NULL)
|
|
return((PCACHEDNODE)NULL);
|
|
|
|
if (Head == pNode)
|
|
Head = pNode->Next;
|
|
|
|
if (Tail == pNode)
|
|
Tail = pNode->Previous;
|
|
|
|
if (pNode->Next != NULL)
|
|
pNode->Next->Previous = pNode->Previous;
|
|
|
|
if (pNode->Previous != NULL)
|
|
pNode->Previous->Next = pNode->Next;
|
|
|
|
CacheSize--;
|
|
return(pNode);
|
|
}
|
|
|
|
void
|
|
WRKGRP_MACHINE_LOCATOR::CacheThisServer(PUZ ServerName)
|
|
{
|
|
|
|
register PCACHEDNODE pNode;
|
|
|
|
DataStructureMutex.Request();
|
|
|
|
pNode = FindCachedEntry(ServerName);
|
|
|
|
if (pNode == NULL)
|
|
{
|
|
|
|
pNode = new CACHEDNODE;
|
|
pNode->Next = pNode->Previous = 0;
|
|
pNode->ServerName[0] = NIL;
|
|
CatUZ(pNode->ServerName, (PUZ)ServerName);
|
|
if (CacheSize == CACHESIZE)
|
|
DeleteCachedEntry(Tail);
|
|
|
|
InsertCacheEntry(pNode);
|
|
}
|
|
else
|
|
{
|
|
if (pNode != Head)
|
|
{
|
|
pNode = DeleteCachedEntry(pNode);
|
|
InsertCacheEntry(pNode);
|
|
}
|
|
}
|
|
|
|
|
|
DataStructureMutex.Clear();
|
|
}
|
|
|