Source code of Windows XP (NT5)
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.

842 lines
19 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. epmapper.cxx
  5. Abstract:
  6. This routine implements the server side DCE runtime APIs. The
  7. routines in this file are used by server applications only.
  8. Author:
  9. Bharat Shah (barats) 3-5-92
  10. Revision History:
  11. 06-03-96 gopalp Added code to cleanup stale EP Mapper entries.
  12. --*/
  13. #include <precomp.hxx>
  14. #include <rpcobj.hxx>
  15. #include <epmap.h>
  16. #include <epmp.h>
  17. #include <twrproto.h>
  18. #include <startsvc.h>
  19. #include <hndlsvr.hxx>
  20. #include <CharConv.hxx>
  21. //
  22. // Global EP cleanup context handle. Initially NULL, this will
  23. // be allocated by Endpoint Mapper. As of now, it points to the
  24. // EP entries registered by this process. This way, the Endpoint
  25. // Mapper can cleanup entries of this process as soon as process
  26. // goes away.
  27. //
  28. void * hEpContext = NULL;
  29. MUTEX *EpContextMutex = NULL;
  30. RPC_STATUS
  31. InitializeEPMapperClient(
  32. void
  33. )
  34. {
  35. RPC_STATUS Status = RPC_S_OK;
  36. EpContextMutex = new MUTEX(&Status,
  37. TRUE // pre-allocate semaphore
  38. );
  39. if (EpContextMutex == NULL)
  40. {
  41. return RPC_S_OUT_OF_MEMORY;
  42. }
  43. if (Status != RPC_S_OK)
  44. {
  45. delete EpContextMutex;
  46. EpContextMutex = NULL;
  47. }
  48. return Status;
  49. }
  50. inline void RequestEPClientMutex(void)
  51. {
  52. EpContextMutex->Request();
  53. }
  54. inline void ClearEPClientMutex(void)
  55. {
  56. EpContextMutex->Clear();
  57. }
  58. RPC_STATUS
  59. BindingAndIfToTower(
  60. IN RPC_IF_HANDLE IfSpec,
  61. IN RPC_BINDING_HANDLE BindingHandle,
  62. OUT twr_t PAPI * PAPI * Tower
  63. )
  64. /*+
  65. Routine Description:
  66. Helper routine that returns a Tower from the Interface Spec
  67. and a bindinh handle
  68. Arguments:
  69. IfSpec - Client or Server IfSpec structure.
  70. BindingHandle - A partially bound binding handle
  71. Tower - Returns a Tower if the Binding Handle had a
  72. dynamic endpoint, else Tower=NULL. The caller needs
  73. to free this memory.
  74. Return Value:
  75. RPC_S_OK - The ansi string was successfully converted into a unicode
  76. string.
  77. RPC_S_OUT_OF_MEMORY - Insufficient memory is available for the unicode
  78. string.
  79. EP_S_CANT_PERFORM_OP - The Binding Handle or IfSpec were in valid.
  80. --*/
  81. {
  82. RPC_STATUS err = 0;
  83. unsigned char *Protseq = 0;
  84. unsigned char *NWAddress= 0;
  85. unsigned char *Binding = 0;
  86. unsigned char *Endpoint = 0;
  87. RPC_CHAR * String = 0;
  88. RPC_IF_ID Ifid;
  89. RPC_TRANSFER_SYNTAX Xferid;
  90. unsigned int Size;
  91. *Tower = NULL;
  92. err = RpcIfInqId(IfSpec, &Ifid);
  93. if (!err)
  94. {
  95. err = I_RpcIfInqTransferSyntaxes(
  96. IfSpec,
  97. &Xferid,
  98. sizeof(Xferid),
  99. &Size
  100. );
  101. }
  102. if (!err)
  103. {
  104. err = I_RpcBindingInqDynamicEndpoint(BindingHandle, &String);
  105. }
  106. if (err)
  107. {
  108. return (err);
  109. }
  110. if (!err)
  111. {
  112. err = RpcBindingToStringBindingA(BindingHandle, &Binding);
  113. }
  114. if (!err)
  115. {
  116. if (String != 0)
  117. {
  118. // It is a dynamic endpoint
  119. Endpoint = UnicodeToAnsiString(String, &err);
  120. if (!err)
  121. {
  122. err = RpcStringBindingParseA(
  123. Binding,
  124. NULL,
  125. &Protseq,
  126. &NWAddress,
  127. NULL,
  128. NULL
  129. );
  130. }
  131. }
  132. else
  133. {
  134. err = RpcStringBindingParseA(
  135. Binding,
  136. NULL,
  137. &Protseq,
  138. &NWAddress,
  139. &Endpoint,
  140. NULL
  141. );
  142. }
  143. }
  144. if (!err)
  145. {
  146. err = TowerConstruct(
  147. &Ifid,
  148. &Xferid,
  149. (char PAPI*)Protseq,
  150. (char PAPI *)Endpoint,
  151. (char PAPI *)NWAddress,
  152. Tower
  153. );
  154. }
  155. if (Endpoint)
  156. RpcStringFreeA(&Endpoint);
  157. if (String)
  158. RpcStringFreeA((unsigned char PAPI * PAPI *)&String);
  159. if (Protseq)
  160. RpcStringFreeA(&Protseq);
  161. if (NWAddress)
  162. RpcStringFreeA(&NWAddress);
  163. if (Binding)
  164. RpcStringFreeA(&Binding);
  165. return(err);
  166. }
  167. RPC_STATUS
  168. RegisterEntries(
  169. IN RPC_IF_HANDLE IfSpec,
  170. IN RPC_BINDING_VECTOR * BindingVector,
  171. IN UUID_VECTOR * ObjUuidVector,
  172. IN unsigned char * Annotation,
  173. IN unsigned long ReplaceNoReplace
  174. )
  175. /*++
  176. Routine Description:
  177. This helper function is called by RpcEpRegister or RpcEpRegisterNoReplace
  178. Depending on the TypeOp, it tries to Add or replace endpoint entries
  179. in the EP-database.
  180. Arguments:
  181. IfSpec - Interface Spec Handle for which the entries are to be registered.
  182. BindingVector - A Vector of Binding Handles which need to be registered
  183. ObjUUIDVector - A Vector of Objects
  184. Annotation - A String representing the Annotation
  185. TypeOp - A Flag : REGISTER_REPLACE or REGISTER_NO_REPLACE
  186. Return Value:
  187. RPC_S_OK - Some of the entries specified were successfully registered.
  188. RPC_S_OUT_OF_MEMORY - Insufficient memory is available,
  189. EP_S_CANT_PERFORM_OP - Misc. local error occured; e.g. could not bind to
  190. the EpMapper.
  191. --*/
  192. {
  193. RPC_STATUS err;
  194. unsigned int i, j, k, Entries, CountBH, CountObj;
  195. RPC_BINDING_HANDLE EpMapperHandle;
  196. unsigned char * PStringBinding = NULL;
  197. twr_p_t Twr;
  198. ept_entry_t * EpEntries = NULL, *p;
  199. unsigned long ArgC = 0;
  200. char *ArgV[1] = { NULL };
  201. if (BindingVector->Count == 0)
  202. {
  203. //
  204. // PNP
  205. //
  206. err = GlobalRpcServer->InterfaceExported(
  207. (PRPC_SERVER_INTERFACE) IfSpec,
  208. ObjUuidVector,
  209. Annotation,
  210. ReplaceNoReplace);
  211. return RPC_S_OK;
  212. }
  213. if (err = BindToEpMapper(&EpMapperHandle,
  214. NULL, // NetworkAddress
  215. NULL, // Protseq
  216. 0, // Options
  217. RPC_C_BINDING_DEFAULT_TIMEOUT,
  218. INFINITE, // CallTimeout
  219. NULL // AuthInfo
  220. ))
  221. {
  222. return err;
  223. }
  224. CountObj = (unsigned int)ObjUuidVector->Count;
  225. CountBH = (unsigned int) BindingVector->Count;
  226. if ((p = (EpEntries = (ept_entry_t *)
  227. I_RpcAllocate(CountBH * sizeof(ept_entry_t)))) == NULL)
  228. {
  229. return(RPC_S_OUT_OF_MEMORY);
  230. }
  231. for (i = 0, Entries = 0; (!err) && (i < CountBH); i++)
  232. {
  233. if (BindingVector->BindingH[i] == 0)
  234. {
  235. continue;
  236. }
  237. if (err = BindingAndIfToTower(IfSpec, BindingVector->BindingH[i], &Twr))
  238. {
  239. err = 0;
  240. continue;
  241. }
  242. if (Twr == NULL)
  243. {
  244. continue;
  245. }
  246. Entries ++;
  247. p->tower = Twr;
  248. lstrcpyA((char PAPI *)p->annotation, (char PAPI *)Annotation);
  249. p++;
  250. }
  251. for (j = 0; j < CountObj; j++)
  252. {
  253. for (k = 0, p = EpEntries; k < Entries; k++, p++)
  254. {
  255. RpcpMemoryCopy(
  256. (char PAPI *)&p->object,
  257. (char PAPI *)ObjUuidVector->Uuid[j],
  258. sizeof(UUID)
  259. );
  260. }
  261. RequestEPClientMutex();
  262. RpcTryExcept
  263. {
  264. ept_insert_ex(
  265. EpMapperHandle,
  266. &hEpContext,
  267. Entries,
  268. EpEntries,
  269. ReplaceNoReplace,
  270. (error_status PAPI *)&err
  271. );
  272. }
  273. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  274. {
  275. err = RpcExceptionCode();
  276. }
  277. RpcEndExcept
  278. ClearEPClientMutex();
  279. if (err == RPC_S_SERVER_UNAVAILABLE)
  280. {
  281. //
  282. //Try to start the epmapper and retry
  283. //
  284. err = StartServiceIfNecessary();
  285. if (err == RPC_S_OK)
  286. {
  287. RequestEPClientMutex();
  288. RpcTryExcept
  289. {
  290. ept_insert_ex(
  291. EpMapperHandle,
  292. &hEpContext,
  293. Entries,
  294. EpEntries,
  295. ReplaceNoReplace,
  296. (error_status PAPI *)&err
  297. );
  298. }
  299. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  300. {
  301. RpcpErrorAddRecord(EEInfoGCRuntime,
  302. EPT_S_CANT_CREATE,
  303. EEInfoDLRegisterEntries10,
  304. RpcExceptionCode());
  305. err = EPT_S_CANT_CREATE;
  306. }
  307. RpcEndExcept
  308. ClearEPClientMutex();
  309. }
  310. }
  311. if (err != RPC_S_OK)
  312. {
  313. RpcpErrorAddRecord(EEInfoGCRuntime,
  314. EPT_S_CANT_CREATE,
  315. EEInfoDLRegisterEntries20,
  316. err);
  317. err = EPT_S_CANT_CREATE;
  318. break;
  319. }
  320. // Subsequent Inserts should be (ALWAYS) NOREPLACE
  321. // ReplaceNoReplace = REGISTER_NOREPLACE;
  322. } // for loop over UUID Vectors
  323. for (i = 0, p = EpEntries; i < Entries; i++,p++)
  324. I_RpcFree(p->tower);
  325. if (EpEntries)
  326. {
  327. I_RpcFree(EpEntries);
  328. }
  329. RpcBindingFree(&EpMapperHandle);
  330. if (err == RPC_S_OK)
  331. {
  332. //
  333. // We successfully registered our bindings,
  334. // reflect that in the interface so that if we get a
  335. // PNP notification, we can update the bindings
  336. //
  337. err = GlobalRpcServer->InterfaceExported(
  338. (PRPC_SERVER_INTERFACE) IfSpec,
  339. ObjUuidVector,
  340. Annotation,
  341. ReplaceNoReplace);
  342. }
  343. return(err);
  344. }
  345. RPC_STATUS RPC_ENTRY
  346. RpcEpRegisterNoReplaceA (
  347. IN RPC_IF_HANDLE IfSpec,
  348. IN RPC_BINDING_VECTOR * BindingVector,
  349. IN UUID_VECTOR * UuidVector OPTIONAL,
  350. IN unsigned char * Annotation
  351. )
  352. /*++
  353. Routine Description:
  354. A server application will call this routine to register
  355. a series of end points with the local endpoint mapper.
  356. Arguments:
  357. Return Value:
  358. --*/
  359. {
  360. UUID_VECTOR UuidVectorNull;
  361. UUID_VECTOR PAPI *PObjUuidVector = &UuidVectorNull;
  362. UUID NilUuid;
  363. unsigned char AnnotStr[] = {'\0'};
  364. THREAD *Thread;
  365. if (!ARGUMENT_PRESENT(Annotation))
  366. Annotation = AnnotStr;
  367. if (strlen((char PAPI *)Annotation) >= ep_max_annotation_size)
  368. return(EPT_S_INVALID_ENTRY);
  369. if (!ARGUMENT_PRESENT( BindingVector))
  370. {
  371. return(RPC_S_NO_BINDINGS);
  372. }
  373. if (ARGUMENT_PRESENT( UuidVector ))
  374. {
  375. PObjUuidVector = UuidVector;
  376. }
  377. else
  378. {
  379. UuidVectorNull.Count = 1;
  380. RpcpMemorySet(&NilUuid, 0, sizeof(UUID));
  381. UuidVectorNull.Uuid[0] = &NilUuid;
  382. }
  383. Thread = ThreadSelf();
  384. if (Thread)
  385. {
  386. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  387. }
  388. return(RegisterEntries(
  389. IfSpec,
  390. BindingVector,
  391. PObjUuidVector,
  392. Annotation,
  393. EP_REGISTER_NOREPLACE
  394. ));
  395. }
  396. RPC_STATUS RPC_ENTRY
  397. RpcEpRegisterNoReplaceW (
  398. IN RPC_IF_HANDLE IfSpec,
  399. IN RPC_BINDING_VECTOR * BindingVector,
  400. IN UUID_VECTOR * UuidVector OPTIONAL,
  401. IN unsigned short * Annotation
  402. )
  403. /*++
  404. Routine Description:
  405. A server application will call this routine to register [Add]
  406. a series of end points with the local endpoint mapper
  407. This is the Unicode version of the API.
  408. Arguments:
  409. IfSpec - Server side Interface specification structure generated
  410. by MIDL, that describes Interface UUId and version
  411. Binding Vector - A vector of binding handles that the server has registered
  412. with the runtime.
  413. UuidVector- A vector of Uuids of objects that the server is supporting
  414. Annotation - Annotation String
  415. Return Value:
  416. --*/
  417. {
  418. CHeapAnsi AnsiString;
  419. USES_CONVERSION;
  420. RPC_STATUS err;
  421. if (ARGUMENT_PRESENT(Annotation))
  422. {
  423. ATTEMPT_HEAP_W2A(AnsiString, Annotation);
  424. }
  425. err = RpcEpRegisterNoReplaceA(
  426. IfSpec,
  427. BindingVector,
  428. UuidVector,
  429. AnsiString
  430. );
  431. return(err);
  432. }
  433. RPC_STATUS RPC_ENTRY
  434. RpcEpRegisterA (
  435. IN RPC_IF_HANDLE IfSpec,
  436. IN RPC_BINDING_VECTOR * BindingVector,
  437. IN UUID_VECTOR * UuidVector OPTIONAL,
  438. IN unsigned char * Annotation
  439. )
  440. /*++
  441. Routine Description:
  442. A server application will call this routine to register
  443. a series of end points with the local endpoint mapper, replacing
  444. existing database entries in the process.
  445. This is the Ansi version of the API.
  446. Arguments:
  447. IfSpec - Server side Interface specification structure generated
  448. by MIDL, that describes Interface UUId and version
  449. Binding Vector- A vector of binding handles that the server has registered
  450. with the runtime.
  451. UuidVector- A vector of Uuids of objects that the server is supporting
  452. Annotation - Annotation String
  453. Return Value:
  454. --*/
  455. {
  456. UUID_VECTOR UuidVectorNull;
  457. UUID_VECTOR PAPI *PObjUuidVector = &UuidVectorNull;
  458. UUID NilUuid;
  459. unsigned char AnnotStr[] = {'\0'};
  460. THREAD *Thread;
  461. if (!ARGUMENT_PRESENT(Annotation))
  462. Annotation = AnnotStr;
  463. if (strlen((char PAPI *)Annotation) >= ep_max_annotation_size)
  464. return(EPT_S_INVALID_ENTRY);
  465. if (!ARGUMENT_PRESENT( BindingVector))
  466. {
  467. return(RPC_S_NO_BINDINGS);
  468. }
  469. if (ARGUMENT_PRESENT( UuidVector ))
  470. {
  471. PObjUuidVector = UuidVector;
  472. }
  473. else
  474. {
  475. UuidVectorNull.Count = 1;
  476. RpcpMemorySet(&NilUuid, 0, sizeof(UUID));
  477. UuidVectorNull.Uuid[0] = &NilUuid;
  478. }
  479. Thread = ThreadSelf();
  480. if (Thread)
  481. {
  482. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  483. }
  484. return(RegisterEntries(
  485. IfSpec,
  486. BindingVector,
  487. PObjUuidVector,
  488. Annotation,
  489. EP_REGISTER_REPLACE
  490. ));
  491. }
  492. RPC_STATUS RPC_ENTRY
  493. RpcEpRegisterW (
  494. IN RPC_IF_HANDLE IfSpec,
  495. IN RPC_BINDING_VECTOR * BindingVector,
  496. IN UUID_VECTOR * UuidVector,
  497. IN unsigned short * Annotation
  498. )
  499. /*++
  500. Routine Description:
  501. A server application will call this routine to register
  502. a series of end points with the local endpoint mapper, replcaing
  503. existing entries in the process.
  504. This is the Unicode version of the API.
  505. Arguments:
  506. IfSpec - Server side Interface specification structure generated
  507. by MIDL, that describes Interface UUId and version
  508. Binding Vector- A vector of binding handles that the server has registered
  509. with the runtime.
  510. UuidVector- A vector of Uuids of objects that the server is supporting
  511. Annotation - Annotation String
  512. Return Value:
  513. --*/
  514. {
  515. USES_CONVERSION;
  516. CHeapAnsi AnsiString;
  517. RPC_STATUS err;
  518. if (ARGUMENT_PRESENT(Annotation))
  519. {
  520. ATTEMPT_HEAP_W2A(AnsiString, Annotation);
  521. }
  522. err = RpcEpRegisterA(
  523. IfSpec,
  524. BindingVector,
  525. UuidVector,
  526. AnsiString
  527. );
  528. return(err);
  529. }
  530. RPC_STATUS RPC_ENTRY
  531. RpcEpUnregister(
  532. IN RPC_IF_HANDLE IfSpec,
  533. IN RPC_BINDING_VECTOR * BindingVector,
  534. IN UUID_VECTOR * UuidVector
  535. )
  536. /*++
  537. Routine Description:
  538. A server application will call this routine to unregister
  539. a series of end points.
  540. Arguments:
  541. IfSpec - Pointer to Interface Specification generated by MIDL
  542. BindingVector - A Vector of Binding handles maintained by runtime
  543. for the server.
  544. UuidVector - A Vector of UUIDs for objects supported by the the server
  545. Return Value:
  546. RPC_S_OK -
  547. RPC_S_OUT_OF_MEMORY - There is no memory available to construct
  548. towers
  549. --*/
  550. {
  551. UUID_VECTOR UuidVectorNull;
  552. UUID_VECTOR PAPI *PObjUuidVector = &UuidVectorNull;
  553. UUID NilUuid;
  554. RPC_STATUS err;
  555. unsigned int i, j, CountBH, CountObj;
  556. RPC_BINDING_HANDLE EpMapperHandle;
  557. ept_entry_t PAPI * EpEntries, * p;
  558. twr_t PAPI *Twr;
  559. if (!ARGUMENT_PRESENT( BindingVector))
  560. {
  561. return(RPC_S_NO_BINDINGS);
  562. }
  563. if (ARGUMENT_PRESENT( UuidVector ))
  564. {
  565. PObjUuidVector = UuidVector;
  566. }
  567. else
  568. {
  569. UuidVectorNull.Count = 1;
  570. RpcpMemorySet(&NilUuid, 0, sizeof(UUID));
  571. UuidVectorNull.Uuid[0] = &NilUuid;
  572. }
  573. if (err = BindToEpMapper(
  574. &EpMapperHandle,
  575. NULL, // NetworkAddress
  576. NULL, // Protseq
  577. 0, // Options
  578. RPC_C_BINDING_DEFAULT_TIMEOUT,
  579. INFINITE, // CallTimeout
  580. NULL // AuthInfo
  581. ))
  582. {
  583. return(err);
  584. }
  585. CountObj = (unsigned int)PObjUuidVector->Count;
  586. if ((EpEntries = (ept_entry_t *)
  587. I_RpcAllocate(sizeof(ept_entry_t)*CountObj)) == NULL)
  588. {
  589. RpcBindingFree(&EpMapperHandle);
  590. return(RPC_S_OUT_OF_MEMORY);
  591. }
  592. RPC_STATUS FinalStatus = EPT_S_CANT_PERFORM_OP;
  593. CountBH = (unsigned int) BindingVector->Count;
  594. for (i = 0; i < CountBH; i++)
  595. {
  596. if (BindingVector->BindingH[i] == 0)
  597. {
  598. continue;
  599. }
  600. if (err = BindingAndIfToTower(IfSpec, BindingVector->BindingH[i], &Twr))
  601. {
  602. FinalStatus = err;
  603. break;
  604. }
  605. if (Twr == NULL)
  606. {
  607. continue;
  608. }
  609. for (p=EpEntries,j = 0; j < CountObj; j++,p++)
  610. {
  611. RpcpMemoryCopy(
  612. (char PAPI *)&p->object,
  613. (char PAPI *)PObjUuidVector->Uuid[j],
  614. sizeof(UUID)
  615. );
  616. p->tower = Twr;
  617. p->annotation[0] = '\0';
  618. }
  619. RequestEPClientMutex();
  620. RpcTryExcept
  621. {
  622. ept_delete_ex(
  623. EpMapperHandle,
  624. &hEpContext,
  625. CountObj,
  626. EpEntries,
  627. (error_status PAPI *)&err
  628. );
  629. }
  630. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  631. {
  632. err = EPT_S_CANT_PERFORM_OP;
  633. }
  634. RpcEndExcept
  635. ClearEPClientMutex();
  636. I_RpcFree(Twr);
  637. } // For loop over Binding Handle Vector
  638. if (FinalStatus != RPC_S_OK)
  639. {
  640. FinalStatus = err;
  641. }
  642. I_RpcFree(EpEntries);
  643. RpcBindingFree(&EpMapperHandle);
  644. return(FinalStatus);
  645. }