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.

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