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.

338 lines
8.0 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. sharesdo.cpp
  7. implement classes for sharing SdoServer among property pages for different users and snapins
  8. FILE HISTORY:
  9. */
  10. //////////////////////////////////////////////////////////////////////
  11. #include "stdafx.h"
  12. #include <rtutils.h>
  13. #include "rasdial.h"
  14. #include "sharesdo.h"
  15. // the server pool pointer used to share SdoServer among pages and snapins
  16. CSdoServerPool* g_pSdoServerPool;
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[]=__FILE__;
  20. #define new DEBUG_NEW
  21. #endif
  22. // DO SDO Attach -- real
  23. HRESULT ConnectToSdoServer(BSTR machine, BSTR user, BSTR passwd,ISdoMachine** ppServer)
  24. {
  25. ASSERT(ppServer);
  26. if(!ppServer) return E_INVALIDARG;
  27. else
  28. *ppServer = NULL;
  29. HRESULT hr = S_OK;
  30. // connect to the new one
  31. TracePrintf(g_dwTraceHandle,_T("CoCreateInstance SdoServer"));
  32. CHECK_HR(hr = CoCreateInstance( CLSID_SdoMachine,
  33. NULL,
  34. CLSCTX_INPROC_SERVER,
  35. IID_ISdoMachine,
  36. (void**)ppServer));
  37. TracePrintf(g_dwTraceHandle,_T(" hr = %8x\r\n"), hr);
  38. ASSERT(*ppServer);
  39. TracePrintf(g_dwTraceHandle, _T("SdoServer::Attach(%s, %s, %s);"), machine, user, passwd);
  40. CHECK_HR(hr = (*ppServer)->Attach(machine));
  41. TracePrintf(g_dwTraceHandle,_T(" hr = %8x\r\n"), hr);
  42. L_ERR:
  43. if(FAILED(hr) && *ppServer)
  44. {
  45. (*ppServer)->Release();
  46. *ppServer = NULL;
  47. }
  48. return hr;
  49. }
  50. // When using Single connection, get the marshaled interface from the stream
  51. HRESULT GetSharedSdoServer(LPCTSTR machine, LPCTSTR user, LPCTSTR passwd, bool* pbConnect, CMarshalSdoServer* pServer)
  52. {
  53. static CCriticalSection cs;
  54. HRESULT hr = S_OK;
  55. if(cs.Lock()) // locked
  56. {
  57. if(NULL == g_pSdoServerPool)
  58. {
  59. try{
  60. g_pSdoServerPool = new CSdoServerPool;
  61. }catch(CMemoryException&)
  62. {
  63. hr = E_OUTOFMEMORY;
  64. }
  65. }
  66. cs.Unlock();
  67. }
  68. else
  69. {
  70. TracePrintf(g_dwTraceHandle,_T(" GetSharedSdoServer, CS lock failed"));
  71. return E_FAIL;
  72. }
  73. if(FAILED(hr))
  74. return hr;
  75. return g_pSdoServerPool->GetMarshalServer(machine, user, passwd, pbConnect, pServer);
  76. }
  77. //======================================================
  78. // class CSharedSdoServerImp
  79. // implementation class of shared server
  80. CSharedSdoServerImp::CSharedSdoServerImp(LPCTSTR machine, LPCTSTR user, LPCTSTR passwd)
  81. : strMachine(machine), strUser(user), strPasswd(passwd), bConnected(false)
  82. {};
  83. // to make this class element of collection, provide following member functions
  84. bool CSharedSdoServerImp::IsFor(LPCTSTR machine, LPCTSTR user, LPCTSTR passwd) const
  85. {
  86. // Compare order, ServerName, UserName, Passwd, and RetriveType
  87. CString strM(machine);
  88. CString strU(user);
  89. CString strP(passwd);
  90. return (
  91. strMachine.CompareNoCase(strM) == 0 &&
  92. strUser.Compare(strU) == 0 &&
  93. strPasswd.Compare(strP) == 0
  94. );
  95. };
  96. // CoCreate SdoServer object
  97. HRESULT CSharedSdoServerImp::CreateServer()
  98. {
  99. // cannot create twice!
  100. ASSERT(!(ISdoMachine*)spServer);
  101. if((ISdoMachine*)spServer) return S_OK;
  102. HRESULT hr = S_OK;
  103. // connect to the new one
  104. TracePrintf(g_dwTraceHandle,_T("CoCreateInstance SdoServer"));
  105. hr = CoCreateInstance( CLSID_SdoMachine,
  106. NULL,
  107. CLSCTX_INPROC_SERVER,
  108. IID_ISdoMachine,
  109. (void**)&spServer);
  110. TracePrintf(g_dwTraceHandle,_T(" hr = %8x\r\n"), hr);
  111. threadId = ::GetCurrentThreadId();
  112. return hr;
  113. };
  114. // get marshal stream, can specify, if immediate connection is required.
  115. HRESULT CSharedSdoServerImp::GetMarshalStream(LPSTREAM *ppStream, bool* pbConnect /* both input and output */)
  116. {
  117. ASSERT(ppStream);
  118. DWORD tid = ::GetCurrentThreadId();
  119. if (tid != threadId)
  120. return E_FAIL; // make sure the interface should be marshaled from the same thread
  121. HRESULT hr = S_OK;
  122. cs.Lock();
  123. if(pbConnect)
  124. {
  125. if(*pbConnect && !bConnected)
  126. {
  127. *pbConnect = false;
  128. CHECK_HR(hr = Connect(NULL));
  129. *pbConnect = true;
  130. }
  131. else
  132. {
  133. *pbConnect = bConnected;
  134. }
  135. }
  136. // Marshal the interface
  137. CHECK_HR(hr = CoMarshalInterThreadInterfaceInStream(IID_ISdoMachine, (ISdoMachine*)spServer, ppStream));
  138. L_ERR:
  139. cs.Unlock();
  140. return hr;
  141. };
  142. // Connect the server to the a machine
  143. HRESULT CSharedSdoServerImp::Connect(ISdoMachine* pServer)
  144. // pServer, marshaled pointer, passed in from a different thread ( than the spServer in the object)
  145. {
  146. cs.Lock();
  147. HRESULT hr = S_OK;
  148. DWORD tid = ::GetCurrentThreadId();
  149. USES_CONVERSION;
  150. if(!bConnected)
  151. {
  152. ASSERT((ISdoMachine*)spServer);
  153. BSTR bstrM = NULL;
  154. BSTR bstrU = NULL;
  155. BSTR bstrP = NULL;
  156. if(!strMachine.IsEmpty())
  157. bstrM = T2BSTR((LPTSTR)(LPCTSTR)strMachine);
  158. if(!strUser.IsEmpty())
  159. bstrM = T2BSTR((LPTSTR)(LPCTSTR)strUser);
  160. if(!strPasswd.IsEmpty())
  161. bstrP = T2BSTR((LPTSTR)(LPCTSTR)strPasswd);
  162. TracePrintf(g_dwTraceHandle, _T("SdoServer::Connect(%s, %s, %s );"), bstrM, bstrU, bstrP);
  163. if(!pServer)
  164. {
  165. // this function should be called within the same thread
  166. // if the request if from a different thread, then this should NOT be NULL
  167. ASSERT(tid == threadId);
  168. pServer = (ISdoMachine*)spServer;
  169. }
  170. hr = pServer->Attach(bstrM);
  171. TracePrintf(g_dwTraceHandle,_T(" hr = %8x\r\n"), hr);
  172. bConnected = (hr == S_OK);
  173. SysFreeString(bstrM);
  174. SysFreeString(bstrU);
  175. SysFreeString(bstrP);
  176. }
  177. cs.Unlock();
  178. return hr;
  179. };
  180. HRESULT CSharedSdoServerImp::GetServerNReleaseStream(LPSTREAM pStream, ISdoMachine** ppServer)
  181. {
  182. #ifdef _DEBUG
  183. DWORD __tid = ::GetCurrentThreadId();
  184. #endif
  185. return CoGetInterfaceAndReleaseStream(pStream, IID_ISdoMachine, (LPVOID*) ppServer);
  186. };
  187. // if connection is needed, should call the connec of CSharedSdoServer, rather than ISdoServer::Connect
  188. HRESULT CMarshalSdoServer::GetServer(ISdoMachine** ppServer)
  189. {
  190. HRESULT hr = S_OK;
  191. if(!(ISdoMachine*)spServer)
  192. {
  193. if((IStream*)spStm)
  194. {
  195. CHECK_HR(hr = CSharedSdoServerImp::GetServerNReleaseStream((IStream*)spStm, (ISdoMachine**)&spServer));
  196. }
  197. spStm.p = NULL; // need to manually clean this, since the above API already Release the COM interface
  198. }
  199. else
  200. CHECK_HR(hr = E_FAIL);
  201. if((ISdoMachine*)spServer)
  202. {
  203. *ppServer = (ISdoMachine*)spServer;
  204. (*ppServer)->AddRef();
  205. }
  206. L_ERR:
  207. return hr; // not valid to call at this point
  208. };
  209. // make SDO connect when / if NOT already done so. Note: multiple thread safe
  210. HRESULT CMarshalSdoServer::Connect()
  211. {
  212. ASSERT(pImp); // should not happen
  213. return pImp->Connect(spServer);
  214. };
  215. void CMarshalSdoServer::Release()
  216. {
  217. pImp = NULL;
  218. spServer.Release();
  219. spStm.Release();
  220. };
  221. CMarshalSdoServer::CMarshalSdoServer(): pImp(NULL)
  222. {};
  223. // estiblish an entry in the pool, if it's new
  224. // get marshaServer object from the thread pool
  225. HRESULT CSdoServerPool::GetMarshalServer(LPCTSTR machineName, LPCTSTR userName, LPCTSTR passwd, bool* pbConnect, CMarshalSdoServer* pServer)
  226. {
  227. ASSERT(pServer);
  228. CSharedSdoServerImp* pImp = NULL;
  229. HRESULT hr = S_OK;
  230. std::list<CSharedSdoServerImp*>::iterator i;
  231. // search if the server is already exist
  232. cs.Lock();
  233. for(i = listServers.begin(); i != listServers.end(); i++)
  234. {
  235. if((*i)->IsFor( machineName, userName, passwd))
  236. {
  237. pImp = (*i);
  238. break;
  239. }
  240. }
  241. // if not, then create one
  242. if(!pImp)
  243. {
  244. try{
  245. pImp = new CSharedSdoServerImp( machineName, userName, passwd);
  246. }catch(...)
  247. {
  248. CHECK_HR(hr = E_OUTOFMEMORY);
  249. }
  250. ASSERT(pImp);
  251. CHECK_HR(hr = pImp->CreateServer());
  252. listServers.push_front(pImp);
  253. }
  254. // marshal it. bConnect will be filled
  255. pServer->Release();
  256. {
  257. CComPtr<IStream> spStm;
  258. CHECK_HR(hr = pImp->GetMarshalStream(&spStm, pbConnect));
  259. // fill the information to the provided buffer
  260. pServer->SetInfo((IStream*)spStm, pImp);
  261. }
  262. L_ERR:
  263. cs.Unlock();
  264. return hr;
  265. };
  266. // clean the POOL
  267. CSdoServerPool::~CSdoServerPool()
  268. {
  269. #ifdef _DEBUG
  270. DWORD __tid = ::GetCurrentThreadId();
  271. #endif
  272. std::list<CSharedSdoServerImp*>::iterator i;
  273. for(i = listServers.begin(); i != listServers.end(); i++)
  274. {
  275. delete (*i);
  276. }
  277. listServers.erase(listServers.begin(), listServers.end());
  278. };