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.

331 lines
8.0 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. #include "precomp.h"
  8. #include <assert.h>
  9. #include <comutl.h>
  10. #include "rpchdr.h"
  11. #include "rpcsend.h"
  12. #include "rpcmsg.h"
  13. extern HRESULT RpcResToWmiRes( RPC_STATUS stat, HRESULT hrDefault );
  14. /*****************************************************************
  15. CMsgRpcSender
  16. ******************************************************************/
  17. HRESULT CMsgRpcSender::Open( LPCWSTR wszTarget,
  18. DWORD dwFlags,
  19. WMIMSG_SNDR_AUTH_INFOP pAuthInfo,
  20. LPCWSTR wszResponse,
  21. IWmiMessageTraceSink* pTraceSink,
  22. IWmiMessageSendReceive** ppSend )
  23. {
  24. HRESULT hr;
  25. ENTER_API_CALL
  26. CWbemPtr<CMsgRpcSend> pSend;
  27. pSend = new CMsgRpcSend( m_pControl,
  28. wszTarget,
  29. dwFlags,
  30. pAuthInfo,
  31. wszResponse,
  32. pTraceSink );
  33. if ( (dwFlags & WMIMSG_FLAG_SNDR_LAZY_INIT) == 0 )
  34. {
  35. hr = pSend->EnsureSender();
  36. if ( FAILED(hr) )
  37. {
  38. return hr;
  39. }
  40. }
  41. return pSend->QueryInterface(IID_IWmiMessageSendReceive, (void**)ppSend);
  42. EXIT_API_CALL
  43. }
  44. /*****************************************************************
  45. CMsgRpcSend
  46. ******************************************************************/
  47. CMsgRpcSend::CMsgRpcSend( CLifeControl* pCtl,
  48. LPCWSTR wszTarget,
  49. DWORD dwFlags,
  50. WMIMSG_SNDR_AUTH_INFOP pAuthInfo,
  51. LPCWSTR wszResponse,
  52. IWmiMessageTraceSink* pTraceSink )
  53. : CUnkBase<IWmiMessageSendReceive,&IID_IWmiMessageSendReceive>(pCtl),
  54. m_dwFlags(dwFlags), m_pTraceSink( pTraceSink ),
  55. m_hBinding(NULL), m_bInit(FALSE)
  56. {
  57. //
  58. // save our computer name.
  59. //
  60. TCHAR achComputer[MAX_COMPUTERNAME_LENGTH+1];
  61. ULONG ulSize = MAX_COMPUTERNAME_LENGTH+1;
  62. GetComputerName( achComputer, &ulSize );
  63. m_wsComputer = achComputer;
  64. //
  65. // if the target is NULL, then we use our computer name as the target.
  66. //
  67. if ( wszTarget != NULL && *wszTarget != '\0' )
  68. {
  69. m_wsTarget = wszTarget;
  70. }
  71. else
  72. {
  73. m_wsTarget = m_wsComputer;
  74. }
  75. if ( pAuthInfo != NULL )
  76. {
  77. if ( pAuthInfo->wszTargetPrincipal != NULL )
  78. {
  79. m_wsTargetPrincipal = pAuthInfo->wszTargetPrincipal;
  80. }
  81. }
  82. }
  83. CMsgRpcSend::~CMsgRpcSend()
  84. {
  85. Clear();
  86. }
  87. HRESULT CMsgRpcSend::HandleTrace( HRESULT hr,
  88. LPCWSTR wszTrace,
  89. IUnknown* pCtx )
  90. {
  91. //
  92. // we use the error sink approach instead of just returning an error
  93. // because sometimes multiple senders are used in one send operation
  94. // ( when using the multi send impl ) and we need to be able to
  95. // distinguish which one failed.
  96. //
  97. if ( m_pTraceSink != NULL )
  98. {
  99. m_pTraceSink->Notify( hr, CLSID_WmiMessageRpcSender, wszTrace, pCtx );
  100. }
  101. return hr;
  102. }
  103. void CMsgRpcSend::Clear()
  104. {
  105. if ( m_hBinding != NULL )
  106. {
  107. RpcBindingFree( &m_hBinding );
  108. m_hBinding = NULL;
  109. }
  110. m_bInit = FALSE;
  111. }
  112. HRESULT CMsgRpcSend::EnsureSender()
  113. {
  114. HRESULT hr = S_OK;
  115. RPC_STATUS stat;
  116. CInCritSec ics(&m_cs);
  117. if ( m_bInit )
  118. {
  119. return WBEM_S_NO_ERROR;
  120. }
  121. Clear();
  122. //
  123. // connect to the stub at the target.
  124. //
  125. stat = RpcBindingFromStringBinding( m_wsTarget, &m_hBinding );
  126. if ( stat != RPC_S_OK )
  127. {
  128. return RpcResToWmiRes( stat, WMIMSG_E_INVALIDADDRESS );
  129. }
  130. //
  131. // binding may be dynamic, so we may have to resolve it.
  132. //
  133. stat = RpcEpResolveBinding( m_hBinding,
  134. IWmiMessageRemoteSendReceive_v1_0_c_ifspec );
  135. if ( stat != RPC_S_OK )
  136. {
  137. return RpcResToWmiRes( stat, WMIMSG_E_TARGETNOTFOUND );
  138. }
  139. //
  140. // set binding auth info based on auth and encryption flags.
  141. //
  142. RPC_SECURITY_QOS qos;
  143. DWORD dwAuthnSvc, dwAuthzSvc, dwAuthnLevel;
  144. LPWSTR wszPrincipal = NULL;
  145. if ( m_wsTargetPrincipal.Length() > 0 )
  146. {
  147. wszPrincipal = m_wsTargetPrincipal;
  148. }
  149. qos.Version = RPC_C_SECURITY_QOS_VERSION;
  150. qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
  151. if ( m_dwFlags & WMIMSG_FLAG_SNDR_ENCRYPT )
  152. {
  153. dwAuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE;
  154. dwAuthzSvc = RPC_C_AUTHZ_DEFAULT;
  155. dwAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  156. qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
  157. qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
  158. }
  159. else if ( m_dwFlags & WMIMSG_FLAG_SNDR_AUTHENTICATE )
  160. {
  161. dwAuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE;
  162. dwAuthzSvc = RPC_C_AUTHZ_DEFAULT;
  163. qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
  164. qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
  165. dwAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
  166. }
  167. else
  168. {
  169. dwAuthnSvc = RPC_C_AUTHN_NONE;
  170. dwAuthzSvc = RPC_C_AUTHZ_NONE;
  171. qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  172. qos.ImpersonationType = RPC_C_IMP_LEVEL_ANONYMOUS;
  173. dwAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
  174. }
  175. stat = RpcBindingSetAuthInfoEx( m_hBinding,
  176. wszPrincipal,
  177. dwAuthnLevel,
  178. dwAuthnSvc,
  179. NULL,
  180. dwAuthzSvc,
  181. &qos );
  182. if ( stat != RPC_S_OK )
  183. {
  184. return RpcResToWmiRes( stat, WMIMSG_E_AUTHFAILURE );
  185. }
  186. m_bInit = TRUE;
  187. return hr;
  188. }
  189. HRESULT CMsgRpcSend::PerformSend( PBYTE pData,
  190. ULONG cData,
  191. PBYTE pAuxData,
  192. ULONG cAuxData )
  193. {
  194. HRESULT hr;
  195. RpcTryExcept
  196. {
  197. hr = ::SendReceive( m_hBinding,
  198. pData,
  199. cData,
  200. pAuxData,
  201. cAuxData );
  202. }
  203. RpcExcept(1)
  204. {
  205. hr = RpcResToWmiRes( RpcExceptionCode(), S_OK );
  206. }
  207. RpcEndExcept
  208. return hr;
  209. }
  210. HRESULT CMsgRpcSend::SendReceive( PBYTE pData,
  211. ULONG cData,
  212. PBYTE pAuxData,
  213. ULONG cAuxData,
  214. DWORD dwFlagStatus,
  215. IUnknown* pCtx )
  216. {
  217. HRESULT hr;
  218. BYTE achHdr[512];
  219. CBuffer HdrStrm( achHdr, 512, FALSE );
  220. CMsgRpcHdr RpcHdr( m_wsComputer, cAuxData );
  221. ENTER_API_CALL
  222. hr = EnsureSender();
  223. if ( FAILED(hr) )
  224. {
  225. return HandleTrace( hr, m_wsTarget, pCtx );
  226. }
  227. //
  228. // create our Rpc hdr and prepend it to the user's hdr data.
  229. //
  230. hr = RpcHdr.Persist( HdrStrm );
  231. if ( FAILED(hr) )
  232. {
  233. return HandleTrace( hr, m_wsTarget, pCtx );
  234. }
  235. hr = HdrStrm.Write( pAuxData, cAuxData, NULL );
  236. if ( FAILED(hr) )
  237. {
  238. return HandleTrace( hr, m_wsTarget, pCtx );
  239. }
  240. hr = PerformSend( pData,
  241. cData,
  242. HdrStrm.GetRawData(),
  243. HdrStrm.GetIndex() );
  244. if ( FAILED(hr) )
  245. {
  246. //
  247. // this is so the next call will reset us.
  248. //
  249. Clear();
  250. hr = RpcResToWmiRes( hr, S_OK );
  251. }
  252. HandleTrace( hr, m_wsTarget, pCtx );
  253. EXIT_API_CALL
  254. return hr;
  255. }