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.

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