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.

1979 lines
50 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. binding.cxx
  5. Abstract:
  6. The implementation of the DCE binding class is contained in this
  7. file.
  8. Author:
  9. Michael Montague (mikemon) 04-Nov-1991
  10. Revision History:
  11. --*/
  12. #include <precomp.hxx>
  13. #include <epmap.h>
  14. #ifdef DOSWIN32RPC
  15. #define DBCS_ENABLED 1
  16. #endif
  17. #ifdef WIN
  18. //NotifyRegister writes over hTask:0x28.
  19. //We sacrifice the 0x40 bytes to appease the Win31 gods here
  20. //
  21. char LeaveSomeRoom[0x30] = { 'x' };
  22. #endif
  23. #ifdef WIN32RPC
  24. UUID MgmtIf = { 0xafa8bd80,0x7d8a,0x11c9,
  25. {0xbe,0xf4,0x08,0x00,0x2b,0x10,0x29,0x89} };
  26. UUID NullUuid = { 0L, 0, 0, {0,0,0,0,0,0,0,0} };
  27. int
  28. IsMgmtIfUuid(
  29. UUID PAPI * IfId
  30. )
  31. {
  32. if (RpcpMemoryCompare(IfId, &MgmtIf, sizeof(UUID)) == 0)
  33. {
  34. return 1;
  35. }
  36. return 0;
  37. }
  38. #endif
  39. RPC_CHAR *
  40. DuplicateString (
  41. IN RPC_CHAR PAPI * String
  42. )
  43. /*++
  44. Routine Description:
  45. When this routine is called, it will duplicate the string into a fresh
  46. string and return it.
  47. Arguments, either:
  48. String - Supplies the string to be duplicated.
  49. Ansi String - Supplies the string to be duplicated.
  50. Return Value:
  51. The duplicated string is returned. If insufficient memory is available
  52. to allocate a fresh string, zero will be returned.
  53. --*/
  54. {
  55. RPC_CHAR * FreshString, * FreshStringScan;
  56. RPC_CHAR PAPI * StringScan;
  57. unsigned int Length;
  58. Length = 1;
  59. StringScan = String;
  60. while (*StringScan++ != 0)
  61. Length += 1;
  62. FreshString = new RPC_CHAR[Length];
  63. if (FreshString == 0)
  64. return(0);
  65. for (FreshStringScan = FreshString, StringScan = String;
  66. *StringScan != 0; FreshStringScan++, StringScan++)
  67. {
  68. *FreshStringScan = *StringScan;
  69. }
  70. *FreshStringScan = *StringScan;
  71. return(FreshString);
  72. }
  73. DCE_BINDING::DCE_BINDING (
  74. IN RPC_CHAR PAPI * ObjectUuid OPTIONAL,
  75. IN RPC_CHAR PAPI * RpcProtocolSequence OPTIONAL,
  76. IN RPC_CHAR PAPI * NetworkAddress OPTIONAL,
  77. IN RPC_CHAR PAPI * Endpoint OPTIONAL,
  78. IN RPC_CHAR PAPI * Options OPTIONAL,
  79. OUT RPC_STATUS PAPI * Status
  80. )
  81. /*++
  82. Routine Description:
  83. The constructor creates a DCE_BINDING object based on the pieces of
  84. the string binding specified.
  85. Arguments:
  86. ObjectUuid - Optionally supplies the object uuid component of the
  87. binding.
  88. RpcProtocolSequence - Optionally supplies the rpc protocol sequence
  89. component of the binding.
  90. NetworkAddress - Optionally supplies the network address component
  91. of the binding.
  92. Endpoint - Optionally supplies the endpoint component of the binding.
  93. Options - Optionally supplies the network options component of the
  94. binding.
  95. Status - Returns the status of the operation. This argument will
  96. be set to one of the following values.
  97. RPC_S_OK - The operation completed successfully.
  98. RPC_S_INVALID_STRING_UUID - The specified object uuid does
  99. not contain the valid string representation of a uuid.
  100. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to
  101. complete the operation.
  102. --*/
  103. {
  104. ALLOCATE_THIS(DCE_BINDING);
  105. *Status = RPC_S_OK;
  106. if ( ARGUMENT_PRESENT(ObjectUuid)
  107. && (ObjectUuid[0] != 0))
  108. {
  109. if (this->ObjectUuid.ConvertFromString(ObjectUuid))
  110. {
  111. *Status = RPC_S_INVALID_STRING_UUID;
  112. this->ObjectUuid.SetToNullUuid();
  113. }
  114. }
  115. else
  116. this->ObjectUuid.SetToNullUuid();
  117. if (ARGUMENT_PRESENT(RpcProtocolSequence))
  118. {
  119. this->RpcProtocolSequence = DuplicateString(RpcProtocolSequence);
  120. if (this->RpcProtocolSequence == 0)
  121. *Status = RPC_S_OUT_OF_MEMORY;
  122. }
  123. else
  124. this->RpcProtocolSequence = 0;
  125. if (ARGUMENT_PRESENT(NetworkAddress))
  126. {
  127. this->NetworkAddress = DuplicateString(NetworkAddress);
  128. if (this->NetworkAddress == 0)
  129. *Status = RPC_S_OUT_OF_MEMORY;
  130. }
  131. else
  132. this->NetworkAddress = 0;
  133. if (ARGUMENT_PRESENT(Endpoint))
  134. {
  135. this->Endpoint = DuplicateString(Endpoint);
  136. if (this->Endpoint == 0)
  137. *Status = RPC_S_OUT_OF_MEMORY;
  138. }
  139. else
  140. this->Endpoint = 0;
  141. if (ARGUMENT_PRESENT(Options))
  142. {
  143. this->Options = DuplicateString(Options);
  144. if (this->Options == 0)
  145. *Status = RPC_S_OUT_OF_MEMORY;
  146. }
  147. else
  148. {
  149. this->Options = AllocateEmptyString();
  150. if (this->Options == 0)
  151. *Status = RPC_S_OUT_OF_MEMORY;
  152. }
  153. }
  154. /*static*/ RPC_CHAR PAPI *
  155. StringCharSearchWithEscape (
  156. IN RPC_CHAR PAPI * String,
  157. IN unsigned int Character
  158. )
  159. /*++
  160. Routine Description:
  161. This routine is the same as the library routine, strchr, except that
  162. the backslash character ('\') is treated as an escape character.
  163. Arguments:
  164. String - Supplies the string in which to search for the character.
  165. Character - Supplies the character to search for in the string.
  166. Return Value:
  167. A pointer to the first occurance of Character in String is returned.
  168. If Character does not exist in String, then 0 is returned.
  169. --*/
  170. {
  171. #ifdef DBCS_ENABLED
  172. ASSERT(IsDBCSLeadByte((RPC_CHAR)Character) == FALSE);
  173. ASSERT(IsDBCSLeadByte(RPC_CONST_CHAR('\\')) == FALSE);
  174. while(*String != (RPC_CHAR)Character)
  175. {
  176. if (*String == 0)
  177. return(0);
  178. if (*String == RPC_CONST_CHAR('\\'))
  179. {
  180. String = (RPC_CHAR *)CharNext((LPCSTR)String);
  181. }
  182. String = (RPC_CHAR *)CharNext((LPCSTR)String);
  183. }
  184. return(String);
  185. #else
  186. while (*String != (RPC_CHAR) Character)
  187. {
  188. if (*String == 0)
  189. return(0);
  190. if (*String == RPC_CONST_CHAR('\\'))
  191. String++;
  192. String++;
  193. }
  194. return(String);
  195. #endif
  196. }
  197. /*static*/ void
  198. StringCopyWithEscape (
  199. OUT RPC_CHAR PAPI * Destination,
  200. IN RPC_CHAR PAPI * Source
  201. )
  202. /*++
  203. Routine Description:
  204. This routine is the same as the library routine, strcpy, except that
  205. the backslash character ('\') is treated as an escape character. When
  206. a character is escaped, the backslash character is not copied to the
  207. Destination.
  208. Arguments:
  209. Destination - Returns a duplicate of the string specified in Source,
  210. but with out escaped characters escaped.
  211. Source - Specifies the string to be copied.
  212. Return Value:
  213. None.
  214. --*/
  215. {
  216. BOOL fLastQuote = FALSE;
  217. #ifdef DBCS_ENABLED
  218. ASSERT(IsDBCSLeadByte('\\') == FALSE);
  219. #endif
  220. while ((*Destination = *Source) != 0)
  221. {
  222. #ifdef DBCS_ENABLED
  223. if (IsDBCSLeadByte(*Source))
  224. {
  225. // Copy the whole DBCS character; don't look for
  226. // escapes within the character.
  227. Destination++;
  228. Source++;
  229. *Destination = *Source;
  230. if (*Source == 0)
  231. {
  232. ASSERT(0); // Bad string, NULL following a lead byte.
  233. return;
  234. }
  235. Destination++;
  236. Source++;
  237. }
  238. else
  239. #endif
  240. {
  241. if ( *Source != RPC_CONST_CHAR('\\')
  242. || fLastQuote == TRUE)
  243. {
  244. Destination++;
  245. fLastQuote = FALSE;
  246. }
  247. else
  248. {
  249. fLastQuote = TRUE;
  250. }
  251. Source++;
  252. }
  253. }
  254. }
  255. /*static*/ RPC_STATUS
  256. ParseAndCopyEndpointField (
  257. OUT RPC_CHAR ** Endpoint,
  258. IN RPC_CHAR PAPI * String
  259. )
  260. /*++
  261. Routine Description:
  262. This routine parses and then copies the endpoint field in String. A
  263. copy of the field is made into a newly allocated string and returned
  264. in Endpoint. String is assumed to contain only the endpoint field;
  265. the terminating ',' or ']' are not included.
  266. Arguments:
  267. Endpoint - Returns a copy of the endpoint field in a newly allocated
  268. string.
  269. String - Supplies the endpoint field to be parsed and copied.
  270. Return Value:
  271. RPC_S_OK - The operation completed successfully.
  272. RPC_S_OUT_OF_MEMORY - There is no memory available to make a copy
  273. of the string.
  274. RPC_S_INVALID_ENDPOINT_FORMAT - The endpoint field is syntactically
  275. incorrect. This error code will be returned if the endpoint field
  276. does not match the following pattern.
  277. [ <Endpoint> | "endpoint=" <Endpoint> ]
  278. --*/
  279. {
  280. // Search will be used to scan along the string to find the end of
  281. // the endpoint field and the '='.
  282. RPC_CHAR PAPI * Search;
  283. Search = StringCharSearchWithEscape(String,RPC_CONST_CHAR('='));
  284. if (Search == 0)
  285. {
  286. // This means that we have the <Endpoint> pattern, so we just
  287. // copy the endpoint field.
  288. Search = StringCharSearchWithEscape(String,0);
  289. *Endpoint = new RPC_CHAR[Search - String + 1];
  290. if (*Endpoint == 0)
  291. return(RPC_S_OUT_OF_MEMORY);
  292. StringCopyWithEscape(*Endpoint,String);
  293. return(RPC_S_OK);
  294. }
  295. // Otherwise, we have the "endpoint=" pattern. First we need to check
  296. // that the string before the '=' is in fact "endpoint".
  297. *Search = 0;
  298. if ( RpcpStringCompare(String, RPC_CONST_STRING("endpoint")) != 0 )
  299. {
  300. *Search = RPC_CONST_CHAR('=');
  301. return(RPC_S_INVALID_ENDPOINT_FORMAT);
  302. }
  303. *Search = RPC_CONST_CHAR('=');
  304. String = Search + 1;
  305. // Now we just need to allocate a new string and copy the endpoint into
  306. // it.
  307. Search = StringCharSearchWithEscape(String,0);
  308. *Endpoint = new RPC_CHAR[Search - String + 1];
  309. if (*Endpoint == 0)
  310. return(RPC_S_OUT_OF_MEMORY);
  311. StringCopyWithEscape(*Endpoint,String);
  312. return(RPC_S_OK);
  313. }
  314. RPC_CHAR *
  315. AllocateEmptyString (
  316. void
  317. )
  318. /*++
  319. Routine Description:
  320. This routine allocates and returns an empty string ("").
  321. Return Value:
  322. A newly allocated empty string will be returned.
  323. --*/
  324. {
  325. RPC_CHAR * String;
  326. String = new RPC_CHAR[1];
  327. if (String != 0)
  328. *String = 0;
  329. return(String);
  330. }
  331. DCE_BINDING::DCE_BINDING (
  332. IN RPC_CHAR PAPI * StringBinding,
  333. OUT RPC_STATUS PAPI * Status
  334. )
  335. /*++
  336. Routine Description:
  337. This constructor creates a DCE_BINDING object from a string binding,
  338. which requires that the string binding be parsed into seperate
  339. strings and validated.
  340. Arguments:
  341. StringBinding - Supplies the string being to be parsed.
  342. Status - Returns the status of the operation. This parameter will
  343. take on the following values:
  344. RPC_S_OK - The operation completed successfully.
  345. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to
  346. allocate space for the fields of the string binding.
  347. RPC_S_INVALID_STRING_BINDING - The string binding is
  348. syntactically invalid.
  349. RPC_S_INVALID_ENDPOINT_FORMAT - The endpoint specified in
  350. the string binding is syntactically incorrect.
  351. RPC_S_INVALID_STRING_UUID - The specified object uuid does not
  352. contain the valid string representation of a uuid.
  353. --*/
  354. {
  355. // String will point to the beginning of the field we are trying to
  356. // parse.
  357. RPC_CHAR PAPI * String;
  358. // Search will be used to scan along the string to find the end of
  359. // the field we are trying to parse.
  360. RPC_CHAR PAPI * Search;
  361. // This will contain the string representation of the object uuid.
  362. RPC_CHAR PAPI * ObjectUuidString;
  363. ALLOCATE_THIS(DCE_BINDING);
  364. // A string binding consists of an optional object uuid, an RPC protocol
  365. // sequence, a network address, an optional endpoint, and zero or more
  366. // option fields.
  367. //
  368. // [ <Object UUID> "@" ] <RPC Protocol Sequence> ":" <Network Address>
  369. // [ "[" ( <Endpoint> | "endpoint=" <Endpoint> | ) [","]
  370. // [ "," <Option Name> "=" <Option Value>
  371. // ( <Option Name> "=" <Option Value> )* ] "]" ]
  372. //
  373. // If an object UUID is specified, then it will be followed by '@'.
  374. // Likewise, if an endpoint and/or option(s) are specified, they will
  375. // be in square brackets. Finally, one or more options are specified,
  376. // then ',' must seperate the optional endpoint from the options. The
  377. // backslash character '\' is treated as an escape character in all
  378. // string binding fields.
  379. // To begin with, we need to set all of the string pointers to zero.
  380. // This is necessary so that when we do memory cleanup for error
  381. // recovery, we know which pointers we allocated a string for.
  382. ObjectUuidString = 0;
  383. RpcProtocolSequence = 0;
  384. NetworkAddress = 0;
  385. Endpoint = 0;
  386. Options = 0;
  387. String = StringBinding;
  388. // To begin with, we need to parse off the object UUID from the string
  389. // if it exists.
  390. Search = StringCharSearchWithEscape(String,RPC_CONST_CHAR('@'));
  391. if (Search == 0)
  392. {
  393. // The string binding does not contain an object UUID.
  394. ObjectUuid.SetToNullUuid();
  395. }
  396. else
  397. {
  398. // There is an object UUID in the string.
  399. // We need to add one for the terminating zero in the
  400. // string.
  401. ObjectUuidString = (RPC_CHAR PAPI *) RpcpFarAllocate(
  402. sizeof(RPC_CHAR)*(Search - String + 1));
  403. if (ObjectUuidString == 0)
  404. {
  405. *Status = RPC_S_OUT_OF_MEMORY;
  406. goto FreeMemoryAndReturn;
  407. }
  408. // Now copy the string.
  409. *Search = 0;
  410. StringCopyWithEscape(ObjectUuidString,String);
  411. *Search = RPC_CONST_CHAR('@');
  412. // Finally, update String so that we are ready to parse the next
  413. // field.
  414. String = Search + 1;
  415. // Now convert the string representation of the object uuid
  416. // into an actual uuid.
  417. if (ObjectUuid.ConvertFromString(ObjectUuidString))
  418. {
  419. *Status = RPC_S_INVALID_STRING_UUID;
  420. goto FreeMemoryAndReturn;
  421. }
  422. RpcpFarFree(ObjectUuidString);
  423. ObjectUuidString = 0;
  424. }
  425. // The RPC protocol sequence field comes next; it is terminated by
  426. // ':'. Both the RPC protocol sequence field and the ':' are required.
  427. Search = StringCharSearchWithEscape(String,RPC_CONST_CHAR(':'));
  428. if (Search == 0)
  429. {
  430. // This is an error, because the RPC protocol sequence field is
  431. // required. We may need to free the string we allocated for
  432. // the object UUID field.
  433. *Status = RPC_S_INVALID_STRING_BINDING;
  434. goto FreeMemoryAndReturn;
  435. }
  436. else
  437. {
  438. // The same comments which applied to copying the object UUID
  439. // apply here as well.
  440. RpcProtocolSequence = new RPC_CHAR[Search - String + 1];
  441. if (RpcProtocolSequence == 0)
  442. {
  443. *Status = RPC_S_OUT_OF_MEMORY;
  444. goto FreeMemoryAndReturn;
  445. }
  446. *Search = 0;
  447. StringCopyWithEscape(RpcProtocolSequence,String);
  448. *Search = RPC_CONST_CHAR(':');
  449. // Finally, update String so that we are ready to parse the next
  450. // field.
  451. String = Search + 1;
  452. }
  453. // Next comes the network address field which is required. It is
  454. // terminated by zero or '['.
  455. Search = StringCharSearchWithEscape(String,RPC_CONST_CHAR('['));
  456. if (Search == 0)
  457. {
  458. // This means that the network address is the last field, so we
  459. // just copy it, and set the remaining fields to be empty strings.
  460. Search = StringCharSearchWithEscape(String,0);
  461. NetworkAddress = new RPC_CHAR[Search - String + 1];
  462. if (NetworkAddress == 0)
  463. {
  464. *Status = RPC_S_OUT_OF_MEMORY;
  465. goto FreeMemoryAndReturn;
  466. }
  467. StringCopyWithEscape(NetworkAddress,String);
  468. Endpoint = AllocateEmptyString();
  469. if (Endpoint == 0)
  470. {
  471. *Status = RPC_S_OUT_OF_MEMORY;
  472. goto FreeMemoryAndReturn;
  473. }
  474. Options = AllocateEmptyString();
  475. if (Options == 0)
  476. {
  477. *Status = RPC_S_OUT_OF_MEMORY;
  478. goto FreeMemoryAndReturn;
  479. }
  480. *Status = RPC_S_OK;
  481. return;
  482. }
  483. // Otherwise, if we reach here, there is an endpoint and/or options
  484. // left to parse. But before we parse them, lets copy the network
  485. // address field.
  486. NetworkAddress = new RPC_CHAR [Search - String + 1];
  487. if (NetworkAddress == 0)
  488. {
  489. *Status = RPC_S_OUT_OF_MEMORY;
  490. goto FreeMemoryAndReturn;
  491. }
  492. *Search = 0;
  493. StringCopyWithEscape(NetworkAddress,String);
  494. *Search = RPC_CONST_CHAR('[');
  495. String = Search + 1;
  496. // Now we are ready to parse off the endpoint and/or options.
  497. // To begin with, we check to see if there is a comma.
  498. Search = StringCharSearchWithEscape(String,RPC_CONST_CHAR(','));
  499. if (Search == 0)
  500. {
  501. // There is only one token in the string binding. See
  502. // if its an endpoint, if not, it must be an option.
  503. // Before we copy the endpoint field, we need to check
  504. // for the closing square bracket.
  505. Search = StringCharSearchWithEscape(String,RPC_CONST_CHAR(']'));
  506. if (Search == 0)
  507. {
  508. // This is an error; the string binding is invalid. We need to
  509. // clean everything up, and return an error.
  510. *Status = RPC_S_INVALID_ENDPOINT_FORMAT;
  511. goto FreeMemoryAndReturn;
  512. }
  513. *Search = 0;
  514. *Status = ParseAndCopyEndpointField(&Endpoint,String);
  515. *Search = RPC_CONST_CHAR(']');
  516. // If the parse succeeded, allocate an empty option.
  517. if (*Status == RPC_S_OK)
  518. {
  519. Options = AllocateEmptyString();
  520. if (Options == 0)
  521. {
  522. *Status = RPC_S_OUT_OF_MEMORY;
  523. goto FreeMemoryAndReturn;
  524. }
  525. }
  526. // If the endpoint parse failed with RPC_S_INVALID_ENDPOINT_FORMAT,
  527. // the token must be an option.
  528. else if (*Status == RPC_S_INVALID_ENDPOINT_FORMAT)
  529. {
  530. Endpoint = AllocateEmptyString();
  531. if (Endpoint == 0)
  532. {
  533. *Status = RPC_S_OUT_OF_MEMORY;
  534. goto FreeMemoryAndReturn;
  535. }
  536. Options = new RPC_CHAR [Search - String + 1];
  537. if (Options == 0)
  538. {
  539. *Status = RPC_S_OUT_OF_MEMORY;
  540. goto FreeMemoryAndReturn;
  541. }
  542. *Search = 0;
  543. StringCopyWithEscape(Options,String);
  544. *Search = RPC_CONST_CHAR(']');
  545. }
  546. // Something bad must have happened, clean up.
  547. else
  548. goto FreeMemoryAndReturn;
  549. *Status = RPC_S_OK;
  550. return;
  551. }
  552. // When we reach here, we know that there are options. We have
  553. // to see if there is an endpoint. If there is, copy it and then
  554. // copy the options. If there isn't, allocate a null endpoint and
  555. // copy the options.
  556. *Search = 0;
  557. *Status = ParseAndCopyEndpointField(&Endpoint,String);
  558. *Search = RPC_CONST_CHAR(',');
  559. // If there was an endpoint, skip that part of the string.
  560. // Otherwise treat it as an option.
  561. if (*Status == RPC_S_OK)
  562. String = Search + 1;
  563. else if (*Status != RPC_S_INVALID_ENDPOINT_FORMAT)
  564. goto FreeMemoryAndReturn;
  565. // There was no endpoint, so allocate an empty string.
  566. else
  567. {
  568. Endpoint = AllocateEmptyString();
  569. if (Endpoint == 0)
  570. {
  571. *Status = RPC_S_OUT_OF_MEMORY;
  572. goto FreeMemoryAndReturn;
  573. }
  574. }
  575. // Even if the caller did not specify the NetworkOptions argument,
  576. // we still want to validate the rest of the string binding.
  577. Search = StringCharSearchWithEscape(String,RPC_CONST_CHAR(']'));
  578. if (Search == 0)
  579. {
  580. // This is an error; the string binding is invalid. We need
  581. // to clean everything up, and return an error.
  582. *Status = RPC_S_INVALID_STRING_BINDING;
  583. goto FreeMemoryAndReturn;
  584. }
  585. // Go ahead and copy the network options field if we reach here.
  586. Options = new RPC_CHAR [Search - String + 1];
  587. if (Options == 0)
  588. {
  589. *Status = RPC_S_OUT_OF_MEMORY;
  590. goto FreeMemoryAndReturn;
  591. }
  592. *Search = 0;
  593. StringCopyWithEscape(Options,String);
  594. *Search = RPC_CONST_CHAR(']');
  595. // Everything worked out fine; we just fall through the memory
  596. // cleanup code and return.
  597. *Status = RPC_S_OK;
  598. // If an error occured up above, we will have set status to the
  599. // appropriate error code, and jumped here. We may also arrive
  600. // here if an error did not occur, hence the check for an error status
  601. // before we clean up the memory.
  602. FreeMemoryAndReturn:
  603. if (*Status != RPC_S_OK)
  604. {
  605. if (ObjectUuidString != 0)
  606. RpcpFarFree(ObjectUuidString);
  607. if (RpcProtocolSequence != 0)
  608. delete RpcProtocolSequence;
  609. if (NetworkAddress != 0)
  610. delete NetworkAddress;
  611. if (Endpoint != 0)
  612. delete Endpoint;
  613. if (Options != 0)
  614. delete Options;
  615. ObjectUuidString = 0;
  616. RpcProtocolSequence = 0;
  617. NetworkAddress = 0;
  618. Endpoint = 0;
  619. Options = 0;
  620. }
  621. }
  622. DCE_BINDING::~DCE_BINDING (
  623. )
  624. /*++
  625. Routine Description:
  626. We cleaning things up here when a DCE_BINDING is getting deleted.
  627. This consists of freeing the strings pointed to by the fields of
  628. the class.
  629. --*/
  630. {
  631. if (RpcProtocolSequence != 0)
  632. delete RpcProtocolSequence;
  633. if (NetworkAddress != 0)
  634. delete NetworkAddress;
  635. if (Endpoint != 0)
  636. delete Endpoint;
  637. if (Options != 0)
  638. delete Options;
  639. }
  640. /*static*/ int
  641. StringLengthWithEscape (
  642. IN RPC_CHAR PAPI * String
  643. )
  644. /*++
  645. Routine Description:
  646. This routine is the same as the library routine, strlen, except that
  647. for that following characters, '@', ':', '\', '[', and ',', are
  648. counted as two characters (to save space for a \) rather than one.
  649. Arguments:
  650. String - Supplies a string whose length will be determined.
  651. Return Value:
  652. The length of the string will be returned including enough space to
  653. escape certain characters.
  654. --*/
  655. {
  656. // We use length to keep track of how long the string is so far.
  657. int Length;
  658. Length = 0;
  659. while (*String != 0)
  660. {
  661. #ifdef DBCS_ENABLED
  662. if (IsDBCSLeadByte(*String))
  663. {
  664. String += 2;
  665. Length += 2;
  666. }
  667. else
  668. #endif
  669. {
  670. if ( (*String == RPC_CONST_CHAR('@'))
  671. || (*String == RPC_CONST_CHAR(':'))
  672. || (*String == RPC_CONST_CHAR('\\'))
  673. || (*String == RPC_CONST_CHAR('['))
  674. || (*String == RPC_CONST_CHAR(']'))
  675. || (*String == RPC_CONST_CHAR(',')))
  676. Length += 2;
  677. else
  678. Length += 1;
  679. String += 1;
  680. }
  681. }
  682. return(Length);
  683. }
  684. /*static*/ RPC_CHAR PAPI *
  685. StringCopyEscapeCharacters (
  686. OUT RPC_CHAR PAPI * Destination,
  687. IN RPC_CHAR PAPI * Source
  688. )
  689. /*++
  690. Routine Description:
  691. Source is copied into destination. When coping into destination, the
  692. following characters are escaped by prefixing them with a '\': '@',
  693. ':', '\', '[', ']', and ','.
  694. Arguments:
  695. Destination - Returns a copy of Source.
  696. Source - Supplies a string to be copied into destination.
  697. Return Value:
  698. A pointer to the terminating zero in Destination is returned.
  699. --*/
  700. {
  701. while ((*Destination = *Source) != 0)
  702. {
  703. #ifdef DBCS_ENABLED
  704. if (IsDBCSLeadByte(*Source))
  705. {
  706. Destination++;
  707. Source++;
  708. *Destination = *Source;
  709. }
  710. else
  711. #endif
  712. {
  713. if ( (*Source == RPC_CONST_CHAR('@'))
  714. || (*Source == RPC_CONST_CHAR(':'))
  715. || (*Source == RPC_CONST_CHAR('\\'))
  716. || (*Source == RPC_CONST_CHAR('['))
  717. || (*Source == RPC_CONST_CHAR(']'))
  718. || (*Source == RPC_CONST_CHAR(',')))
  719. {
  720. *Destination++ = RPC_CONST_CHAR('\\');
  721. *Destination = *Source;
  722. }
  723. }
  724. Destination++;
  725. Source++;
  726. }
  727. *Destination = 0;
  728. return(Destination);
  729. }
  730. RPC_CHAR PAPI *
  731. DCE_BINDING::StringBindingCompose (
  732. IN RPC_UUID PAPI * Uuid OPTIONAL
  733. )
  734. /*++
  735. Routine Description:
  736. This method creates a string binding from a DCE_BINDING by combining
  737. the components of a string binding.
  738. Arguments:
  739. Uuid - Optionally supplies a uuid to use in composing the string
  740. binding rather than the object uuid contained in the DCE_BINDING.
  741. Return Value:
  742. String Binding - A newly allocated and created (from the components)
  743. is returned.
  744. 0 - Insufficient memory is available to allocate the string binding.
  745. --*/
  746. {
  747. // We will use the following automatic variable to calculate the
  748. // required length of the string.
  749. int Length;
  750. // Copy is used to copy the fields of the string binding into the
  751. // string binding.
  752. RPC_CHAR PAPI * Copy;
  753. // StringBinding will contain the string binding we are supposed
  754. // to be creating here.
  755. RPC_CHAR PAPI * StringBinding;
  756. // This routine is written as follows. First we need to calculate
  757. // the amount of space required to hold the string binding. This
  758. // is not quite straight forward as it seems: we need to escape
  759. // '@', ':', '\', '[', ']', and ',' characters in the string binding
  760. // we create. After allocating the string, we copy each piece in,
  761. // escaping characters as necessary.
  762. // Go through and figure out how much space each field of the string
  763. // binding will take up.
  764. if (!ARGUMENT_PRESENT(Uuid))
  765. Uuid = &ObjectUuid;
  766. if (Uuid->IsNullUuid() == 0)
  767. {
  768. // The extra plus one is to save space for the '@' which seperates
  769. // the object UUID field from the RPC protocol sequence field. The
  770. // length of the string representation of a uuid is always 36
  771. // characters.
  772. Length = 36 + 1;
  773. }
  774. else
  775. {
  776. Length = 0;
  777. }
  778. if (RpcProtocolSequence != 0)
  779. {
  780. Length += StringLengthWithEscape(RpcProtocolSequence);
  781. }
  782. // We need to save space for the ':' seperating the RPC protocol
  783. // sequence field from the network address field.
  784. Length += 1;
  785. if (NetworkAddress != 0)
  786. Length += StringLengthWithEscape(NetworkAddress);
  787. if ( (Endpoint != 0)
  788. && (Endpoint[0] != 0))
  789. {
  790. // The plus two is to save space for the '[' and ']' surrounding
  791. // the endpoint and options fields.
  792. Length += StringLengthWithEscape(Endpoint) + 2;
  793. if ( (Options != 0)
  794. && (Options[0] != 0))
  795. {
  796. // The extra plus one is for the ',' which goes before the
  797. // options field.
  798. Length += StringLengthWithEscape(Options) + 1;
  799. }
  800. }
  801. else
  802. {
  803. if ( (Options != 0)
  804. && (Options[0] != 0))
  805. {
  806. // We need to add three to the length to save space for the
  807. // '[' and ']' which will go around the options, and the ','
  808. // which goes before the options.
  809. Length += StringLengthWithEscape(Options) + 3;
  810. }
  811. }
  812. // Finally, include space for the terminating zero in the string.
  813. Length += 1;
  814. // Now we allocate space for the string binding and copy all of the
  815. // pieces into it.
  816. StringBinding = (RPC_CHAR PAPI *)
  817. RpcpFarAllocate(Length * sizeof(RPC_CHAR));
  818. if (StringBinding == 0)
  819. return(0);
  820. if (Uuid->IsNullUuid() == 0)
  821. {
  822. Copy = Uuid->ConvertToString(StringBinding);
  823. *Copy++ = RPC_CONST_CHAR('@');
  824. }
  825. else
  826. {
  827. Copy = StringBinding;
  828. }
  829. if (RpcProtocolSequence != 0)
  830. {
  831. Copy = StringCopyEscapeCharacters(Copy, RpcProtocolSequence);
  832. }
  833. *Copy++ = RPC_CONST_CHAR(':');
  834. if (NetworkAddress != 0)
  835. {
  836. Copy = StringCopyEscapeCharacters(Copy, NetworkAddress);
  837. }
  838. if ( (Endpoint != 0)
  839. && (Endpoint[0] != 0))
  840. {
  841. *Copy++ = RPC_CONST_CHAR('[');
  842. Copy = StringCopyEscapeCharacters(Copy, Endpoint);
  843. if ( (Options != 0)
  844. && (Options[0] != 0))
  845. {
  846. *Copy++ = RPC_CONST_CHAR(',');
  847. Copy = StringCopyEscapeCharacters(Copy, Options);
  848. }
  849. *Copy++ = RPC_CONST_CHAR(']');
  850. }
  851. else
  852. {
  853. if ( (Options != 0)
  854. && (Options[0] != 0))
  855. {
  856. *Copy++ = RPC_CONST_CHAR('[');
  857. *Copy++ = RPC_CONST_CHAR(',');
  858. Copy = StringCopyEscapeCharacters(Copy, Options);
  859. *Copy++ = RPC_CONST_CHAR(']');
  860. }
  861. }
  862. // And do not forget to terminate the string.
  863. *Copy = 0;
  864. return(StringBinding);
  865. }
  866. #if defined(WIN) || defined(MAC)
  867. RPC_CHAR PAPI *
  868. AllocateEmptyStringPAPI (
  869. void
  870. )
  871. /*++
  872. Routine Description:
  873. This routine allocates and returns an empty string ("").
  874. Return Value:
  875. A newly allocated empty string will be returned.
  876. --*/
  877. {
  878. RPC_CHAR PAPI * String;
  879. String = (RPC_CHAR PAPI *) RpcpFarAllocate(sizeof(RPC_CHAR));
  880. if (String != 0)
  881. *String = 0;
  882. return(String);
  883. }
  884. RPC_CHAR PAPI *
  885. DuplicateStringPAPI (
  886. IN RPC_CHAR * String
  887. )
  888. /*++
  889. Routine Description:
  890. When this routine is called, it will duplicate the string into a fresh
  891. string and return it.
  892. Arguments:
  893. String - Supplies the string to be duplicated.
  894. Return Value:
  895. The duplicated string is returned. If insufficient memory is available
  896. to allocate a fresh string, zero will be returned.
  897. --*/
  898. {
  899. RPC_CHAR PAPI * FreshString, PAPI * FreshStringScan;
  900. RPC_CHAR * StringScan;
  901. unsigned int Length;
  902. Length = 1;
  903. StringScan = String;
  904. while (*StringScan++ != 0)
  905. Length += 1;
  906. FreshString = (RPC_CHAR PAPI *) RpcpFarAllocate(Length * sizeof(RPC_CHAR));
  907. if (FreshString == 0)
  908. return(0);
  909. for (FreshStringScan = FreshString, StringScan = String;
  910. *StringScan != 0; FreshStringScan++, StringScan++)
  911. *FreshStringScan = *StringScan;
  912. *FreshStringScan = *StringScan;
  913. return(FreshString);
  914. }
  915. #endif // WIN
  916. RPC_CHAR PAPI *
  917. DCE_BINDING::ObjectUuidCompose (
  918. OUT RPC_STATUS PAPI * Status
  919. )
  920. /*++
  921. Routine Description:
  922. This method returns a string representation of the object UUID
  923. component of the DCE_BINDING. The string representation is
  924. suitable for using as the object UUID component of a string binding.
  925. Arguments:
  926. Status - Returns the status of the operation if there is insufficient
  927. memory to allocate for the string to be returned.
  928. Return Value:
  929. The string representation of the object UUID is returned in a freshly
  930. allocated string.
  931. --*/
  932. {
  933. RPC_CHAR PAPI * String;
  934. if (ObjectUuid.IsNullUuid() != 0)
  935. return(AllocateEmptyStringPAPI());
  936. // The string representation of a uuid is always 36 characters long
  937. // (and the extra character is for the terminating zero).
  938. String = (RPC_CHAR PAPI *) RpcpFarAllocate(37 * sizeof(RPC_CHAR));
  939. if (String == 0)
  940. *Status = RPC_S_OUT_OF_MEMORY;
  941. else
  942. {
  943. ObjectUuid.ConvertToString(String);
  944. String[36] = 0;
  945. }
  946. return(String);
  947. }
  948. RPC_CHAR PAPI *
  949. DCE_BINDING::RpcProtocolSequenceCompose (
  950. OUT RPC_STATUS PAPI * Status
  951. )
  952. /*++
  953. Routine Description:
  954. This method returns a string representation of the RPC protocol sequence
  955. component of the DCE_BINDING. The string representation is
  956. suitable for using as the RPC protocol sequence component of a
  957. string binding.
  958. Arguments:
  959. Status - Returns the status of the operation if there is insufficient
  960. memory to allocate for the string to be returned.
  961. Return Value:
  962. The string representation of the RPC protocol sequence is returned
  963. in a freshly allocated string.
  964. --*/
  965. {
  966. RPC_CHAR PAPI * String;
  967. if (RpcProtocolSequence == 0)
  968. return(AllocateEmptyStringPAPI());
  969. String = DuplicateStringPAPI(RpcProtocolSequence);
  970. if (String == 0)
  971. *Status = RPC_S_OUT_OF_MEMORY;
  972. return(String);
  973. }
  974. RPC_CHAR PAPI *
  975. DCE_BINDING::NetworkAddressCompose (
  976. OUT RPC_STATUS PAPI * Status
  977. )
  978. /*++
  979. Routine Description:
  980. This method returns a string representation of the network address
  981. component of the DCE_BINDING. The string representation is
  982. suitable for using as the network address component of a string binding.
  983. Arguments:
  984. Status - Returns the status of the operation if there is insufficient
  985. memory to allocate for the string to be returned.
  986. Return Value:
  987. The string representation of the network address is returned in a freshly
  988. allocated string.
  989. --*/
  990. {
  991. RPC_CHAR PAPI * String;
  992. if (NetworkAddress == 0)
  993. return(AllocateEmptyStringPAPI());
  994. String = DuplicateStringPAPI(NetworkAddress);
  995. if (String == 0)
  996. *Status = RPC_S_OUT_OF_MEMORY;
  997. return(String);
  998. }
  999. RPC_CHAR PAPI *
  1000. DCE_BINDING::EndpointCompose (
  1001. OUT RPC_STATUS PAPI * Status
  1002. )
  1003. /*++
  1004. Routine Description:
  1005. This method returns a string representation of the endpoint
  1006. component of the DCE_BINDING. The string representation is
  1007. suitable for using as the endpoint component of a string binding.
  1008. Arguments:
  1009. Status - Returns the status of the operation if there is insufficient
  1010. memory to allocate for the string to be returned.
  1011. Return Value:
  1012. The string representation of the endpoint is returned in a freshly
  1013. allocated string.
  1014. --*/
  1015. {
  1016. RPC_CHAR PAPI * String;
  1017. if (Endpoint == 0)
  1018. return(AllocateEmptyStringPAPI());
  1019. String = DuplicateStringPAPI(Endpoint);
  1020. if (String == 0)
  1021. *Status = RPC_S_OUT_OF_MEMORY;
  1022. return(String);
  1023. }
  1024. RPC_CHAR PAPI *
  1025. DCE_BINDING::OptionsCompose (
  1026. OUT RPC_STATUS PAPI * Status
  1027. )
  1028. /*++
  1029. Routine Description:
  1030. This method returns a string representation of the options
  1031. component of the DCE_BINDING. The string representation is
  1032. suitable for using as the options component of a string binding.
  1033. Arguments:
  1034. Status - Returns the status of the operation if there is insufficient
  1035. memory to allocate for the string to be returned.
  1036. Return Value:
  1037. The string representation of the options is returned in a freshly
  1038. allocated string.
  1039. --*/
  1040. {
  1041. RPC_CHAR PAPI * String;
  1042. if (Options == 0)
  1043. return(AllocateEmptyStringPAPI());
  1044. String = DuplicateStringPAPI(Options);
  1045. if (String == 0)
  1046. *Status = RPC_S_OUT_OF_MEMORY;
  1047. return(String);
  1048. }
  1049. BINDING_HANDLE *
  1050. DCE_BINDING::CreateBindingHandle (
  1051. OUT RPC_STATUS PAPI * Status
  1052. )
  1053. /*++
  1054. Routine Description:
  1055. We will create a binding handle specific to the rpc protocol sequence
  1056. specified by the DCE_BINDING object. The object uuid will be
  1057. passed on to the created binding handle. Ownership of this
  1058. passes to this routine. If an error occurs, it will be deleted.
  1059. Arguments:
  1060. Status - Returns the status of the operation; this status will be
  1061. one of the following values.
  1062. RPC_S_OK - We had no trouble allocating the binding handle.
  1063. RPC_S_OUT_OF_MEMORY - Insufficient memory was available to
  1064. complete the operation.
  1065. RPC_S_INVALID_RPC_PROTSEQ - The rpc protocol sequence is
  1066. syntactically invalid.
  1067. RPC_S_PROTSEQ_NOT_SUPPORTED - The requested rpc protocol sequence
  1068. is not supported.
  1069. Return Value:
  1070. The created binding handle will be returned, or zero if an error
  1071. occured.
  1072. --*/
  1073. {
  1074. BINDING_HANDLE * BindingHandle;
  1075. void * TransportInterface;
  1076. #ifdef WIN32RPC
  1077. #ifndef NTENV
  1078. if ( RpcpMemoryCompare(RpcProtocolSequence, RPC_CONST_STRING("mswmsg"),
  1079. 6) == 0 )
  1080. {
  1081. BindingHandle = WmsgCreateBindingHandle();
  1082. if (BindingHandle == 0)
  1083. {
  1084. delete this;
  1085. *Status = RPC_S_OUT_OF_MEMORY;
  1086. return(0);
  1087. }
  1088. }
  1089. else
  1090. #endif
  1091. if ( RpcpMemoryCompare(RpcProtocolSequence, RPC_CONST_STRING("ncalrpc"),
  1092. 8 * sizeof(RPC_CHAR)) == 0 )
  1093. {
  1094. #ifdef NTENV
  1095. BindingHandle = WmsgCreateBindingHandle();
  1096. #else
  1097. BindingHandle = SpcCreateBindingHandle();
  1098. #endif
  1099. if (BindingHandle == 0)
  1100. {
  1101. delete this;
  1102. *Status = RPC_S_OUT_OF_MEMORY;
  1103. return(0);
  1104. }
  1105. }
  1106. #else // WIN32RPC
  1107. if ( RpcpMemoryCompare(RpcProtocolSequence, RPC_CONST_STRING("ncalrpc"),
  1108. 8 * sizeof(RPC_CHAR)) == 0 )
  1109. {
  1110. *Status = RPC_S_PROTSEQ_NOT_SUPPORTED;
  1111. delete this;
  1112. return(0);
  1113. }
  1114. #endif // WIN32RPC
  1115. #if !defined(MAC) && (!defined(DOSWIN32RPC) || defined(WIN96))
  1116. else if ( RpcpMemoryCompare(RpcProtocolSequence,
  1117. RPC_CONST_STRING("ncadg_"), 6*sizeof(RPC_CHAR)) == 0)
  1118. {
  1119. BindingHandle = DgCreateBindingHandle();
  1120. if (BindingHandle == 0)
  1121. {
  1122. delete this;
  1123. *Status = RPC_S_OUT_OF_MEMORY;
  1124. return 0;
  1125. }
  1126. TransportInterface = OsfClientMapRpcProtocolSequence(
  1127. RpcProtocolSequence,
  1128. Status
  1129. );
  1130. if (*Status != RPC_S_OK)
  1131. {
  1132. delete BindingHandle;
  1133. delete this;
  1134. return 0;
  1135. }
  1136. }
  1137. #endif // DOSWIN32RPC
  1138. #ifdef MAC
  1139. else if ( RpcpMemoryCompare(RpcProtocolSequence,
  1140. RPC_CONST_STRING("ncadg_"), 6*sizeof(RPC_CHAR)) == 0)
  1141. {
  1142. delete this ;
  1143. *Status = RPC_S_PROTSEQ_NOT_SUPPORTED ;
  1144. return 0 ;
  1145. }
  1146. #endif
  1147. else if ( RpcpMemoryCompare(RPC_CONST_STRING("ncacn_"),
  1148. RpcProtocolSequence, 6 * sizeof(RPC_CHAR)) == 0 )
  1149. {
  1150. BindingHandle = OsfCreateBindingHandle();
  1151. if (BindingHandle == 0)
  1152. {
  1153. delete this;
  1154. *Status = RPC_S_OUT_OF_MEMORY;
  1155. return(0);
  1156. }
  1157. TransportInterface = OsfClientMapRpcProtocolSequence(
  1158. RpcProtocolSequence, Status);
  1159. if (*Status != RPC_S_OK)
  1160. {
  1161. delete BindingHandle;
  1162. delete this;
  1163. return(0);
  1164. }
  1165. }
  1166. else
  1167. {
  1168. *Status = RPC_S_INVALID_RPC_PROTSEQ;
  1169. delete this;
  1170. return(0);
  1171. }
  1172. BindingHandle->SetObjectUuid(&ObjectUuid);
  1173. BindingHandle->PrepareBindingHandle(TransportInterface,this);
  1174. *Status = RPC_S_OK;
  1175. return(BindingHandle);
  1176. }
  1177. void
  1178. DCE_BINDING::AddEndpoint(
  1179. IN RPC_CHAR *Endpoint
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. This routine can be used to update the endpoint stored in the DCE_BINDING.
  1184. If the DCE_BINDING already has an endpoint it is deleted.
  1185. Arguments:
  1186. Endpoint - The new endpoint to store in this DCE_BINDING. Ownership
  1187. passes to this DCE_BINDING.
  1188. Return Value:
  1189. n/a
  1190. --*/
  1191. {
  1192. if (this->Endpoint)
  1193. delete this->Endpoint;
  1194. this->Endpoint = Endpoint;
  1195. }
  1196. RPC_STATUS
  1197. DCE_BINDING::ResolveEndpointIfNecessary (
  1198. IN PRPC_CLIENT_INTERFACE RpcInterfaceInformation,
  1199. IN RPC_UUID * ObjectUuid,
  1200. IN OUT void PAPI * PAPI * EpLookupHandle,
  1201. IN BOOL UseEpMapperEp,
  1202. IN unsigned Timeout
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. This routine will determine the endpoint if it is not specified.
  1207. The arguments specifies interface information necessary to resolve
  1208. the endpoint, as well as the object uuid.
  1209. Arguments:
  1210. RpcInterfaceInformation - Supplies the interface information necessary
  1211. to resolve the endpoint.
  1212. ObjectUuid - Supplies the object uuid in the binding.
  1213. EpLookupHandle - Supplies the current value of the endpoint mapper
  1214. lookup handle for a binding, and returns the new value.
  1215. Return Value:
  1216. RPC_S_OK - The endpoint is fully resolved.
  1217. RPC_S_NO_ENDPOINT_FOUND - The endpoint can not be resolved.
  1218. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to resolve
  1219. the endpoint.
  1220. EPT_S_NOT_REGISTERED - There are no more endpoints to be found
  1221. for the specified combination of interface, network address,
  1222. and lookup handle.
  1223. EPT_S_CANT_PERFORM_OP - The operation failed due to misc. error e.g.
  1224. unable to bind to the EpMapper.
  1225. --*/
  1226. {
  1227. unsigned int Index;
  1228. RPC_STATUS RpcStatus;
  1229. #ifdef NTENV
  1230. UNICODE_STRING UnicodeString;
  1231. #endif // NTENV
  1232. if ( (Endpoint == 0)
  1233. || (Endpoint[0] == 0) )
  1234. {
  1235. // This binding does not have an endpoint, so we must perform
  1236. // binding resolution to obtain an endpoint. First we look
  1237. // in the interface information to see if an endpoint corresponding
  1238. // to the rpc protocol sequence for this binding is there.
  1239. for (Index = 0;
  1240. Index < RpcInterfaceInformation->RpcProtseqEndpointCount;
  1241. Index++)
  1242. {
  1243. #ifdef NTENV
  1244. RpcStatus = AnsiToUnicodeString(
  1245. RpcInterfaceInformation->RpcProtseqEndpoint[
  1246. Index].RpcProtocolSequence, &UnicodeString);
  1247. if (RpcStatus != RPC_S_OK)
  1248. return(RpcStatus);
  1249. if ( RpcpStringCompare(RpcProtocolSequence,
  1250. UnicodeString.Buffer) == 0 )
  1251. #else
  1252. if ( RpcpStringCompare(RpcProtocolSequence,
  1253. RpcInterfaceInformation->RpcProtseqEndpoint[
  1254. Index].RpcProtocolSequence) == 0 )
  1255. #endif // NTENV
  1256. {
  1257. #ifdef NTENV
  1258. RtlFreeUnicodeString(&UnicodeString);
  1259. #endif // NTENV
  1260. if (Endpoint != 0)
  1261. {
  1262. delete Endpoint;
  1263. Endpoint = 0;
  1264. }
  1265. #ifdef NTENV
  1266. RpcStatus = AnsiToUnicodeString(
  1267. RpcInterfaceInformation->RpcProtseqEndpoint[
  1268. Index].Endpoint, &UnicodeString);
  1269. if (RpcStatus != RPC_S_OK)
  1270. return(RpcStatus);
  1271. Endpoint = DuplicateString(UnicodeString.Buffer);
  1272. RtlFreeUnicodeString(&UnicodeString);
  1273. #else
  1274. Endpoint = DuplicateString(
  1275. RpcInterfaceInformation->RpcProtseqEndpoint[
  1276. Index].Endpoint);
  1277. #endif // NTENV
  1278. if (Endpoint == 0)
  1279. return(RPC_S_OUT_OF_MEMORY);
  1280. return(RPC_S_OK);
  1281. }
  1282. #ifdef NTENV
  1283. RtlFreeUnicodeString(&UnicodeString);
  1284. #endif // NTENV
  1285. }
  1286. //The endpoint has not been supplied so resolve the endpoint.
  1287. //CLH 2/17/94 If datagram and forward is required (that is
  1288. //RpcEpResolveBinding has not been called), then simply put
  1289. //the endpoint mapper's endpoint into this binding handles endpoint.
  1290. //The endpoint mapper on the destination node will resolve the
  1291. //endpoint and its runtime will forward the pkt.
  1292. if (Endpoint != 0)
  1293. {
  1294. delete Endpoint;
  1295. Endpoint = 0;
  1296. }
  1297. //
  1298. // We cannot allow management interfaces to be resolved if they dont contain
  1299. // an object uuid.
  1300. //
  1301. #ifdef WIN32RPC
  1302. if ( (IsMgmtIfUuid ((UUID PAPI * )
  1303. &RpcInterfaceInformation->InterfaceId.SyntaxGUID))
  1304. &&( (ObjectUuid == 0) ||
  1305. (RpcpMemoryCompare(ObjectUuid, &NullUuid, sizeof(UUID)) == 0) ) )
  1306. {
  1307. return(RPC_S_BINDING_INCOMPLETE);
  1308. }
  1309. #endif
  1310. if ( (RpcpMemoryCompare(RpcProtocolSequence,
  1311. RPC_CONST_STRING("ncadg_"), 6*sizeof(RPC_CHAR)) == 0)
  1312. && (UseEpMapperEp != 0) )
  1313. {
  1314. RpcStatus = EpGetEpmapperEndpoint(
  1315. ((RPC_CHAR * PAPI *) &Endpoint),
  1316. RpcProtocolSequence);
  1317. return((RpcStatus == RPC_S_OK) ?
  1318. RPC_P_EPMAPPER_EP : RpcStatus);
  1319. }
  1320. else
  1321. {
  1322. // Otherwise, we need to contact the endpoint mapper to
  1323. // resolve the endpoint.
  1324. return(EpResolveEndpoint((UUID PAPI *) ObjectUuid,
  1325. &RpcInterfaceInformation->InterfaceId,
  1326. &RpcInterfaceInformation->TransferSyntax,
  1327. RpcProtocolSequence, NetworkAddress, EpLookupHandle, Timeout,
  1328. (RPC_CHAR * PAPI *) &Endpoint));
  1329. }
  1330. }
  1331. return(RPC_S_OK);
  1332. }
  1333. DCE_BINDING::Compare (
  1334. IN DCE_BINDING * DceBinding
  1335. )
  1336. /*++
  1337. Routine Description:
  1338. This method compares two DCE_BINDING objects for equality.
  1339. Arguments:
  1340. DceBinding - Supplies a DCE_BINDING object to compare with this.
  1341. Return Value:
  1342. Zero will be returned if the specified DCE_BINDING object is the
  1343. same as this. Otherwise, non-zero will be returned.
  1344. --*/
  1345. {
  1346. int Result;
  1347. Result = memcmp(&(DceBinding->ObjectUuid), &ObjectUuid, sizeof(UUID));
  1348. if (Result != 0)
  1349. return(Result);
  1350. if (RpcProtocolSequence != 0)
  1351. {
  1352. if (DceBinding->RpcProtocolSequence != 0)
  1353. {
  1354. Result = RpcpStringCompare(DceBinding->RpcProtocolSequence,
  1355. RpcProtocolSequence);
  1356. if (Result != 0)
  1357. return(Result);
  1358. }
  1359. else
  1360. return(1);
  1361. }
  1362. else
  1363. {
  1364. if (DceBinding->RpcProtocolSequence != 0)
  1365. return(1);
  1366. }
  1367. if (NetworkAddress != 0)
  1368. {
  1369. if (DceBinding->NetworkAddress != 0)
  1370. {
  1371. Result = RpcpStringCompare(DceBinding->NetworkAddress,
  1372. NetworkAddress);
  1373. if (Result != 0)
  1374. return(Result);
  1375. }
  1376. else
  1377. return(1);
  1378. }
  1379. else
  1380. {
  1381. if (DceBinding->NetworkAddress != 0)
  1382. return(1);
  1383. }
  1384. if (Endpoint != 0)
  1385. {
  1386. if (DceBinding->Endpoint != 0)
  1387. {
  1388. Result = RpcpStringCompare(DceBinding->Endpoint, Endpoint);
  1389. if (Result != 0)
  1390. return(Result);
  1391. }
  1392. else
  1393. return(1);
  1394. }
  1395. else
  1396. {
  1397. if (DceBinding->Endpoint != 0)
  1398. return(1);
  1399. }
  1400. if (Options != 0)
  1401. {
  1402. if (DceBinding->Options != 0)
  1403. {
  1404. Result = RpcpStringCompare(DceBinding->Options, Options);
  1405. if (Result != 0)
  1406. return(Result);
  1407. }
  1408. else
  1409. return(1);
  1410. }
  1411. else
  1412. {
  1413. if (DceBinding->Options != 0)
  1414. return(1);
  1415. }
  1416. return(0);
  1417. }
  1418. DCE_BINDING *
  1419. DCE_BINDING::DuplicateDceBinding (
  1420. )
  1421. /*++
  1422. Routine Description:
  1423. We duplicate this DCE binding in this method.
  1424. Return Value:
  1425. A duplicate DCE_BINDING to this DCE_BINDING will be returned, if
  1426. everthing works correctly. Otherwise, zero will be returned
  1427. indicating an out of memory error.
  1428. --*/
  1429. {
  1430. DCE_BINDING * DceBinding;
  1431. RPC_STATUS Status;
  1432. RPC_CHAR ObjectUuidString[37];
  1433. ObjectUuid.ConvertToString(ObjectUuidString);
  1434. ObjectUuidString[36] = 0;
  1435. DceBinding = new DCE_BINDING(ObjectUuidString,RpcProtocolSequence,
  1436. NetworkAddress,Endpoint,Options,&Status);
  1437. if (Status != RPC_S_OK)
  1438. {
  1439. ASSERT(Status == RPC_S_OUT_OF_MEMORY);
  1440. return(0);
  1441. }
  1442. return(DceBinding);
  1443. }
  1444. void
  1445. DCE_BINDING::MakePartiallyBound (
  1446. )
  1447. /*++
  1448. Routine Description:
  1449. We need to make the binding into a partially bound one by setting the
  1450. endpoint to zero. This is really easy to do.
  1451. --*/
  1452. {
  1453. if (Endpoint != 0)
  1454. {
  1455. delete Endpoint;
  1456. Endpoint = 0;
  1457. }
  1458. }
  1459. RPC_STATUS
  1460. IsRpcProtocolSequenceSupported (
  1461. IN RPC_CHAR PAPI * RpcProtocolSequence
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. This routine determines if the specified rpc protocol sequence is
  1466. supported. It will optionally return the parts of the rpc protocol
  1467. sequence (rpc protocol specifier, and address + interface specifiers).
  1468. Arguments:
  1469. RpcProtocolSequence - Supplies an rpc protocol sequence to check.
  1470. RpcProtocolPart - Optionally returns the rpc protocol part of the
  1471. rpc protocol sequence.
  1472. AddressAndInterfacePart - Optionally returns the address and interface
  1473. parts of the rpc protocol sequence.
  1474. Return Value:
  1475. RPC_S_OK - The specified rpc protocol sequence is supported.
  1476. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to check
  1477. the rpc protocol sequence.
  1478. RPC_S_PROTSEQ_NOT_SUPPORTED - The specified rpc protocol sequence is not
  1479. supported (but it appears to be valid).
  1480. RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
  1481. syntactically invalid.
  1482. --*/
  1483. {
  1484. RPC_STATUS Status;
  1485. #ifdef WIN32
  1486. if ( RpcpMemoryCompare(RpcProtocolSequence, RPC_CONST_STRING("mswmsg"),
  1487. 7 * sizeof(RPC_CHAR)) == 0 )
  1488. {
  1489. return(RPC_S_OK);
  1490. }
  1491. #else
  1492. if ( RpcpMemoryCompare(RpcProtocolSequence, RPC_CONST_STRING("mswmsg"),
  1493. 7 * sizeof(RPC_CHAR)) == 0 )
  1494. {
  1495. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  1496. }
  1497. #endif
  1498. #ifdef WIN32
  1499. if ( RpcpMemoryCompare(RpcProtocolSequence, RPC_CONST_STRING("ncalrpc"),
  1500. 8 * sizeof(RPC_CHAR)) == 0 )
  1501. {
  1502. return(RPC_S_OK);
  1503. }
  1504. #else // WIN32
  1505. if ( RpcpMemoryCompare(RpcProtocolSequence, RPC_CONST_STRING("ncalrpc"),
  1506. 8 * sizeof(RPC_CHAR)) == 0 )
  1507. {
  1508. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  1509. }
  1510. #endif // NTENV
  1511. else if ( (RpcpMemoryCompare(RPC_CONST_STRING("ncacn_"),
  1512. RpcProtocolSequence, 6 * sizeof(RPC_CHAR)) == 0 )
  1513. || ( RpcpMemoryCompare(RPC_CONST_STRING("ncadg_"), RpcProtocolSequence,
  1514. 6 * sizeof(RPC_CHAR)) == 0 ) )
  1515. {
  1516. OsfClientMapRpcProtocolSequence(RpcProtocolSequence,&Status);
  1517. if (Status == RPC_S_OK)
  1518. {
  1519. return(RPC_S_OK);
  1520. }
  1521. return(RPC_S_PROTSEQ_NOT_SUPPORTED);
  1522. }
  1523. return(RPC_S_INVALID_RPC_PROTSEQ);
  1524. }