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.

748 lines
17 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. cbind.cxx
  5. Abstract:
  6. This is the client side NSI service support layer. These functions
  7. provide for binding to the locator or other name server.
  8. Author:
  9. Steven Zeck (stevez) 03/04/92
  10. --*/
  11. extern "C"
  12. {
  13. #define NSI_ASCII
  14. #include <nsi.h>
  15. #ifndef NTENV
  16. #include <netcons.h>
  17. #include <neterr.h>
  18. #include <server.h>
  19. #include <access.h>
  20. #include <regapi.h>
  21. #include <mailslot.h>
  22. #include <wksta.h>
  23. #ifndef USHORT
  24. #define USHORT unsigned short
  25. #endif
  26. #else
  27. #include <windows.h>
  28. #include <lmcons.h>
  29. #include <lmapibuf.h>
  30. #include <lmaccess.h>
  31. #include <lmserver.h>
  32. #include <stdlib.h>
  33. #include "startsvc.h"
  34. #endif
  35. #include <string.h>
  36. #ifndef NTENV
  37. #include "locquery.h"
  38. #endif
  39. extern "C"
  40. {
  41. unsigned long RPC_ENTRY
  42. I_GetDefaultEntrySyntax(
  43. );
  44. }
  45. void RpcNsLmDiscard(void);
  46. #ifndef NTENV
  47. unsigned short BroadcastAQuery(unsigned long Query,
  48. char __RPC_FAR * Buffer,
  49. unsigned short Count);
  50. #define MAXLOCATORSTOTRY 8
  51. #endif
  52. #ifdef NTENV
  53. #define LOCALLOCATOR "\\\\."
  54. #endif
  55. #if defined(DOS) && !defined(WIN)
  56. extern int _NsAllocatorInitialized;
  57. extern __RPC_API NsAllocatorSetup();
  58. #define INIT_DOS_ALLOCATOR_IF_NECESSARY \
  59. { if (!_NsAllocatorInitialized) NsAllocatorSetup(); }
  60. #else // DOS only
  61. #define INIT_DOS_ALLOCATOR_IF_NECESSARY
  62. #endif // DOS only
  63. } // extern "C"
  64. RPC_BINDING_HANDLE NsiClntBinding; // global binding handle to locator
  65. unsigned char * NsiStringBinding;
  66. enum {
  67. BindingNil = 0,
  68. BindingDC,
  69. #ifndef NTENV
  70. BindingBackupFirst,
  71. BindingBackup,
  72. #endif
  73. BindingFound,
  74. BindingFoundRetry,
  75. #ifndef NTENV
  76. BindToBackupViaBC,
  77. BindToAnyViaBC
  78. #endif
  79. };
  80. #define NilOffset (-1)
  81. typedef struct
  82. {
  83. unsigned char *ProtoSeq;
  84. unsigned char *NetworkAddress;
  85. unsigned char *Endpoint;
  86. HKEY RegHandle;
  87. unsigned int NumberServers;
  88. int AddressOffset;
  89. void *Buffer;
  90. char *ServerList;
  91. int State;
  92. } RPC_LOCATOR_BIND_CONTEXT, *PRPC_LOCATOR_BIND_CONTEXT;
  93. #define MAX_SERVER_NAME 20
  94. static RPC_LOCATOR_BIND_CONTEXT near BindSearch;
  95. WIDE_STRING *DefaultName;
  96. long DefaultSyntax = RPC_C_NS_SYNTAX_DCE;
  97. int fSyntaxDefaultsLoaded;
  98. #ifndef NTENV
  99. char __RPC_FAR * MailslotName = "\\\\*\\mailslot\\Resp_s";
  100. char __RPC_FAR * LocalMS = "\\mailslot\\Resp_c";
  101. #define RESPONSETIME 4096L
  102. #endif
  103. unsigned char *
  104. RegGetString(
  105. IN void * RegHandle,
  106. IN char * KeyName
  107. )
  108. /*++
  109. Routine Description:
  110. Get a string from the registery.
  111. Arguments:
  112. KeyName - name of key to lookup.
  113. Returns:
  114. pointer to the allocated string, or Nil if not found
  115. --*/
  116. {
  117. char Buffer[300];
  118. DWORD BufferLength = sizeof(Buffer);
  119. DWORD Type;
  120. #ifdef NTENV
  121. if (RegQueryValueEx((HKEY)RegHandle, KeyName, 0, &Type,
  122. (unsigned char far*)Buffer, &BufferLength))
  123. #else
  124. if (RegQueryValue((HKEY)RegHandle, KeyName,
  125. (char far*)Buffer, &BufferLength))
  126. #endif
  127. return(0);
  128. return(CopyString(Buffer));
  129. }
  130. static RPC_STATUS
  131. Bind(
  132. )
  133. /*++
  134. Routine Description:
  135. Bind to the locator server
  136. Returns:
  137. RpcBindingFromStringBinding()
  138. --*/
  139. {
  140. RPC_STATUS status;
  141. unsigned char AddressBuffer[100];
  142. if (NsiClntBinding)
  143. {
  144. status = RpcBindingFree(&NsiClntBinding);
  145. ASSERT(!status);
  146. }
  147. status = RpcStringFree(&NsiStringBinding);
  148. ASSERT(!status);
  149. // Get the next path componet from the NetworkAddress field.
  150. // Conponets are ; delimited fields.
  151. ASSERT(BindSearch.AddressOffset >= 0);
  152. for (int i = 0; i < sizeof(AddressBuffer); BindSearch.AddressOffset++, i++)
  153. {
  154. AddressBuffer[i] =
  155. BindSearch.NetworkAddress[BindSearch.AddressOffset];
  156. if (BindSearch.NetworkAddress[BindSearch.AddressOffset] == ';')
  157. {
  158. BindSearch.AddressOffset++;
  159. // If there are two ;; in a row, then pass through the ;
  160. // as a literal instead of a path seperator.
  161. if (BindSearch.NetworkAddress[BindSearch.AddressOffset] == ';')
  162. continue;
  163. AddressBuffer[i] = 0;
  164. break;
  165. }
  166. if (BindSearch.NetworkAddress[BindSearch.AddressOffset] == 0)
  167. {
  168. BindSearch.AddressOffset = NilOffset;
  169. break;
  170. }
  171. }
  172. status = RpcStringBindingCompose(0, BindSearch.ProtoSeq,
  173. AddressBuffer, BindSearch.Endpoint,
  174. 0, &NsiStringBinding);
  175. if (status)
  176. return(status);
  177. return (RpcBindingFromStringBinding(NsiStringBinding, &NsiClntBinding));
  178. }
  179. RPC_STATUS RPC_ENTRY
  180. I_NsClientBindSearch(
  181. )
  182. /*++
  183. Routine Description:
  184. The function binds to the locator, first it tries to bind to a
  185. local machine, then it attempts to bind to the domain controller.
  186. Arguments:
  187. BindingSearchContext - context of search for the locator.
  188. Returns:
  189. RPC_S_OK, RPC_S_NO_BINDINGS, RPC_S_CANNOT_BIND, RPC_S_OUT_OF_RESOURCES
  190. --*/
  191. {
  192. long status;
  193. #ifndef NTENV
  194. unsigned short cbSI;
  195. #define SERVER_INFO struct server_info_0
  196. #define ServerName(p) ((struct server_info_0 *)p)->sv0_name
  197. unsigned short Count = 1;
  198. QUERYLOCATORREPLY Reply, __RPC_FAR * QueryReply;
  199. #else
  200. #define SERVER_INFO SERVER_INFO_100
  201. #define ServerName(p) ((SERVER_INFO_100 *)p)->sv100_name
  202. #endif
  203. INIT_DOS_ALLOCATOR_IF_NECESSARY;
  204. switch (BindSearch.State)
  205. {
  206. case BindingNil:
  207. RequestGlobalMutex();
  208. case BindingFoundRetry:
  209. memset(&BindSearch, 0, sizeof(RPC_LOCATOR_BIND_CONTEXT));
  210. BindSearch.State++;
  211. // We store the binding information on the name service in
  212. // the registry. Get the information into BindingHandle.
  213. #ifdef NTENV
  214. status = RegOpenKeyEx(RPC_REG_ROOT, REG_NSI, 0L, KEY_READ,
  215. &BindSearch.RegHandle);
  216. #else
  217. status = RegOpenKey(RPC_REG_ROOT, REG_NSI, &BindSearch.RegHandle);
  218. #endif
  219. if (status)
  220. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  221. BindSearch.ProtoSeq = RegGetString((void *) BindSearch.RegHandle, "Protocol");
  222. BindSearch.NetworkAddress = RegGetString((void *) BindSearch.RegHandle,
  223. "NetworkAddress");
  224. BindSearch.Endpoint = RegGetString((void *) BindSearch.RegHandle, "Endpoint");
  225. GetDefaultEntrys((void *) BindSearch.RegHandle);
  226. if (!BindSearch.ProtoSeq || !BindSearch.Endpoint)
  227. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  228. #ifdef NTENV
  229. if (
  230. (BindSearch.NetworkAddress == NULL)
  231. || (BindSearch.NetworkAddress[0] == '\0')
  232. || (!strncmp((char *) BindSearch.NetworkAddress, LOCALLOCATOR,
  233. strlen(LOCALLOCATOR)))
  234. )
  235. {
  236. StartServiceIfNecessary();
  237. }
  238. #endif
  239. return (Bind());
  240. case BindingDC:
  241. if (BindSearch.AddressOffset != NilOffset)
  242. return (Bind());
  243. #ifdef NTENV
  244. //Looks like we forgot to free NetWork addreess..
  245. //Not really- BindDone does it.
  246. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  247. #else
  248. if (BindSearch.NetworkAddress)
  249. delete BindSearch.NetworkAddress;
  250. // Don't search the Net if we aren't looking for the locator.
  251. if (strcmp((char *)BindSearch.Endpoint, "\\pipe\\locator"))
  252. {
  253. BindSearch.State = BindingNil;
  254. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  255. }
  256. BindSearch.State++;
  257. BindSearch.NetworkAddress = new unsigned char [MAX_SERVER_NAME];
  258. // second, try the domain controller
  259. if (NetGetDCName(0, 0, (char far *) BindSearch.NetworkAddress,
  260. MAX_SERVER_NAME))
  261. {
  262. BindSearch.State = BindingNil;
  263. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  264. }
  265. BindSearch.AddressOffset = 0;
  266. return(Bind());
  267. case BindingBackupFirst:
  268. BindSearch.State++;
  269. BindSearch.NumberServers = 0;
  270. // third, try all the member servers. First get the # of bytes
  271. // needed to hold all the names, then retrive them.
  272. NetServerEnum2(0, 0, 0, 0,
  273. (USHORT *) &BindSearch.NumberServers,
  274. (USHORT *) &BindSearch.NumberServers,
  275. SV_TYPE_DOMAIN_BAKCTRL, 0);
  276. cbSI = (BindSearch.NumberServers+2) * sizeof(SERVER_INFO);
  277. BindSearch.Buffer = new char [cbSI];
  278. BindSearch.ServerList = (char *) BindSearch.Buffer;
  279. if (!BindSearch.ServerList)
  280. {
  281. BindSearch.State = BindingNil;
  282. return(RPC_S_OUT_OF_RESOURCES);
  283. }
  284. if (NetServerEnum2(0, 0, (char far *)BindSearch.ServerList, cbSI,
  285. (USHORT *) &BindSearch.NumberServers,
  286. (USHORT *) &BindSearch.NumberServers,
  287. SV_TYPE_DOMAIN_BAKCTRL, 0))
  288. {
  289. delete BindSearch.Buffer;
  290. BindSearch.State = BindingNil;
  291. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  292. }
  293. case BindingBackup:
  294. if (BindSearch.NumberServers == 0)
  295. {
  296. delete BindSearch.Buffer;
  297. BindSearch.Buffer = new char [sizeof(QUERYLOCATORREPLY) *
  298. MAXLOCATORSTOTRY];
  299. if (BindSearch.Buffer == NULL)
  300. {
  301. BindSearch.State = BindingNil;
  302. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  303. }
  304. BindSearch.State = BindToBackupViaBC;
  305. BindSearch.ServerList = (char *)BindSearch.Buffer;
  306. BindSearch.NumberServers = BroadcastAQuery(
  307. QUERY_DC_LOCATOR,
  308. (char __RPC_FAR *)BindSearch.Buffer,
  309. MAXLOCATORSTOTRY
  310. );
  311. }
  312. else
  313. {
  314. BindSearch.NumberServers--;
  315. BindSearch.NetworkAddress[0] = '\\';
  316. BindSearch.NetworkAddress[1] = '\\';
  317. strcpy((char far *)BindSearch.NetworkAddress+2,
  318. ServerName(BindSearch.ServerList));
  319. BindSearch.ServerList += sizeof(SERVER_INFO);
  320. BindSearch.AddressOffset = 0;
  321. return(Bind());
  322. }
  323. case BindToBackupViaBC:
  324. if (BindSearch.NumberServers == 0)
  325. {
  326. //The buffer is already setup, use it for next phase
  327. BindSearch.NumberServers = BroadcastAQuery(
  328. QUERY_ANY_LOCATOR,
  329. (char __RPC_FAR *)BindSearch.Buffer,
  330. MAXLOCATORSTOTRY
  331. );
  332. BindSearch.State = BindToAnyViaBC;
  333. BindSearch.ServerList = (char *) BindSearch.Buffer;
  334. }
  335. else
  336. {
  337. BindSearch.NumberServers--;
  338. QueryReply = (QUERYLOCATORREPLY __RPC_FAR *)
  339. BindSearch.ServerList;
  340. UnicodeToAscii(QueryReply->SenderName);
  341. strcpy((char __RPC_FAR *) BindSearch.NetworkAddress,
  342. (char __RPC_FAR *)QueryReply->SenderName);
  343. BindSearch.ServerList = (char __RPC_FAR *)(QueryReply+1);
  344. BindSearch.AddressOffset = 0;
  345. return(Bind());
  346. }
  347. //In the If case - we intentionally fall through to the
  348. //BindAny state.
  349. case BindToAnyViaBC:
  350. if (BindSearch.NumberServers == 0)
  351. {
  352. BindSearch.State = BindingNil;
  353. delete BindSearch.Buffer;
  354. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  355. }
  356. else
  357. {
  358. BindSearch.NumberServers--;
  359. QueryReply = (QUERYLOCATORREPLY __RPC_FAR *)
  360. BindSearch.ServerList;
  361. UnicodeToAscii(QueryReply->SenderName);
  362. strcpy((char __RPC_FAR *) BindSearch.NetworkAddress,
  363. (char __RPC_FAR *)QueryReply->SenderName);
  364. BindSearch.ServerList = (char __RPC_FAR *)(QueryReply+1);
  365. BindSearch.AddressOffset = 0;
  366. return(Bind());
  367. }
  368. break;
  369. #endif
  370. case BindingFound:
  371. BindSearch.State++;
  372. RequestGlobalMutex();
  373. return(RpcBindingFromStringBinding(NsiStringBinding, &NsiClntBinding));
  374. }
  375. ASSERT(!"Bad Search State");
  376. BindSearch.State = BindingNil;
  377. return(RPC_S_NAME_SERVICE_UNAVAILABLE);
  378. }
  379. void RPC_ENTRY
  380. I_NsClientBindDone(
  381. )
  382. /*++
  383. Routine Description:
  384. The function cleans up after binding to the locator.
  385. Returns:
  386. --*/
  387. {
  388. long status;
  389. RPC_STATUS RpcStatus;
  390. switch (BindSearch.State)
  391. {
  392. case BindingFound:
  393. break;
  394. case BindingNil:
  395. break;
  396. case BindingDC:
  397. case BindingFoundRetry:
  398. BindSearch.State = BindingFound;
  399. break;
  400. #ifndef NTENV
  401. case BindToAnyViaBC:
  402. case BindToBackupViaBC:
  403. case BindingBackup:
  404. delete BindSearch.Buffer;
  405. #endif
  406. #ifndef NTENV
  407. case BindingBackupFirst:
  408. status = RegSetValue(BindSearch.RegHandle, "NetworkAddress",
  409. REG_SZ, (LPSTR) BindSearch.NetworkAddress,
  410. strlen((CONST_CHAR *)BindSearch.NetworkAddress) + 1);
  411. BindSearch.State = BindingFound;
  412. ASSERT(!status);
  413. break;
  414. #endif
  415. default:
  416. ASSERT(!"Bad State - \n");
  417. }
  418. if (BindSearch.RegHandle)
  419. {
  420. status = RegCloseKey(BindSearch.RegHandle);
  421. ASSERT(!status);
  422. BindSearch.RegHandle = 0;
  423. delete BindSearch.NetworkAddress;
  424. delete BindSearch.ProtoSeq;
  425. delete BindSearch.Endpoint;
  426. }
  427. #if defined(DOS) && !defined(WIN)
  428. // Unloaded the big fat lanman stuff now that we are done searching.
  429. RpcNsLmDiscard();
  430. #endif
  431. ClearGlobalMutex();
  432. RpcStatus = RpcBindingFree(&NsiClntBinding);
  433. ASSERT(!RpcStatus);
  434. }
  435. unsigned long RPC_ENTRY
  436. I_GetDefaultEntrySyntax(
  437. )
  438. /*++
  439. Routine Description:
  440. Called by the runtime DLL when it needs to know the default syntax.
  441. Currently this is used only by RpcBindingInqEntry().
  442. Arguments:
  443. none
  444. Return Value:
  445. the entry syntax
  446. Exceptions:
  447. none
  448. --*/
  449. {
  450. return (unsigned long) DefaultSyntax;
  451. }
  452. #ifndef NTENV
  453. unsigned short BroadcastAQuery(
  454. unsigned long Type,
  455. char __RPC_FAR * Buffer,
  456. unsigned short Count
  457. )
  458. {
  459. unsigned short Err;
  460. unsigned MSHandle;
  461. unsigned short Returned, NextSize, NextPri, Avail;
  462. unsigned short RetCount = 0;
  463. QUERYLOCATOR Query;
  464. unsigned long TimeRemaining = RESPONSETIME;
  465. wksta_info_10 __RPC_FAR * Wkio10;
  466. char __RPC_FAR * pBuf;
  467. unsigned short __RPC_FAR * pUZ;
  468. //First try and get the computer name
  469. Err = NetWkstaGetInfo(
  470. 0L,
  471. 10,
  472. (char __RPC_FAR *) 0L,
  473. 0,
  474. &Avail);
  475. ASSERT(Err == NERR_BufTooSmall);
  476. Wkio10 = (wksta_info_10 __RPC_FAR *) new char [Avail];
  477. if (Wkio10 == 0L)
  478. {
  479. return 0;
  480. }
  481. Err = NetWkstaGetInfo(
  482. 0L,
  483. 10,
  484. (char __RPC_FAR *) Wkio10,
  485. Avail,
  486. &Avail
  487. );
  488. //Format the Query!
  489. Query.MessageType = Type;
  490. Query.SenderOsType= OS_WIN31DOS;
  491. for (pBuf = &Wkio10->wki10_computername[0],pUZ = &Query.RequesterName[0];
  492. *pBuf !=0;
  493. pBuf++, pUZ++)
  494. *pUZ = *pBuf;
  495. *pUZ = 0;
  496. Err = DosMakeMailslot(
  497. LocalMS,
  498. sizeof(QUERYLOCATORREPLY),
  499. 0,
  500. &MSHandle
  501. );
  502. if (Err != NERR_Success)
  503. {
  504. return 0;
  505. }
  506. Err = DosWriteMailslot(
  507. MailslotName,
  508. (char __RPC_FAR *) &Query,
  509. sizeof(Query),
  510. 0, //Priority
  511. 2, //Class
  512. 0 //Timeout
  513. );
  514. if (Err != NERR_Success)
  515. goto CleanupAndExit;
  516. //Now sit in a loop and wait
  517. //for WAITRESPONSE secs
  518. while ((TimeRemaining) && (RetCount < Count))
  519. {
  520. Err = DosReadMailslot(
  521. MSHandle,
  522. Buffer,
  523. &Returned,
  524. &NextSize,
  525. &NextPri,
  526. TimeRemaining
  527. );
  528. if (Err == NERR_Success)
  529. {
  530. ASSERT (Returned == sizeof(QUERYLOCATORREPLY));
  531. Buffer += sizeof(QUERYLOCATORREPLY);
  532. RetCount ++;
  533. TimeRemaining >> 1;
  534. continue;
  535. }
  536. break;
  537. } //end of while ReadMS
  538. CleanupAndExit:
  539. DosDeleteMailslot(MSHandle);
  540. return (RetCount);
  541. }
  542. #endif