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.

336 lines
9.0 KiB

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