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.

952 lines
26 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. rpcutil.c
  5. Abstract:
  6. This module defines functions that may help to replace the rpc util
  7. functions from rpcutil.lib
  8. Author:
  9. Murali R. Krishnan ( MuraliK ) 15-Sept-1995
  10. Environment:
  11. Win32 User Mode
  12. Project:
  13. Common Code for Internet Services
  14. Functions Exported:
  15. MIDL_user_allocate()
  16. MIDL_user_free()
  17. RpcBindHandleForServer()
  18. RpcBindHandleFree()
  19. Revision History:
  20. Murali R. Krishnan (MuraliK) 21-Dec-1995 Support TcpIp binding & free.
  21. Murali R. Krishnan (MuraliK) 20-Feb-1996 Support Lpc binding & free.
  22. --*/
  23. /************************************************************
  24. * Include Headers
  25. ************************************************************/
  26. # include <windows.h>
  27. # include <rpc.h>
  28. # include "apiutil.h"
  29. # if DBG
  30. # include <stdio.h>
  31. # include <stdlib.h>
  32. # define DBGPRINTF(s) { CHAR rgchBuff[1024]; \
  33. sprintf s ; \
  34. OutputDebugStringA( rgchBuff); \
  35. }
  36. # define DBG_CONTEXT ( rgchBuff)
  37. # else // DBG
  38. # define DBGPRINTF(s) /* nothing */
  39. # define DBG_CONTEXT /* nothing */
  40. # endif // DBG
  41. #define ISRPC_CLIENT_OVER_TCPIP 0x00000001
  42. #define ISRPC_CLIENT_OVER_NP 0x00000002
  43. #define ISRPC_CLIENT_OVER_SPX 0x00000004
  44. #define ISRPC_CLIENT_OVER_LPC 0x00000008
  45. // # define MAX_COMPUTERNAME_LENGTH (255)
  46. /************************************************************
  47. * Functions
  48. ************************************************************/
  49. PVOID
  50. MIDL_user_allocate(IN size_t size)
  51. /*++
  52. Routine Description:
  53. MIDL memory allocation.
  54. Arguments:
  55. size : Memory size requested.
  56. Return Value:
  57. Pointer to the allocated memory block.
  58. --*/
  59. {
  60. PVOID pvBlob;
  61. pvBlob = LocalAlloc( LPTR, size);
  62. return( pvBlob );
  63. } // MIDL_user_allocate()
  64. VOID
  65. MIDL_user_free(IN PVOID pvBlob)
  66. /*++
  67. Routine Description:
  68. MIDL memory free .
  69. Arguments:
  70. pvBlob : Pointer to a memory block that is freed.
  71. Return Value:
  72. None.
  73. --*/
  74. {
  75. LocalFree( pvBlob);
  76. return;
  77. } // MIDL_user_free()
  78. RPC_STATUS
  79. RpcBindHandleOverNamedPipe( OUT handle_t * pBindingHandle,
  80. IN LPWSTR pwszServerName,
  81. IN LPWSTR pwszEndpoint,
  82. IN LPWSTR pwszOptions,
  83. IN LPWSTR pwszInterfaceName
  84. )
  85. /*++
  86. This function uses the parameters supplied and generates a named pipe
  87. binding handle for RPC.
  88. Arguments:
  89. pBindingHandle pointer to location which will contain binding handle
  90. on successful return
  91. pwszServerName pointer to string containing the name of the server
  92. to which, this function will obtain a binding.
  93. pwszEndpoint pointer to string containing the Named Pipe Endpoint
  94. pwszOptions pointer to string containing any additional options for
  95. binding.
  96. Returns:
  97. RPC_STATUS - RPC_S_OK on success
  98. Also on success, the binding handle is stored in pBindingHandle.
  99. It should freed after usage, using the RpcBindingFree() function.
  100. --*/
  101. {
  102. RPC_STATUS rpcStatus;
  103. LPWSTR pwszBinding = NULL;
  104. if ( pBindingHandle != NULL) {
  105. *pBindingHandle = NULL; // init the value
  106. }
  107. //
  108. // Compose the binding string for named pipe binding
  109. //
  110. rpcStatus = RpcStringBindingComposeW(0, // ObjUuid
  111. L"ncacn_np", // prot seq: named pipe
  112. pwszServerName, // NetworkAddr
  113. pwszEndpoint, // Endpoint
  114. pwszOptions, // Options
  115. &pwszBinding); // StringBinding
  116. if ( rpcStatus == RPC_S_OK ) {
  117. //
  118. // establish the binding handle using string binding.
  119. //
  120. rpcStatus = RpcBindingFromStringBindingW(pwszBinding,
  121. pBindingHandle );
  122. }
  123. if ( rpcStatus == RPC_S_OK) {
  124. //
  125. // set up the security information
  126. //
  127. rpcStatus =
  128. RpcBindingSetAuthInfoW(*pBindingHandle,
  129. pwszInterfaceName, // pszPrincipalName
  130. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  131. RPC_C_AUTHN_WINNT,
  132. NULL, // AuthnIdentity
  133. 0 // AuthzSvc
  134. );
  135. DBGPRINTF( (DBG_CONTEXT,
  136. "RpcBindingSetAuthInfo(%S(Interface=%S), %p)"
  137. " return %d.\n",
  138. pwszBinding,
  139. pwszInterfaceName,
  140. *pBindingHandle,
  141. rpcStatus
  142. )
  143. );
  144. }
  145. //
  146. // Cleanup and return back.
  147. //
  148. if ( pwszBinding != NULL) {
  149. RpcStringFreeW(&pwszBinding);
  150. }
  151. if ( rpcStatus != RPC_S_OK) {
  152. if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
  153. // RPC should have freed the binding handle.
  154. // We will free it now.
  155. RpcBindingFree(*pBindingHandle);
  156. *pBindingHandle = NULL;
  157. }
  158. }
  159. return (rpcStatus);
  160. } // RpcBindHandleOverNamedPipe()
  161. RPC_STATUS
  162. RpcBindHandleOverLpc( OUT handle_t * pBindingHandle,
  163. IN LPWSTR pwszEndpoint,
  164. IN LPWSTR pwszOptions,
  165. IN LPWSTR pwszInterfaceName
  166. )
  167. /*++
  168. This function uses the parameters supplied and generates a lpc
  169. binding handle for RPC.
  170. Arguments:
  171. pBindingHandle pointer to location which will contain binding handle
  172. on successful return
  173. pwszEndpoint pointer to string containing the lpc Endpoint
  174. pwszOptions pointer to string containing any additional options for
  175. binding.
  176. Returns:
  177. RPC_STATUS - RPC_S_OK on success
  178. Also on success, the binding handle is stored in pBindingHandle.
  179. It should freed after usage, using the RpcBindingFree() function.
  180. --*/
  181. {
  182. RPC_STATUS rpcStatus;
  183. LPWSTR pwszBinding = NULL;
  184. if ( pBindingHandle != NULL) {
  185. *pBindingHandle = NULL; // init the value
  186. }
  187. //
  188. // Compose the binding string for named pipe binding
  189. //
  190. rpcStatus = RpcStringBindingComposeW(0, // ObjUuid
  191. L"ncalrpc", // prot seq: lpc
  192. NULL, // NetworkAddr
  193. pwszEndpoint, // Endpoint
  194. pwszOptions, // Options
  195. &pwszBinding); // StringBinding
  196. if ( rpcStatus == RPC_S_OK ) {
  197. //
  198. // establish the binding handle using string binding.
  199. //
  200. rpcStatus = RpcBindingFromStringBindingW(pwszBinding,
  201. pBindingHandle );
  202. }
  203. if ( rpcStatus == RPC_S_OK) {
  204. //
  205. // set up the security information
  206. //
  207. rpcStatus =
  208. RpcBindingSetAuthInfoW(*pBindingHandle,
  209. pwszInterfaceName, // pszPrincipalName
  210. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  211. RPC_C_AUTHN_WINNT,
  212. NULL, // AuthnIdentity
  213. 0 // AuthzSvc
  214. );
  215. DBGPRINTF( (DBG_CONTEXT,
  216. "RpcBindingSetAuthInfo(%S(Interface=%S), %p)"
  217. " return %d.\n",
  218. pwszBinding,
  219. pwszInterfaceName,
  220. *pBindingHandle,
  221. rpcStatus
  222. )
  223. );
  224. }
  225. //
  226. // Cleanup and return back.
  227. //
  228. if ( pwszBinding != NULL) {
  229. RpcStringFreeW(&pwszBinding);
  230. }
  231. if ( rpcStatus != RPC_S_OK) {
  232. if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
  233. // RPC should have freed the binding handle.
  234. // We will free it now.
  235. RpcBindingFree(*pBindingHandle);
  236. *pBindingHandle = NULL;
  237. }
  238. }
  239. return (rpcStatus);
  240. } // RpcBindHandleOverLpc()
  241. #ifndef CHICAGO
  242. //
  243. // If changes are made to the NT version, check out the windows 95
  244. // version located right after this routine and see if the change
  245. // needs to be propagated there too.
  246. //
  247. RPC_STATUS
  248. RpcBindHandleOverTcpIp( OUT handle_t * pBindingHandle,
  249. IN LPWSTR pwszServerName,
  250. IN LPWSTR pwszInterfaceName
  251. )
  252. /*++
  253. NT Version
  254. This function uses the parameters supplied and generates a dynamic end point
  255. binding handle for RPC over TCP/IP.
  256. Arguments:
  257. pBindingHandle pointer to location which will contain binding handle
  258. on successful return
  259. pwszServerName pointer to string containing the name of the server
  260. to which, this function will obtain a binding.
  261. pwszInterfaceName pointer to string containing the interface name
  262. Returns:
  263. RPC_STATUS - RPC_S_OK on success
  264. Also on success, the binding handle is stored in pBindingHandle.
  265. It should freed after usage, using the RpcBindingFree() function.
  266. --*/
  267. {
  268. RPC_STATUS rpcStatus;
  269. LPWSTR pwszBinding = NULL;
  270. if ( pBindingHandle != NULL) {
  271. *pBindingHandle = NULL; // init the value
  272. }
  273. //
  274. // Compose the binding string for named pipe binding
  275. //
  276. rpcStatus = RpcStringBindingComposeW(0, // ObjUuid
  277. L"ncacn_ip_tcp", // tcpip seq
  278. pwszServerName, // NetworkAddr
  279. NULL, // Endpoint
  280. L"", // Options
  281. &pwszBinding); // StringBinding
  282. DBGPRINTF( (DBG_CONTEXT, "\nRpcStringBindingComposeW(%S, %S) return %S."
  283. " Error = %ld\n",
  284. L"ncacn_ip_tcp",
  285. pwszServerName,
  286. pwszBinding,
  287. rpcStatus)
  288. );
  289. if ( rpcStatus == RPC_S_OK ) {
  290. //
  291. // establish the binding handle using string binding.
  292. //
  293. rpcStatus = RpcBindingFromStringBindingW(pwszBinding,
  294. pBindingHandle );
  295. DBGPRINTF( (DBG_CONTEXT,
  296. "RpcBindingFromStringBindingW(%S) return %d."
  297. "Binding=%p\n",
  298. pwszBinding,
  299. rpcStatus,
  300. *pBindingHandle)
  301. );
  302. }
  303. if ( rpcStatus == RPC_S_OK) {
  304. //
  305. // set up the security information
  306. //
  307. rpcStatus =
  308. RpcBindingSetAuthInfoW(*pBindingHandle,
  309. pwszInterfaceName, // pszPrincipalName
  310. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  311. RPC_C_AUTHN_WINNT,
  312. NULL, // AuthnIdentity
  313. 0 // AuthzSvc
  314. );
  315. DBGPRINTF( (DBG_CONTEXT,
  316. "RpcBindingSetAuthInfo(%S(Interface=%S), %p)"
  317. " return %d.\n",
  318. pwszBinding,
  319. pwszInterfaceName,
  320. *pBindingHandle,
  321. rpcStatus
  322. )
  323. );
  324. }
  325. //
  326. // Cleanup and return back.
  327. //
  328. if ( pwszBinding != NULL) {
  329. DWORD rpcStatus1 = RpcStringFreeW(&pwszBinding);
  330. DBGPRINTF( (DBG_CONTEXT, "RpcStringFreeW() returns %d.",
  331. rpcStatus1)
  332. );
  333. }
  334. if ( rpcStatus != RPC_S_OK) {
  335. if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
  336. // RPC should have freed the binding handle.
  337. // We will free it now.
  338. DWORD rpcStatus1 = RpcBindingFree(*pBindingHandle);
  339. DBGPRINTF( (DBG_CONTEXT, "RpcBindingFree() returns %d.\n",
  340. rpcStatus1)
  341. );
  342. *pBindingHandle = NULL;
  343. }
  344. }
  345. return (rpcStatus);
  346. } // RpcBindHandleOverTcpIp()
  347. #else // CHICAGO
  348. RPC_STATUS
  349. RpcBindHandleOverTcpIp( OUT handle_t * pBindingHandle,
  350. IN LPWSTR pwszServerName,
  351. IN LPWSTR pwszInterfaceName
  352. )
  353. /*++
  354. Windows 95 version
  355. This function uses the parameters supplied and generates a dynamic end point
  356. binding handle for RPC over TCP/IP.
  357. Arguments:
  358. pBindingHandle pointer to location which will contain binding handle
  359. on successful return
  360. pwszServerName pointer to string containing the name of the server
  361. to which, this function will obtain a binding.
  362. pwszInterfaceName pointer to string containing the interface name
  363. Returns:
  364. RPC_STATUS - RPC_S_OK on success
  365. Also on success, the binding handle is stored in pBindingHandle.
  366. It should freed after usage, using the RpcBindingFree() function.
  367. --*/
  368. {
  369. RPC_STATUS rpcStatus;
  370. LPSTR pszBindingA = NULL;
  371. CHAR szServerA[MAX_PATH];
  372. CHAR szInterfaceA[MAX_PATH];
  373. int cch;
  374. if ( pBindingHandle != NULL) {
  375. *pBindingHandle = NULL; // init the value
  376. }
  377. *szServerA = '0';
  378. if (pwszServerName)
  379. cch = WideCharToMultiByte(CP_ACP,
  380. 0,
  381. pwszServerName,
  382. -1,
  383. szServerA,
  384. sizeof(szServerA)/sizeof(CHAR),
  385. NULL,NULL
  386. );
  387. *szInterfaceA = '0';
  388. if(pwszInterfaceName)
  389. cch = WideCharToMultiByte(CP_ACP,
  390. 0,
  391. pwszInterfaceName,
  392. -1,
  393. szInterfaceA,
  394. sizeof(szInterfaceA)/sizeof(CHAR),
  395. NULL,NULL
  396. );
  397. //
  398. // Compose the binding string for named pipe binding
  399. //
  400. rpcStatus = RpcStringBindingCompose(0, // ObjUuid
  401. "ncacn_ip_tcp", // tcpip seq
  402. szServerA, // NetworkAddr
  403. NULL, // Endpoint
  404. NULL, //L"", // Options
  405. &pszBindingA); // StringBinding
  406. DBGPRINTF( (DBG_CONTEXT, "\nRpcStringBindingCompose(%s, %s) return %s."
  407. " Error = %ld\n",
  408. "ncacn_ip_tcp",
  409. szServerA,
  410. pszBindingA,
  411. rpcStatus)
  412. );
  413. if ( rpcStatus == RPC_S_OK ) {
  414. //
  415. // establish the binding handle using string binding.
  416. //
  417. rpcStatus = RpcBindingFromStringBinding(pszBindingA,
  418. pBindingHandle );
  419. DBGPRINTF( (DBG_CONTEXT,
  420. "RpcBindingFromStringBinding(%s) return %d."
  421. "Binding=%08x\n",
  422. pszBindingA,
  423. rpcStatus,
  424. *pBindingHandle)
  425. );
  426. }
  427. if ( rpcStatus == RPC_S_OK) {
  428. //
  429. // set up the security information
  430. //
  431. rpcStatus =
  432. RpcBindingSetAuthInfo(*pBindingHandle,
  433. szInterfaceA, // pszPrincipalName
  434. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  435. RPC_C_AUTHN_WINNT,
  436. NULL, // AuthnIdentity
  437. 0 // AuthzSvc
  438. );
  439. DBGPRINTF( (DBG_CONTEXT,
  440. "RpcBindingSetAuthInfo(%s(Interface=%s), %08x)"
  441. " return %d.\n",
  442. pszBindingA,
  443. szInterfaceA,
  444. *pBindingHandle,
  445. rpcStatus
  446. )
  447. );
  448. }
  449. //
  450. // Cleanup and return back.
  451. //
  452. if ( pszBindingA != NULL) {
  453. DWORD rpcStatus1 = RpcStringFree(&pszBindingA);
  454. DBGPRINTF( (DBG_CONTEXT, "RpcStringFreeW() returns %d.",
  455. rpcStatus1)
  456. );
  457. }
  458. if ( rpcStatus != RPC_S_OK) {
  459. if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
  460. // RPC should have freed the binding handle.
  461. // We will free it now.
  462. DWORD rpcStatus1 = RpcBindingFree(*pBindingHandle);
  463. DBGPRINTF( (DBG_CONTEXT, "RpcBindingFree() returns %d.\n",
  464. rpcStatus1)
  465. );
  466. *pBindingHandle = NULL;
  467. }
  468. }
  469. return (rpcStatus);
  470. } // RpcBindHandleOverTcpIp()
  471. #endif
  472. #ifndef CHICAGO
  473. DWORD
  474. RpcuFindProtocolToUse( IN LPCWSTR pwszServerName)
  475. /*++
  476. Given the server name this funciton determines the protocol
  477. to use for RPC binding.
  478. The transport used is determined dynamically based on following rules.
  479. If server name is NULL or 127.0.0.1 or same as local computer name
  480. then use the LPC.
  481. If server name starts with a leading "\\" (double slash),
  482. then attempt RPC binding over NamedPipe.
  483. If server name does not start with leading "\\",
  484. then attempt RPC binding over TCPIP.
  485. If TCPIP binding fails, then this function tries binding over NamedPipe.
  486. Argument:
  487. pwszServerName - pointer to string containing the name of the server
  488. Returns:
  489. DWORD containing the type of protocol to use.
  490. --*/
  491. {
  492. static WCHAR g_wchLocalMachineName[ MAX_COMPUTERNAME_LENGTH + 1];
  493. BOOL fLeadingSlashes;
  494. DWORD dwBindProtocol = ISRPC_CLIENT_OVER_NP;
  495. BOOL fLocalMachine;
  496. if ( pwszServerName == NULL ||
  497. _wcsicmp( L"127.0.0.1", pwszServerName) == 0) {
  498. return (ISRPC_CLIENT_OVER_LPC);
  499. }
  500. if ( g_wchLocalMachineName[0] == L'\0') {
  501. DWORD cchComputerNameLen = MAX_COMPUTERNAME_LENGTH;
  502. //
  503. // Obtain the local computer name
  504. //
  505. if (!GetComputerNameW( g_wchLocalMachineName,
  506. &cchComputerNameLen)
  507. ) {
  508. *g_wchLocalMachineName = L'\0';
  509. }
  510. }
  511. fLeadingSlashes = ((*pwszServerName == L'\\') &&
  512. (*(pwszServerName+1) == L'\\')
  513. );
  514. //
  515. // Check to see if machine name matches local computer name
  516. // if so, use LPC
  517. //
  518. fLocalMachine = !_wcsicmp( g_wchLocalMachineName,
  519. ((fLeadingSlashes) ?
  520. (pwszServerName + 2) : pwszServerName)
  521. );
  522. if ( fLocalMachine) {
  523. return (ISRPC_CLIENT_OVER_LPC);
  524. }
  525. if ( !fLeadingSlashes) {
  526. DWORD nDots;
  527. LPCWSTR pszName;
  528. //
  529. // Check if the name has dotted decimal name.
  530. // If so then suggest TCP binding.
  531. //
  532. for( nDots = 0, pszName = pwszServerName;
  533. ((pszName = wcschr( pszName, L'.' )) != NULL);
  534. nDots++, pszName++)
  535. ;
  536. if ( nDots == 3) {
  537. //
  538. // if the string has 3 DOTs exactly then this string must represent
  539. // an IpAddress.
  540. //
  541. return(ISRPC_CLIENT_OVER_TCPIP);
  542. }
  543. }
  544. return ( ISRPC_CLIENT_OVER_NP);
  545. } // RpcuFindProtocolToUse()
  546. #endif
  547. RPC_STATUS
  548. RpcBindHandleForServer( OUT handle_t * pBindingHandle,
  549. IN LPWSTR pwszServerName,
  550. IN LPWSTR pwszInterfaceName,
  551. IN LPWSTR pwszOptions
  552. )
  553. /*++
  554. This function uses the parameters supplied and generates a binding
  555. handle for RPC.
  556. It is assumed that binding over named pipe uses static end point
  557. with the interface name and options as provided.
  558. Arguments:
  559. pBindingHandle pointer to location which will contain binding handle
  560. on successful return
  561. pwszServerName pointer to string containing the name of the server
  562. to which, this function will obtain a binding.
  563. pwszInterfaceName pointer to string containing the interface name
  564. pwszOptions pointer to string containing any additional options for
  565. binding.
  566. Returns:
  567. RPC_STATUS - RPC_S_OK on success
  568. Also on success, the binding handle is stored in pBindingHandle.
  569. It should freed after usage, using the RpcBindingFree() function.
  570. --*/
  571. {
  572. RPC_STATUS rpcStatus = RPC_S_SERVER_UNAVAILABLE;
  573. LPWSTR pwszBinding = NULL;
  574. DWORD dwBindProtocol = 0;
  575. if ( pBindingHandle != NULL) {
  576. *pBindingHandle = NULL; // init the value
  577. }
  578. #ifndef CHICAGO
  579. dwBindProtocol = RpcuFindProtocolToUse( pwszServerName);
  580. #else
  581. dwBindProtocol = ISRPC_CLIENT_OVER_TCPIP;
  582. #endif
  583. switch ( dwBindProtocol) {
  584. case ISRPC_CLIENT_OVER_LPC:
  585. {
  586. WCHAR rgchLpc[1024];
  587. //
  588. // generate a LPC end point name from the interface name.
  589. // the End point = <InterfaceName>_LPC
  590. //
  591. if ( lstrlenW( pwszInterfaceName) >=
  592. ( sizeof(rgchLpc)/sizeof(WCHAR) - 6)) {
  593. SetLastError( ERROR_INVALID_PARAMETER);
  594. return ( ERROR_INVALID_PARAMETER);
  595. }
  596. lstrcpynW( rgchLpc, pwszInterfaceName, sizeof(rgchLpc)/sizeof(WCHAR) - 4);
  597. lstrcatW( rgchLpc, L"_LPC");
  598. //
  599. // Attempt binding over static LPC.
  600. //
  601. rpcStatus = RpcBindHandleOverLpc( pBindingHandle,
  602. rgchLpc,
  603. pwszOptions,
  604. pwszInterfaceName
  605. );
  606. DBGPRINTF(( DBG_CONTEXT,
  607. " RpcBindingOverLpc(%S) returns %d."
  608. " Handle = %p\n",
  609. pwszServerName, rpcStatus, *pBindingHandle));
  610. break;
  611. }
  612. case ISRPC_CLIENT_OVER_TCPIP:
  613. // # ifdef RPC_BIND_OVER_TCP
  614. //
  615. // Attempt binding over TCPIP using Dynamic Endpoint.
  616. //
  617. rpcStatus = RpcBindHandleOverTcpIp( pBindingHandle,
  618. pwszServerName,
  619. pwszInterfaceName);
  620. DBGPRINTF(( DBG_CONTEXT,
  621. " RpcBindingOverTcpIp(%S) returns %d. Handle = %p\n",
  622. pwszServerName, rpcStatus, *pBindingHandle));
  623. if ( rpcStatus == RPC_S_OK) {
  624. break; // done with RPC binding over TCP
  625. }
  626. // Fall Through
  627. // # endif // RPC_BIND_OVER_TCP
  628. case ISRPC_CLIENT_OVER_NP:
  629. {
  630. WCHAR rgchNp[1024];
  631. //
  632. // generate a NamedPipe end point name from the interface name.
  633. // the End point = \PIPE\<InterfaceName>
  634. //
  635. lstrcpyW( rgchNp, L"\\PIPE\\");
  636. if ( lstrlenW( pwszInterfaceName) >=
  637. ( sizeof(rgchNp)/sizeof(WCHAR) - 10)) {
  638. SetLastError( ERROR_INVALID_PARAMETER);
  639. return ( ERROR_INVALID_PARAMETER);
  640. }
  641. lstrcatW( rgchNp, pwszInterfaceName);
  642. //
  643. // Attempt binding over static NamedPipe.
  644. //
  645. rpcStatus = RpcBindHandleOverNamedPipe( pBindingHandle,
  646. pwszServerName,
  647. rgchNp,
  648. pwszOptions,
  649. pwszInterfaceName
  650. );
  651. DBGPRINTF(( DBG_CONTEXT,
  652. " RpcBindingOverNamedPipe(%S) returns %d."
  653. " Handle = %p\n",
  654. pwszServerName, rpcStatus, *pBindingHandle));
  655. break;
  656. }
  657. default:
  658. break;
  659. } // switch()
  660. return ( rpcStatus);
  661. } // RpcBindHandleForServer()
  662. RPC_STATUS
  663. RpcBindHandleFree(IN OUT handle_t * pBindingHandle)
  664. /*++
  665. Description:
  666. This function frees up the binding handle allocated using
  667. RpcBindHandleForServer(). It uses RPC Binding Free routing to do this.
  668. This function acts just as a thunk so that the alloc/free of RPC contexts
  669. are consolidated within this module.
  670. Arguments:
  671. pBindingHandle pointer to RPC binding handle that needs to be freed.
  672. Returns:
  673. RPC_STATUS - containig the RPC status. RPC_S_OK for success.
  674. --*/
  675. {
  676. return ( RpcBindingFree( pBindingHandle));
  677. } // RpcBindHandleFree()
  678. /************************ End of File ***********************/