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.

1585 lines
33 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. isrpc.cxx
  5. Abstract:
  6. Contains ISRPC class implementation.
  7. Author:
  8. Murali R. Krishnan 11-Dec-1995
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. /************************************************************
  14. * Include Headers
  15. ************************************************************/
  16. #ifndef dllexp
  17. #define dllexp __declspec( dllexport )
  18. #endif
  19. //
  20. // System include files.
  21. //
  22. #include "smtpinc.h"
  23. #ifdef __cplusplus
  24. extern "C" {
  25. #endif
  26. #include <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <windows.h>
  30. #include <winsock2.h>
  31. #include <lm.h>
  32. #include <stdio.h>
  33. #include <stdarg.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <tchar.h>
  37. #ifdef __cplusplus
  38. } // extern "C"
  39. #endif // __cplusplus
  40. #include <isrpc.hxx>
  41. /************************************************************
  42. * Functions
  43. ************************************************************/
  44. DWORD
  45. InetinfoStartRpcServerListen(
  46. VOID
  47. )
  48. /*++
  49. Routine Description:
  50. This function starts RpcServerListen for this process. The first
  51. service that is calling this function will actually start the
  52. RpcServerListen, subsequent calls are just noted down in num count.
  53. Arguments:
  54. None.
  55. Return Value:
  56. None.
  57. --*/
  58. {
  59. RPC_STATUS Status = RPC_S_OK;
  60. Status = RpcServerListen(
  61. 1, // minimum num threads.
  62. RPC_C_LISTEN_MAX_CALLS_DEFAULT, // max concurrent calls.
  63. TRUE ); // don't wait
  64. return( Status );
  65. }
  66. DWORD
  67. InetinfoStopRpcServerListen(
  68. VOID
  69. )
  70. /*++
  71. Routine Description:
  72. Arguments:
  73. None.
  74. Return Value:
  75. None.
  76. --*/
  77. {
  78. RPC_STATUS Status = RPC_S_OK;
  79. Status = RpcMgmtStopServerListening(0);
  80. //
  81. // wait for all RPC threads to go away.
  82. //
  83. if( Status == RPC_S_OK) {
  84. Status = RpcMgmtWaitServerListen();
  85. }
  86. return( Status );
  87. }
  88. ISRPC::ISRPC(IN LPCTSTR pszServiceName)
  89. /*++
  90. This function constructs a new ISRPC object, initializing the
  91. members to proper state.
  92. Always the ISRPC members will use RPC_C_AUTHN_WINNT.
  93. Arguments:
  94. pszServiceName - pointer to string containing the name of the service
  95. dwServiceAuthId - DWORD containing the service Authentication Identifier.
  96. Returns:
  97. A valid initialized ISRPC object on success.
  98. --*/
  99. : m_dwProtocols ( 0),
  100. m_fInterfaceAdded ( FALSE),
  101. m_fEpRegistered ( FALSE),
  102. m_fServerStarted ( FALSE),
  103. m_hRpcInterface ( NULL),
  104. m_pszServiceName ( pszServiceName),
  105. m_pBindingVector ( NULL)
  106. {
  107. //DBG_REQUIRE( SetSecurityDescriptor() == NO_ERROR);
  108. SetSecurityDescriptor();
  109. #if 0
  110. IF_DEBUG( DLL_RPC) {
  111. DBGPRINTF(( DBG_CONTEXT,
  112. " Created new ISRPC object for %s at %08x\n",
  113. m_pszServiceName, this));
  114. }
  115. #endif
  116. } // ISRPC::ISRPC()
  117. ISRPC::~ISRPC(VOID)
  118. /*++
  119. This function cleans up the ISRPC object and releases any dynamic memory or
  120. state associated with this object.
  121. --*/
  122. {
  123. CleanupData();
  124. #if 0
  125. IF_DEBUG( DLL_RPC) {
  126. DBGPRINTF(( DBG_CONTEXT,
  127. " Destroyed ISRPC object for %s at %08x\n",
  128. m_pszServiceName, this));
  129. }
  130. #endif
  131. } // ISRPC::~ISRPC()
  132. DWORD
  133. ISRPC::CleanupData(VOID)
  134. /*++
  135. Routine Description:
  136. This member function cleans up the ISRPC object.
  137. Arguments:
  138. None.
  139. Return Value:
  140. None.
  141. --*/
  142. {
  143. DWORD rpcStatus = RPC_S_OK;
  144. #if 0
  145. IF_DEBUG( DLL_RPC) {
  146. DBGPRINTF(( DBG_CONTEXT,
  147. " ISRPC(%08x)::Cleaning up for %s\n",
  148. m_pszServiceName));
  149. }
  150. #endif
  151. if ( m_fServerStarted) {
  152. rpcStatus = StopServer( );
  153. }
  154. //DBG_ASSERT( rpcStatus == RPC_S_OK);
  155. rpcStatus = UnRegisterInterface();
  156. m_dwProtocols = 0;
  157. m_hRpcInterface = NULL;
  158. return (rpcStatus);
  159. } // ISRPC::CleanupData()
  160. DWORD
  161. ISRPC::RegisterInterface( IN RPC_IF_HANDLE hRpcInterface)
  162. /*++
  163. This function registers the RPC inteface in the object.
  164. If there is already a valid instance present in the object,
  165. this function fails and returns error.
  166. If this is the new interface specified, the function registers the
  167. interface both for dynamic and static bindings.
  168. Should be called after calling AddProtocol() and before StartServer()
  169. Arguments:
  170. hRpcInteface - RPC inteface handle.
  171. Returns:
  172. Win32 Error Code - NO_ERROR on success.
  173. --*/
  174. {
  175. DWORD dwError = NO_ERROR;
  176. if ( m_dwProtocols == 0) {
  177. // No protocol added. Return failure.
  178. return ( ERROR_INVALID_PARAMETER);
  179. }
  180. if ( m_hRpcInterface != NULL) {
  181. dwError = ( RPC_S_DUPLICATE_ENDPOINT);
  182. } else {
  183. //
  184. // since there is no duplicate, just set the new value and return.
  185. //
  186. if ( hRpcInterface == NULL) {
  187. dwError = ERROR_INVALID_PARAMETER;
  188. } else {
  189. m_hRpcInterface = hRpcInterface;
  190. }
  191. }
  192. if ( dwError == RPC_S_OK) {
  193. dwError = RpcServerRegisterIf(m_hRpcInterface,
  194. 0, // MgrUuid
  195. 0 // MgrEpv (Entry Point Vector)
  196. );
  197. if ( dwError == RPC_S_OK ) {
  198. m_fInterfaceAdded = TRUE;
  199. //
  200. // Establish the dynamic bindings if any.
  201. //
  202. if ( (m_dwProtocols & (ISRPC_OVER_TCPIP | ISRPC_OVER_SPX)) != 0) {
  203. dwError = RpcServerInqBindings( &m_pBindingVector);
  204. if ( dwError == RPC_S_OK) {
  205. //DBG_ASSERT( m_pBindingVector != NULL);
  206. dwError = RpcEpRegister(m_hRpcInterface,
  207. m_pBindingVector,
  208. NULL,
  209. (unsigned char *) "" );
  210. if ( dwError == RPC_S_OK) {
  211. m_fEpRegistered = TRUE;
  212. }
  213. } // Ep registering
  214. } // dynamic bindings
  215. } // registration successful
  216. }
  217. #if 0
  218. IF_DEBUG(DLL_RPC) {
  219. DBGPRINTF(( DBG_CONTEXT, "ISRPC(%08x)::RegisterInterface(%08x)"
  220. " returns %ld\n",
  221. this, hRpcInterface, dwError));
  222. }
  223. #endif
  224. return ( dwError);
  225. } // ISRPC::RegisterInterface()
  226. DWORD
  227. ISRPC::UnRegisterInterface( VOID)
  228. /*++
  229. This function unregisters the RPC inteface in the object.
  230. Should be called after after StopServer() and before cleanup.
  231. Arguments:
  232. None
  233. Returns:
  234. Win32 Error Code - NO_ERROR on success.
  235. --*/
  236. {
  237. DWORD rpcStatus = RPC_S_OK;
  238. if ( m_fEpRegistered) {
  239. //DBG_ASSERT( m_hRpcInterface != NULL && m_pBindingVector != NULL);
  240. rpcStatus = RpcEpUnregister(m_hRpcInterface,
  241. m_pBindingVector,
  242. NULL // pUuidVector
  243. );
  244. //_ASSERT( rpcStatus == RPC_S_OK);
  245. m_fEpRegistered = FALSE;
  246. }
  247. if ( m_pBindingVector != NULL) {
  248. rpcStatus = RpcBindingVectorFree( &m_pBindingVector);
  249. //_ASSERT( rpcStatus == RPC_S_OK);
  250. m_pBindingVector = NULL;
  251. }
  252. if ( m_fInterfaceAdded != NULL) {
  253. rpcStatus = RpcServerUnregisterIf(m_hRpcInterface,
  254. NULL, // MgrUuid
  255. TRUE // wait for calls to complete
  256. );
  257. //_ASSERT(rpcStatus == RPC_S_OK);
  258. m_fInterfaceAdded = FALSE;
  259. }
  260. return ( rpcStatus);
  261. } // ISRPC::UnRegisterInterface()
  262. DWORD
  263. ISRPC::AddProtocol( IN DWORD Protocol)
  264. /*++
  265. Routine Description:
  266. This member function adds another protocol to the binding list.
  267. Arguments:
  268. protocol - protocol binding opcode.
  269. fDynamic - Boolean indicating if the call should do dynamic or static
  270. RPC binding for the protocol specified.
  271. Return Value:
  272. RPC error code.
  273. --*/
  274. {
  275. DWORD rpcStatus = RPC_S_OK;
  276. if ( Protocol & ISRPC_OVER_LPC ) {
  277. // Currently we only support static binding
  278. rpcStatus = BindOverLpc( FALSE);
  279. }
  280. #ifndef CHICAGO
  281. //
  282. // Enable all remote bindings
  283. //
  284. if ( rpcStatus == RPC_S_OK ) {
  285. if ( Protocol & ISRPC_OVER_TCPIP ) {
  286. // Currently we only support dynamic binding
  287. rpcStatus = BindOverTcp( TRUE);
  288. }
  289. if ( rpcStatus == RPC_S_OK && Protocol & ISRPC_OVER_NP ) {
  290. // Currently we only support static binding
  291. rpcStatus = BindOverNamedPipe( FALSE);
  292. }
  293. if ( rpcStatus == RPC_S_OK && Protocol & ISRPC_OVER_SPX ) {
  294. // Currently we only support dynamic binding
  295. rpcStatus = BindOverSpx( TRUE);
  296. }
  297. }
  298. #else // CHICAGO
  299. rpcStatus = RPC_S_OK;
  300. if ( Protocol & ISRPC_OVER_TCPIP ) {
  301. // Currently we only support dynamic binding
  302. rpcStatus = BindOverTcp( TRUE);
  303. }
  304. if ( Protocol & ISRPC_OVER_NB ) {
  305. // Currently we only support dynamic binding
  306. // Ignore status for NB for now
  307. (VOID)BindOverNetBios(TRUE);
  308. }
  309. #endif // CHICAGO
  310. #if 0
  311. IF_DEBUG( DLL_RPC) {
  312. DBGPRINTF(( DBG_CONTEXT,
  313. "ISRPC(%08x)::AddProtocol(%08x) returns %ld.\n",
  314. this, Protocol, rpcStatus ));
  315. }
  316. #endif
  317. return( rpcStatus );
  318. } // ISRPC::AddProtocol()
  319. DWORD
  320. ISRPC::RemoveProtocol(IN DWORD Protocol)
  321. /*++
  322. Routine Description:
  323. This member function removes a protocol from the binding list.
  324. Arguments:
  325. protocol - protocol binding opcode.
  326. Return Value:
  327. RPC error code.
  328. Note:
  329. As a side effect, this function removes the dynamic endpoing on
  330. TCPIP when SPX binding is removed and vice-versa.
  331. --*/
  332. {
  333. #if 0
  334. DBGPRINTF(( DBG_CONTEXT,
  335. " ISRPC(%08x)::RemoveProtocol(%s) is not implemented\n",
  336. this, m_pszServiceName));
  337. DBG_ASSERT( FALSE);
  338. #endif
  339. return ( ERROR_CALL_NOT_IMPLEMENTED);
  340. } // ISRPC::RemoveProtocol()
  341. DWORD
  342. ISRPC::StartServer(
  343. VOID
  344. )
  345. /*++
  346. Routine Description:
  347. This member function start RPC server.
  348. Arguments:
  349. None.
  350. Return Value:
  351. RPC error code.
  352. --*/
  353. {
  354. DWORD rpcStatus;
  355. //
  356. // add the interface.
  357. //
  358. if ( m_hRpcInterface == NULL) {
  359. return (ERROR_INVALID_PARAMETER);
  360. }
  361. //
  362. // start rpc server.
  363. //
  364. #ifndef SERVICE_AS_EXE
  365. rpcStatus = InetinfoStartRpcServerListen();
  366. #else
  367. rpcStatus = RpcServerListen(
  368. 1, // minimum num threads.
  369. 1, // max concurrent calls.
  370. TRUE ); // don't wait
  371. #endif // SERVICE_AS_EXE
  372. if ( rpcStatus == RPC_S_OK ) {
  373. m_fServerStarted = TRUE;
  374. }
  375. #if 0
  376. IF_DEBUG( DLL_RPC) {
  377. DBGPRINTF(( DBG_CONTEXT, "ISRPC(%08x)::StartServer(%s) returns %ld\n",
  378. this, m_pszServiceName, rpcStatus));
  379. }
  380. #endif
  381. return( rpcStatus );
  382. } // ISRPC::StartServer()
  383. DWORD
  384. ISRPC::StopServer(
  385. VOID
  386. )
  387. {
  388. DWORD rpcStatus = RPC_S_OK;
  389. if( m_fServerStarted ) {
  390. #ifndef SERVICE_AS_EXE
  391. rpcStatus = InetinfoStopRpcServerListen();
  392. #else
  393. //
  394. // stop server listen.
  395. //
  396. rpcStatus = RpcMgmtStopServerListening(0);
  397. //
  398. // wait for all RPC threads to go away.
  399. //
  400. if( rpcStatus == RPC_S_OK) {
  401. rpcStatus = RpcMgmtWaitServerListen();
  402. }
  403. #endif // SERVICE_AS_EXE
  404. m_fServerStarted = FALSE;
  405. }
  406. #if 0
  407. IF_DEBUG( DLL_RPC) {
  408. DBGPRINTF(( DBG_CONTEXT,
  409. "ISRPC(%08x)::StopServer( %s) returns %d\n",
  410. this, m_pszServiceName, rpcStatus));
  411. }
  412. #endif
  413. return ( rpcStatus);
  414. } // ISRPC::StopServer()
  415. DWORD
  416. ISRPC::EnumBindingStrings(
  417. IN OUT LPINET_BINDINGS pBindings
  418. )
  419. /*++
  420. Routine Description:
  421. This member function enumurates the binding strings of the protocols
  422. bound to the server.
  423. Arguments:
  424. pBindings : pointer to a binding strings structure. The caller
  425. should call FreeBindingStrings member function to free the string
  426. after use.
  427. Return Value:
  428. Windows Error Code;
  429. --*/
  430. {
  431. DWORD dwError;
  432. RPC_BINDING_VECTOR * pBindingVector = NULL;
  433. LPINET_BIND_INFO pBindingsInfo;
  434. DWORD dwCount = 0;
  435. DWORD i;
  436. //
  437. // query RPC for RPC_BINDING_VECTORS.
  438. //
  439. dwError = RpcServerInqBindings( &pBindingVector );
  440. if( dwError != NO_ERROR ) {
  441. goto Cleanup;
  442. }
  443. //DBG_ASSERT( pBindingVector->Count > 0 );
  444. //
  445. // alloc memory for INET_RPC_BINDING_STRINGS.
  446. //
  447. pBindingsInfo = (LPINET_BIND_INFO)
  448. LocalAlloc( GPTR, sizeof(INET_BIND_INFO) * pBindingVector->Count );
  449. if( pBindingsInfo == NULL ) {
  450. dwError = ERROR_NOT_ENOUGH_MEMORY;
  451. goto Cleanup;
  452. }
  453. //
  454. // convert binding handle to binding vectors.
  455. //
  456. pBindings->NumBindings = 0;
  457. pBindings->BindingsInfo = pBindingsInfo;
  458. for( i = 0; i < pBindingVector->Count; i++ ) {
  459. LPSTR BindingString;
  460. BindingString = NULL;
  461. dwError = RpcBindingToStringBindingA(pBindingVector->BindingH[i],
  462. (LPBYTE *)&BindingString );
  463. if( dwError != NO_ERROR ) {
  464. goto Cleanup;
  465. }
  466. #if 0
  467. IF_DEBUG( DLL_RPC) {
  468. DBGPRINTF(( DBG_CONTEXT, "Binding Handle[%d] = %08x. String = %s\n",
  469. i, pBindingVector->BindingH[i], BindingString));
  470. }
  471. #endif
  472. //
  473. // check to we get only our named-pipe endpoint.
  474. //
  475. if( strstr( BindingString, "ncacn_np" ) != NULL ) {
  476. //
  477. // found a named-pipe binding string.
  478. //
  479. if( strstr(BindingString,
  480. m_pszServiceName ) == NULL ) {
  481. //
  482. // found a non service named-pipe entry.
  483. // ignore it.
  484. //
  485. RpcStringFreeA( (LPBYTE *)&BindingString );
  486. } else {
  487. #if 0
  488. IF_DEBUG( DLL_RPC) {
  489. DBGPRINTF(( DBG_CONTEXT, "Binding String Chosen = %s\n",
  490. BindingString));
  491. }
  492. #endif
  493. pBindings->BindingsInfo[dwCount].Length =
  494. (strlen(BindingString) + 1) * sizeof(CHAR);
  495. pBindings->BindingsInfo[dwCount].BindData = BindingString;
  496. dwCount++;
  497. }
  498. }
  499. } // for
  500. dwError = NO_ERROR;
  501. pBindings->NumBindings = dwCount;
  502. #if 0
  503. IF_DEBUG( DLL_RPC) {
  504. DBGPRINTF(( DBG_CONTEXT, "Binding Vectors chosen"
  505. " Service = %s, NumBindings = %d of Total = %d\n",
  506. m_pszServiceName, dwCount, pBindingVector->Count));
  507. }
  508. #endif
  509. Cleanup:
  510. if( pBindingVector != NULL ) {
  511. DWORD LocalError;
  512. LocalError = RpcBindingVectorFree( &pBindingVector );
  513. //DBG_ASSERT( LocalError == NO_ERROR );
  514. }
  515. if( dwError != NO_ERROR ) {
  516. FreeBindingStrings( pBindings );
  517. pBindings->NumBindings = 0;
  518. #if 0
  519. IF_DEBUG( DLL_RPC) {
  520. DBGPRINTF(( DBG_CONTEXT,
  521. "ISRPC(%08x)::EnumBindingStrings(%s) failed, %ld.",
  522. this, m_pszServiceName, dwError ));
  523. }
  524. #endif
  525. }
  526. return( dwError );
  527. } // ISRPC::EnumBindingStrings()
  528. VOID
  529. ISRPC::FreeBindingStrings(
  530. IN OUT LPINET_BINDINGS pInetBindings
  531. )
  532. /*++
  533. Routine Description:
  534. This member function deletes a binding vector that was returned by the
  535. EnumBindingStrings member function.
  536. Arguments:
  537. pBindings : pointer to a binding vector.
  538. Return Value:
  539. Windows Error Code;
  540. --*/
  541. {
  542. DWORD dwError;
  543. DWORD i;
  544. //
  545. // free binding strings.
  546. //
  547. for( i = 0; i < pInetBindings->NumBindings; i++) {
  548. dwError = RpcStringFreeA( ((LPBYTE *)&pInetBindings
  549. ->BindingsInfo[i].BindData ));
  550. //DBG_ASSERT( dwError == NO_ERROR );
  551. }
  552. pInetBindings->NumBindings = 0;
  553. //
  554. // free bindings info array.
  555. //
  556. if( pInetBindings->BindingsInfo != NULL ) {
  557. LocalFree( (HANDLE)pInetBindings->BindingsInfo );
  558. pInetBindings->BindingsInfo = NULL;
  559. }
  560. return;
  561. } // ISRPC::FreeBindingStrings()
  562. DWORD
  563. ISRPC::BindOverTcp(IN BOOL fDynamic)
  564. {
  565. DWORD rpcStatus = RPC_S_OK;
  566. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_TCPIP) == 0);
  567. if ( !fDynamic) {
  568. rpcStatus = ( ERROR_CALL_NOT_IMPLEMENTED);
  569. } else {
  570. rpcStatus = ( ISRPC::DynamicBindOverTcp());
  571. }
  572. if ( rpcStatus == RPC_S_OK) {
  573. m_dwProtocols |= ISRPC_OVER_TCPIP;
  574. }
  575. #if 0
  576. IF_DEBUG( DLL_RPC) {
  577. DBGPRINTF(( DBG_CONTEXT, "(%08x)::BindOverTcp(%s) returns %d\n",
  578. this, m_pszServiceName, rpcStatus));
  579. }
  580. #endif
  581. return ( rpcStatus);
  582. } // ISRPC::BindOverTcpIp()
  583. #ifdef CHICAGO
  584. DWORD
  585. ISRPC::BindOverNetBios(IN BOOL fDynamic)
  586. {
  587. DWORD rpcStatus = RPC_S_OK;
  588. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_NB) == 0);
  589. if ( !fDynamic) {
  590. return ( ERROR_CALL_NOT_IMPLEMENTED);
  591. }
  592. // We will use Dynamic endpoint for the NetBios binding.
  593. rpcStatus =
  594. RpcServerUseProtseqW(
  595. L"ncacn_nb_ipx", // protocol string.
  596. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  597. &sm_sid ); // security
  598. rpcStatus =
  599. RpcServerUseProtseqW(
  600. L"ncacn_nb_tcp", // protocol string.
  601. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  602. &sm_sid ); // security
  603. switch (rpcStatus) {
  604. case RPC_S_OK:
  605. //
  606. // set the protocol bit.
  607. //
  608. m_dwProtocols |= ISRPC_OVER_NB;
  609. break;
  610. case RPC_S_DUPLICATE_ENDPOINT:
  611. //DBGPRINTF(( DBG_CONTEXT,
  612. // "(%08x) ncacn_nb is already added for %s\n",
  613. // this,
  614. // m_pszServiceName));
  615. rpcStatus = RPC_S_OK;
  616. break;
  617. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  618. case RPC_S_CANT_CREATE_ENDPOINT:
  619. //DBGPRINTF(( DBG_CONTEXT,
  620. // "(%08x) ncacn_nb is not supported for %s (%ld).\n",
  621. // this, m_pszServiceName, rpcStatus ));
  622. rpcStatus = RPC_S_OK;
  623. break;
  624. default:
  625. break;
  626. } // switch()
  627. //
  628. // if the security support provider is not enabled, do so.
  629. //
  630. if( rpcStatus == RPC_S_OK && !IsSecurityEnabled() ) {
  631. rpcStatus = AddSecurity();
  632. }
  633. #if 0
  634. IF_DEBUG( DLL_RPC) {
  635. DBGPRINTF(( DBG_CONTEXT, "(%08x)::BindOverNetBios(%s) returns %d\n",
  636. this, m_pszServiceName, rpcStatus));
  637. }
  638. #endif
  639. return ( rpcStatus);
  640. } // ISRPC::BindOverNetBios()
  641. #endif // CHICAGO
  642. DWORD
  643. ISRPC::BindOverNamedPipe(IN BOOL fDynamic)
  644. {
  645. DWORD rpcStatus = RPC_S_OK;
  646. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_NP) == 0);
  647. //
  648. // On Named Pipe, we support only static bindings. No dynamic Binding.
  649. //
  650. if ( fDynamic) {
  651. return ( ERROR_CALL_NOT_IMPLEMENTED);
  652. }
  653. if( (m_dwProtocols & ISRPC_OVER_NP) == 0 ) {
  654. WCHAR rgchNp[1024];
  655. wsprintfW( rgchNp,
  656. #ifdef UNICODE
  657. L"%ws%s"
  658. #else
  659. L"%ws%S"
  660. #endif // UNICODE
  661. ,
  662. ISRPC_NAMED_PIPE_PREFIX_W,
  663. m_pszServiceName);
  664. //
  665. // Establish a static Named pipe binding.
  666. //
  667. rpcStatus =
  668. RpcServerUseProtseqEpW(
  669. L"ncacn_np", // protocol string.
  670. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  671. rgchNp, // end point!
  672. NULL ); // security
  673. #if 0
  674. IF_DEBUG( DLL_RPC) {
  675. CHAR pszBuff[100];
  676. wsprintfA( pszBuff, "%S", rgchNp);
  677. DBGPRINTF(( DBG_CONTEXT,
  678. " RpcServerUseProtseqEpW( %s, %d, %s, %08x) returns"
  679. " %d\n",
  680. "ncacn_np", ISRPC_PROTSEQ_MAX_REQS,
  681. pszBuff, &sm_sid, rpcStatus));
  682. }
  683. #endif
  684. switch (rpcStatus) {
  685. case RPC_S_OK:
  686. //
  687. // set the protocol bit.
  688. //
  689. m_dwProtocols |= ISRPC_OVER_NP;
  690. break;
  691. case RPC_S_DUPLICATE_ENDPOINT:
  692. //
  693. // Ignore the duplicate end point error
  694. //
  695. //DBGPRINTF(( DBG_CONTEXT,
  696. // "(%08x) ncacn_np is already added for %s\n",
  697. // this,
  698. // m_pszServiceName));
  699. m_dwProtocols |= ISRPC_OVER_NP;
  700. rpcStatus = RPC_S_OK;
  701. break;
  702. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  703. case RPC_S_CANT_CREATE_ENDPOINT:
  704. //DBGPRINTF(( DBG_CONTEXT,
  705. // "(%08x) ncacn_np is not supported for %s (%ld).\n",
  706. // this, m_pszServiceName, rpcStatus ));
  707. rpcStatus = RPC_S_OK;
  708. break;
  709. default:
  710. break;
  711. } // switch()
  712. }
  713. return ( rpcStatus);
  714. } // ISRPC::BindOverNamedPipe()
  715. DWORD
  716. ISRPC::BindOverLpc(IN BOOL fDynamic)
  717. {
  718. DWORD rpcStatus = RPC_S_OK;
  719. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_LPC) == 0);
  720. //
  721. // On LPC, we support only static bindings. No dynamic Binding.
  722. //
  723. if ( fDynamic) {
  724. return ( ERROR_CALL_NOT_IMPLEMENTED);
  725. }
  726. if( (m_dwProtocols & ISRPC_OVER_LPC) == 0 ) {
  727. WCHAR rgchLpc[1024];
  728. // LPC Endpoint string is: <InterfaceName>_LPC
  729. wsprintfW( rgchLpc,
  730. #ifdef UNICODE
  731. L"%s_%ws"
  732. #else
  733. L"%S_%ws"
  734. #endif // UNICODE
  735. ,
  736. m_pszServiceName,
  737. ISRPC_LPC_NAME_SUFFIX_W);
  738. //
  739. // Establish a static Lpc binding.
  740. //
  741. rpcStatus =
  742. RpcServerUseProtseqEpW(
  743. L"ncalrpc", // protocol string.
  744. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  745. rgchLpc, // end point!
  746. &sm_sid ); // security
  747. #if 0
  748. IF_DEBUG( DLL_RPC) {
  749. CHAR pszBuff[100];
  750. wsprintfA( pszBuff, "%S", rgchLpc);
  751. DBGPRINTF(( DBG_CONTEXT,
  752. " RpcServerUseProtseqEpW( %s, %d, %s, %08x) returns"
  753. " %d\n",
  754. "ncalrpc", ISRPC_PROTSEQ_MAX_REQS,
  755. pszBuff, &sm_sid, rpcStatus));
  756. }
  757. #endif
  758. switch (rpcStatus) {
  759. case RPC_S_OK:
  760. //
  761. // set the protocol bit.
  762. //
  763. m_dwProtocols |= ISRPC_OVER_LPC;
  764. break;
  765. case RPC_S_DUPLICATE_ENDPOINT:
  766. //
  767. // Ignore the duplicate end point error
  768. //
  769. //DBGPRINTF(( DBG_CONTEXT,
  770. // "(%08x) ncalrpc is already added for %s\n",
  771. // this,
  772. // m_pszServiceName));
  773. m_dwProtocols |= ISRPC_OVER_LPC;
  774. rpcStatus = RPC_S_OK;
  775. break;
  776. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  777. case RPC_S_CANT_CREATE_ENDPOINT:
  778. //DBGPRINTF(( DBG_CONTEXT,
  779. // "(%08x) ncalrpc is not supported for %s (%ld).\n",
  780. // this, m_pszServiceName, rpcStatus ));
  781. rpcStatus = RPC_S_OK;
  782. break;
  783. default:
  784. break;
  785. } // switch()
  786. }
  787. return ( rpcStatus);
  788. } // ISRPC::BindOverLpc()
  789. DWORD
  790. ISRPC::BindOverSpx(IN BOOL fDynamic)
  791. {
  792. DWORD rpcStatus = RPC_S_OK;
  793. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_SPX) == 0);
  794. if ( !fDynamic) {
  795. rpcStatus = ( ERROR_CALL_NOT_IMPLEMENTED);
  796. } else {
  797. rpcStatus = ISRPC::DynamicBindOverSpx();
  798. }
  799. if ( rpcStatus == RPC_S_OK) {
  800. m_dwProtocols |= ISRPC_OVER_SPX;
  801. }
  802. #if 0
  803. IF_DEBUG( DLL_RPC) {
  804. DBGPRINTF(( DBG_CONTEXT, "(%08x)::BindOverSpx(%s) returns %d\n",
  805. this, m_pszServiceName, rpcStatus));
  806. }
  807. #endif
  808. return ( rpcStatus);
  809. } // ISRPC::BindOverSpx()
  810. # if DBG
  811. VOID
  812. ISRPC::Print(VOID) const
  813. {
  814. #if 0
  815. DBGPRINTF(( DBG_CONTEXT,
  816. " ISRPC(%08x). SvcName=%s\n"
  817. " Protocols = %d.\n"
  818. " RPC Interface = %08x. Binding Vector = %08x\n"
  819. " InterfaceAdded = %d.\n"
  820. " EpRegistered = %d. ServerStarted = %d.\n"
  821. ,
  822. this, m_pszServiceName,
  823. m_dwProtocols,
  824. m_hRpcInterface, m_pBindingVector,
  825. m_fInterfaceAdded,
  826. m_fEpRegistered, m_fServerStarted
  827. ));
  828. #endif
  829. } // ISRPC::Print()
  830. # endif // DBG
  831. /******************************
  832. * STATIC Member Definitions
  833. ******************************/
  834. DWORD ISRPC::sm_dwProtocols = 0;
  835. SECURITY_DESCRIPTOR ISRPC::sm_sid;
  836. BOOL ISRPC::sm_fSecurityEnabled = FALSE;
  837. DWORD
  838. ISRPC::Initialize(VOID)
  839. {
  840. sm_dwProtocols = 0;
  841. return SetSecurityDescriptor();
  842. } // ISRPC::Initialize()
  843. DWORD
  844. ISRPC::Cleanup(VOID)
  845. {
  846. //
  847. // Free up the security descriptor
  848. //
  849. if (sm_sid.Dacl)
  850. delete [] (BYTE *) (sm_sid.Dacl);
  851. ZeroMemory( (PVOID) &sm_sid, sizeof(sm_sid));
  852. //
  853. // For now nothing to do. Just a place holder.
  854. //
  855. return ( NO_ERROR);
  856. } // ISRPC::Cleanup()
  857. DWORD
  858. ISRPC::DynamicBindOverTcp(VOID)
  859. /*++
  860. This static function (ISRPC member) establishes a dynamic endpoing
  861. RPC binding over TCP/IP, using a run-time library call to RPC.
  862. RPC run-time library allows one to create as many dynamic end points
  863. as one wishes. So we maintain external state and control the number
  864. of end points created to 1.
  865. Arguments:
  866. None
  867. Returns:
  868. RPC status - RPC_S_OK for success.
  869. --*/
  870. {
  871. DWORD rpcStatus = RPC_S_OK;
  872. if( (sm_dwProtocols & ISRPC_OVER_TCPIP) == 0 ) {
  873. //
  874. // Not already present. Add dynamic endpoint over TCP/IP
  875. //
  876. rpcStatus =
  877. RpcServerUseProtseqW(
  878. L"ncacn_ip_tcp", // protocol string.
  879. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  880. &sm_sid ); // security
  881. switch (rpcStatus) {
  882. case RPC_S_OK:
  883. //
  884. // set the protocol bit.
  885. //
  886. sm_dwProtocols |= ISRPC_OVER_TCPIP;
  887. break;
  888. case RPC_S_DUPLICATE_ENDPOINT:
  889. //DBGPRINTF(( DBG_CONTEXT,
  890. // "ncacn_ip_tcp is already added.\n"));
  891. sm_dwProtocols |= ISRPC_OVER_TCPIP;
  892. rpcStatus = RPC_S_OK;
  893. break;
  894. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  895. case RPC_S_CANT_CREATE_ENDPOINT:
  896. //DBGPRINTF(( DBG_CONTEXT,
  897. // "ncacn_ip_tcp is not supported. Error = %ld\n",
  898. // rpcStatus));
  899. break;
  900. default:
  901. break;
  902. } // switch()
  903. //
  904. // if the security support provider is not enabled, do so.
  905. //
  906. if( rpcStatus == RPC_S_OK && !IsSecurityEnabled() ) {
  907. rpcStatus = AddSecurity();
  908. }
  909. }
  910. #if 0
  911. IF_DEBUG( DLL_RPC) {
  912. DBGPRINTF(( DBG_CONTEXT, "DynamicBindOverTcp() returns %d\n",
  913. rpcStatus));
  914. }
  915. #endif
  916. return ( rpcStatus);
  917. } // ISRPC::DynamicBindOverTcp()
  918. DWORD
  919. ISRPC::DynamicBindOverSpx(VOID)
  920. /*++
  921. This static function (ISRPC member) establishes a dynamic endpoing
  922. RPC binding over SPX, using a run-time library call to RPC.
  923. RPC run-time library allows one to create as many dynamic end points
  924. as one wishes. So we maintain external state and control the number
  925. of end points created to 1.
  926. Arguments:
  927. None
  928. Returns:
  929. RPC status - RPC_S_OK for success.
  930. --*/
  931. {
  932. DWORD rpcStatus = RPC_S_OK;
  933. if( (sm_dwProtocols & ISRPC_OVER_SPX) == 0 ) {
  934. // Use dynamic end point for the server.
  935. rpcStatus =
  936. RpcServerUseProtseqW(
  937. L"ncacn_spx", // protocol string.
  938. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  939. &sm_sid ); // security
  940. switch (rpcStatus) {
  941. case RPC_S_OK:
  942. //
  943. // set the protocol bit.
  944. //
  945. sm_dwProtocols |= ISRPC_OVER_SPX;
  946. break;
  947. case RPC_S_DUPLICATE_ENDPOINT:
  948. //DBGPRINTF(( DBG_CONTEXT,
  949. // "ncacn_spx is already added.\n"
  950. // ));
  951. sm_dwProtocols |= ISRPC_OVER_SPX;
  952. rpcStatus = RPC_S_OK;
  953. break;
  954. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  955. case RPC_S_CANT_CREATE_ENDPOINT:
  956. //DBGPRINTF(( DBG_CONTEXT,
  957. // "ncacn_spx is not supported. Error (%ld).\n",
  958. // rpcStatus ));
  959. break;
  960. default:
  961. break;
  962. } // switch()
  963. //
  964. // if the security support provider is not enabled, do so.
  965. //
  966. if( rpcStatus == RPC_S_OK && !IsSecurityEnabled()) {
  967. rpcStatus = AddSecurity();
  968. }
  969. }
  970. #if 0
  971. IF_DEBUG( DLL_RPC) {
  972. DBGPRINTF(( DBG_CONTEXT, "DynamicBindOverSpx() returns %d\n",
  973. rpcStatus));
  974. }
  975. #endif
  976. return ( rpcStatus);
  977. } // ISRPC::DynamicBindOverSpx()
  978. //----------------------------------------------------------------
  979. // Description:
  980. // Initializes a SECURITY_DESCRIPTOR to allow access to all
  981. // ("World").
  982. // Arguments:
  983. // pSd Pass in a pointer to the SECURITY_DESCRIPTOR
  984. // Returns:
  985. // ERROR_SUCCESS if initialization proceeded successfully.
  986. // Win32 error if some failure occurred.
  987. //----------------------------------------------------------------
  988. DWORD InitializeWorldSecurityDescriptor (PSECURITY_DESCRIPTOR pSd)
  989. {
  990. DWORD dwErr = ERROR_SUCCESS;
  991. PSID pSidWorld = NULL;
  992. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  993. ACL *pAcl = NULL;
  994. DWORD dwAclSize = 0;
  995. _ASSERT (pSd);
  996. if (!AllocateAndInitializeSid (
  997. &WorldAuthority,
  998. 1,
  999. SECURITY_WORLD_RID,
  1000. 0,0,0,0,0,0,0,
  1001. &pSidWorld)){
  1002. dwErr = GetLastError ();
  1003. goto Exit;
  1004. }
  1005. dwAclSize = sizeof (ACL) + // Length of ACL
  1006. (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD)) + // Length of ACE #1
  1007. GetLengthSid (pSidWorld) + // Length of SID for ACE #1
  1008. (sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD)) + // Length of ACE #2
  1009. GetLengthSid (pSidWorld); // Length of SID for ACE #1
  1010. pAcl = (PACL) new BYTE [dwAclSize];
  1011. if (!pAcl) {
  1012. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1013. goto Exit;
  1014. }
  1015. if (!InitializeSecurityDescriptor (pSd, SECURITY_DESCRIPTOR_REVISION)) {
  1016. dwErr = GetLastError ();
  1017. goto Exit;
  1018. }
  1019. if (!InitializeAcl (
  1020. pAcl,
  1021. dwAclSize,
  1022. ACL_REVISION)) {
  1023. dwErr = GetLastError ();
  1024. goto Exit;
  1025. }
  1026. if (!AddAccessDeniedAce (pAcl, ACL_REVISION, WRITE_DAC | WRITE_OWNER, pSidWorld) ||
  1027. !AddAccessAllowedAce (pAcl, ACL_REVISION, GENERIC_ALL, pSidWorld)) {
  1028. dwErr = GetLastError ();
  1029. goto Exit;
  1030. }
  1031. if (!SetSecurityDescriptorDacl (pSd, TRUE, pAcl, FALSE)) {
  1032. dwErr = GetLastError ();
  1033. goto Exit;
  1034. }
  1035. pAcl = NULL; // Now pAcl is set on pSd... and will be deleted as pSd->Dacl
  1036. Exit:
  1037. if (pSidWorld)
  1038. FreeSid (pSidWorld);
  1039. if (pAcl)
  1040. delete [] pAcl;
  1041. return dwErr;
  1042. }
  1043. DWORD
  1044. ISRPC::SetSecurityDescriptor( VOID)
  1045. /*++
  1046. Routine Description:
  1047. This member function builds the security descriptor used by RPC module.
  1048. Arguments:
  1049. None.
  1050. Return Value:
  1051. Windows error code.
  1052. --*/
  1053. {
  1054. DWORD dwError = NO_ERROR;
  1055. //
  1056. // build a security descriptor that will grant everyone
  1057. // all access to the object --- this is done by setting a
  1058. // "World" DACL in the SECURITY_DESCRIPTOR.
  1059. //
  1060. dwError = InitializeWorldSecurityDescriptor(&sm_sid);
  1061. if (dwError != ERROR_SUCCESS) {
  1062. //
  1063. // free up security discriptor memory and set it to NULL.
  1064. //
  1065. if (sm_sid.Dacl)
  1066. delete [] (BYTE*) sm_sid.Dacl;
  1067. memset( (PVOID ) &sm_sid, 0, sizeof(sm_sid));
  1068. }
  1069. return( dwError );
  1070. } // ISRPC::SetSecurityDescriptor()
  1071. DWORD
  1072. ISRPC::AddSecurity(
  1073. VOID
  1074. )
  1075. /*++
  1076. Routine Description:
  1077. This member function adds security support provider over RPC.
  1078. Arguments:
  1079. None.
  1080. Return Value:
  1081. Windows error code.
  1082. --*/
  1083. {
  1084. DWORD rpcStatus;
  1085. //
  1086. // Register for authentication using WinNT.
  1087. //
  1088. rpcStatus = RpcServerRegisterAuthInfo(
  1089. (unsigned char * ) NULL, // app name to security provider
  1090. RPC_C_AUTHN_WINNT, // Auth package ID.
  1091. NULL, // RPC_C_AUTHN_WINNT ==> NULL
  1092. NULL // args ptr for authn function.
  1093. );
  1094. if ( rpcStatus == RPC_S_OK) {
  1095. sm_fSecurityEnabled = TRUE;
  1096. }
  1097. #if 0
  1098. IF_DEBUG( DLL_RPC) {
  1099. DBGPRINTF(( DBG_CONTEXT, "AddSecurity() returns Error %u\n",
  1100. rpcStatus));
  1101. }
  1102. #endif
  1103. return (rpcStatus);
  1104. } // ISRPC::AddSecurity()