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.

3562 lines
85 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. worker.c
  5. Abstract:
  6. This file contains the real stuff for the EP Mapper.
  7. Author:
  8. Bharat Shah (barat) 17-2-92
  9. Revision History:
  10. 06-03-97 gopalp Added code to cleanup stale EP Mapper entries.
  11. --*/
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <sysinc.h>
  17. #include <wincrypt.h>
  18. #include <rpc.h>
  19. #include <rpcndr.h>
  20. #include "epmp.h"
  21. #include "eptypes.h"
  22. #include "local.h"
  23. #include "twrproto.h"
  24. #include <winsock2.h>
  25. #define StringCompareA lstrcmpiA
  26. #define StringLengthA lstrlenA
  27. #define EP_S_DUPLICATE_ENTRY 0x16c9a0d8
  28. RPC_IF_ID LocalNullUuid = {0};
  29. UUID MgmtIf = {
  30. 0xafa8bd80,
  31. 0x7d8a,
  32. 0x11c9,
  33. {0xbe, 0xf4, 0x08, 0x00, 0x2b, 0x10, 0x29, 0x89}
  34. };
  35. const int IP_ADDR_OFFSET = 0x4b;
  36. void
  37. PatchTower(
  38. IN OUT twr_t *Tower,
  39. IN int address)
  40. {
  41. int UNALIGNED *pIPAddr;
  42. pIPAddr = (int UNALIGNED *) (((char *) Tower) + IP_ADDR_OFFSET);
  43. //
  44. // Patch the tower
  45. //
  46. *pIPAddr = address;
  47. }
  48. //
  49. // Forward definitions
  50. //
  51. USHORT
  52. GetProtseqIdAnsi(
  53. PSTR Protseq
  54. );
  55. RPC_STATUS
  56. DelayedUseProtseq(
  57. USHORT id
  58. );
  59. VOID
  60. CompleteDelayedUseProtseqs(
  61. void
  62. );
  63. void
  64. DeletePSEP(
  65. PIFOBJNode Node,
  66. char * Protseq,
  67. char * Endpoint
  68. );
  69. void
  70. PurgeOldEntries(
  71. PIFOBJNode Node,
  72. PPSEPNode List,
  73. BOOL StrictMatch
  74. );
  75. RPC_STATUS
  76. MatchPSAndEP (
  77. PPSEPNode Node,
  78. void *Pseq,
  79. void * Endpoint,
  80. unsigned long Version
  81. );
  82. PPSEPNode
  83. FindPSEP (
  84. register PPSEPNode List,
  85. char * Pseq,
  86. char * Endpoint,
  87. unsigned long Version,
  88. PFNPointer2 Compare
  89. );
  90. PIFOBJNode
  91. FindIFOBJNode(
  92. register PIFOBJNode List,
  93. UUID * Obj,
  94. UUID * IF,
  95. unsigned long Version,
  96. PSID pSID,
  97. unsigned long Inq,
  98. unsigned long VersOpts,
  99. PFNPointer Compare
  100. );
  101. PIENTRY
  102. MatchByKey(
  103. register PIENTRY pList,
  104. unsigned long key
  105. )
  106. /*++
  107. Routine Description:
  108. This routine Seqrches the Link-list of IF-OBJ nodes based on
  109. key supplied.
  110. Arguments:
  111. List - The Linked list [head] - to be searched
  112. key - The Id
  113. Return Value:
  114. Returns a pointer to the matching IFObj node in the list or returns NULL.
  115. --*/
  116. {
  117. CheckInSem();
  118. for (; pList && pList->Id < key; pList = pList->Next)
  119. {
  120. ; // Empty body
  121. }
  122. return(pList);
  123. }
  124. RPC_STATUS RPC_ENTRY
  125. GetForwardEp(
  126. UUID *IfId,
  127. RPC_VERSION * IFVersion,
  128. UUID *Object,
  129. unsigned char * Protseq,
  130. void * * EpString
  131. )
  132. /*++
  133. Routine Description:
  134. Server rutime has received a pkt destined for a dynamically
  135. declared endpoint. Epmapper must return the servers endpoint
  136. to enable the runtime to correctly forward the pkt.
  137. Arguments:
  138. IF - Server Interface UUID
  139. IFVersion - Version of the Interface
  140. Obj - UUID of the Object
  141. Protseq - Ptotocol sequence the interface is using.
  142. EpString - Place to store the endpoint structure.
  143. Return Value:
  144. Returns a pointer to a string containing the server's endpoint.
  145. RPC_S_OUT_OF_MEMORY
  146. EPT_S_NOT_REGISTERED
  147. ---*/
  148. {
  149. PIFOBJNode pNode;
  150. PPSEPNode pPSEPNode;
  151. unsigned short len;
  152. char * String;
  153. PFNPointer Match;
  154. unsigned long InqType;
  155. unsigned long Version = VERSION(IFVersion->MajorVersion,
  156. IFVersion->MinorVersion);
  157. if (memcmp((char *)IfId, (char *)&MgmtIf, sizeof(UUID)) == 0)
  158. {
  159. InqType = RPC_C_EP_MATCH_BY_OBJ;
  160. Match = SearchIFObjNode;
  161. }
  162. else
  163. {
  164. InqType = 0;
  165. Match = WildCardMatch;
  166. }
  167. *EpString = 0;
  168. EnterSem();
  169. pNode = IFObjList;
  170. if (pNode == 0)
  171. {
  172. LeaveSem();
  173. return(EPT_S_NOT_REGISTERED);
  174. }
  175. while (pNode != 0)
  176. {
  177. // We do not have support for registrant SID matching for DG.
  178. pNode = FindIFOBJNode(
  179. pNode,
  180. Object,
  181. IfId,
  182. Version,
  183. NULL,
  184. InqType,
  185. 0,
  186. Match
  187. );
  188. if (pNode == 0)
  189. {
  190. LeaveSem();
  191. return(EPT_S_NOT_REGISTERED);
  192. }
  193. pPSEPNode = pNode->PSEPlist;
  194. pPSEPNode = FindPSEP(
  195. pPSEPNode,
  196. Protseq,
  197. NULL,
  198. 0L,
  199. MatchPSAndEP
  200. );
  201. if (pPSEPNode == 0)
  202. {
  203. pNode = pNode->Next;
  204. if (pNode == 0)
  205. {
  206. LeaveSem();
  207. return(EPT_S_NOT_REGISTERED);
  208. }
  209. continue;
  210. }
  211. // We now have a PSEPNode. We just ought to return the first one!
  212. // Use I_RpcAllocate To Allocate because runtime will free this!
  213. String = I_RpcAllocate( len = (strlen(pPSEPNode->EP) + 1) );
  214. if (String == 0)
  215. {
  216. LeaveSem();
  217. return(RPC_S_OUT_OF_MEMORY);
  218. }
  219. memcpy(String, pPSEPNode->EP, len);
  220. *EpString = String;
  221. LeaveSem();
  222. return(RPC_S_OK);
  223. } // while loop
  224. // we never go through here.
  225. return(EPT_S_NOT_REGISTERED);
  226. }
  227. RPC_STATUS
  228. SearchIFObjNode(
  229. PIFOBJNode pNode,
  230. UUID *Object,
  231. UUID *IfUuid,
  232. unsigned long Version,
  233. PSID pSID,
  234. unsigned long InqType,
  235. unsigned long VersOption
  236. )
  237. /*++
  238. Routine Description:
  239. This routine Seqrches the Link-list of IF-OBJ nodes based on
  240. Obj, IFUuid, IFVersion, Inqtype [Ignore OBJ, IgnoreIF, etc],
  241. and VersOption [Identical Ver, Compatible Vers. etc]
  242. Arguments:
  243. List - The Linked list head - to be searched
  244. Obj - UUID of the Object
  245. IF - Interface UUID
  246. Version - Version of the Interface
  247. pSID - SID of the registering principal. NULL will match any principal's entry.
  248. InqType - Type of Inquiry [Filter options based on IF/Obj/Both
  249. VersOpts - Filter options based on Version
  250. Return Value:
  251. Returns a pointer to the matching IFObj node in the list or returns NULL.
  252. --*/
  253. {
  254. switch (InqType)
  255. {
  256. default:
  257. case RPC_C_EP_ALL_ELTS:
  258. return 0;
  259. case RPC_C_EP_MATCH_BY_BOTH:
  260. if (memcmp(
  261. (char *)&pNode->ObjUuid,
  262. (char *)Object,
  263. sizeof(UUID))
  264. ||
  265. // !(pSID -> EqualSid (pNode->pSID, pSID))
  266. !(!pSID || EqualSid (pNode->pSID, pSID))
  267. )
  268. return(1);
  269. // Intentionally Fall through ..
  270. case RPC_C_EP_MATCH_BY_IF:
  271. return(!(
  272. (
  273. !memcmp(
  274. (char *)&pNode->IFUuid,
  275. (char *)IfUuid,
  276. sizeof(UUID)
  277. )
  278. )
  279. &&
  280. (
  281. ( (VersOption == RPC_C_VERS_UPTO)
  282. && pNode->IFVersion <= Version)
  283. || ( (VersOption == RPC_C_VERS_COMPATIBLE)
  284. && ((pNode->IFVersion & 0xFFFF0000) ==
  285. (Version & 0xFFFF0000))
  286. && (pNode->IFVersion >= Version)
  287. )
  288. || ( (VersOption == RPC_C_VERS_EXACT)
  289. && (pNode->IFVersion == Version)
  290. )
  291. || (VersOption == RPC_C_VERS_ALL)
  292. || ( (VersOption == RPC_C_VERS_MAJOR_ONLY)
  293. && ((pNode->IFVersion & 0xFFFF0000L)
  294. == (Version & 0xFFFF0000L))
  295. )
  296. || ( (VersOption ==
  297. I_RPC_C_VERS_UPTO_AND_COMPATIBLE)
  298. && ((pNode->IFVersion & 0xFFFF0000L)
  299. == (Version & 0xFFFF0000L))
  300. && (pNode->IFVersion <= Version)
  301. )
  302. )
  303. )
  304. ||
  305. !(!pSID || EqualSid (pNode->pSID, pSID))
  306. ); // return(
  307. case RPC_C_EP_MATCH_BY_OBJ:
  308. return(
  309. memcmp(
  310. (char *)&pNode->ObjUuid,
  311. (char *)Object,
  312. sizeof(UUID)
  313. )
  314. ||
  315. !(!pSID || EqualSid (pNode->pSID, pSID))
  316. );
  317. } // switch
  318. }
  319. PIFOBJNode
  320. FindIFOBJNode(
  321. register PIFOBJNode List,
  322. UUID * Obj,
  323. UUID * IF,
  324. unsigned long Version,
  325. PSID pSID,
  326. unsigned long Inq,
  327. unsigned long VersOpts,
  328. PFNPointer Compare
  329. )
  330. /*++
  331. Routine Description:
  332. This routine Searches the Linked list of IFOBJ nodes based on
  333. Obj, IF, and the SID of the registering principal.
  334. Arguments:
  335. List - The Linked list head - to be searched
  336. Obj - UUID of the Object
  337. IF - Interface UUID
  338. Version - Version of the Interface
  339. pSID - The SID of the registering principal
  340. Inq - Type of Inquiry [Filter based on IF/OB/Both]
  341. VersOpt - Filter based on version [<=, >=, == etc]
  342. Compare() - A pointer to function used for searching.
  343. WildCardMatch or ExactMatch.
  344. Return Value:
  345. Returns a pointer to the matching IFObj node in the list or returns NULL.
  346. --*/
  347. {
  348. CheckInSem();
  349. for (; (List !=NULL) && (*Compare)(List, Obj, IF, Version, pSID, Inq, VersOpts);
  350. List = List->Next)
  351. {
  352. ; // Empty body
  353. }
  354. return (List);
  355. }
  356. PPSEPNode
  357. FindPSEP (
  358. register PPSEPNode List,
  359. char * Pseq,
  360. char * Endpoint,
  361. unsigned long Version,
  362. PFNPointer2 Compare
  363. )
  364. /*++
  365. Routine Description:
  366. This routine Searches the Link-list of PSEP nodes based on
  367. Protocol sequence and Endpoint specified.
  368. Arguments:
  369. List - The Linked list head - to be searched
  370. Pseq - Protocol sequence string specified
  371. Endpoint - Endpoint string specified
  372. Version - Version of the Interface
  373. Compare() - A pointer to function used for searching.
  374. Return Value:
  375. Returns a pointer to the matching PSEP node in the list or returns NULL.
  376. --*/
  377. {
  378. CheckInSem();
  379. for (; List && (*Compare)(List, Pseq, Endpoint, Version); List = List->Next)
  380. {
  381. ; // Empty body
  382. }
  383. return (List);
  384. if (Version); // May need this if we overload FindNode and collapse
  385. // FindPSEP and FindIFOBJ
  386. }
  387. RPC_STATUS
  388. ExactMatch(
  389. PIFOBJNode Node,
  390. UUID *Obj,
  391. UUID *IF,
  392. unsigned long Version,
  393. PSID pSID,
  394. unsigned long InqType,
  395. unsigned long VersOptions
  396. )
  397. /*++
  398. Routine Description:
  399. This routine compares a Node in the IFOBJList to [Obj, IF, Version] triple
  400. and returns 0 if there is an exact match else returns 1
  401. Arguments:
  402. Node - An IFOBJ node
  403. Obj - UUID of the Object
  404. IF - Interface UUID
  405. Version - Version of the Interface
  406. Return Value:
  407. Returns 0 if there is an exact match; 1 otherwise
  408. --*/
  409. {
  410. return(( memcmp(&Node->ObjUuid, Obj,sizeof(UUID))
  411. || memcmp(&Node->IFUuid, IF, sizeof(UUID))
  412. || (Node->IFVersion != Version))
  413. ||
  414. // !(pSID -> EqualSid (pNode->pSID, pSID))
  415. !(!pSID || EqualSid (Node->pSID, pSID))
  416. );
  417. }
  418. RPC_STATUS
  419. WildCardMatch (
  420. PIFOBJNode Node,
  421. UUID *Obj,
  422. UUID *IF,
  423. unsigned long Version,
  424. PSID pSID,
  425. unsigned long InqType,
  426. unsigned long VersOptions
  427. )
  428. /*++
  429. Routine Description:
  430. This routine compares a Node in the IFOBJList to [Obj, IF, Version] triple
  431. and returns 0 if there is an exact match or if registered IF-Obj node
  432. has a NULL Obj UUid and version of the registed IF_Obj is >= that
  433. supplied
  434. Arguments:
  435. Node - An IFOBJ node
  436. Obj - UUID of the Object
  437. IF - Interface UUID
  438. Version - Version of the Interface
  439. Return Value:
  440. Returns 0 if there is a wild card match ; 1 otherwise
  441. --*/
  442. {
  443. if ( (!memcmp(&Node->IFUuid, IF, sizeof(UUID)))
  444. && ((Node->IFVersion & 0xFFFF0000L) == (Version & 0xFFFF0000L))
  445. && (Node->IFVersion >= Version)
  446. && ((!memcmp(&Node->ObjUuid, Obj, sizeof(UUID))) ||
  447. (IsNullUuid(&Node->ObjUuid)) )
  448. &&
  449. // pSID -> EqualSid (Node->pSID, pSID)
  450. (!pSID || EqualSid (Node->pSID, pSID)) )
  451. {
  452. return(0);
  453. }
  454. return(1);
  455. }
  456. RPC_STATUS
  457. MatchPSAndEP (
  458. PPSEPNode Node,
  459. void *Pseq,
  460. void * Endpoint,
  461. unsigned long Version
  462. )
  463. /*++
  464. Routine Description:
  465. This routine Matches A Node on PSEP list with given Protseq and Endpoint
  466. If Pseq is given pseqs are matched, if Endpoint is given Endpoints
  467. are matched, if neither is given returns true, if both are given
  468. both are matched.
  469. Arguments:
  470. Node - A PSEP node on PSEP list.
  471. Pseq - Protocol Sequence string
  472. Endpoint - Endpoint string
  473. Return Value:
  474. Returns 0 if Matched successfully, 1 otherwise.
  475. --*/
  476. {
  477. return ( (Pseq && RpcpStringCompareA(Node->Protseq, Pseq))
  478. || (Endpoint && RpcpStringCompareA(Node->EP, Endpoint)) );
  479. }
  480. void
  481. PurgeOldEntries(
  482. PIFOBJNode Node,
  483. PPSEPNode List,
  484. BOOL StrictMatch
  485. )
  486. {
  487. PPSEPNode Tmp, DeleteMe;
  488. char * Endpoint = 0;
  489. CheckInSem();
  490. Tmp = Node->PSEPlist;
  491. while (Tmp != 0)
  492. {
  493. if (StrictMatch == TRUE)
  494. Endpoint = Tmp->EP;
  495. if (DeleteMe = FindPSEP(List, Tmp->Protseq, Endpoint, 0L, MatchPSAndEP))
  496. {
  497. DeleteMe = Tmp;
  498. Tmp = Tmp->Next;
  499. UnLinkFromPSEPList(&Node->PSEPlist, DeleteMe);
  500. DeleteMe->Signature = FREE;
  501. FreeMem(DeleteMe);
  502. }
  503. else
  504. {
  505. Tmp = Tmp->Next;
  506. }
  507. }
  508. }
  509. RPC_STATUS
  510. IsNullUuid (
  511. UUID * Uuid
  512. )
  513. /*++
  514. Routine Description:
  515. This routine checks if a UUID is Nil
  516. Arguments:
  517. Uuid - UUID to be tested
  518. Return Value:
  519. Returns 1 if it is a Nil UUID
  520. 0 otherwise.
  521. --*/
  522. {
  523. unsigned long PAPI * Vector;
  524. Vector = (unsigned long PAPI *) Uuid;
  525. if ( (Vector[0] == 0)
  526. && (Vector[1] == 0)
  527. && (Vector[2] == 0)
  528. && (Vector[3] == 0))
  529. return(1);
  530. return(0);
  531. }
  532. twr_p_t
  533. NewTower(
  534. twr_p_t Tower
  535. )
  536. /*++
  537. Routine Description:
  538. This routine returns a New, Duplicated tower
  539. Arguments:
  540. Tower - The tower that needs to be duplicated.
  541. Return Value:
  542. Retunes a pointer to a new tower if successful else returns
  543. NULL
  544. --*/
  545. {
  546. unsigned short len;
  547. twr_p_t NewTower;
  548. len = (unsigned short)(sizeof(Tower->tower_length) + Tower->tower_length);
  549. if ((NewTower = MIDL_user_allocate(len)) != NULL)
  550. {
  551. memcpy((char *)NewTower, (char *)Tower, len);
  552. }
  553. return(NewTower);
  554. }
  555. const unsigned long EPLookupHandleSignature = 0xFAFAFAFA;
  556. PSAVEDCONTEXT
  557. GetNewContext(
  558. unsigned long Type
  559. )
  560. /*++
  561. Routine Description
  562. ++*/
  563. {
  564. PSAVEDCONTEXT Context;
  565. if ( ((Context = AllocMem(sizeof(SAVEDCONTEXT))) == 0) )
  566. return 0;
  567. memset(Context, 0, sizeof(SAVEDCONTEXT));
  568. Context->Cb = sizeof(SAVEDCONTEXT);
  569. Context->Type = Type;
  570. Context->Signature = EPLookupHandleSignature;
  571. EnLinkContext(Context);
  572. return(Context);
  573. }
  574. const unsigned int EPMapSignature = 0xCBBCCBBC;
  575. const unsigned int EPLookupSignature = 0xABBAABBA;
  576. RPC_STATUS
  577. AddToSavedContext(
  578. PSAVEDCONTEXT Context,
  579. PIFOBJNode Node,
  580. PPSEPNode Psep,
  581. unsigned long Calltype,
  582. BOOL fPatchTower,
  583. int PatchTowerAddress
  584. )
  585. {
  586. void * NewNode;
  587. PSAVEDTOWER SavedTower;
  588. PSAVED_EPT SavedEndpoint;
  589. unsigned long Size;
  590. unsigned long TowerSize;
  591. ASSERT(Calltype == Context->Type);
  592. switch (Calltype)
  593. {
  594. case EP_MAP:
  595. Size = sizeof(SAVEDTOWER) ;
  596. if ((NewNode = AllocMem(Size)) == 0)
  597. return(RPC_S_OUT_OF_MEMORY);
  598. SavedTower = (PSAVEDTOWER) NewNode;
  599. memset(SavedTower, 0, Size);
  600. SavedTower->Cb = Size;
  601. SavedTower->Signature = EPMapSignature;
  602. SavedTower->Tower = NewTower(Psep->Tower);
  603. if (SavedTower->Tower == 0)
  604. {
  605. FreeMem(NewNode);
  606. return(RPC_S_OUT_OF_MEMORY);
  607. }
  608. if (fPatchTower)
  609. {
  610. PatchTower(SavedTower->Tower, PatchTowerAddress);
  611. }
  612. break;
  613. case EP_LOOKUP:
  614. Size = sizeof(SAVED_EPT) + strlen(Node->Annotation) + 1;
  615. if ((NewNode = AllocMem(Size)) == 0)
  616. return(RPC_S_OUT_OF_MEMORY);
  617. SavedEndpoint = (PSAVED_EPT) NewNode;
  618. memset(SavedEndpoint, 0, Size);
  619. SavedEndpoint->Cb = Size;
  620. SavedEndpoint->Signature = EPLookupSignature;
  621. SavedEndpoint->Tower = NewTower(Psep->Tower);
  622. SavedEndpoint->Annotation = (char *)NewNode +
  623. sizeof(SAVED_EPT);
  624. memcpy( (char *) &SavedEndpoint->Object,
  625. (char *)&Node->ObjUuid,
  626. sizeof(UUID)
  627. );
  628. strcpy(SavedEndpoint->Annotation, Node->Annotation);
  629. if (SavedEndpoint->Tower == 0)
  630. {
  631. FreeMem(NewNode);
  632. return(RPC_S_OUT_OF_MEMORY);
  633. }
  634. if (fPatchTower)
  635. {
  636. PatchTower(SavedEndpoint->Tower, PatchTowerAddress);
  637. }
  638. break;
  639. default:
  640. ASSERT(!"Unknown lookup type\n");
  641. return(RPC_S_INTERNAL_ERROR);
  642. break;
  643. }
  644. Link((PIENTRY *)(&Context->List), NewNode);
  645. return(RPC_S_OK);
  646. }
  647. RPC_STATUS
  648. GetEntriesFromSavedContext(
  649. PSAVEDCONTEXT Context,
  650. char * Buffer,
  651. unsigned long Requested,
  652. unsigned long *Returned
  653. )
  654. {
  655. PIENTRY SavedEntry = (PIENTRY)Context->List;
  656. PIENTRY TmpEntry;
  657. unsigned long Type = Context->Type;
  658. while ( (*Returned < Requested) && (SavedEntry != 0) )
  659. {
  660. switch (Type)
  661. {
  662. case EP_MAP:
  663. ((I_Tower *)Buffer)->Tower = ((PSAVEDTOWER)SavedEntry)->Tower;
  664. Buffer = Buffer + sizeof(I_Tower);
  665. break;
  666. case EP_LOOKUP:
  667. ((ept_entry_t *)Buffer)->tower = ((PSAVED_EPT)SavedEntry)->Tower;
  668. strcpy(((ept_entry_t *)Buffer)->annotation,
  669. ((PSAVED_EPT)SavedEntry)->Annotation);
  670. memcpy(Buffer,(char *)&((PSAVED_EPT)SavedEntry)->Object,
  671. sizeof(UUID));
  672. Buffer = Buffer + sizeof(ept_entry_t);
  673. break;
  674. default:
  675. ASSERT(!"Unknown Inquiry Type");
  676. break;
  677. }
  678. (*Returned)++;
  679. TmpEntry = SavedEntry;
  680. SavedEntry = SavedEntry->Next;
  681. UnLink((PIENTRY *)&Context->List, TmpEntry);
  682. FreeMem(TmpEntry);
  683. }
  684. return(RPC_S_OK);
  685. }
  686. RPC_STATUS
  687. GetEntries(
  688. UUID *ObjUuid,
  689. UUID *IFUuid,
  690. unsigned long Version,
  691. char * Pseq,
  692. PSID pSID,
  693. ept_lookup_handle_t *key,
  694. char * Buffer,
  695. unsigned long Calltype,
  696. unsigned long Requested,
  697. unsigned long *Returned,
  698. unsigned long InqType,
  699. unsigned long VersOptions,
  700. PFNPointer Match
  701. )
  702. /*++
  703. Routine Description:
  704. This is a generic routine for retreiving a series [as spec. by Requested]
  705. of Towers (in case of Map) or ept_entry_t's in case of Lookup.
  706. Arguments:
  707. ObjUuid - Object Uuid
  708. IfUuid - Interface Uuid
  709. Version - InterfaceVersion [hi ushort = VerMajor, lo ushort VerMinor]
  710. Pseq - An ascii string specifying the protocol seq.
  711. pSID - SID of the registering principal. NULL will retrieve without regard to SID.
  712. key - A resume key - If NULL, search is started from the beginning
  713. if non-null, represents an encoding from where the epmapper
  714. supposed to start searching. It is an opaque value as far
  715. as the client is concerned.
  716. Buffer - A buffer of entries returned
  717. Calltype - A flag to indicate whether Ep_entries or string bindings
  718. are to be returned.
  719. Requested - Max no. of entries requested
  720. Returned - Actual no of entroes returned
  721. Return Value:
  722. RPC_S_OUT_OF_MEMORY
  723. RPC_S_OK
  724. EP_S_NOT_REGISTERED
  725. --*/
  726. {
  727. PIFOBJNode pNode=NULL, pList = IFObjList;
  728. unsigned long err=0, fResumeNodeFound=0;
  729. PPSEPNode pPSEPNode;
  730. char * buffer = Buffer;
  731. PSAVEDCONTEXT Context = (PSAVEDCONTEXT) *key;
  732. ept_lookup_handle_t LOOKUP_FINISHED = (ept_lookup_handle_t) LongToPtr(0xffffffff);
  733. int UNALIGNED *pIPAddr;
  734. BOOL fPatchTower;
  735. int PatchTowerAddress;
  736. SOCKADDR_STORAGE SockAddr;
  737. ULONG BufferSize;
  738. int FormatType;
  739. RPC_STATUS RpcStatus;
  740. *Returned = 0;
  741. EnterSem();
  742. if (*key)
  743. {
  744. if (*key == LOOKUP_FINISHED)
  745. {
  746. *key = 0;
  747. LeaveSem();
  748. return(EP_S_NOT_REGISTERED);
  749. }
  750. if (Context->Signature != EPLookupHandleSignature)
  751. {
  752. LeaveSem();
  753. return EP_S_CANT_PERFORM_OP;
  754. }
  755. err = GetEntriesFromSavedContext(Context, Buffer, Requested, Returned);
  756. if (Context->List == 0)
  757. {
  758. UnLink((PIENTRY *)&GlobalContextList, (PIENTRY)Context);
  759. FreeMem(Context);
  760. // Setting the Key To FFFFFFFFL is a hack for down level
  761. // Version 1.0 Ep Clients who never expected getting a key 0
  762. // and Success!
  763. if (Requested <= 1)
  764. *key = LOOKUP_FINISHED;
  765. else
  766. *key = 0L;
  767. LeaveSem();
  768. return(err);
  769. }
  770. LeaveSem();
  771. return(err);
  772. }
  773. *key = 0;
  774. while ((!err))
  775. {
  776. if ((pNode = FindIFOBJNode(
  777. pList,
  778. ObjUuid,
  779. IFUuid,
  780. Version,
  781. pSID,
  782. InqType,
  783. VersOptions,
  784. Match)) == 0)
  785. {
  786. break;
  787. }
  788. pPSEPNode = pNode->PSEPlist;
  789. while (pPSEPNode != 0)
  790. {
  791. if ((pPSEPNode = FindPSEP(pPSEPNode, Pseq, NULL, 0L,
  792. MatchPSAndEP)) == 0)
  793. break;
  794. fPatchTower = FALSE;
  795. if (StringCompareA(pPSEPNode->Protseq, "ncacn_ip_tcp") == 0
  796. || StringCompareA(pPSEPNode->Protseq, "ncadg_ip_udp") == 0
  797. || StringCompareA(pPSEPNode->Protseq, "ncacn_http") == 0)
  798. {
  799. pIPAddr = (int UNALIGNED *) ((char *) pPSEPNode->Tower + IP_ADDR_OFFSET);
  800. if (*pIPAddr == 0)
  801. {
  802. BufferSize = sizeof(SockAddr);
  803. RpcStatus = I_RpcServerInqLocalConnAddress(NULL,
  804. &SockAddr,
  805. &BufferSize,
  806. &FormatType);
  807. if (RpcStatus == RPC_S_OK)
  808. {
  809. // IPv6 towers don't exist yet - they are not defined
  810. // by DCE. Do patching for IPv4 only
  811. if (FormatType == RPC_P_ADDR_FORMAT_TCP_IPV4)
  812. {
  813. PatchTowerAddress = ((SOCKADDR_IN *)&SockAddr)->sin_addr.S_un.S_addr;
  814. fPatchTower = TRUE;
  815. }
  816. }
  817. }
  818. }
  819. if (*Returned < Requested)
  820. {
  821. err = PackDataIntoBuffer(&buffer, pNode, pPSEPNode, Calltype, fPatchTower, PatchTowerAddress);
  822. if (err == RPC_S_OK)
  823. {
  824. (*Returned)++;
  825. }
  826. else
  827. {
  828. ASSERT(err == RPC_S_OUT_OF_MEMORY);
  829. break;
  830. }
  831. }
  832. else
  833. {
  834. if (Context == 0)
  835. {
  836. *key = (ept_lookup_handle_t) (Context = GetNewContext(Calltype));
  837. if (Context == 0)
  838. {
  839. err = RPC_S_OUT_OF_MEMORY;
  840. break;
  841. }
  842. }
  843. AddToSavedContext(Context, pNode, pPSEPNode, Calltype, fPatchTower, PatchTowerAddress);
  844. }
  845. pPSEPNode = pPSEPNode->Next;
  846. } // while - over PSEPList
  847. pList = pNode->Next;
  848. } // while - over IFOBJList
  849. LeaveSem();
  850. if ((*Returned == 0) && Requested && (!err))
  851. {
  852. err = EP_S_NOT_REGISTERED;
  853. }
  854. if ((*Returned <= Requested) && (Context == 0))
  855. {
  856. if (Requested <= 1)
  857. *key = LOOKUP_FINISHED;
  858. else
  859. *key = 0L;
  860. }
  861. return(err);
  862. }
  863. RPC_STATUS
  864. PackDataIntoBuffer(
  865. char * * Buffer,
  866. PIFOBJNode Node,
  867. PPSEPNode PSEP,
  868. unsigned long Type,
  869. BOOL fPatchTower,
  870. int PatchTowerAddress
  871. )
  872. /*++
  873. Routine Description:
  874. This routine copies 1 entry [Either a Tower or ept_entry]
  875. in the Buffer, increments buffer appropriately.
  876. Arguments:
  877. BindingHandle - An explicit binding handle to the EP.
  878. Node - IFOBJNode
  879. PSEP - PSEPNode
  880. Type - Type of entry to be copied
  881. PatchTower - if TRUE, the newly created tower needs to be patched. If
  882. FALSE, the tower doesn't need to be patched
  883. PatchTowerAddress - an IPv4 representation of the address to be put
  884. in the tower. The IPv4 address must be in network byte order
  885. Return Value:
  886. RPC_S_OK or RPC_S_* for error
  887. --*/
  888. {
  889. I_Tower * Twr;
  890. ept_entry_t *p;
  891. switch (Type)
  892. {
  893. case EP_MAP:
  894. Twr = (I_Tower *)(* Buffer);
  895. Twr->Tower = NewTower(PSEP->Tower);
  896. if (Twr->Tower == 0)
  897. {
  898. return(RPC_S_OUT_OF_MEMORY);
  899. }
  900. if (fPatchTower)
  901. PatchTower(Twr->Tower, PatchTowerAddress);
  902. *Buffer += sizeof(I_Tower);
  903. break;
  904. case EP_LOOKUP:
  905. p = (ept_entry_t *)(*Buffer);
  906. p->tower = NewTower(PSEP->Tower);
  907. if (p->tower == 0)
  908. {
  909. return(RPC_S_OUT_OF_MEMORY);
  910. }
  911. if (fPatchTower)
  912. PatchTower(p->tower, PatchTowerAddress);
  913. memcpy( *Buffer, (char *)&Node->ObjUuid, sizeof(UUID) );
  914. strcpy(p->annotation, Node->Annotation);
  915. *Buffer += sizeof(ept_entry_t);
  916. break;
  917. default:
  918. ASSERT(!"Unknown type");
  919. break;
  920. }
  921. return(RPC_S_OK);
  922. }
  923. void
  924. ept_cleanup_handle_t_rundown(
  925. ept_cleanup_handle_t hEpCleanup
  926. )
  927. /*++
  928. Routine Description:
  929. This routine cleans up the entries registered by the process
  930. associated with this context handle hEpCleanup.
  931. Arguments:
  932. hEpCleanup - The context handle for which the rundown is
  933. being done.
  934. Return Value:
  935. None.
  936. --*/
  937. {
  938. PIFOBJNode NodesListToDelete = NULL;
  939. PIFOBJNode pIterator, DeleteMe, pPreviousNode;
  940. PPSEPNode pTempPSEP, pDeletePSEP;
  941. PEP_CLEANUP ProcessCtxt = (PEP_CLEANUP) hEpCleanup;
  942. #ifdef DBG_DETAIL
  943. PIFOBJNode pTemp, pLast;
  944. #endif // DBG_DETAIL
  945. if (ProcessCtxt == NULL)
  946. {
  947. return;
  948. }
  949. EnterSem();
  950. ASSERT(IFObjList);
  951. ASSERT(cTotalEpEntries > 0);
  952. ASSERT(ProcessCtxt->EntryList);
  953. ASSERT(ProcessCtxt->cEntries > 0);
  954. ASSERT(ProcessCtxt->EntryList->OwnerOfList == ProcessCtxt);
  955. ASSERT_PROCESS_CONTEXT_LIST_COUNT(ProcessCtxt, ProcessCtxt->cEntries);
  956. #ifdef DBG_DETAIL
  957. DbgPrint("RPCSS: Entered Cleanup Rundown for [%p] with (%d) entries\n",
  958. hEpCleanup, ProcessCtxt->cEntries);
  959. DbgPrint("RPCSS: Dump of IFOBJList\n");
  960. pTemp = IFObjList;
  961. pLast = IFObjList;
  962. while (pTemp)
  963. {
  964. DbgPrint("RPCSS: \t\t[%p]\n", pTemp);
  965. pLast = pTemp;
  966. pTemp = pTemp->Next;
  967. }
  968. DbgPrint("RPCSS: --------------------\n");
  969. while (pLast)
  970. {
  971. DbgPrint("RPCSS: \t\t\t[%p]\n", pLast);
  972. pLast = pLast->Prev;
  973. }
  974. #endif // DBG_DETAIL
  975. // Save the previous Node.
  976. pPreviousNode = ProcessCtxt->EntryList->Prev;
  977. pIterator = ProcessCtxt->EntryList;
  978. while ((pIterator != NULL) && (pIterator->OwnerOfList == ProcessCtxt))
  979. {
  980. ProcessCtxt->cEntries--;
  981. cTotalEpEntries--;
  982. #ifdef DBG_DETAIL
  983. DbgPrint("RPCSS: cTotalEpEntries-- [%p] (%d) - Cleanup\n", hEpCleanup, cTotalEpEntries);
  984. #endif // DBG_DETAIL
  985. DeleteMe = pIterator;
  986. pIterator = pIterator->Next;
  987. // Add to a list that will be deleted later.
  988. DeleteMe->Next = NodesListToDelete;
  989. NodesListToDelete = DeleteMe;
  990. DeleteMe->Signature = FREE;
  991. }
  992. ASSERT(ProcessCtxt->cEntries == 0);
  993. //
  994. // Adjust the links
  995. //
  996. if (pPreviousNode)
  997. {
  998. // Adjust forward link
  999. pPreviousNode->Next = pIterator;
  1000. }
  1001. else
  1002. {
  1003. ASSERT(ProcessCtxt->EntryList == IFObjList);
  1004. }
  1005. if (pIterator)
  1006. {
  1007. // Adjust backward link
  1008. pIterator->Prev = pPreviousNode;
  1009. }
  1010. //
  1011. // Empty the EP Mapper table, if necessary.
  1012. //
  1013. if (ProcessCtxt->EntryList == IFObjList)
  1014. {
  1015. if (pIterator)
  1016. {
  1017. ASSERT(cTotalEpEntries > 0);
  1018. // New Head for Ep Mapper list
  1019. IFObjList = pIterator;
  1020. }
  1021. else
  1022. {
  1023. ASSERT(cTotalEpEntries == 0);
  1024. // Memory for this node is already freed in the while loop above.
  1025. IFObjList = NULL;
  1026. }
  1027. }
  1028. else
  1029. {
  1030. ASSERT(cTotalEpEntries > 0);
  1031. }
  1032. LeaveSem();
  1033. //
  1034. // Free entities outside the lock.
  1035. //
  1036. FreeMem(ProcessCtxt);
  1037. while (NodesListToDelete != NULL)
  1038. {
  1039. DeleteMe = NodesListToDelete;
  1040. NodesListToDelete = NodesListToDelete->Next;
  1041. // Delete the PSEP list.
  1042. pTempPSEP = DeleteMe->PSEPlist;
  1043. while (pTempPSEP != NULL)
  1044. {
  1045. pDeletePSEP = pTempPSEP;
  1046. pTempPSEP = pTempPSEP->Next;
  1047. FreeMem(pDeletePSEP);
  1048. }
  1049. I_RpcFree(DeleteMe->pSID);
  1050. FreeMem(DeleteMe);
  1051. }
  1052. }
  1053. void
  1054. ept_insert(
  1055. handle_t h,
  1056. unsigned32 NumEntries,
  1057. ept_entry_t Entries[],
  1058. unsigned long Replace,
  1059. error_status *Status
  1060. )
  1061. /*++
  1062. Routine Description:
  1063. This function is no longer supported by EpMapper. RPC Runtime does not
  1064. call this function anymore. And, no one else should be...
  1065. --*/
  1066. {
  1067. if (Status == NULL)
  1068. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1069. *Status = EPT_S_CANT_PERFORM_OP;
  1070. }
  1071. RPC_STATUS GetCurrentUserSid(
  1072. IN BOOL fImpersonating,
  1073. OUT PSID *ppSid
  1074. )
  1075. /*++
  1076. Routine Description:
  1077. Returns the SID of the thread if thread token could be queried, or the process.
  1078. It is the responsibility of the caller to free the SID.
  1079. Return Value:
  1080. RPC_S_OK on sucess
  1081. --*/
  1082. {
  1083. HANDLE hUserToken;
  1084. HANDLE hThread = GetCurrentThread(); // We don't need to close this handle.
  1085. DWORD dwStatus = 0;
  1086. DWORD dwSizeNeeded = 0;
  1087. TOKEN_USER *pTokenData;
  1088. BOOL b;
  1089. DWORD cbSid;
  1090. // First, try to get the access token from the thread, in case
  1091. // we are impersonating.
  1092. if (!hThread)
  1093. {
  1094. return RPC_S_OUT_OF_RESOURCES;
  1095. }
  1096. b = OpenThreadToken(hThread,
  1097. TOKEN_READ,
  1098. FALSE, // Use context of the thread...
  1099. &hUserToken);
  1100. // We could not get the thread's token
  1101. if (!b)
  1102. {
  1103. dwStatus = GetLastError();
  1104. // If we are getting an impersonation token we have to fail
  1105. // since retrieving the process token would be incorrect.
  1106. if (fImpersonating)
  1107. {
  1108. ASSERT(dwStatus != ERROR_NO_TOKEN);
  1109. return RPC_S_OUT_OF_RESOURCES;
  1110. }
  1111. if (dwStatus == ERROR_NO_TOKEN)
  1112. {
  1113. // Try to get the process' access token.
  1114. HANDLE hProcess = GetCurrentProcess(); // This never fails.
  1115. ASSERT(hProcess);
  1116. // Reset the status since we are trying again to get the token.
  1117. dwStatus = NO_ERROR;
  1118. b = OpenProcessToken(hProcess,
  1119. TOKEN_READ,
  1120. &hUserToken);
  1121. if (!b)
  1122. {
  1123. dwStatus = GetLastError();
  1124. }
  1125. }
  1126. }
  1127. // Both ways of getting the token failed.
  1128. if (dwStatus)
  1129. {
  1130. return RPC_S_OUT_OF_RESOURCES;
  1131. }
  1132. // We have a token.
  1133. ASSERT(hUserToken);
  1134. // Query for the size of user information.
  1135. b = GetTokenInformation( hUserToken,
  1136. TokenUser,
  1137. 0,
  1138. 0,
  1139. &dwSizeNeeded
  1140. );
  1141. // Query should have failed.
  1142. ASSERT(!b && (GetLastError() == ERROR_INSUFFICIENT_BUFFER));
  1143. // Allocate and retrieve the user info.
  1144. pTokenData = (TOKEN_USER*)_alloca(dwSizeNeeded);
  1145. if (!GetTokenInformation( hUserToken,
  1146. TokenUser,
  1147. pTokenData,
  1148. dwSizeNeeded,
  1149. &dwSizeNeeded ))
  1150. {
  1151. CloseHandle(hUserToken);
  1152. return RPC_S_OUT_OF_RESOURCES;
  1153. }
  1154. CloseHandle(hUserToken);
  1155. // Copy out the SID to be returned.
  1156. cbSid = GetLengthSid(pTokenData->User.Sid);
  1157. *ppSid = (PSID) I_RpcAllocate(cbSid);
  1158. if (*ppSid == NULL)
  1159. {
  1160. return RPC_S_OUT_OF_RESOURCES;
  1161. }
  1162. CopySid(cbSid, *ppSid, pTokenData->User.Sid);
  1163. // The caller will have to free the copy.
  1164. return RPC_S_OK;
  1165. }
  1166. void
  1167. ept_insert_ex(
  1168. IN handle_t h,
  1169. IN OUT ept_cleanup_handle_t *hEpCleanup,
  1170. IN unsigned32 NumEntries,
  1171. IN ept_entry_t Entries[],
  1172. IN unsigned long Replace,
  1173. OUT error_status *Status
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. This is the exposed rpc interface routine that adds a series of
  1178. endpoints to the Endpoint Mapper database.
  1179. Arguments:
  1180. h - An explicit binding handle to the EP.
  1181. hEpCleanup - A context handle used to purge the Endpoint Mapper
  1182. database of stale entries.
  1183. NumEntries - Number of Entries to be added.
  1184. Entries - An array of ept_entry_t entries.
  1185. Replace - TRUE => Replace existing entries.
  1186. FALSE=> Just add.
  1187. Return Value:
  1188. RPC_S_OK - The endpoint was successfully deleted.
  1189. RPC_S_OUT_OF_MEMORY - There is no memory to perform the op.
  1190. EPT_S_CANT_PERFORM - Invalid entry.
  1191. --*/
  1192. {
  1193. ept_entry_t * Ep;
  1194. unsigned short i, j;
  1195. unsigned int TransType = 0x0;
  1196. unsigned long err = 0;
  1197. unsigned long Version;
  1198. unsigned char protseqid;
  1199. char *Protseq, *Endpoint;
  1200. RPC_IF_ID IfId;
  1201. PPSEPNode List = 0;
  1202. PPSEPNode pPSEPNode, TmpPsep, pTempPSEP, pDeletePSEP;
  1203. unsigned long cb;
  1204. twr_t * Tower;
  1205. BOOL bIFNodeFound = FALSE;
  1206. PIFOBJNode NodesListToDelete = NULL;
  1207. PIFOBJNode Node, NewNode, DeleteMe = NULL;
  1208. UUID * Object;
  1209. char * Annotation;
  1210. RPC_STATUS Err;
  1211. SECURITY_DESCRIPTOR SecurityDescriptor, * PSecurityDesc;
  1212. BOOL Bool;
  1213. // SID of the principal registering the endpoint.
  1214. PSID pSID;
  1215. if (Status == NULL)
  1216. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1217. // Security callback for the local epmp interface ensures that
  1218. // the function may be called over lpc only.
  1219. //
  1220. // Create a temporary PSEP list from the Tower entries.
  1221. //
  1222. for (Ep = &Entries[0], i = 0; i < NumEntries; Ep++,i++)
  1223. {
  1224. err = TowerExplode(
  1225. Ep->tower,
  1226. &IfId,
  1227. NULL,
  1228. &Protseq,
  1229. &Endpoint,
  1230. 0
  1231. );
  1232. if (err == RPC_S_OUT_OF_MEMORY)
  1233. break;
  1234. if (err)
  1235. {
  1236. err = RPC_S_OK;
  1237. continue;
  1238. }
  1239. Object = &Ep->object;
  1240. Annotation = (char *)&Ep->annotation;
  1241. Tower = Ep->tower;
  1242. cb = sizeof(PSEPNode) +
  1243. strlen(Protseq) +
  1244. strlen(Endpoint) +
  1245. 2 + // for the 2 null terminators
  1246. Tower->tower_length +
  1247. sizeof(Tower->tower_length) +
  1248. 4; // We need to align tower on DWORD
  1249. if ( (pPSEPNode = AllocMem(cb)) == NULL )
  1250. {
  1251. I_RpcFree(Protseq);
  1252. I_RpcFree(Endpoint);
  1253. err = RPC_S_OUT_OF_MEMORY;
  1254. break;
  1255. }
  1256. // Mark this protseq to start listening if needed.
  1257. protseqid = (unsigned char) GetProtseqIdAnsi(Protseq);
  1258. DelayedUseProtseq(protseqid);
  1259. //
  1260. // Add a node to the temporary PSEP list
  1261. //
  1262. memset(pPSEPNode, 0, cb);
  1263. pPSEPNode->Signature = PSEPSIGN;
  1264. pPSEPNode->Cb = cb;
  1265. // Protseq
  1266. //
  1267. // Protseq is located after the PPSEPNode structure in the block at address pPSEPNode
  1268. // allocated above. We created the block so that it would contain enough space for
  1269. // Protseq, Endpoint, and Tower so that we would not allocate them separately.
  1270. pPSEPNode->Protseq = (char *) (pPSEPNode + 1);
  1271. strcpy(pPSEPNode->Protseq, Protseq);
  1272. // Endpoint
  1273. //
  1274. // Similarly to Protseq, EP is located in the same heap block following the Protseq.
  1275. pPSEPNode->EP = pPSEPNode->Protseq + strlen(pPSEPNode->Protseq) + 1;
  1276. strcpy(pPSEPNode->EP, Endpoint);
  1277. // Tower. We add necessary pad so that Tower is aligned to a DWORD.
  1278. pPSEPNode->Tower = (twr_t PAPI *)(pPSEPNode->EP +
  1279. strlen(pPSEPNode->EP) + 1);
  1280. (char PAPI*)(pPSEPNode->Tower) += 4 - ((ULONG_PTR)
  1281. (pPSEPNode->Tower) & 3);
  1282. memcpy((char PAPI *)pPSEPNode->Tower,
  1283. Tower,
  1284. Tower->tower_length + sizeof(Tower->tower_length)
  1285. );
  1286. // Finally, add.
  1287. EnterSem();
  1288. EnLinkOnPSEPList(&List, pPSEPNode);
  1289. LeaveSem();
  1290. I_RpcFree(Protseq);
  1291. I_RpcFree(Endpoint);
  1292. }
  1293. if ((err == RPC_S_OUT_OF_MEMORY) || (List == 0))
  1294. {
  1295. *Status = err;
  1296. return;
  1297. }
  1298. CompleteDelayedUseProtseqs();
  1299. Version = VERSION(IfId.VersMajor, IfId.VersMinor);
  1300. // Get the SID of the caller to be included in the IFOBJ structure.
  1301. Err = RpcImpersonateClient(NULL);
  1302. if (Err != RPC_S_OK)
  1303. {
  1304. RpcRaiseException(Err);
  1305. }
  1306. Err = GetCurrentUserSid(TRUE, &pSID);
  1307. if (Err != RPC_S_OK)
  1308. {
  1309. Err = RpcRevertToSelf();
  1310. ASSERT(Err == RPC_S_OK);
  1311. RpcRaiseException(Err);
  1312. }
  1313. ASSERT(pSID != NULL);
  1314. Err = RpcRevertToSelf();
  1315. ASSERT(Err == RPC_S_OK);
  1316. //
  1317. // Find if a compatible Endpoint Mapper entry is already present.
  1318. //
  1319. if (*hEpCleanup != NULL)
  1320. {
  1321. //
  1322. // The requesting process has previously registered entries
  1323. // with the Endpoint Mapper.
  1324. //
  1325. ASSERT_PROCESS_CONTEXT_LIST_COUNT((PEP_CLEANUP)*hEpCleanup, ((PEP_CLEANUP)*hEpCleanup)->cEntries);
  1326. ASSERT(((PEP_CLEANUP)*hEpCleanup)->MagicVal == CLEANUP_MAGIC_VALUE);
  1327. ASSERT(((PEP_CLEANUP)*hEpCleanup)->cEntries != 0);
  1328. if ( (((PEP_CLEANUP)*hEpCleanup)->MagicVal != CLEANUP_MAGIC_VALUE)
  1329. || (((PEP_CLEANUP)*hEpCleanup)->cEntries == 0))
  1330. {
  1331. *Status = EPT_S_CANT_PERFORM_OP;
  1332. I_RpcFree(pSID);
  1333. return;
  1334. }
  1335. EnterSem();
  1336. if (Replace == TRUE) // Common case
  1337. {
  1338. //
  1339. // If we find a compatible entry, we just replace its PSEP list
  1340. // with the temporary list that we just created.
  1341. //
  1342. Node = ((PEP_CLEANUP)*hEpCleanup)->EntryList;
  1343. while (Node != 0)
  1344. {
  1345. Node = FindIFOBJNode(
  1346. Node,
  1347. Object,
  1348. &IfId.Uuid,
  1349. Version,
  1350. pSID,
  1351. RPC_C_EP_MATCH_BY_BOTH,
  1352. I_RPC_C_VERS_UPTO_AND_COMPATIBLE,
  1353. SearchIFObjNode
  1354. );
  1355. if ((Node == 0) || (Node->OwnerOfList != *hEpCleanup))
  1356. break;
  1357. // Matching Endpoint Mapper entry found.
  1358. PurgeOldEntries(Node, List, FALSE);
  1359. if (Node->IFVersion == Version)
  1360. {
  1361. bIFNodeFound = TRUE;
  1362. // Seek to the end of Tmp and then Link
  1363. TmpPsep = List;
  1364. while (TmpPsep->Next != 0)
  1365. TmpPsep = TmpPsep->Next;
  1366. TmpPsep->Next = Node->PSEPlist;
  1367. Node->PSEPlist = List;
  1368. }
  1369. if (Node->PSEPlist == 0)
  1370. {
  1371. DeleteMe = Node;
  1372. Node = Node->Next;
  1373. err = UnLinkFromIFOBJList((PEP_CLEANUP)*hEpCleanup, DeleteMe);
  1374. ASSERT(err == RPC_S_OK);
  1375. // Add to a list that will be deleted later...
  1376. DeleteMe->Next = NodesListToDelete;
  1377. NodesListToDelete = DeleteMe;
  1378. DeleteMe->Signature = FREE;
  1379. }
  1380. else
  1381. {
  1382. Node = Node->Next;
  1383. }
  1384. } // while loop
  1385. }
  1386. else // (Replace != TRUE)
  1387. {
  1388. //
  1389. // If we find an entry with an exact match, we append
  1390. // the temporary PSEP list to the entry's PSEP list.
  1391. //
  1392. Node = ((PEP_CLEANUP)*hEpCleanup)->EntryList;
  1393. NewNode = FindIFOBJNode(
  1394. Node,
  1395. Object,
  1396. &IfId.Uuid,
  1397. Version,
  1398. pSID,
  1399. 0,
  1400. 0,
  1401. ExactMatch
  1402. );
  1403. if (NewNode && (NewNode->OwnerOfList == *hEpCleanup))
  1404. {
  1405. bIFNodeFound = TRUE;
  1406. PurgeOldEntries(NewNode, List, TRUE);
  1407. // Seek to the end of Tmp and then Link
  1408. TmpPsep = List;
  1409. while (TmpPsep->Next != 0)
  1410. TmpPsep = TmpPsep->Next;
  1411. TmpPsep->Next = NewNode->PSEPlist;
  1412. NewNode->PSEPlist = List;
  1413. }
  1414. } // if (Replace == TRUE)
  1415. LeaveSem();
  1416. } // if (*hpCleanup != NULL)
  1417. //
  1418. // Free the list outside the lock.
  1419. //
  1420. while (NodesListToDelete != NULL)
  1421. {
  1422. DeleteMe = NodesListToDelete;
  1423. NodesListToDelete = NodesListToDelete->Next;
  1424. // Delete the PSEP list.
  1425. pTempPSEP = DeleteMe->PSEPlist;
  1426. while (pTempPSEP != NULL)
  1427. {
  1428. pDeletePSEP = pTempPSEP;
  1429. pTempPSEP = pTempPSEP->Next;
  1430. FreeMem(pDeletePSEP);
  1431. }
  1432. FreeMem(DeleteMe);
  1433. }
  1434. if (bIFNodeFound == FALSE)
  1435. {
  1436. //
  1437. // One of the following is TRUE:
  1438. // a. The process is registering with EP Mapper for the first time.
  1439. // b. No compatible Ep entry was found.
  1440. //
  1441. //
  1442. // Allocate a new EP Mapper entry.
  1443. //
  1444. cb = sizeof(IFOBJNode);
  1445. // We will put Annotation in the same heap block after IFOBJNode.
  1446. cb += strlen(Annotation) + 1;
  1447. if ((NewNode = AllocMem(cb)) == NULL)
  1448. {
  1449. *Status = RPC_S_OUT_OF_MEMORY;
  1450. I_RpcFree(pSID);
  1451. return;
  1452. }
  1453. //
  1454. // Fill-in the new entry
  1455. //
  1456. memset(NewNode, 0, cb);
  1457. NewNode->Cb = cb;
  1458. NewNode->Signature = IFOBJSIGN;
  1459. NewNode->IFVersion = Version;
  1460. memcpy((char *)&NewNode->ObjUuid, (char *)Object, sizeof(UUID));
  1461. memcpy((char *)&NewNode->IFUuid, (char *)&IfId.Uuid, sizeof(UUID));
  1462. // Put Annotation in the IFOBJNode's heap block after the structure.
  1463. strcpy((NewNode->Annotation=(char *)(NewNode+1)), Annotation);
  1464. // The SID now migrated to the IFOBJNode.
  1465. NewNode->pSID = pSID;
  1466. if (IsNullUuid(Object))
  1467. NewNode->IFOBJid = MAKEGLOBALIFOBJID(MAXIFOBJID);
  1468. else
  1469. NewNode->IFOBJid = MAKEGLOBALIFOBJID(GlobalIFOBJid--);
  1470. //
  1471. // Create a new context for this process, if necessary
  1472. //
  1473. if (*hEpCleanup == NULL)
  1474. {
  1475. *hEpCleanup = AllocMem(sizeof(EP_CLEANUP));
  1476. if (*hEpCleanup == NULL)
  1477. {
  1478. FreeMem(NewNode);
  1479. I_RpcFree(NewNode->pSID);
  1480. *Status = RPC_S_OUT_OF_MEMORY;
  1481. return;
  1482. }
  1483. memset(*hEpCleanup, 0x0, sizeof(EP_CLEANUP));
  1484. ((PEP_CLEANUP)*hEpCleanup)->MagicVal = CLEANUP_MAGIC_VALUE;
  1485. }
  1486. //
  1487. // Insert the new entry into the EP Mapper table.
  1488. //
  1489. EnterSem();
  1490. err = EnLinkOnIFOBJList((PEP_CLEANUP)*hEpCleanup, NewNode);
  1491. ASSERT(err == RPC_S_OK);
  1492. NewNode->PSEPlist = List;
  1493. LeaveSem();
  1494. }
  1495. *Status = err;
  1496. }
  1497. void
  1498. ept_delete(
  1499. handle_t h,
  1500. unsigned32 NumEntries,
  1501. ept_entry_t Entries[],
  1502. error_status *Status
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. This function is no longer supported by EpMapper. RPC Runtime does not
  1507. call this function anymore. And, no one else should be...
  1508. --*/
  1509. {
  1510. if (Status == NULL)
  1511. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1512. *Status = EPT_S_CANT_PERFORM_OP;
  1513. }
  1514. RPC_STATUS
  1515. ept_delete_ex_helper(
  1516. IN ept_cleanup_handle_t hEpCleanup,
  1517. IN UUID *Object,
  1518. IN UUID *Interface,
  1519. IN unsigned long IFVersion,
  1520. IN char PAPI * Protseq,
  1521. IN char PAPI * Endpoint
  1522. )
  1523. /*++
  1524. Routine Description:
  1525. This routine deletes an Endpoint registered with the EP Mapper
  1526. Arguments:
  1527. hEpCleanup - A context handle used to purge the Endpoint Mapper
  1528. database of stale entries.
  1529. Object - Object Uuid.
  1530. Interface - If Uuid
  1531. IFVersion - Version of the IF [Hi ushort=Major, Lo ushort=Minor]
  1532. Protseq - Protocol Sequence
  1533. Endpoint - Endpoint string
  1534. Notes:
  1535. a. This routine has to be called by holding a mutex.
  1536. Return Value:
  1537. RPC_S_OK - The endpoint was successfully deleted
  1538. EPT_S_NOT_REGISTERED - No matching entries were found
  1539. --*/
  1540. {
  1541. PIFOBJNode pNode;
  1542. PPSEPNode pPSEPNode = NULL;
  1543. unsigned long cb, err = 0;
  1544. PEP_T p;
  1545. PEP_CLEANUP ProcessCtx;
  1546. if (!Protseq || !Endpoint)
  1547. {
  1548. return(EPT_S_NOT_REGISTERED);
  1549. }
  1550. CheckInSem();
  1551. ProcessCtx = (PEP_CLEANUP)hEpCleanup;
  1552. if (ProcessCtx->EntryList == NULL)
  1553. return EPT_S_NOT_REGISTERED;
  1554. // Search without regard to the registrant's SID.
  1555. pNode = FindIFOBJNode(
  1556. ProcessCtx->EntryList,
  1557. Object,
  1558. Interface,
  1559. IFVersion,
  1560. NULL,
  1561. 0L,
  1562. 0L,
  1563. ExactMatch
  1564. );
  1565. if ((pNode != NULL) && (pNode->PSEPlist != NULL))
  1566. {
  1567. pPSEPNode = FindPSEP(
  1568. pNode->PSEPlist,
  1569. Protseq,
  1570. Endpoint,
  1571. 0L,
  1572. MatchPSAndEP
  1573. );
  1574. }
  1575. if (pPSEPNode != NULL)
  1576. {
  1577. UnLinkFromPSEPList(&pNode->PSEPlist, pPSEPNode);
  1578. if (pNode->PSEPlist == NULL)
  1579. {
  1580. err = UnLinkFromIFOBJList((PEP_CLEANUP)hEpCleanup, pNode);
  1581. ASSERT(err == RPC_S_OK);
  1582. if (err != RPC_S_OK)
  1583. {
  1584. // Restore the PSEPList
  1585. EnLinkOnPSEPList(&pNode->PSEPlist, pPSEPNode);
  1586. return err;
  1587. }
  1588. pNode->Signature = FREE;
  1589. I_RpcFree(pNode->pSID);
  1590. FreeMem(pNode);
  1591. }
  1592. pPSEPNode->Signature = FREE;
  1593. FreeMem(pPSEPNode);
  1594. }
  1595. else
  1596. {
  1597. err = EPT_S_NOT_REGISTERED;
  1598. }
  1599. return(err);
  1600. }
  1601. void
  1602. ept_delete_ex(
  1603. IN handle_t h,
  1604. IN OUT ept_cleanup_handle_t *hEpCleanup,
  1605. IN unsigned32 NumEntries,
  1606. IN ept_entry_t Entries[],
  1607. OUT error_status *Status
  1608. )
  1609. /*++
  1610. Routine Description:
  1611. This routine deletes the specified Endpoints
  1612. Arguments:
  1613. BindingHandle - An explicit binding handle to the EP.
  1614. NumEntries - #of entries in the Bunffer that need to be deleted.
  1615. Entries[] - Buffer of #NumEntries of ept_entry_t structures
  1616. Return Value:
  1617. RPC_S_OK - The endpoint was successfully deleted
  1618. EPT_S_NOT_REGISTERED - No matching entries were found
  1619. --*/
  1620. {
  1621. ept_entry_t * Ep;
  1622. unsigned short i;
  1623. unsigned int TransType = 0x0;
  1624. RPC_STATUS err;
  1625. RPC_STATUS DeleteStatus;
  1626. unsigned long Version;
  1627. char *Protseq, *Endpoint;
  1628. RPC_IF_ID IfId;
  1629. RPC_TRANSFER_SYNTAX XferId;
  1630. if (Status == NULL)
  1631. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1632. // Security callback for the local epmp interface ensures that
  1633. // the function may be called over lpc only.
  1634. if ( !( (*hEpCleanup)
  1635. && (((PEP_CLEANUP)*hEpCleanup)->MagicVal == CLEANUP_MAGIC_VALUE)
  1636. && (((PEP_CLEANUP)*hEpCleanup)->cEntries != 0)
  1637. )
  1638. )
  1639. {
  1640. //
  1641. // Cannot ASSERT here. This is possible. (ep1-26, ep2-3)
  1642. //
  1643. //ASSERT(*hEpCleanup);
  1644. //ASSERT(((PEP_CLEANUP)*hEpCleanup)->MagicVal == CLEANUP_MAGIC_VALUE);
  1645. //ASSERT(((PEP_CLEANUP)*hEpCleanup)->cEntries != 0);
  1646. *Status = EPT_S_CANT_PERFORM_OP;
  1647. return;
  1648. }
  1649. *Status = EPT_S_NOT_REGISTERED;
  1650. DeleteStatus = RPC_S_OK;
  1651. for (Ep = &Entries[0], i = 0; i < NumEntries; Ep++,i++)
  1652. {
  1653. err = TowerExplode(
  1654. Ep->tower,
  1655. &IfId,
  1656. &XferId,
  1657. &Protseq,
  1658. &Endpoint,
  1659. 0
  1660. );
  1661. if (err == RPC_S_OUT_OF_MEMORY)
  1662. {
  1663. *Status = RPC_S_OUT_OF_MEMORY;
  1664. break;
  1665. }
  1666. if (err)
  1667. {
  1668. continue;
  1669. }
  1670. Version = VERSION(IfId.VersMajor, IfId.VersMinor);
  1671. EnterSem();
  1672. //
  1673. // NOTE:
  1674. //
  1675. // If even one call to ept_delete_ex_helper() fails, we want to return
  1676. // failure from ept_delete_ex(). This is different from the past where
  1677. // if one call succeeded, then the function returned success.
  1678. //
  1679. err = ept_delete_ex_helper(
  1680. *hEpCleanup,
  1681. &Ep->object,
  1682. &IfId.Uuid,
  1683. Version,
  1684. Protseq,
  1685. Endpoint
  1686. );
  1687. if (err)
  1688. {
  1689. // Save the last failure status.
  1690. DeleteStatus = err;
  1691. }
  1692. if (((PEP_CLEANUP)*hEpCleanup)->cEntries == 0)
  1693. {
  1694. //
  1695. // No entry left in this process's list. Time to zero out this
  1696. // process's context handle.
  1697. //
  1698. //ASSERT(((PEP_CLEANUP)*hEpCleanup)->EntryList == NULL);
  1699. FreeMem(*hEpCleanup);
  1700. *hEpCleanup = NULL;
  1701. }
  1702. LeaveSem();
  1703. if (Protseq)
  1704. I_RpcFree(Protseq);
  1705. if (Endpoint)
  1706. I_RpcFree(Endpoint);
  1707. }
  1708. if (err)
  1709. {
  1710. // RPC_S_OUT_OF_MEMORY OR the last call to
  1711. // ept_delete_ex_helper() failed.
  1712. *Status = err;
  1713. }
  1714. else
  1715. {
  1716. // RPC_S_OK OR one of the calls to ept_delete_ex_helper() (but
  1717. // not the last one) failed.
  1718. *Status = DeleteStatus;
  1719. }
  1720. }
  1721. void
  1722. ept_lookup(
  1723. handle_t hEpMapper,
  1724. unsigned32 InquiryType,
  1725. UUID * Object,
  1726. RPC_IF_ID * Ifid,
  1727. unsigned32 VersOptions,
  1728. ept_lookup_handle_t *LookupHandle,
  1729. unsigned32 MaxRequested,
  1730. unsigned32 *NumEntries,
  1731. ept_entry_t Entries[],
  1732. error_status *Status
  1733. )
  1734. /*++
  1735. Routine Description:
  1736. This routine returns upto MaxRequested, ept_entry(s) currently
  1737. registered with the Endpoint mapper based on the
  1738. Obj, Interface, Protocol sequence and filters VersOptions and
  1739. InqType
  1740. Arguments:
  1741. hEpMapper - An explicit binding handle to the EP.
  1742. InquiryType - Search Filter [Seach based on IF, Obj or Both]
  1743. Object - Object Uuid. specified by the client
  1744. Ifid - Interface Uuid spec. by the client.
  1745. InId - The If Specification [IF Uuid+IfVersion]
  1746. VersOptions - Search Filter based on Versions [Versins <, >, ==]
  1747. LookupHandle - A resume key - If NULL, search is started from the beginning
  1748. if non-null, represents an encoding from where the epmapper is
  1749. is supposed to start searching. It is an opaque value as far as the
  1750. as far as the client is concerned.
  1751. MaxRequested - Max number of entries requested by the client.
  1752. NumEntries - The actual number of entries returned by the mapper.
  1753. Entries - Buffer of ept_entries returned.
  1754. Return Value:
  1755. RPC_S_OUT_OF_MEMORY
  1756. RPC_S_OK - At least one matching entry is being returned.
  1757. EP_S_NOT_REGISTERED - No matching entries were found
  1758. EPT_S_CANT_PERFORM_OP - MaxRequested value exceed ep_max_lookup_results
  1759. --*/
  1760. {
  1761. unsigned long Version;
  1762. if (Status == NULL)
  1763. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1764. if (Ifid == NULL)
  1765. {
  1766. Ifid = &LocalNullUuid;
  1767. }
  1768. else
  1769. {
  1770. // Multiple full pointers in one method might point to the same memory.
  1771. // We need to check for pointer values being the same in the manager routine
  1772. // because reading these is unsafe and may case read-AVs.
  1773. if ((void *)Ifid == (void *)Object)
  1774. {
  1775. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1776. }
  1777. }
  1778. if (Object == NULL)
  1779. {
  1780. Object = (UUID *) &LocalNullUuid;
  1781. }
  1782. switch (VersOptions)
  1783. {
  1784. case RPC_C_VERS_ALL:
  1785. Version = 0;
  1786. break;
  1787. case RPC_C_VERS_COMPATIBLE:
  1788. case RPC_C_VERS_EXACT:
  1789. case RPC_C_VERS_UPTO:
  1790. Version = VERSION(Ifid->VersMajor, Ifid->VersMinor);
  1791. break;
  1792. case RPC_C_VERS_MAJOR_ONLY:
  1793. Version = VERSION(Ifid->VersMajor, 0);
  1794. break;
  1795. default:
  1796. break;
  1797. }
  1798. *Status = GetEntries(
  1799. Object,
  1800. &Ifid->Uuid,
  1801. Version,
  1802. NULL,
  1803. NULL,
  1804. LookupHandle,
  1805. (char *)Entries,
  1806. EP_LOOKUP,
  1807. MaxRequested,
  1808. NumEntries,
  1809. InquiryType,
  1810. VersOptions,
  1811. SearchIFObjNode
  1812. );
  1813. }
  1814. void
  1815. ept_map_auth(
  1816. handle_t h,
  1817. UUID *Obj OPTIONAL,
  1818. twr_p_t MapTower,
  1819. PISID pSID,
  1820. ept_lookup_handle_t *MapHandle,
  1821. unsigned32 MaxTowers,
  1822. unsigned32 *NumTowers,
  1823. twr_p_t *ITowers,
  1824. error_status *Status
  1825. )
  1826. /*++
  1827. Routine Description:
  1828. This routine returns a fully-resolved string binding, for a given
  1829. Obj, Interface, and Protocol sequence if an appropriate entry is
  1830. found. Else returns EP_S_NOT_REGISTERED.
  1831. Arguments:
  1832. h - An explicit binding handle to the EP.
  1833. Obj - Object Uuid specified by the client.
  1834. MapTower - The input tower containing the protseq to query.
  1835. pSID - The SID specified by the client. If non-NULL, only entries registered
  1836. by the principal with this SID will be returned. If NULL, any matching entry
  1837. will be returned without regard to the registering SID.
  1838. MapHandle - A resume key - If NULL, search is started from the beginning
  1839. if non-null, represents an encoding from where the epmapper is
  1840. supposed to start searching. It is an opaque value as far as the
  1841. client is concerned.
  1842. MaxTowers - Max number of entries requested by the client.
  1843. NumTowers - The actual number of entries returned by the mapper.
  1844. ITowers - The fully resolved bindings.
  1845. Return Value:
  1846. RPC_S_OUT_OF_MEMORY
  1847. RPC_S_OK
  1848. EP_S_NOT_REGISTERED
  1849. --*/
  1850. {
  1851. RPC_IF_ID Ifid;
  1852. RPC_TRANSFER_SYNTAX Xferid;
  1853. char *Protseq;
  1854. unsigned long Version;
  1855. char * String = 0;
  1856. if (Status == NULL)
  1857. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1858. if (pSID != NULL && !IsValidSid(pSID))
  1859. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1860. if (Obj == 0)
  1861. {
  1862. Obj = (UUID *) &LocalNullUuid;
  1863. }
  1864. else
  1865. {
  1866. // Multiple full pointers in one method might point to the same memory.
  1867. // We need to check for pointer values being the same in the manager routine
  1868. // because reading these is unsafe and may case read-AVs.
  1869. if ((void *)Obj == (void *)MapTower)
  1870. {
  1871. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1872. }
  1873. }
  1874. *Status = TowerExplode(
  1875. MapTower,
  1876. &Ifid,
  1877. &Xferid,
  1878. &Protseq,
  1879. NULL,
  1880. 0
  1881. );
  1882. if (*Status)
  1883. {
  1884. *NumTowers = 0;
  1885. return;
  1886. }
  1887. Version = VERSION(Ifid.VersMajor,Ifid.VersMinor);
  1888. if (memcmp((char *)&Ifid.Uuid, (char *)&MgmtIf, sizeof(UUID)) == 0)
  1889. {
  1890. if ((Obj == 0) || IsNullUuid(Obj))
  1891. {
  1892. *NumTowers = 0;
  1893. *Status = RPC_S_BINDING_INCOMPLETE;
  1894. }
  1895. else
  1896. {
  1897. *Status = GetEntries(
  1898. Obj,
  1899. &Ifid.Uuid,
  1900. Version,
  1901. Protseq,
  1902. pSID,
  1903. MapHandle,
  1904. (char *)ITowers,
  1905. EP_MAP,
  1906. MaxTowers,
  1907. NumTowers,
  1908. RPC_C_EP_MATCH_BY_OBJ,
  1909. RPC_C_VERS_ALL,
  1910. SearchIFObjNode
  1911. );
  1912. }
  1913. }
  1914. else
  1915. {
  1916. *Status = GetEntries(
  1917. Obj,
  1918. &Ifid.Uuid,
  1919. Version,
  1920. Protseq,
  1921. pSID,
  1922. MapHandle,
  1923. (char *)ITowers,
  1924. EP_MAP,
  1925. MaxTowers,
  1926. NumTowers,
  1927. 0L,
  1928. 0L,
  1929. WildCardMatch
  1930. );
  1931. }
  1932. if (Protseq)
  1933. I_RpcFree(Protseq);
  1934. }
  1935. void
  1936. ept_map(
  1937. handle_t h,
  1938. UUID *Obj OPTIONAL,
  1939. twr_p_t MapTower,
  1940. ept_lookup_handle_t *MapHandle,
  1941. unsigned32 MaxTowers,
  1942. unsigned32 *NumTowers,
  1943. twr_p_t *ITowers,
  1944. error_status *Status
  1945. )
  1946. /*++
  1947. Routine Description:
  1948. This routine returns a fully-resolved string binding, for a given
  1949. Obj, Interface, and Protocol sequence if an appropriate entry is
  1950. found. The funciton does not verify the SID of the registering principal.
  1951. If an entry is not found returns EP_S_NOT_REGISTERED.
  1952. Arguments:
  1953. Idenitcal to those of ept_map_auth
  1954. Return Value:
  1955. Idenitcal to those of ept_map_auth
  1956. --*/
  1957. {
  1958. ept_map_auth(h,
  1959. Obj,
  1960. MapTower,
  1961. NULL,
  1962. MapHandle,
  1963. MaxTowers,
  1964. NumTowers,
  1965. ITowers,
  1966. Status);
  1967. }
  1968. void
  1969. ept_inq_object(
  1970. handle_t BindingHandle,
  1971. UUID *Object,
  1972. error_status *status
  1973. )
  1974. /*++
  1975. Routine Description:
  1976. Not supported
  1977. Arguments:
  1978. BindingHandle - An explicit binding handle to the EP.
  1979. Object _ No idea whose UUID this is.
  1980. Return Value:
  1981. EPT_S_CANT_PERFORM_OP
  1982. --*/
  1983. {
  1984. if (status == NULL)
  1985. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  1986. *status = EPT_S_CANT_PERFORM_OP;
  1987. }
  1988. void
  1989. DeletePSEP(
  1990. PIFOBJNode Node,
  1991. char * Protseq,
  1992. char * Endpoint
  1993. )
  1994. {
  1995. PSEPNode *Psep, *Tmp;
  1996. if (Node == 0)
  1997. return;
  1998. Psep = Node->PSEPlist;
  1999. while (Psep != 0)
  2000. {
  2001. Psep = FindPSEP(
  2002. Psep,
  2003. Protseq,
  2004. Endpoint,
  2005. 0L,
  2006. MatchPSAndEP
  2007. );
  2008. if (Psep != 0)
  2009. {
  2010. Tmp = Psep;
  2011. Psep = Psep->Next;
  2012. UnLinkFromPSEPList(&Node->PSEPlist, Tmp);
  2013. Tmp->Signature = FREE;
  2014. FreeMem(Tmp);
  2015. }
  2016. }
  2017. }
  2018. void
  2019. ept_mgmt_delete(
  2020. handle_t BindingHandle,
  2021. boolean32 ObjectSpecd,
  2022. UUID * Object,
  2023. twr_p_t Tower,
  2024. error_status *Error
  2025. )
  2026. /*++
  2027. Routine Description:
  2028. Not supported
  2029. Arguments:
  2030. BindingHandle - An explicit binding handle to the EP.
  2031. Object _ ObjUUid
  2032. Tower - Tower specifying the Endpoints to be deleted.
  2033. Return Value:
  2034. EPT_S_CANT_PERFORM_OP
  2035. --*/
  2036. {
  2037. if (Error == NULL)
  2038. RpcRaiseException(EPT_S_CANT_PERFORM_OP);
  2039. *Error = EP_S_CANT_PERFORM_OP;
  2040. }
  2041. void ept_lookup_handle_t_rundown (ept_lookup_handle_t h)
  2042. {
  2043. PSAVEDCONTEXT Context = (PSAVEDCONTEXT) h;
  2044. PIENTRY Entry;
  2045. unsigned long Type;
  2046. PIENTRY Tmp;
  2047. twr_t * Tower;
  2048. ASSERT (Context != 0);
  2049. if ( (PtrToUlong(Context)) == 0xFFFFFFFF)
  2050. return;
  2051. Type = Context->Type;
  2052. EnterSem();
  2053. Entry = (PIENTRY)Context->List;
  2054. while (Entry != 0)
  2055. {
  2056. switch (Type)
  2057. {
  2058. case EP_MAP:
  2059. Tower = ((PSAVEDTOWER)Entry)->Tower;
  2060. break;
  2061. case EP_LOOKUP:
  2062. Tower = ((PSAVED_EPT)Entry)->Tower;
  2063. break;
  2064. default:
  2065. ASSERT(!"Unknown Inquiry Type");
  2066. break;
  2067. }
  2068. MIDL_user_free(Tower);
  2069. Tmp = Entry;
  2070. Entry = Entry->Next;
  2071. FreeMem(Tmp);
  2072. }
  2073. // Now free The Context
  2074. UnLink((PIENTRY *)&GlobalContextList, (PIENTRY)Context);
  2075. LeaveSem();
  2076. FreeMem(Context);
  2077. }
  2078. void
  2079. ept_lookup_handle_free(
  2080. handle_t h,
  2081. ept_lookup_handle_t * ept_context_handle,
  2082. error_status * status
  2083. )
  2084. {
  2085. if ( (ept_context_handle != 0) && (*ept_context_handle != 0))
  2086. {
  2087. ept_lookup_handle_t_rundown( *ept_context_handle );
  2088. *ept_context_handle = 0;
  2089. }
  2090. *status = 0;
  2091. }
  2092. #define MAX(x,y) ((x) < (y)) ? (y) : (x)
  2093. #define MIN(x,y) ((x) > (y)) ? (y) : (x)
  2094. #ifdef DEBUGRPC
  2095. #define DEBUG_MIN(x,y) MIN((x),(y))
  2096. #else
  2097. #define DEBUG_MIN(x,y) MAX((x),(y))
  2098. #endif
  2099. error_status_t
  2100. OpenEndpointMapper(
  2101. IN handle_t hServer,
  2102. OUT HPROCESS *pProcessHandle
  2103. )
  2104. {
  2105. PROCESS *pProcess = MIDL_user_allocate(sizeof(PROCESS));
  2106. if (!pProcess)
  2107. {
  2108. *pProcessHandle = 0;
  2109. return(RPC_S_OUT_OF_MEMORY);
  2110. }
  2111. pProcess->MagicVal = PROCESS_MAGIC_VALUE;
  2112. pProcess->pPorts = 0;
  2113. *pProcessHandle = (PVOID)pProcess;
  2114. return(RPC_S_OK);
  2115. }
  2116. //
  2117. // Port Management stuff
  2118. //
  2119. //
  2120. // Port Management Globals
  2121. //
  2122. const RPC_CHAR *PortConfigKey = RPC_CONST_STRING("Software\\Microsoft\\Rpc\\Internet");
  2123. const RPC_CHAR *DefaultPortType = RPC_CONST_STRING("UseInternetPorts");
  2124. const RPC_CHAR *ExplictPortType = RPC_CONST_STRING("PortsInternetAvailable");
  2125. const RPC_CHAR *PortRanges = RPC_CONST_STRING("Ports");
  2126. CRITICAL_SECTION PortLock;
  2127. BOOL fValidConfiguration = FALSE;
  2128. BOOL fPortRestrictions = FALSE;
  2129. PORT_TYPE SystemDefaultPortType = 0;
  2130. IP_PORT *pFreeInternetPorts = 0;
  2131. IP_PORT *pFreeIntranetPorts = 0;
  2132. PORT_RANGE *InternetPorts = 0;
  2133. PORT_RANGE *IntranetPorts = 0;
  2134. //
  2135. // Port management APIs
  2136. //
  2137. RPC_STATUS
  2138. InitializeIpPortManager(
  2139. void
  2140. )
  2141. {
  2142. HKEY hkey;
  2143. RPC_STATUS status;
  2144. DWORD size, type, value;
  2145. RPC_CHAR *pstr;
  2146. PORT_RANGE *pSet;
  2147. PORT_RANGE *pLast;
  2148. PORT_RANGE *pCurrent;
  2149. PORT_RANGE *pComplement;
  2150. PORT_RANGE *pNew;
  2151. LONG min, max;
  2152. InitializeCriticalSectionAndSpinCount(&PortLock, PREALLOCATE_EVENT_MASK);
  2153. status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2154. PortConfigKey,
  2155. 0,
  2156. KEY_READ,
  2157. &hkey);
  2158. if (status != RPC_S_OK)
  2159. {
  2160. if (status != ERROR_FILE_NOT_FOUND)
  2161. {
  2162. #if DBG
  2163. PrintToDebugger("RPCSS: Unable to open port config key: %d\n", status);
  2164. #endif
  2165. }
  2166. ASSERT(status == ERROR_FILE_NOT_FOUND);
  2167. fValidConfiguration = TRUE;
  2168. return(RPC_S_OK);
  2169. }
  2170. size = sizeof(value);
  2171. status = RegQueryValueEx(hkey,
  2172. DefaultPortType,
  2173. 0,
  2174. &type,
  2175. (PBYTE)&value,
  2176. &size);
  2177. if ( status != RPC_S_OK
  2178. || type != REG_SZ
  2179. || ( *(RPC_CHAR *)&value != 'Y'
  2180. && *(RPC_CHAR *)&value != 'y'
  2181. && *(RPC_CHAR *)&value != 'N'
  2182. && *(RPC_CHAR *)&value != 'n') )
  2183. {
  2184. RegCloseKey(hkey);
  2185. ASSERT(fValidConfiguration == FALSE);
  2186. return(RPC_S_OK);
  2187. }
  2188. if ( *(RPC_CHAR *)&value == 'Y'
  2189. || *(RPC_CHAR *)&value == 'y')
  2190. {
  2191. SystemDefaultPortType = PORT_INTERNET;
  2192. }
  2193. else
  2194. {
  2195. SystemDefaultPortType = PORT_INTRANET;
  2196. }
  2197. size = sizeof(value);
  2198. status = RegQueryValueEx(hkey,
  2199. ExplictPortType,
  2200. 0,
  2201. &type,
  2202. (PBYTE)&value,
  2203. &size);
  2204. if ( status != RPC_S_OK
  2205. || type != REG_SZ
  2206. || ( *(RPC_CHAR *)&value != 'Y'
  2207. && *(RPC_CHAR *)&value != 'y'
  2208. && *(RPC_CHAR *)&value != 'N'
  2209. && *(RPC_CHAR *)&value != 'n') )
  2210. {
  2211. RegCloseKey(hkey);
  2212. ASSERT(fValidConfiguration == FALSE);
  2213. return(RPC_S_OK);
  2214. }
  2215. if ( *(RPC_CHAR *)&value == 'Y'
  2216. || *(RPC_CHAR *)&value == 'y')
  2217. {
  2218. value = PORT_INTERNET;
  2219. }
  2220. else
  2221. {
  2222. value = PORT_INTRANET;
  2223. }
  2224. size = DEBUG_MIN(1, 100);
  2225. do
  2226. {
  2227. ASSERT(size);
  2228. pstr = alloca(size);
  2229. ASSERT(pstr);
  2230. status = RegQueryValueEx(hkey,
  2231. PortRanges,
  2232. 0,
  2233. &type,
  2234. (PBYTE)pstr,
  2235. &size);
  2236. }
  2237. while (status == ERROR_MORE_DATA);
  2238. RegCloseKey(hkey);
  2239. if ( status != RPC_S_OK
  2240. || type != REG_MULTI_SZ)
  2241. {
  2242. ASSERT(fValidConfiguration == FALSE);
  2243. return(RPC_S_OK);
  2244. }
  2245. //
  2246. // The user is going to specify a range of ports in the registery
  2247. // with a flag indicating if these ports are internet or intranet.
  2248. //
  2249. // ie, 500-550
  2250. // 560
  2251. // 559
  2252. // 2000-2048
  2253. // 2029-2049
  2254. //
  2255. // Note that order (in the REG_MULTI_SZ) and overlapping sets
  2256. // are ok. We must handle creating a port range list for this
  2257. // array and for the complement BUT NOT INCLUDING <=1024 by default.
  2258. //
  2259. // completment set to above is:
  2260. //
  2261. // 1025-1999
  2262. // 2050-32767
  2263. //
  2264. #define MIN_PORT 1025 // Only important for complement sets.
  2265. #define MAX_PORT 65535
  2266. pSet = 0;
  2267. pLast = 0;
  2268. while(*pstr)
  2269. {
  2270. RPC_CHAR *t;
  2271. #ifdef UNICODE
  2272. min = wcstol(pstr, &t, 10);
  2273. #else
  2274. min = strtol(pstr, &t, 10);
  2275. #endif
  2276. if (min > MAX_PORT || min < 0)
  2277. {
  2278. status = RPC_S_INVALID_ARG;
  2279. break;
  2280. }
  2281. if ( *t != 0
  2282. #ifdef UNICODE
  2283. && *t != L'-')
  2284. #else
  2285. && *t != '-')
  2286. #endif
  2287. {
  2288. status = RPC_S_INVALID_ARG;
  2289. break;
  2290. }
  2291. if (*t == 0)
  2292. {
  2293. max = min;
  2294. }
  2295. else
  2296. {
  2297. #ifdef UNICODE
  2298. max = wcstol(t + 1, &t, 10);
  2299. #else
  2300. min = strtol(t + 1, &t, 10);
  2301. #endif
  2302. if (max > MAX_PORT || max < 0 || max < min)
  2303. {
  2304. status = RPC_S_INVALID_ARG;
  2305. break;
  2306. }
  2307. }
  2308. ASSERT(min <= max);
  2309. // Ok, got some ports, allocate a structure for them..
  2310. pNew = MIDL_user_allocate(sizeof(PORT_RANGE));
  2311. if (0 == pNew)
  2312. {
  2313. status = RPC_S_OUT_OF_MEMORY;
  2314. break;
  2315. }
  2316. pNew->pNext = 0;
  2317. pNew->Min = (unsigned short) min;
  2318. pNew->Max = (unsigned short) max;
  2319. // We can to maintain the set of ranges in order. As we insert
  2320. // we'll fix any ranges which overlap.
  2321. pCurrent = pSet;
  2322. pLast = 0;
  2323. for (;;)
  2324. {
  2325. if (0 == pSet)
  2326. {
  2327. pSet = pNew;
  2328. break;
  2329. }
  2330. if ( pNew->Min <= (pCurrent->Max + 1)
  2331. && pNew->Max >= (pCurrent->Min - 1) )
  2332. {
  2333. // The ranges overlap or touch. We'll merge them now..
  2334. pCurrent->Min = MIN(pNew->Min, pCurrent->Min);
  2335. pCurrent->Max = MAX(pCurrent->Max, pNew->Max);
  2336. MIDL_user_free(pNew);
  2337. // Since the new larger range may overlap another existing
  2338. // range we just insert the larger range as if it was new...
  2339. pNew = pCurrent;
  2340. // Take current out of the list.
  2341. if (pLast)
  2342. {
  2343. pLast->pNext = pCurrent->pNext;
  2344. }
  2345. if (pSet == pNew)
  2346. {
  2347. pSet = pSet->pNext;
  2348. }
  2349. // Restart
  2350. pCurrent = pSet;
  2351. pLast = 0;
  2352. continue;
  2353. }
  2354. if (pNew->Min < pCurrent->Min)
  2355. {
  2356. // Found the spot
  2357. if (pLast)
  2358. {
  2359. pLast->pNext = pNew;
  2360. pNew->pNext = pCurrent;
  2361. }
  2362. else
  2363. {
  2364. ASSERT(pCurrent == pSet);
  2365. pNew->pNext = pCurrent;
  2366. pSet = pNew;
  2367. }
  2368. break;
  2369. }
  2370. // Continue the search
  2371. pLast = pCurrent;
  2372. pCurrent = pCurrent->pNext;
  2373. if (0 == pCurrent)
  2374. {
  2375. // Reached the end of the list, insert it here.
  2376. pLast->pNext = pNew;
  2377. ASSERT(pNew->pNext == 0);
  2378. break;
  2379. }
  2380. }
  2381. ASSERT(pSet);
  2382. // Advance to the next string of the final null.
  2383. pstr = RpcpCharacter(pstr, 0) + 1;
  2384. }
  2385. if (pSet == 0)
  2386. {
  2387. status = RPC_S_INVALID_ARG;
  2388. }
  2389. if (value == PORT_INTERNET)
  2390. {
  2391. InternetPorts = pSet;
  2392. }
  2393. else
  2394. {
  2395. IntranetPorts = pSet;
  2396. }
  2397. if (status == RPC_S_OK)
  2398. {
  2399. // We've constructed the set of ports in the registry,
  2400. // now we need to compute the complement set.
  2401. pComplement = 0;
  2402. pCurrent = 0;
  2403. min = MIN_PORT;
  2404. while(pSet)
  2405. {
  2406. if (min < pSet->Min)
  2407. {
  2408. max = pSet->Min - 1;
  2409. ASSERT(max >= min);
  2410. pNew = MIDL_user_allocate(sizeof(PORT_RANGE));
  2411. if (0 == pNew)
  2412. {
  2413. status = RPC_S_OUT_OF_MEMORY;
  2414. break;
  2415. }
  2416. pNew->pNext = 0;
  2417. pNew->Min = (unsigned short) min;
  2418. pNew->Max = (unsigned short) max;
  2419. if (pComplement == 0)
  2420. {
  2421. pComplement = pCurrent = pNew;
  2422. }
  2423. else
  2424. {
  2425. ASSERT(pCurrent);
  2426. pCurrent->pNext = pNew;
  2427. pCurrent = pNew;
  2428. }
  2429. }
  2430. min = MAX(MIN_PORT, pSet->Max + 1);
  2431. pSet = pSet->pNext;
  2432. }
  2433. if (status == RPC_S_OK && min < MAX_PORT)
  2434. {
  2435. // Final port in orginal set less then max, allocate final
  2436. // range for the set complement.
  2437. pNew = MIDL_user_allocate(sizeof(PORT_RANGE));
  2438. if (0 != pNew)
  2439. {
  2440. pNew->Min = (unsigned short) min;
  2441. pNew->Max = MAX_PORT;
  2442. pNew->pNext = 0;
  2443. if (pCurrent)
  2444. {
  2445. pCurrent->pNext = pNew;
  2446. }
  2447. else
  2448. {
  2449. ASSERT(min == MIN_PORT);
  2450. pComplement = pNew;
  2451. }
  2452. }
  2453. else
  2454. {
  2455. status = RPC_S_OUT_OF_MEMORY;
  2456. }
  2457. }
  2458. // Even if we failed assign the pointer, it's either
  2459. // null or needs to be freed.
  2460. if (value == PORT_INTERNET)
  2461. {
  2462. ASSERT(IntranetPorts == 0);
  2463. IntranetPorts = pComplement;
  2464. }
  2465. else
  2466. {
  2467. ASSERT(InternetPorts == 0);
  2468. InternetPorts = pComplement;
  2469. }
  2470. }
  2471. if (status != RPC_S_OK)
  2472. {
  2473. ASSERT(fValidConfiguration == FALSE);
  2474. while(InternetPorts)
  2475. {
  2476. PORT_RANGE *pT = InternetPorts;
  2477. InternetPorts = InternetPorts->pNext;
  2478. MIDL_user_free(pT);
  2479. }
  2480. while(IntranetPorts)
  2481. {
  2482. PORT_RANGE *pT = IntranetPorts;
  2483. IntranetPorts = IntranetPorts->pNext;
  2484. MIDL_user_free(pT);
  2485. }
  2486. return(RPC_S_OK);
  2487. }
  2488. fValidConfiguration = TRUE;
  2489. fPortRestrictions = TRUE;
  2490. return(RPC_S_OK);
  2491. }
  2492. BOOL
  2493. AllocatePort(
  2494. OUT IP_PORT **ppPort,
  2495. IN OUT IP_PORT **ppPortFreeList,
  2496. IN PORT_RANGE *pPortList
  2497. )
  2498. /*++
  2499. Routine Description:
  2500. Allocates a port object for a specific process. It first tries
  2501. to use any ports in the free list. If there's nothing in the
  2502. port this then it tries to find a free port in the PortList
  2503. which is one of the sets computed during startup.
  2504. Arguments:
  2505. ppPort - Will contain the allocated port object if successful.
  2506. ppPortFreeList - Pointer to the head of the free list associated
  2507. with this type of port. Maybe modified during this call.
  2508. pPortList - Port ranges associated with this type of port.
  2509. Return Value:
  2510. TRUE - Port allocated
  2511. FALSE - Port not allocated
  2512. --*/
  2513. {
  2514. IP_PORT *pPort = 0;
  2515. // First see if there is free port to reuse.
  2516. if (*ppPortFreeList)
  2517. {
  2518. EnterCriticalSection(&PortLock);
  2519. if (*ppPortFreeList)
  2520. {
  2521. pPort = *ppPortFreeList;
  2522. *ppPortFreeList = pPort->pNext;
  2523. pPort->pNext = 0;
  2524. }
  2525. LeaveCriticalSection(&PortLock);
  2526. }
  2527. if (pPort == 0)
  2528. {
  2529. // No port in the free list, try to allocate one
  2530. // Assume we'll find a free port..
  2531. pPort = MIDL_user_allocate(sizeof(IP_PORT));
  2532. if (0 != pPort)
  2533. {
  2534. pPort->pNext = 0;
  2535. EnterCriticalSection(&PortLock);
  2536. while ( pPortList
  2537. && pPortList->Min > pPortList->Max)
  2538. {
  2539. pPortList = pPortList->pNext;
  2540. }
  2541. if (pPortList)
  2542. {
  2543. ASSERT(pPortList->Min <= pPortList->Max);
  2544. pPort->Port = pPortList->Min;
  2545. pPortList->Min++;
  2546. // We could remove empty ranges from the list.
  2547. }
  2548. LeaveCriticalSection(&PortLock);
  2549. if (0 == pPortList)
  2550. {
  2551. MIDL_user_free(pPort);
  2552. pPort = 0;
  2553. #ifdef DEBUGRPC
  2554. DbgPrint("RPC: Out of reserved ports\n");
  2555. #endif
  2556. }
  2557. }
  2558. }
  2559. // REVIEW: Post SUR we should look at adding events for
  2560. // allocation and failure to allocate IP ports
  2561. *ppPort = pPort;
  2562. return(pPort != 0);
  2563. }
  2564. error_status_t
  2565. AllocateReservedIPPort(
  2566. IN HPROCESS hProcess,
  2567. IN PORT_TYPE PortType,
  2568. OUT long *pAllocationStatus,
  2569. OUT unsigned short *pAllocatedPort
  2570. )
  2571. /*++
  2572. Routine Description:
  2573. Remote manager for RPC runtime to call locally to allocate
  2574. a local port. The call and process parameters must be valid
  2575. and called only locally. Based on the PortType paramet a
  2576. IP port maybe allocated for the calling process. The
  2577. allocationstatus contains the result of the port allocation
  2578. step.
  2579. Arguments:
  2580. hProcess - Valid process context handle allocated with
  2581. a call to OpenEndpointMapper.
  2582. PortType - One of
  2583. PORT_INTERNET
  2584. PORT_INTRANET
  2585. PORT_DEFAULT
  2586. Used to determine which port range to allocate from.
  2587. pAllocationStatus -
  2588. RPC_S_OK - successfully allocated a port.
  2589. RPC_S_OUT_OF_RESOURES - no ports available.
  2590. pAllocatePort - If allocation status is RPC_S_OK then
  2591. this contains the value of the port allocated.
  2592. If zero it means that there are no port restrictions
  2593. and any port maybe used.
  2594. Return Value:
  2595. RPC_S_OK
  2596. RPC_S_INVALID_ARG - configuration error or PortType out of range.
  2597. RPC_S_ACCESS_ DENIED - not called locally.
  2598. --*/
  2599. {
  2600. PROCESS *pProcess = (PROCESS *)hProcess;
  2601. IP_PORT *pPort;
  2602. BOOL b;
  2603. *pAllocatedPort = 0;
  2604. *pAllocationStatus = RPC_S_OK;
  2605. ASSERT(pProcess);
  2606. if (!fValidConfiguration)
  2607. {
  2608. return(RPC_S_INVALID_ARG);
  2609. }
  2610. // Security callback for the local epmp interface ensures that
  2611. // the function may be called over lpc only.
  2612. if ( (0 == pProcess) || (pProcess->MagicVal != PROCESS_MAGIC_VALUE ) )
  2613. {
  2614. return(RPC_S_ACCESS_DENIED);
  2615. }
  2616. if (PortType > PORT_DEFAULT || PortType < PORT_INTERNET)
  2617. {
  2618. return(RPC_S_INVALID_ARG);
  2619. }
  2620. if (fPortRestrictions == FALSE)
  2621. {
  2622. // No port restrictions on this machine, just use zero.
  2623. // This is the common case.
  2624. ASSERT(*pAllocatedPort == 0);
  2625. ASSERT(*pAllocationStatus == 0);
  2626. return(RPC_S_OK);
  2627. }
  2628. // Need to actually allocate a unique port for this process.
  2629. if (PortType == PORT_DEFAULT)
  2630. {
  2631. // Allocate using default policy
  2632. PortType = SystemDefaultPortType;
  2633. }
  2634. ASSERT(PortType == PORT_INTERNET || PortType == PORT_INTRANET);
  2635. pPort = 0;
  2636. if (PortType == PORT_INTERNET)
  2637. {
  2638. b = AllocatePort(&pPort,
  2639. &pFreeInternetPorts,
  2640. InternetPorts
  2641. );
  2642. }
  2643. else
  2644. {
  2645. b = AllocatePort(&pPort,
  2646. &pFreeIntranetPorts,
  2647. IntranetPorts);
  2648. }
  2649. if (!b)
  2650. {
  2651. ASSERT(pPort == 0);
  2652. // REVIEW: Do we want a unique error code if no ports
  2653. // are available?
  2654. *pAllocationStatus = RPC_S_OUT_OF_RESOURCES;
  2655. return(RPC_S_OK);
  2656. }
  2657. ASSERT(pPort);
  2658. ASSERT(pPort->pNext == 0);
  2659. pPort->Type = (unsigned short) PortType;
  2660. pPort->pNext = pProcess->pPorts;
  2661. pProcess->pPorts = pPort;
  2662. *pAllocatedPort = pPort->Port;
  2663. ASSERT(*pAllocationStatus == RPC_S_OK);
  2664. return(RPC_S_OK);
  2665. }
  2666. void
  2667. HPROCESS_rundown(
  2668. HPROCESS hProcess
  2669. )
  2670. {
  2671. PROCESS *pProcess = (PROCESS *)hProcess;
  2672. IP_PORT *pCurrent;
  2673. IP_PORT *pSave;
  2674. ASSERT(pProcess);
  2675. ASSERT(pProcess->MagicVal == PROCESS_MAGIC_VALUE);
  2676. pCurrent = pProcess->pPorts;
  2677. if (pCurrent)
  2678. {
  2679. EnterCriticalSection(&PortLock);
  2680. do
  2681. {
  2682. pSave = pCurrent->pNext;
  2683. if (pCurrent->Type == PORT_INTERNET)
  2684. {
  2685. pCurrent->pNext = pFreeInternetPorts;
  2686. pFreeInternetPorts = pCurrent;
  2687. }
  2688. else
  2689. {
  2690. ASSERT(pCurrent->Type == PORT_INTRANET);
  2691. pCurrent->pNext = pFreeIntranetPorts;
  2692. pFreeIntranetPorts = pCurrent;
  2693. }
  2694. pCurrent = pSave;
  2695. }
  2696. while(pCurrent);
  2697. LeaveCriticalSection(&PortLock);
  2698. }
  2699. MIDL_user_free(pProcess);
  2700. return;
  2701. }
  2702. RPC_STATUS RPC_ENTRY
  2703. LocalEpmpSecurityCallback (
  2704. IN RPC_IF_HANDLE InterfaceUuid,
  2705. IN void *Context
  2706. )
  2707. /*++
  2708. Routine Description:
  2709. Security callback for the localepmp interface.
  2710. The interface may only be called by local clients.
  2711. For local protseqs we will return RPC_S_OK and RPC_S_ACCESS_DENIED
  2712. otherwise.
  2713. Arguments:
  2714. InterfaceUuid - Interface for which the callback is being issued.
  2715. Context - The client binding handle.
  2716. Return Value:
  2717. RPC_S_OK - the client is calling over lrpc
  2718. RPC_S_ACCESS_DENIED - not called over lrpc
  2719. --*/
  2720. {
  2721. RPC_STATUS Status;
  2722. unsigned int TransportType;
  2723. Status = I_RpcBindingInqTransportType(Context, &TransportType);
  2724. ASSERT(Status == RPC_S_OK);
  2725. if (Status != RPC_S_OK || TransportType != TRANSPORT_TYPE_LPC)
  2726. {
  2727. return(RPC_S_ACCESS_DENIED);
  2728. }
  2729. return RPC_S_OK;
  2730. }