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.
 
 
 
 
 
 

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();
}