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.

682 lines
18 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. stiapi.h
  5. Abstract:
  6. Common RPC related utility functions
  7. Functions Exported:
  8. MIDL_user_allocate()
  9. MIDL_user_free()
  10. RpcBindHandleForServer()
  11. RpcBindHandleFree()
  12. Author:
  13. Vlad Sadovsky (vlads) 26-Jan-1997
  14. Revision History:
  15. 26-Jan-1997 VladS created
  16. --*/
  17. #include "cplusinc.h"
  18. #include "sticomm.h"
  19. # include <rpc.h>
  20. # include "apiutil.h"
  21. #include "simstr.h"
  22. /************************************************************
  23. * Functions
  24. ************************************************************/
  25. extern "C"
  26. {
  27. PVOID
  28. MIDL_user_allocate(IN size_t size)
  29. /*++
  30. Routine Description:
  31. MIDL memory allocation.
  32. Arguments:
  33. size : Memory size requested.
  34. Return Value:
  35. Pointer to the allocated memory block.
  36. --*/
  37. {
  38. PVOID pvBlob;
  39. pvBlob = LocalAlloc( LPTR, size);
  40. return( pvBlob );
  41. } // MIDL_user_allocate()
  42. VOID
  43. MIDL_user_free(IN PVOID pvBlob)
  44. /*++
  45. Routine Description:
  46. MIDL memory free .
  47. Arguments:
  48. pvBlob : Pointer to a memory block that is freed.
  49. Return Value:
  50. None.
  51. --*/
  52. {
  53. LocalFree( pvBlob);
  54. return;
  55. } // MIDL_user_free()
  56. }
  57. static CHAR szLocalAddress[] = "127.0.0.1";
  58. RPC_STATUS
  59. RpcBindHandleOverLocal( OUT handle_t * pBindingHandle,
  60. IN LPWSTR pwszInterfaceName
  61. )
  62. /*++
  63. This function uses the parameters supplied and generates static
  64. binding handle for RPC over LRPC
  65. Arguments:
  66. pBindingHandle pointer to location which will contain binding handle
  67. on successful return
  68. pwszInterfaceName pointer to string containing the interface name
  69. Returns:
  70. RPC_STATUS - RPC_S_OK on success
  71. Also on success, the binding handle is stored in pBindingHandle.
  72. It should freed after usage, using the RpcBindingFree() function.
  73. --*/
  74. {
  75. RPC_STATUS rpcStatus;
  76. LPTSTR pszBinding = NULL;
  77. BOOL fLocalCall = FALSE;
  78. if ( pBindingHandle != NULL) {
  79. *pBindingHandle = NULL; // init the value
  80. }
  81. //
  82. // Compose the binding string for local binding
  83. //
  84. rpcStatus = RpcStringBindingCompose(0, // ObjUuid
  85. (RPC_STRING)STI_LRPC_SEQ, // transport seq
  86. (RPC_STRING)TEXT(""), // NetworkAddr
  87. (RPC_STRING)STI_LRPC_ENDPOINT, // Endpoint
  88. NULL, // Options
  89. (RPC_STRING *)&pszBinding);// StringBinding
  90. if ( rpcStatus == RPC_S_OK ) {
  91. //
  92. // establish the binding handle using string binding.
  93. //
  94. rpcStatus = RpcBindingFromStringBinding((RPC_STRING)pszBinding,pBindingHandle );
  95. if (rpcStatus == RPC_S_OK)
  96. {
  97. //
  98. // Check that the server we're connecting to has the appropriate credentials.
  99. // For XP CLient, we know the principal name is LocalSystem.
  100. //
  101. CSimpleStringWide cswStiSvcPrincipalName = L"NT Authority\\System";
  102. RPC_SECURITY_QOS RpcSecQos = {0};
  103. RpcSecQos.Version = RPC_C_SECURITY_QOS_VERSION_1;
  104. RpcSecQos.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
  105. RpcSecQos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  106. RpcSecQos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  107. rpcStatus = RpcBindingSetAuthInfoExW(*pBindingHandle,
  108. (WCHAR*)cswStiSvcPrincipalName.String(),
  109. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  110. RPC_C_AUTHN_WINNT,
  111. NULL,
  112. RPC_C_AUTHZ_NONE,
  113. &RpcSecQos);
  114. }
  115. }
  116. //
  117. // Cleanup and return back.
  118. //
  119. if ( pszBinding != NULL) {
  120. DWORD rpcStatus1 = RpcStringFree((RPC_STRING *)&pszBinding);
  121. }
  122. if ( rpcStatus != RPC_S_OK) {
  123. if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
  124. // RPC should have freed the binding handle.
  125. // We will free it now.
  126. DWORD rpcStatus1 = RpcBindingFree(pBindingHandle);
  127. *pBindingHandle = NULL;
  128. }
  129. }
  130. return (rpcStatus);
  131. } // RpcBindHandleOverLocal()
  132. #ifdef STI_REMOTE_BINDING
  133. RPC_STATUS
  134. RpcBindHandleOverTcpIp( OUT handle_t * pBindingHandle,
  135. IN LPWSTR pwszServerName,
  136. IN LPWSTR pwszInterfaceName
  137. )
  138. /*++
  139. This function uses the parameters supplied and generates a dynamic end point
  140. binding handle for RPC over TCP/IP.
  141. Arguments:
  142. pBindingHandle pointer to location which will contain binding handle
  143. on successful return
  144. pwszServerName pointer to string containing the name of the server
  145. to which, this function will obtain a binding.
  146. pwszInterfaceName pointer to string containing the interface name
  147. Returns:
  148. RPC_STATUS - RPC_S_OK on success
  149. Also on success, the binding handle is stored in pBindingHandle.
  150. It should freed after usage, using the RpcBindingFree() function.
  151. --*/
  152. {
  153. RPC_STATUS rpcStatus;
  154. LPSTR pszBindingA = NULL;
  155. CHAR szServerA[MAX_PATH];
  156. CHAR szInterfaceA[MAX_PATH];
  157. int cch;
  158. BOOL fLocalCall = FALSE;
  159. if ( pBindingHandle != NULL) {
  160. *pBindingHandle = NULL; // init the value
  161. }
  162. *szServerA = '0';
  163. if (pwszServerName ) {
  164. cch = WideCharToMultiByte(CP_ACP,
  165. 0,
  166. pwszServerName,
  167. -1,
  168. szServerA,
  169. sizeof(szServerA)/sizeof(CHAR),
  170. NULL,NULL
  171. );
  172. }
  173. // If empty server name has been passed - use address of local machine
  174. if (!*szServerA || !lstrcmpi(szServerA,szLocalAddress)) {
  175. fLocalCall = TRUE;
  176. lstrcpy(szServerA,szLocalAddress);
  177. }
  178. *szInterfaceA = '0';
  179. if(pwszInterfaceName)
  180. cch = WideCharToMultiByte(CP_ACP,
  181. 0,
  182. pwszInterfaceName,
  183. -1,
  184. szInterfaceA,
  185. sizeof(szInterfaceA)/sizeof(CHAR),
  186. NULL,NULL
  187. );
  188. //
  189. // Compose the binding string for TCP/IP binding
  190. //
  191. rpcStatus = RpcStringBindingCompose(0, // ObjUuid
  192. "ncacn_ip_tcp", // tcpip seq
  193. szServerA, // NetworkAddr
  194. NULL, // Endpoint
  195. NULL, //L"", // Options
  196. &pszBindingA); // StringBinding
  197. DBGPRINTF( (DBG_CONTEXT, "\nRpcStringBindingCompose(%s, %s) return %s."
  198. " Error = %ld\n",
  199. "ncacn_ip_tcp",
  200. szServerA,
  201. pszBindingA,
  202. rpcStatus)
  203. );
  204. if ( rpcStatus == RPC_S_OK ) {
  205. //
  206. // establish the binding handle using string binding.
  207. //
  208. rpcStatus = RpcBindingFromStringBinding(pszBindingA,
  209. pBindingHandle );
  210. DBGPRINTF( (DBG_CONTEXT,
  211. "RpcBindingFromStringBinding(%s) return %d."
  212. "Binding=%08x\n",
  213. pszBindingA,
  214. rpcStatus,
  215. *pBindingHandle)
  216. );
  217. }
  218. if ( (rpcStatus == RPC_S_OK) && !fLocalCall) {
  219. //
  220. // set up the security information
  221. //
  222. rpcStatus =
  223. RpcBindingSetAuthInfo(*pBindingHandle,
  224. szInterfaceA, // pszPrincipalName
  225. RPC_C_AUTHN_LEVEL_CONNECT,
  226. RPC_C_AUTHN_WINNT,
  227. NULL, // AuthnIdentity
  228. 0 // AuthzSvc
  229. );
  230. DBGPRINTF( (DBG_CONTEXT,
  231. "RpcBindingSetAuthInfo(%s(Interface=%s), %08x)"
  232. " return %d.\n",
  233. pszBindingA,
  234. szInterfaceA,
  235. *pBindingHandle,
  236. rpcStatus
  237. )
  238. );
  239. }
  240. //
  241. // Cleanup and return back.
  242. //
  243. if ( pszBindingA != NULL) {
  244. DWORD rpcStatus1 = RpcStringFree(&pszBindingA);
  245. DBGPRINTF( (DBG_CONTEXT, "RpcStringFreeW() returns %d.",
  246. rpcStatus1)
  247. );
  248. }
  249. if ( rpcStatus != RPC_S_OK) {
  250. if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
  251. // RPC should have freed the binding handle.
  252. // We will free it now.
  253. DWORD rpcStatus1 = RpcBindingFree(*pBindingHandle);
  254. DBGPRINTF( (DBG_CONTEXT, "RpcBindingFree() returns %d.\n",
  255. rpcStatus1)
  256. );
  257. *pBindingHandle = NULL;
  258. }
  259. }
  260. return (rpcStatus);
  261. } // RpcBindHandleOverTcpIp()
  262. RPC_STATUS
  263. RpcBindHandleOverNamedPipe( OUT handle_t * pBindingHandle,
  264. IN LPWSTR pwszServerName,
  265. IN LPWSTR pwszEndpoint,
  266. IN LPWSTR pwszOptions
  267. )
  268. /*++
  269. This function uses the parameters supplied and generates a named pipe
  270. binding handle for RPC.
  271. Arguments:
  272. pBindingHandle pointer to location which will contain binding handle
  273. on successful return
  274. pwszServerName pointer to string containing the name of the server
  275. to which, this function will obtain a binding.
  276. pwszEndpoint pointer to string containing the Named Pipe Endpoint
  277. pwszOptions pointer to string containing any additional options for
  278. binding.
  279. Returns:
  280. RPC_STATUS - RPC_S_OK on success
  281. Also on success, the binding handle is stored in pBindingHandle.
  282. It should freed after usage, using the RpcBindingFree() function.
  283. --*/
  284. {
  285. RPC_STATUS rpcStatus;
  286. LPWSTR pwszBinding = NULL;
  287. LPSTR pszBindingA = NULL;
  288. CHAR szServerA[MAX_PATH+2];
  289. CHAR szEndpointA[MAX_PATH];
  290. CHAR szOptionsA[MAX_PATH];
  291. PSTR pszStartServerName;
  292. int cch;
  293. BOOL fLocalCall = FALSE;
  294. if ( pBindingHandle != NULL) {
  295. *pBindingHandle = NULL; // init the value
  296. }
  297. *szServerA = '0';
  298. if (pwszServerName ) {
  299. // We are trying to bind over NP transport, so server name should start with leading slashes
  300. if(*pwszServerName == L'\\' &&
  301. *(pwszServerName+1) == L'\\') {
  302. pszStartServerName = szServerA;
  303. }
  304. else {
  305. lstrcpy(szServerA,TEXT("\\\\"));
  306. pszStartServerName = szServerA+2;
  307. }
  308. cch = WideCharToMultiByte(CP_ACP,
  309. 0,
  310. pwszServerName,
  311. -1,
  312. pszStartServerName,
  313. sizeof(szServerA)/sizeof(CHAR)-2,
  314. NULL,NULL
  315. );
  316. }
  317. if (!*szServerA) {
  318. return ERROR_INVALID_PARAMETER;
  319. }
  320. // Remove extra slashes if there are too many
  321. *szEndpointA = '0';
  322. if(pwszEndpoint)
  323. cch = WideCharToMultiByte(CP_ACP,
  324. 0,
  325. pwszEndpoint,
  326. -1,
  327. szEndpointA,
  328. sizeof(szEndpointA)/sizeof(CHAR),
  329. NULL,NULL
  330. );
  331. *szOptionsA = '0';
  332. if(pwszOptions)
  333. cch = WideCharToMultiByte(CP_ACP,
  334. 0,
  335. pwszOptions,
  336. -1,
  337. szOptionsA,
  338. sizeof(szOptionsA)/sizeof(CHAR),
  339. NULL,NULL
  340. );
  341. //
  342. // Compose the binding string for named pipe binding
  343. //
  344. rpcStatus = RpcStringBindingCompose(0, // ObjUuid
  345. "ncacn_np", // prot seq: named pipe
  346. szServerA, // NetworkAddr
  347. szEndpointA, // Endpoint
  348. "", //szOptionsA, // Options
  349. &pszBindingA); // StringBinding
  350. if ( rpcStatus == RPC_S_OK ) {
  351. //
  352. // establish the binding handle using string binding.
  353. //
  354. rpcStatus = RpcBindingFromStringBinding(pszBindingA,
  355. pBindingHandle );
  356. }
  357. //
  358. // Cleanup and return back.
  359. //
  360. if ( pwszBinding != NULL) {
  361. RpcStringFree(&pszBindingA);
  362. }
  363. if ( rpcStatus != RPC_S_OK) {
  364. if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
  365. // RPC should have freed the binding handle.
  366. // We will free it now.
  367. RpcBindingFree(*pBindingHandle);
  368. *pBindingHandle = NULL;
  369. }
  370. }
  371. return (rpcStatus);
  372. } // RpcBindHandleOverNamedPipe()
  373. #endif // STI_REMOTE_BINDING
  374. RPC_STATUS
  375. RpcBindHandleForServer( OUT handle_t * pBindingHandle,
  376. IN LPWSTR pwszServerName,
  377. IN LPWSTR pwszInterfaceName,
  378. IN LPWSTR pwszOptions
  379. )
  380. /*++
  381. This function uses the parameters supplied and generates a binding
  382. handle for RPC.
  383. The transport used is determined dynamically based on following rules.
  384. If server name starts with a leading "\\" (double slash),
  385. then attempt RPC binding over NamedPipe.
  386. If server name does not start with leading "\\",
  387. then attempt RPC binding over TCPIP.
  388. If TCPIP binding fails, then this function tries binding over NamedPipe.
  389. It is assumed that binding over named pipe uses static end point
  390. with the interface name and options as provided.
  391. Arguments:
  392. pBindingHandle pointer to location which will contain binding handle
  393. on successful return
  394. pwszServerName pointer to string containing the name of the server
  395. to which, this function will obtain a binding.
  396. pwszInterfaceName pointer to string containing the interface name
  397. pwszOptions pointer to string containing any additional options for
  398. binding.
  399. Returns:
  400. RPC_STATUS - RPC_S_OK on success
  401. Also on success, the binding handle is stored in pBindingHandle.
  402. It should freed after usage, using the RpcBindingFree() function.
  403. --*/
  404. {
  405. RPC_STATUS rpcStatus = RPC_S_SERVER_UNAVAILABLE;
  406. LPWSTR pwszBinding = NULL;
  407. if ( pBindingHandle != NULL) {
  408. *pBindingHandle = NULL; // init the value
  409. }
  410. //
  411. // STI interfaces are not remotable, so only try binding to local server
  412. //
  413. if ( pwszServerName == NULL ||
  414. *pwszServerName == L'\0' ) {
  415. rpcStatus = RpcBindHandleOverLocal( pBindingHandle,
  416. pwszInterfaceName);
  417. }
  418. else {
  419. rpcStatus = RPC_S_INVALID_NET_ADDR;
  420. }
  421. # ifdef STI_REMOTE_BINDING
  422. #ifdef CHICAGO
  423. //
  424. // On Windows9x if there is no VRedir installed, RPC refuses to bind over
  425. // TCP/IP or NetBIOS. TO resolve this issue server always listens on LRPC
  426. // and if client is requesting local operation ( by passing empty string or NULL)
  427. // as first parameter binding is done over LRPC. Note, that passing non-null IP address
  428. // ( even if it points to local machine, like 127.0.0.1 ) will result in binding over TCP/IP
  429. // and may now work .
  430. //
  431. if ( pwszServerName == NULL ||
  432. *pwszServerName == L'\0' ) {
  433. rpcStatus = RpcBindHandleOverLocal( pBindingHandle,
  434. pwszInterfaceName);
  435. }
  436. else {
  437. if ( pwszServerName[0] != L'\\' &&
  438. pwszServerName[1] != L'\\' ) {
  439. //
  440. // Attempt binding over TCPIP using Dynamic Endpoint.
  441. //
  442. rpcStatus = RpcBindHandleOverTcpIp( pBindingHandle,
  443. pwszServerName,
  444. pwszInterfaceName);
  445. } else {
  446. rpcStatus = RPC_S_INVALID_NET_ADDR;
  447. }
  448. }
  449. #endif
  450. if ( rpcStatus != RPC_S_OK) {
  451. WCHAR rgchNp[1024];
  452. //
  453. // generate a NamedPipe end point name from the interface name.
  454. // the End point = \PIPE\<InterfaceName>
  455. //
  456. wcscpy( rgchNp, L"\\PIPE\\");
  457. wcscat( rgchNp, pwszInterfaceName);
  458. //
  459. // Attempt binding over static NamedPipe.
  460. //
  461. rpcStatus = RpcBindHandleOverNamedPipe( pBindingHandle,
  462. pwszServerName,
  463. rgchNp,
  464. pwszOptions
  465. );
  466. DBGPRINTF(( DBG_CONTEXT,
  467. " RpcBindingOverNamedPipe(%S) returns %d. Handle = %08x\n",
  468. pwszServerName, rpcStatus, *pBindingHandle));
  469. }
  470. # endif // STI_REMOTE_BINDING
  471. return ( rpcStatus);
  472. } // RpcBindHandleForServer()
  473. RPC_STATUS
  474. RpcBindHandleFree(IN OUT handle_t * pBindingHandle)
  475. /*++
  476. Description:
  477. This function frees up the binding handle allocated using
  478. RpcBindHandleForServer(). It uses RPC Binding Free routing to do this.
  479. This function acts just as a thunk so that the alloc/free of RPC contexts
  480. are consolidated within this module.
  481. Arguments:
  482. pBindingHandle pointer to RPC binding handle that needs to be freed.
  483. Returns:
  484. RPC_STATUS - containig the RPC status. RPC_S_OK for success.
  485. --*/
  486. {
  487. return ( RpcBindingFree( pBindingHandle));
  488. } // RpcBindHandleFree()
  489. /************************ End of File ***********************/