Leaked source code of windows server 2003
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.

802 lines
19 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  3. Module Name:
  4. nsiclnt.cxx
  5. Abstract:
  6. This is the client side NSI service support layer. These are wrappers
  7. which call the name service provider.
  8. Author:
  9. Steven Zeck (stevez) 03/04/92
  10. --*/
  11. #include <nsi.h>
  12. #include <string.h>
  13. #include <time.h>
  14. // This structure is used in binding handle select processing.
  15. typedef struct
  16. {
  17. unsigned long Count;
  18. int IndexMatch[1];
  19. } MATCH_VECTOR;
  20. RPC_STATUS RPC_ENTRY
  21. I_NsBindingFoundBogus(RPC_BINDING_HANDLE *BindingHandle, DWORD BindId);
  22. RPC_STATUS RPC_ENTRY
  23. I_NsClientBindSearch(RPC_BINDING_HANDLE *NsiClntBinding, DWORD *BindId);
  24. void RPC_ENTRY
  25. I_NsClientBindDone(RPC_BINDING_HANDLE *NsiClntBinding, DWORD BindId);
  26. RPC_STATUS RPC_ENTRY
  27. RpcNsBindingLookupBeginW(
  28. IN unsigned long EntryNameSyntax,
  29. IN unsigned short __RPC_FAR * EntryName,
  30. IN RPC_IF_HANDLE RpcIfHandle,
  31. IN UUID __RPC_FAR * Object OPTIONAL,
  32. IN unsigned long BindingMaxCount,
  33. OUT RPC_NS_HANDLE *LookupContext
  34. )
  35. /*++
  36. Routine Description:
  37. Query the named server for the requested binding handles. This will
  38. request a query from name server to be performed and store the results
  39. to be retrieved with RpcNsBindingLookupNext().
  40. Arguments:
  41. EntryNameSyntax - This value describes the type/format of the EntryName.
  42. EntryName - Name that this export will be stored in. This is just a
  43. token that is passed on the the Name Server.
  44. RpcIfHandle - The interface that is being exported.
  45. Object - the object UUID that you are looking for (or in combination
  46. with RpcIfHandle).
  47. BindingMaxCount - The maxium size of the binding vector to be returned
  48. to the RpcNsBindingLookupNext function.
  49. LookupContext - handle to be used to pass to RpcNsBindingImportNext,
  50. This is really allocated by RpcNsLookupBinding
  51. SearchOptions - used by the auto handle binding routines and Micosoft
  52. name server.
  53. Returns:
  54. RPC_S_OK, RPC_S_NO_MORE_BINDINGS
  55. --*/
  56. {
  57. RPC_STATUS status;
  58. UNSIGNED16 NsiStatus;
  59. NSI_INTERFACE_ID_T NilIfOnWire, __RPC_FAR *IfPtr;
  60. RPC_BINDING_HANDLE NsiClntBinding = NULL;
  61. DWORD BindId = 0;
  62. if (RpcIfHandle == NULL)
  63. {
  64. IfPtr = &NilIfOnWire;
  65. memset(IfPtr, 0, sizeof(NSI_INTERFACE_ID_T));
  66. }
  67. else
  68. {
  69. IfPtr = (NSI_INTERFACE_ID_T __RPC_FAR *)
  70. &((PRPC_CLIENT_INTERFACE)RpcIfHandle)->InterfaceId;
  71. }
  72. while ((status = I_NsClientBindSearch(&NsiClntBinding, &BindId)) == RPC_S_OK)
  73. {
  74. // Provide the default entry name if there is none.
  75. if ((! EntryName || *EntryName == 0) && DefaultName)
  76. {
  77. EntryName = &(*DefaultName);
  78. EntryNameSyntax = DefaultSyntax;
  79. }
  80. else if (! EntryNameSyntax)
  81. EntryNameSyntax = DefaultSyntax;
  82. RpcTryExcept
  83. {
  84. nsi_binding_lookup_begin(NsiClntBinding, EntryNameSyntax, EntryName,
  85. IfPtr,
  86. (NSI_UUID_P_T) Object, BindingMaxCount, 0,
  87. LookupContext, &NsiStatus);
  88. }
  89. RpcExcept(1)
  90. {
  91. *LookupContext = 0;
  92. NsiStatus = MapException(RpcExceptionCode());
  93. }
  94. RpcEndExcept
  95. status = NsiMapStatus(NsiStatus);
  96. if (NsiStatus != NSI_S_NAME_SERVICE_UNAVAILABLE)
  97. break;
  98. I_NsBindingFoundBogus(&NsiClntBinding, BindId);
  99. }
  100. I_NsClientBindDone(&NsiClntBinding, BindId);
  101. return(status);
  102. }
  103. RPC_STATUS RPC_ENTRY
  104. RpcNsBindingLookupNext(
  105. IN RPC_NS_HANDLE LookupContext,
  106. OUT RPC_BINDING_VECTOR **BindingVector
  107. )
  108. /*++
  109. Routine Description:
  110. Retrieve the next group of bindings queryed from RpcNsBindingLookupBegin().
  111. Arguments:
  112. LookupContext - handle to allocated by RpcNsBindingLookupBegin()
  113. BindingVector - returns a pointer to a binding vector.
  114. Returns:
  115. RPC_S_OK, RPC_S_NO_MORE_BINDINGS, RPC_S_OUT_OF_MEMORY,
  116. nsi_binding_lookup_next()
  117. --*/
  118. {
  119. RPC_STATUS status;
  120. UNSIGNED16 NsiStatus;
  121. NSI_BINDING_VECTOR_T * NsiBindingVector;
  122. RPC_BINDING_HANDLE Handle;
  123. unsigned int HandleValide, Index;
  124. NsiBindingVector = 0;
  125. *BindingVector = 0;
  126. RpcTryExcept
  127. {
  128. nsi_binding_lookup_next((NSI_NS_HANDLE_T *) LookupContext,
  129. &NsiBindingVector, &NsiStatus);
  130. }
  131. RpcExcept(1)
  132. {
  133. NsiStatus = MapException(RpcExceptionCode());
  134. }
  135. RpcEndExcept
  136. if (NsiStatus)
  137. return(NsiMapStatus(NsiStatus));
  138. // Convert the string bindings to binding handles. This done by
  139. // replacing the StringBinding with RPC_BINDING_HANDLE to a
  140. // RPC_BINDING_VECTOR allocated by the runtime.
  141. *BindingVector = (RPC_BINDING_VECTOR *) I_RpcAllocate((unsigned int) (
  142. sizeof(RPC_BINDING_VECTOR) - sizeof(RPC_BINDING_HANDLE) +
  143. sizeof(RPC_BINDING_HANDLE) * NsiBindingVector->count));
  144. if (! *BindingVector)
  145. return(RPC_S_OUT_OF_MEMORY);
  146. for (Index = 0, HandleValide = 0;
  147. Index < NsiBindingVector->count; Index++)
  148. {
  149. Handle = 0;
  150. if (!UnicodeToRtString(NsiBindingVector->binding[Index].string))
  151. status = RpcBindingFromStringBinding(
  152. (RT_CHAR *)NsiBindingVector->binding[Index].string, &Handle);
  153. if (!status && NsiBindingVector->binding[Index].entry_name)
  154. {
  155. if (!UnicodeToRtString( NsiBindingVector->binding[Index].entry_name))
  156. {
  157. #ifdef NTENV
  158. status = I_RpcNsBindingSetEntryNameW(Handle,
  159. #else
  160. status = I_RpcNsBindingSetEntryName(Handle,
  161. #endif
  162. NsiBindingVector->binding[Index].entry_name_syntax,
  163. (RT_CHAR *)NsiBindingVector->binding[Index].entry_name);
  164. }
  165. }
  166. if (NsiBindingVector->binding[Index].entry_name)
  167. I_RpcFree(NsiBindingVector->binding[Index].entry_name);
  168. I_RpcFree(NsiBindingVector->binding[Index].string);
  169. // only copy the handle to the output if the Binding was OK.
  170. if (! status)
  171. (*BindingVector)->BindingH[HandleValide++] = Handle;
  172. }
  173. (*BindingVector)->Count = HandleValide;
  174. I_RpcFree(NsiBindingVector);
  175. return((HandleValide > 0)? RPC_S_OK: RPC_S_NO_MORE_BINDINGS);
  176. }
  177. RPC_STATUS RPC_ENTRY
  178. RpcNsBindingLookupDone(
  179. OUT RPC_NS_HANDLE *LookupContext
  180. )
  181. /*++
  182. Routine Description:
  183. Close the context opened with RpcNsBindingLookupBegin();
  184. Arguments:
  185. LookupContext - context handle to close
  186. Returns:
  187. nsi_binding_lookup_done()
  188. --*/
  189. {
  190. UNSIGNED16 NsiStatus = NSI_S_OK;
  191. RpcTryExcept
  192. {
  193. nsi_binding_lookup_done((NSI_NS_HANDLE_T *) LookupContext, &NsiStatus);
  194. }
  195. RpcExcept(1)
  196. {
  197. NsiStatus = MapException(RpcExceptionCode());
  198. }
  199. RpcEndExcept
  200. // RpcBindingFree(&NsiClntBinding);
  201. *LookupContext = 0;
  202. return(NsiMapStatus(NsiStatus));
  203. }
  204. RPC_STATUS RPC_ENTRY
  205. RpcNsBindingImportBeginW(
  206. IN unsigned long EntryNameSyntax,
  207. IN unsigned short __RPC_FAR * EntryName,
  208. IN RPC_IF_HANDLE RpcIfHandle,
  209. IN UUID __RPC_FAR * Object OPTIONAL,
  210. OUT RPC_NS_HANDLE *ImportContextOut
  211. )
  212. /*++
  213. Routine Description:
  214. Query the named server for the requested binding handles. This function
  215. is implemented in terms of RpcNsLookupBinding.
  216. Arguments:
  217. EntryNameSyntax - This value describes the type/format of the EntryName.
  218. EntryName - Name that this export will be stored in. This is just a
  219. token that is passed on the the Name Server.
  220. RpcIfHandle - The interface that is being exported.
  221. Object - the object UUID that you are looking for (or in combination
  222. with RpcIfHandle).
  223. ImportContext - handle to be used to pass to RpcNsBindingImportNext,
  224. This is really allocated by RpcNsLookupBinding
  225. SearchOptions - used by the auto handle binding routines and Micosoft
  226. name server.
  227. Returns:
  228. RpcNsBindingLookupBegin(), RPC_S_OUT_OF_MEMORY, RPS_S_OK
  229. --*/
  230. {
  231. RPC_STATUS status;
  232. RPC_NS_HANDLE LookupContext;
  233. PRPC_IMPORT_CONTEXT_P ImportContext;
  234. const int BindingVectorSize = 10;
  235. *ImportContextOut = 0;
  236. status = RpcNsBindingLookupBeginW(EntryNameSyntax, EntryName,
  237. RpcIfHandle, Object, BindingVectorSize, &LookupContext);
  238. if (status)
  239. return(status);
  240. // Allocate an import context which contains a lookup context,
  241. // a StringBinding vector and an index to the current StringBinding
  242. // in the vector.
  243. if (!(ImportContext = (PRPC_IMPORT_CONTEXT_P)
  244. I_RpcAllocate(sizeof(RPC_IMPORT_CONTEXT_P))) )
  245. return(RPC_S_OUT_OF_MEMORY);
  246. ImportContext->LookupContext = LookupContext;
  247. ImportContext->Bindings = 0;
  248. *ImportContextOut = ImportContext;
  249. return(RPC_S_OK);
  250. }
  251. RPC_STATUS RPC_ENTRY
  252. RpcNsBindingImportNext(
  253. IN RPC_NS_HANDLE ImportContextIn,
  254. OUT RPC_BINDING_HANDLE __RPC_FAR * RpcBinding
  255. )
  256. /*++
  257. Routine Description:
  258. Get the next StringBinding in the Import StringBinding vector. If
  259. the vector is empty, call RpcNsBindingLookupBegin() to get a new
  260. vector.
  261. Arguments:
  262. ImportContext - handle to be used get a new string binding vector from
  263. RpcNsBindingLookupNext()
  264. RpcBinding - place to return a binding. This Binding Handle ownership
  265. passes to caller.
  266. Returns:
  267. RPC_S_OK, RpcNsBindingLookupNext()
  268. --*/
  269. {
  270. RPC_STATUS status;
  271. PRPC_IMPORT_CONTEXT_P ImportContext;
  272. ImportContext = (PRPC_IMPORT_CONTEXT_P) ImportContextIn;
  273. if (!ImportContext)
  274. return(RPC_S_NO_CONTEXT_AVAILABLE);
  275. if (ImportContext->Bindings)
  276. {
  277. status = RpcNsBindingSelect(ImportContext->Bindings, RpcBinding);
  278. if (status == RPC_S_OK)
  279. return(RPC_S_OK);
  280. if (status != RPC_S_NO_MORE_BINDINGS)
  281. return(status);
  282. }
  283. // The vector was empty or there were no more entris. Get another vector.
  284. if (ImportContext->Bindings)
  285. RpcBindingVectorFree(&ImportContext->Bindings);
  286. status = RpcNsBindingLookupNext(ImportContext->LookupContext,
  287. &ImportContext->Bindings);
  288. if (status)
  289. return(status);
  290. return(RpcNsBindingSelect(ImportContext->Bindings, RpcBinding));
  291. }
  292. RPC_STATUS RPC_ENTRY
  293. RpcNsBindingImportDone(
  294. IN RPC_NS_HANDLE *ImportContextIn
  295. )
  296. /*++
  297. Routine Description:
  298. Close an Import Context handle when done. Free up the current
  299. Bindings vector, LookupContext and ImportContext structure.
  300. Arguments:
  301. ImportContext - handle to close.
  302. Returns:
  303. RPC_S_OK, RpcNsBindingLookupDone()
  304. --*/
  305. {
  306. RPC_STATUS status;
  307. PRPC_IMPORT_CONTEXT_P ImportContext;
  308. ImportContext = (PRPC_IMPORT_CONTEXT_P) *ImportContextIn;
  309. if (! ImportContext)
  310. return(RPC_S_OK);
  311. if (ImportContext->Bindings)
  312. RpcBindingVectorFree(&ImportContext->Bindings);
  313. status = RpcNsBindingLookupDone(&ImportContext->LookupContext);
  314. I_RpcFree (ImportContext);
  315. *ImportContextIn = 0;
  316. return(status);
  317. }
  318. RPC_STATUS RPC_ENTRY
  319. RpcNsMgmtHandleSetExpAge(
  320. IN RPC_NS_HANDLE NsHandle,
  321. IN unsigned long ExpirationAge
  322. )
  323. /*++
  324. Routine Description:
  325. Set the maxium age that a cached entry will be returned in reponse
  326. to a name service inquirary transaction.
  327. Arguments:
  328. NsHandle - context handle created with one of the RpcNs*Begin APIs
  329. Returns:
  330. nsi_mgmt_handle_set_exp_age()
  331. --*/
  332. {
  333. UNSIGNED16 NsiStatus;
  334. RPC_NS_HANDLE LookupContext =
  335. ((PRPC_IMPORT_CONTEXT_P)NsHandle)->LookupContext;
  336. RpcTryExcept
  337. {
  338. nsi_mgmt_handle_set_exp_age(LookupContext, ExpirationAge, &NsiStatus);
  339. }
  340. RpcExcept(1)
  341. {
  342. NsiStatus = MapException(RpcExceptionCode());
  343. }
  344. RpcEndExcept
  345. return(NsiMapStatus(NsiStatus));
  346. }
  347. #define isLocalName(NetWorkAddress) (1) //BUGBUG
  348. static RPC_STATUS
  349. GetMatchingProtocols(
  350. IN RPC_BINDING_VECTOR *BindingVector,
  351. OUT MATCH_VECTOR *MatchVector,
  352. IN char * SearchProtocol, OPTIONAL
  353. IN int fLocalOnly
  354. )
  355. /*++
  356. Routine Description:
  357. Construct a match binding vector with protocols that we are interested in.
  358. PERF: When we know how to parse NetWorkAddress to know when it is
  359. a local name, we should select those first
  360. Arguments:
  361. BindingVector - vector of binding handles to select from.
  362. MatchVector - place to put the results.
  363. SearchProtocol - Protocol we are looking for. A Nil matches everything.
  364. Returns:
  365. The number of protocols that we matched in the match vector.
  366. RPC_S_OK, RpcBindingToStringBinding(), RpcStringBindingParse()
  367. --*/
  368. {
  369. RPC_STATUS Status;
  370. unsigned int Index;
  371. RT_CHAR * StringBinding, *ProtocolSeq, *NetAddress;
  372. int fProtocolsMatched;
  373. MatchVector->Count = 0;
  374. for (Index = 0; Index < BindingVector->Count; Index++)
  375. {
  376. if (!BindingVector->BindingH[Index])
  377. continue;
  378. // Convert the binding handle to a string and then extract
  379. // the fields we are interested in.
  380. if (Status = RpcBindingToStringBinding(
  381. BindingVector->BindingH[Index], &StringBinding))
  382. return (Status);
  383. if (Status = RpcStringBindingParse(StringBinding, 0,
  384. &ProtocolSeq, &NetAddress, 0, 0))
  385. return (Status);
  386. fProtocolsMatched = 1;
  387. if (SearchProtocol)
  388. {
  389. char * STmp = SearchProtocol;
  390. for (RT_CHAR *pT = ProtocolSeq; *pT &&
  391. (char) *pT++ == *STmp++; ) ;
  392. if (*STmp)
  393. fProtocolsMatched = 0;
  394. }
  395. // If we are looking for a local name only and the matched
  396. // protocol isn't local, throw this one out.
  397. if (fLocalOnly && !isLocalName(NetAddress))
  398. fProtocolsMatched = 0;
  399. // Return all the strings to the RPC runtime.
  400. if (Status = RpcStringFree(&ProtocolSeq))
  401. return(Status);
  402. if (Status = RpcStringFree(&NetAddress))
  403. return(Status);
  404. if (Status = RpcStringFree(&StringBinding))
  405. return(Status);
  406. if (! fProtocolsMatched)
  407. continue;
  408. // A match is recorded as an index into the original vector.
  409. MatchVector->IndexMatch[MatchVector->Count++] = Index;
  410. }
  411. return(RPC_S_OK);
  412. }
  413. int
  414. RandomNumber(
  415. )
  416. /*++
  417. Routine Description:
  418. Yet another pseudo-random number generator.
  419. Returns:
  420. New random number, in the range 0..32767.
  421. --*/
  422. {
  423. static long holdrand;
  424. static int fInitialized = 0;
  425. // Start with a different seed everytime.
  426. if (!fInitialized)
  427. {
  428. fInitialized = 1;
  429. // holdrand = clock();
  430. }
  431. return( (int) (holdrand = (long) ( (holdrand * 214013L + 2531011L)
  432. >> 16 & 0x7fff ) ));
  433. }
  434. RPC_STATUS RPC_ENTRY
  435. RpcNsBindingSelect(
  436. IN OUT RPC_BINDING_VECTOR *BindingVector,
  437. OUT RPC_BINDING_HANDLE __RPC_FAR * RpcBinding
  438. )
  439. /*++
  440. Routine Description:
  441. This function will select a Binding handle from a vector of binding
  442. handles. Since we know a little bit about our binding handles, we
  443. will chose the more effiecent types of handles first. We select
  444. groups of bindings unordered via a random number generator.
  445. Arguments:
  446. BindingVector - vector of binding handles to select from
  447. RpcBinding - place to return the binding handle. The ownership of
  448. the handle passes to the caller.
  449. Returns:
  450. RPC_S_OK, RPC_S_OUT_OF_MEMORY, RPC_S_NO_MORE_BINDINGS, GetMatchingProtocols()
  451. --*/
  452. {
  453. static char * PreferredProtocol[] =
  454. {
  455. "ncalrpc",
  456. "ncacn_np",
  457. 0
  458. };
  459. int CountPreferredProtocol = sizeof(PreferredProtocol) / sizeof(void *);
  460. RPC_STATUS Status;
  461. MATCH_VECTOR *MatchVector;
  462. int IndexSelected;
  463. int ProtocolIndex;
  464. int fLocalOnly;
  465. *RpcBinding = 0;
  466. MatchVector = (MATCH_VECTOR *) I_RpcAllocate((unsigned int)
  467. (sizeof(MATCH_VECTOR) + sizeof(int) * BindingVector->Count));
  468. if (!MatchVector)
  469. return(RPC_S_OUT_OF_MEMORY);
  470. // For all the protocols returned, first try the local ones, then
  471. // the remote.
  472. for (fLocalOnly = 1; fLocalOnly >= 0; fLocalOnly--)
  473. {
  474. for (ProtocolIndex = 0; ProtocolIndex < CountPreferredProtocol;
  475. ProtocolIndex++)
  476. {
  477. // First, get the perferred protocols into a match vector.
  478. // The match vector has a range from 0..number of matching protocols.
  479. // We need this so we know what range to generate a random number.
  480. if (Status = GetMatchingProtocols(BindingVector, MatchVector,
  481. PreferredProtocol[ProtocolIndex], fLocalOnly))
  482. return(Status);
  483. // If we found any, select one and return it.
  484. if (MatchVector->Count)
  485. {
  486. IndexSelected = MatchVector->
  487. IndexMatch[RandomNumber() % MatchVector->Count];
  488. *RpcBinding = BindingVector->BindingH[IndexSelected];
  489. // Remove selected one from binding vector.
  490. BindingVector->BindingH[IndexSelected] = 0;
  491. I_RpcFree (MatchVector);
  492. return(RPC_S_OK);
  493. }
  494. }
  495. }
  496. I_RpcFree (MatchVector);
  497. return(RPC_S_NO_MORE_BINDINGS);
  498. }
  499. RPC_STATUS RPC_ENTRY
  500. RpcNsBindingLookupBeginA(
  501. IN unsigned long EntryNameSyntax,
  502. IN unsigned char __RPC_FAR * EntryName,
  503. IN RPC_IF_HANDLE RpcIfSpec,
  504. IN UUID __RPC_FAR * ObjUuid OPTIONAL,
  505. IN unsigned long BindingMaxCount,
  506. OUT RPC_NS_HANDLE *LookupContext
  507. )
  508. /*++
  509. Routine Description:
  510. This is an ASCII wrapper to the UNICODE version of the API. It
  511. converts all char * -> short * strings and calls the UNICODE version.
  512. --*/
  513. {
  514. WIDE_STRING EntryNameW(EntryName);
  515. if (EntryNameW.OutOfMemory())
  516. return(RPC_S_OUT_OF_MEMORY);
  517. return(RpcNsBindingLookupBeginW(EntryNameSyntax, &EntryNameW,
  518. RpcIfSpec, ObjUuid, BindingMaxCount, LookupContext));
  519. }
  520. RPC_STATUS RPC_ENTRY
  521. RpcNsBindingImportBeginA(
  522. IN unsigned long EntryNameSyntax,
  523. IN unsigned char __RPC_FAR * EntryName,
  524. IN RPC_IF_HANDLE RpcIfSpec,
  525. IN UUID __RPC_FAR * ObjUuid OPTIONAL,
  526. OUT RPC_NS_HANDLE *ImportContext
  527. )
  528. /*++
  529. Routine Description:
  530. This is an ASCII wrapper to the UNICODE version of the API. It
  531. converts all char * -> short * strings and calls the UNICODE version.
  532. --*/
  533. {
  534. WIDE_STRING EntryNameW(EntryName);
  535. if (EntryNameW.OutOfMemory())
  536. return(RPC_S_OUT_OF_MEMORY);
  537. return(RpcNsBindingImportBeginW(EntryNameSyntax, &EntryNameW,
  538. RpcIfSpec, ObjUuid, ImportContext));
  539. }