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.

376 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1995-1996 Microsoft Corporation
  3. Module Name:
  4. Mid.cxx
  5. Abstract:
  6. Implements the CMid class.
  7. Author:
  8. Mario Goertzel [MarioGo]
  9. Revision History:
  10. MarioGo 12-13-95 Bits 'n pieces
  11. MarioGo 02-01-96 Move binding handles out of mid
  12. --*/
  13. #include<or.hxx>
  14. class CObjexPPing : public CParallelPing
  15. {
  16. public:
  17. CObjexPPing(WCHAR *pBindings, CMid *pMid) :
  18. _pBindings(pBindings),
  19. _pMid(pMid)
  20. {}
  21. BOOL NextCall(PROTSEQINFO *pProtseqInfo)
  22. {
  23. if (*_pBindings)
  24. {
  25. pProtseqInfo->pvUserInfo = _pBindings;
  26. pProtseqInfo->hRpc = _pMid->MakeBinding(_pBindings);
  27. _pBindings = OrStringSearch(_pBindings, 0) +1;
  28. return TRUE;
  29. }
  30. else
  31. {
  32. return FALSE;
  33. }
  34. }
  35. void ReleaseCall(PROTSEQINFO *pProtseqInfo)
  36. {
  37. if (pProtseqInfo->hRpc)
  38. {
  39. RpcBindingFree(&pProtseqInfo->hRpc);
  40. }
  41. }
  42. private:
  43. WCHAR * _pBindings;
  44. CMid * _pMid;
  45. };
  46. void dsaProtocolMerge(DUALSTRINGARRAY *pdsaSrc, DUALSTRINGARRAY **ppdsaDest)
  47. /*++
  48. Routine Description:
  49. Gives string bindings intersected with the allowed string bindings
  50. for this machine.
  51. Arguments:
  52. pdsaSrc - string bindings to intersect
  53. ppdsaDest - generated string bindings
  54. Return Value:
  55. none
  56. --*/
  57. {
  58. *ppdsaDest = (DUALSTRINGARRAY *)PrivMemAlloc(pdsaSrc->wNumEntries*sizeof(WCHAR) + sizeof(DUALSTRINGARRAY));
  59. if (!*ppdsaDest)
  60. {
  61. return;
  62. }
  63. LPWSTR pTempDest = (*ppdsaDest)->aStringArray;
  64. // NOTE: Do not change the order of these loops
  65. // It is pertinent to correctly order the final
  66. // string.
  67. for (ULONG i=0; i<cMyProtseqs; i++)
  68. {
  69. for (LPWSTR pTempSrc = pdsaSrc->aStringArray;
  70. *pTempSrc;
  71. pTempSrc = OrStringSearch(pTempSrc, 0) + 1)
  72. {
  73. if (aMyProtseqs[i] == *pTempSrc)
  74. {
  75. // tower ids are the same
  76. wcscpy(pTempDest, pTempSrc);
  77. pTempDest = OrStringSearch(pTempDest, 0) + 1;
  78. }
  79. }
  80. }
  81. ULONG_PTR len = pTempDest - (*ppdsaDest)->aStringArray;
  82. if ( len == 0)
  83. {
  84. *pTempDest = 0;
  85. pTempDest++;
  86. len++;
  87. }
  88. // copy sec bindings
  89. *pTempDest = 0;
  90. pTempDest++;
  91. len++;
  92. (*ppdsaDest)->wSecurityOffset = (USHORT) len;
  93. memcpy(pTempDest, pdsaSrc->aStringArray + pdsaSrc->wSecurityOffset,
  94. (pdsaSrc->wNumEntries - pdsaSrc->wSecurityOffset)*sizeof(WCHAR));
  95. len += pdsaSrc->wNumEntries - pdsaSrc->wSecurityOffset;
  96. (*ppdsaDest)->wNumEntries = (USHORT) len;
  97. }
  98. CMid::CMid( DUALSTRINGARRAY *pdsa, BOOL fLocal, ID OldMid ) :
  99. _fLocal(fLocal),
  100. _fStale(FALSE),
  101. _fDynamic(FALSE),
  102. _fInitialized(FALSE),
  103. _StringBinding(NULL),
  104. _fSecure(FALSE),
  105. _pdsaValidStringBindings(0)
  106. /*++
  107. Routine Description:
  108. Constructs a CMid object.
  109. Arguments:
  110. pdsa - The dual string array of the server rpcss.
  111. fLocal - TRUE if the mid represents this machine.
  112. OldMid - Optional reassigned machine id.
  113. Return Value:
  114. none
  115. --*/
  116. {
  117. DWORD i;
  118. // this must be allocated to include the size of the embedded dsa.
  119. dsaCopy(&_dsa, pdsa);
  120. // Set _fSecure iff we find an authentication service in the
  121. // dual string array that we are willing to use.
  122. _wAuthnSvc = RPC_C_AUTHN_NONE;
  123. for (i = 0; i < s_cRpcssSvc; i++)
  124. {
  125. if (ValidAuthnSvc( &_dsa, s_aRpcssSvc[i].wId ))
  126. {
  127. _fSecure = TRUE;
  128. break;
  129. }
  130. }
  131. if (OldMid)
  132. {
  133. _id = OldMid;
  134. ASSERT(fLocal);
  135. }
  136. else
  137. {
  138. _id = AllocateId();
  139. }
  140. }
  141. RPC_BINDING_HANDLE
  142. CMid::MakeBinding(WCHAR *pBinding)
  143. /*++
  144. Routine Description:
  145. Creates a binding handle from a specified string binding or a default
  146. string binding with or without an endpoint.
  147. Arguments:
  148. pBinding - The string binding to use or NULL for the default.
  149. Return Value:
  150. binding handle
  151. --*/
  152. {
  153. if (!pBinding)
  154. {
  155. pBinding = _StringBinding;
  156. }
  157. if (pBinding)
  158. {
  159. if (_fDynamic)
  160. {
  161. // Create binding without an endpoint.
  162. return ::GetBinding(pBinding);
  163. }
  164. else
  165. {
  166. return GetBindingToOr(pBinding);
  167. }
  168. }
  169. return 0;
  170. }
  171. RPC_BINDING_HANDLE
  172. CMid::GetBinding()
  173. /*++
  174. Routine Description:
  175. Gets an RPC binding handle to the remote machine.
  176. Arguments:
  177. None
  178. Return Value:
  179. 0 - when no more binding are available.
  180. non-zero - A binding to the machine.
  181. --*/
  182. {
  183. if (IsLocal())
  184. {
  185. return(0);
  186. }
  187. //
  188. // if the Mid is already initialized, then just
  189. // return the binding.
  190. //
  191. if (_fInitialized)
  192. {
  193. return MakeBinding();
  194. }
  195. //
  196. // merge the strings
  197. //
  198. DUALSTRINGARRAY *pdsaValidStringBindings = 0;
  199. if (!_pdsaValidStringBindings)
  200. {
  201. // merge with valid protocols for this server
  202. gpClientLock->LockExclusive();
  203. if (!_pdsaValidStringBindings)
  204. {
  205. dsaProtocolMerge(&_dsa, &pdsaValidStringBindings);
  206. if (!pdsaValidStringBindings)
  207. {
  208. gpClientLock->UnlockExclusive();
  209. return 0;
  210. }
  211. ASSERT(pdsaValidStringBindings);
  212. _pdsaValidStringBindings = pdsaValidStringBindings;
  213. }
  214. gpClientLock->UnlockExclusive();
  215. }
  216. // Ping the server on all bindings in parallel to get
  217. // the correct binding for this server. This loop executes
  218. // twice to try the bindings w/o the endpoint.
  219. //
  220. ULONG ndx;
  221. BOOL bNoEndpoint = FALSE;
  222. RPC_BINDING_HANDLE hserver = NULL;
  223. { // scope the parallel ping object
  224. CObjexPPing ping(_pdsaValidStringBindings->aStringArray, this);
  225. RPC_STATUS status;
  226. for (;;)
  227. {
  228. status = ping.Ping();
  229. if ( RPC_S_UNKNOWN_IF == status )
  230. {
  231. if ( ! bNoEndpoint )
  232. {
  233. for ( unsigned int ProtseqIndex = 0; ProtseqIndex < ping.HandleCount(); ProtseqIndex++ )
  234. {
  235. RPC_BINDING_HANDLE tmpBinding;
  236. status = RpcBindingCopy( ping.Info(ProtseqIndex)->hRpc, &tmpBinding);
  237. if (status != RPC_S_OK)
  238. break;
  239. status = RpcBindingFree( &(ping.Info(ProtseqIndex)->hRpc));
  240. if (status != RPC_S_OK)
  241. {
  242. RpcBindingFree(&tmpBinding);
  243. break;
  244. }
  245. status = RpcBindingReset(tmpBinding);
  246. if (status != RPC_S_OK)
  247. {
  248. RpcBindingFree(&tmpBinding);
  249. break;
  250. }
  251. ping.Info(ProtseqIndex)->hRpc = tmpBinding;
  252. }
  253. bNoEndpoint = TRUE;
  254. continue;
  255. }
  256. }
  257. if (status == RPC_S_OK && bNoEndpoint)
  258. {
  259. _fDynamic = TRUE;
  260. }
  261. break;
  262. }
  263. if (status == RPC_S_OK)
  264. {
  265. hserver = ping.GetWinner()->hRpc;
  266. ping.GetWinner()->hRpc = NULL;
  267. if (!_StringBinding)
  268. {
  269. gpClientLock->LockExclusive();
  270. if (!_StringBinding)
  271. {
  272. _StringBinding = (WCHAR *) ping.GetWinner()->pvUserInfo;
  273. }
  274. gpClientLock->UnlockExclusive();
  275. }
  276. }
  277. ping.Reset();
  278. } // end scope for ping object
  279. //
  280. // the mid is initialized now
  281. //
  282. _fInitialized = TRUE;
  283. return hserver;
  284. }