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.

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