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

4 years ago
  1. #include "core.hxx"
  2. #include "locquery.h"
  3. #include "locclass.hxx"
  4. #include "mailslot.hxx"
  5. #define PIPENAME ( (unsigned short *)L"\\PIPE\\LOCATOR" )
  6. #define PROTSEQ ( (unsigned short *)L"ncacn_np" )
  7. extern "C" {
  8. void CLIENT_I_nsi_ping_locator(
  9. handle_t hLocatortoPing,
  10. error_status_t *status);
  11. }
  12. /*
  13. Class __LOCATOR
  14. */
  15. extern NATIVE_CLASS_LOCATOR *Locator;
  16. handle_t
  17. NATIVE_CLASS_LOCATOR::GetBindingToMasterLocator(
  18. int * Status)
  19. {
  20. if ( Status ) ;
  21. ASSERT(!"should never be triggered");
  22. return((handle_t)0);
  23. }
  24. void
  25. NATIVE_CLASS_LOCATOR::CacheThisServer(
  26. PUZ ServerName)
  27. {
  28. //we really dont do much in the default case
  29. }
  30. /*
  31. void
  32. NATIVE_CLASS_LOCATOR::SetupHelperRoutine(
  33. )
  34. {
  35. ASSERT(!"should never be triggered");
  36. }
  37. */
  38. /*
  39. void
  40. NATIVE_CLASS_LOCATOR::DestroyBindingToMasterLocator()
  41. {
  42. ASSERT(!"should never be triggered");
  43. }
  44. */
  45. void NATIVE_CLASS_LOCATOR::SetIamMasterLocator()
  46. {
  47. IamMasterLocatorFlag = TRUE;
  48. }
  49. handle_t
  50. NATIVE_CLASS_LOCATOR::GetBindingToNamedLocator(
  51. unsigned short * Server,
  52. int * Status
  53. )
  54. {
  55. RPC_BINDING_HANDLE hNewHandle = NULL;
  56. unsigned short * StringBindingW = 0;
  57. *Status = RpcStringBindingComposeW(
  58. 0,
  59. PROTSEQ,
  60. (unsigned short *)Server,
  61. PIPENAME,
  62. 0,
  63. &StringBindingW
  64. );
  65. if (*Status == RPC_S_OK)
  66. {
  67. *Status = RpcBindingFromStringBindingW(
  68. StringBindingW,
  69. &hNewHandle
  70. );
  71. }
  72. if (*Status == RPC_S_OK)
  73. {
  74. CLIENT_I_nsi_ping_locator(
  75. hNewHandle,
  76. (error_status_t *)Status
  77. );
  78. }
  79. if (*Status == RPC_S_OK)
  80. {
  81. //Now Update The DataStructure and Mark The State Etc
  82. DataStructureMutex.Request();
  83. if (State == BOUND)
  84. {
  85. //oops someone already bound to something while we getDCing
  86. //lets try and use the same thing
  87. *Status = RpcBindingFree(&hNewHandle);
  88. RpcStringFreeW(&StringBindingW);
  89. ASSERT(*Status == RPC_S_OK);
  90. }
  91. else
  92. {
  93. State = BOUND;
  94. MasterLocatorStringBinding = StringBindingW;
  95. MasterLocator = StrdupUZ((PUZ)Server);
  96. }
  97. DataStructureMutex.Clear();
  98. }
  99. return((handle_t) hNewHandle);
  100. }
  101. BOOL
  102. NATIVE_CLASS_LOCATOR::IsReplyNeeded(
  103. PQUERYLOCATOR Query)
  104. {
  105. switch (Query->MessageType)
  106. {
  107. case QUERY_MASTER_LOCATOR:
  108. return (Locator->InqIfIamMasterLocator());
  109. case QUERY_ANY_LOCATOR:
  110. return(TRUE);
  111. case QUERY_DC_LOCATOR:
  112. return((SysType == ROLE_LMNT_BACKUPDC) ||
  113. (SysType == ROLE_LMNT_PDC));
  114. case QUERY_BOUND_LOCATOR:
  115. return((State == BOUND) ||
  116. (Locator->InqIfIamMasterLocator()));
  117. default:
  118. DLIST(3, "Bogus Query MsgType=" << Query->MessageType << nl);
  119. };
  120. return (FALSE);
  121. }
  122. handle_t
  123. DOMAIN_MACHINE_LOCATOR::GetBindingToMasterLocator(
  124. int * RetStatus)
  125. {
  126. /*
  127. Routine Description:
  128. Returns a binding handle to the master locator.
  129. Returns RPC_S_SERVER_UNAVAILABLE if master is unavailable
  130. */
  131. handle_t hNewHandle = 0;
  132. unsigned long IState;
  133. LPBYTE ServerNameBuffer = 0;
  134. LPBYTE Buffer = 0;
  135. DWORD ReturnedEntries, TotalEntries;
  136. LPSERVER_INFO_100 LPServerInfo;
  137. UICHAR UZServerName[UNCLEN+1];
  138. DataStructureMutex.Request();
  139. if ((IState = State) == BOUND)
  140. {
  141. *RetStatus =
  142. RpcBindingFromStringBindingW(
  143. MasterLocatorStringBinding,
  144. &hNewHandle
  145. );
  146. }
  147. DataStructureMutex.Clear();
  148. if (IState == BOUND)
  149. {
  150. ASSERT(*RetStatus == RPC_S_OK);
  151. return(hNewHandle);
  152. }
  153. //Now try Locators on PDC and then BDCs
  154. *RetStatus = NetGetDCName(
  155. 0,
  156. 0,
  157. &ServerNameBuffer
  158. );
  159. if (*RetStatus == NERR_Success)
  160. {
  161. DLIST(3, "PDC=> " << (PUZ) ServerNameBuffer << nl);
  162. hNewHandle = GetBindingToNamedLocator (
  163. (unsigned short *) ServerNameBuffer,
  164. (int *)RetStatus
  165. );
  166. if (*RetStatus == RPC_S_OK)
  167. {
  168. IState = BOUND;
  169. }
  170. }
  171. if (ServerNameBuffer != 0)
  172. {
  173. NetApiBufferFree(ServerNameBuffer);
  174. }
  175. if (IState == BOUND)
  176. {
  177. ASSERT(*RetStatus == RPC_S_OK);
  178. return(hNewHandle);
  179. }
  180. //If we are here we need to try all the BDCs.
  181. *RetStatus = NetServerEnum(
  182. 0,
  183. 100,
  184. &Buffer,
  185. 0xffffffff,
  186. &ReturnedEntries,
  187. &TotalEntries,
  188. SV_TYPE_DOMAIN_BAKCTRL,
  189. 0,
  190. 0
  191. );
  192. if (*RetStatus != NERR_Success)
  193. {
  194. goto Cleanup;
  195. }
  196. LPServerInfo = (LPSERVER_INFO_100)Buffer;
  197. while (ReturnedEntries != 0)
  198. {
  199. ServerNameBuffer = (LPBYTE)LPServerInfo->sv100_name;
  200. UZServerName[0] = '\\';
  201. UZServerName[1] = '\\';
  202. UZServerName[2] = 0;
  203. CatUZ(UZServerName, (PUZ)ServerNameBuffer);
  204. DLIST(3, "now trying BDC [" << UZServerName << "] \n");
  205. hNewHandle = GetBindingToNamedLocator (
  206. (unsigned short *) UZServerName,
  207. (int *)RetStatus
  208. );
  209. if (*RetStatus == RPC_S_OK)
  210. break;
  211. LPServerInfo++;
  212. ReturnedEntries--;
  213. }
  214. Cleanup:
  215. if (Buffer != NULL)
  216. NetApiBufferFree(Buffer);
  217. if (*RetStatus != RPC_S_OK)
  218. *RetStatus = RPC_S_SERVER_UNAVAILABLE;
  219. return(hNewHandle);
  220. }
  221. void
  222. WRKGRP_MACHINE_LOCATOR::TryBroadcastingForMasterLocator(
  223. )
  224. {
  225. QUERYLOCATOR Query;
  226. STATUS Status;
  227. int MailStatus;
  228. WRITE_MAIL_SLOT BSResponder(RESPONDERMSLOT_S, DomainName, &Status);
  229. if (Status != NSI_S_OK)
  230. {
  231. //Log it but ignore it
  232. DLIST(3, "Attempted Broadcast Failure Err=" << Status << nl);
  233. return;
  234. }
  235. Query.SenderOsType = OS_NTWKGRP;
  236. Query.MessageType = QUERY_MASTER_LOCATOR;
  237. Query.RequesterName[0] = 0;
  238. CatUZ(Query.RequesterName, SelfName);
  239. MailStatus = BSResponder.Write((PB) &Query, sizeof(Query));
  240. if (MailStatus != 0)
  241. {
  242. //Log it, but not much else we can do
  243. DLIST(3, "Attempted Write to BroadcastMS Err=" << Status << nl);
  244. return;
  245. }
  246. }
  247. handle_t
  248. WRKGRP_MACHINE_LOCATOR::GetBindingToMasterLocator(
  249. int * RetStatus)
  250. {
  251. /*
  252. Routine Description:
  253. Returns a binding handle to the master locator.
  254. Returns RPC_S_SERVER_UNAVAILABLE if master is unavailable
  255. */
  256. handle_t hNewHandle;
  257. unsigned long IState;
  258. UICHAR ServerName[UNCLEN+1];
  259. PCACHEDNODE pNode;
  260. BOOL TriedBroadcasting = FALSE;
  261. DataStructureMutex.Request();
  262. if ((IState = State) == BOUND)
  263. {
  264. *RetStatus = RpcBindingFromStringBindingW(
  265. MasterLocatorStringBinding,
  266. &hNewHandle
  267. );
  268. }
  269. DataStructureMutex.Clear();
  270. if (IState == BOUND)
  271. {
  272. ASSERT(*RetStatus == RPC_S_OK);
  273. return(hNewHandle);
  274. }
  275. //Now try all the cached locators, one after the other!
  276. while (1)
  277. {
  278. DataStructureMutex.Request();
  279. if (Head == NULL)
  280. {
  281. if (TriedBroadcasting == FALSE)
  282. {
  283. TryBroadcastingForMasterLocator();
  284. TriedBroadcasting = TRUE;
  285. DataStructureMutex.Clear();
  286. continue;
  287. }
  288. *RetStatus = RPC_S_SERVER_UNAVAILABLE;
  289. DataStructureMutex.Clear();
  290. break;
  291. }
  292. ServerName[0] = NIL;
  293. CatUZ((PUZ)ServerName, (PUZ)Head->ServerName);
  294. DataStructureMutex.Clear();
  295. hNewHandle = GetBindingToNamedLocator (
  296. (unsigned short *) ServerName,
  297. (int *)RetStatus
  298. );
  299. if (*RetStatus == RPC_S_OK)
  300. {
  301. return(hNewHandle);
  302. }
  303. else
  304. {
  305. DataStructureMutex.Request();
  306. pNode = FindCachedEntry(ServerName);
  307. pNode = DeleteCachedEntry(pNode);
  308. delete pNode;
  309. DataStructureMutex.Clear();
  310. }
  311. }
  312. }
  313. void
  314. NATIVE_CLASS_LOCATOR::DestroyBindingToMasterLocator()
  315. {
  316. DataStructureMutex.Request();
  317. State = UNBOUND;
  318. if (MasterLocator != 0)
  319. {
  320. delete MasterLocator;
  321. }
  322. if (MasterLocatorStringBinding != 0)
  323. {
  324. RpcStringFreeW(&MasterLocatorStringBinding);
  325. }
  326. MasterLocatorStringBinding = 0;
  327. DataStructureMutex.Clear();
  328. }
  329. void
  330. NATIVE_CLASS_LOCATOR::ProcessMessage(
  331. PQUERYLOCATOR Query,
  332. int * Status
  333. )
  334. {
  335. QUERYLOCATORREPLY Reply;
  336. int MailStatus;
  337. STATUS Err;
  338. *Status = NSI_S_OK;
  339. if (IsReplyNeeded(Query) == FALSE)
  340. return;
  341. //Copy SelfName
  342. Reply.SenderName[0] = Nil;
  343. CatUZ(Reply.SenderName, SelfName);
  344. Reply.Uptime = CurrentTimeMS() - LocatorStartTime;
  345. if (((InqIfIamMasterLocator() == TRUE)) || (SysType == ROLE_LMNT_PDC))
  346. {
  347. Reply.Hint = REPLY_MASTER_LOCATOR;
  348. }
  349. else
  350. if (State == BOUND)
  351. {
  352. Reply.Hint = REPLY_BOUND_LOCATOR;
  353. }
  354. else
  355. {
  356. Reply.Hint =
  357. ((SysType == ROLE_LMNT_BACKUPDC) ?
  358. REPLY_DC_LOCATOR : REPLY_OTHER_LOCATOR);
  359. }
  360. //Now form the return Mailslot name
  361. //
  362. UICHAR ReplyMSName[sizeof(RESPONDERMSLOT_C) +
  363. sizeof(Query->RequesterName)];
  364. ReplyMSName[0] = '\\';
  365. ReplyMSName[1] = '\\';
  366. ReplyMSName[2] = Nil;
  367. CatUZ(CatUZ(ReplyMSName, Query->RequesterName), RESPONDERMSLOT_C);
  368. WRITE_MAIL_SLOT MSReply(ReplyMSName, NIL, &Err);
  369. if (Err != NSI_S_OK)
  370. {
  371. DLIST( 3, "Error (" << *Status << ") creating a MSlot" << nl);
  372. return;
  373. }
  374. MailStatus = MSReply.Write((char *) &Reply, sizeof(Reply));
  375. if (MailStatus)
  376. {
  377. DLIST( 3, "Error (" << *Status << ") writting to MSlot" << nl);
  378. return;
  379. }
  380. }
  381. void
  382. DomainLocatorResponder(
  383. )
  384. /*++
  385. Routine Description:
  386. Each Locator has an additional thread that creates a mailslot
  387. This thread replies to queries that seek to find the master locator.
  388. This particular Responder runs on Domain locators only
  389. --*/
  390. {
  391. int Status;
  392. int MailStatus;
  393. int LongStatus;
  394. unsigned short LookupStatus;
  395. QUERYLOCATOR Query;
  396. QUERYLOCATORREPLY Reply;
  397. int cbBytesRead;
  398. READ_MAIL_SLOT hMSRead(RESPONDERMSLOT_S, sizeof(QUERYLOCATOR), &Status);
  399. DLIST(2, "starting LocatorSearchResponder Thread..\n");
  400. if (Status != NSI_S_OK)
  401. {
  402. AbortServer("Error in new mailslot", Status);
  403. }
  404. Reply.SenderName[0] = NIL;
  405. CatUZ(Reply.SenderName, SelfName);
  406. while (1)
  407. {
  408. ASSERT(AssertHeap());
  409. MailStatus = hMSRead.Read((PB) &Query, cbBytesRead);
  410. if (MailStatus)
  411. AbortServer("Mailslot read error", MailStatus);
  412. if (!CmpUZ(Query.RequesterName, SelfName))
  413. continue;
  414. DLIST(3, Query.RequesterName << " did query for locator" << nl);
  415. if (cbBytesRead != sizeof(QUERYLOCATOR))
  416. {
  417. DLIST(3, "Bummer, Bad Message of size(" << cbBytesRead
  418. << ") recvd" << nl);
  419. continue;
  420. }
  421. Locator->ProcessMessage(&Query, &LongStatus);
  422. }
  423. }
  424. void
  425. NATIVE_CLASS_LOCATOR::SetupHelperRoutine(
  426. )
  427. {
  428. void * pThreadHandle;
  429. DWORD ThreadId;
  430. pThreadHandle = CreateThread(
  431. 0,
  432. 0,
  433. (LPTHREAD_START_ROUTINE)DomainLocatorResponder,
  434. 0,
  435. 0,
  436. &ThreadId
  437. );
  438. }
  439. PCACHEDNODE
  440. WRKGRP_MACHINE_LOCATOR::FindCachedEntry(PUZ ServerName)
  441. {
  442. PCACHEDNODE pNode;
  443. for(pNode = Head; pNode; pNode = pNode->Next)
  444. {
  445. if ( CmpUZ(pNode->ServerName, (PUZ)ServerName) == 0 )
  446. {
  447. break;
  448. }
  449. }
  450. return(pNode);
  451. }
  452. void
  453. WRKGRP_MACHINE_LOCATOR::InsertCacheEntry(PCACHEDNODE pNode)
  454. {
  455. if (Tail == NULL)
  456. {
  457. ASSERT(Head == NULL);
  458. Tail = pNode;
  459. }
  460. pNode->Previous = 0;
  461. pNode->Next = Head;
  462. if (Head != NULL)
  463. Head->Previous = pNode;
  464. Head = pNode;
  465. CacheSize ++;
  466. }
  467. PCACHEDNODE
  468. WRKGRP_MACHINE_LOCATOR::DeleteCachedEntry(PCACHEDNODE pNode)
  469. {
  470. if (pNode == NULL)
  471. return((PCACHEDNODE)NULL);
  472. if (Head == pNode)
  473. Head = pNode->Next;
  474. if (Tail == pNode)
  475. Tail = pNode->Previous;
  476. if (pNode->Next != NULL)
  477. pNode->Next->Previous = pNode->Previous;
  478. if (pNode->Previous != NULL)
  479. pNode->Previous->Next = pNode->Next;
  480. CacheSize--;
  481. return(pNode);
  482. }
  483. void
  484. WRKGRP_MACHINE_LOCATOR::CacheThisServer(PUZ ServerName)
  485. {
  486. register PCACHEDNODE pNode;
  487. DataStructureMutex.Request();
  488. pNode = FindCachedEntry(ServerName);
  489. if (pNode == NULL)
  490. {
  491. pNode = new CACHEDNODE;
  492. pNode->Next = pNode->Previous = 0;
  493. pNode->ServerName[0] = NIL;
  494. CatUZ(pNode->ServerName, (PUZ)ServerName);
  495. if (CacheSize == CACHESIZE)
  496. DeleteCachedEntry(Tail);
  497. InsertCacheEntry(pNode);
  498. }
  499. else
  500. {
  501. if (pNode != Head)
  502. {
  503. pNode = DeleteCachedEntry(pNode);
  504. InsertCacheEntry(pNode);
  505. }
  506. }
  507. DataStructureMutex.Clear();
  508. }