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.

1538 lines
36 KiB

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