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.

548 lines
11 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. #include "precomp.h"
  3. #ifdef EXT_DEBUG
  4. #undef THIS_FILE
  5. static char THIS_FILE[] = __FILE__;
  6. #endif
  7. #include "ServiceThread.h"
  8. #include <process.h>
  9. #include "..\common\T_DataExtractor.h"
  10. #include <cominit.h>
  11. #include "util.h"
  12. const wchar_t* MMC_SNAPIN_MACHINE_NAME = L"MMC_SNAPIN_MACHINE_NAME";
  13. CLIPFORMAT WbemServiceThread::MACHINE_NAME = 0;
  14. // Allows user to manually leave critical section, checks if inside before leaving
  15. class CCheckedInCritSec
  16. {
  17. protected:
  18. CRITICAL_SECTION* m_pcs;
  19. BOOL m_fInside;
  20. public:
  21. CCheckedInCritSec(CRITICAL_SECTION* pcs) : m_pcs(pcs), m_fInside( FALSE )
  22. {
  23. EnterCriticalSection(m_pcs);
  24. m_fInside = TRUE;
  25. }
  26. ~CCheckedInCritSec()
  27. {
  28. Leave();
  29. }
  30. void Enter( void )
  31. {
  32. if ( !m_fInside )
  33. {
  34. EnterCriticalSection(m_pcs);
  35. m_fInside = TRUE;
  36. }
  37. }
  38. void Leave( void )
  39. {
  40. if ( m_fInside )
  41. {
  42. m_fInside = FALSE;
  43. LeaveCriticalSection(m_pcs);
  44. }
  45. }
  46. BOOL IsEntered( void )
  47. { return m_fInside; }
  48. };
  49. //--------------------------
  50. WbemServiceThread::WbemServiceThread():
  51. m_cRef(1),
  52. m_pStream(NULL)
  53. {
  54. m_hr = 0;
  55. m_status = notStarted;
  56. m_machineName = L"AGAINWITHTEKLINGONS";
  57. MACHINE_NAME = (CLIPFORMAT) RegisterClipboardFormat(_T("MMC_SNAPIN_MACHINE_NAME"));
  58. m_credentials = 0;
  59. m_doWork = CreateEvent(NULL, FALSE, FALSE, NULL);
  60. m_ptrReady = CreateEvent(NULL, FALSE, FALSE, NULL);
  61. m_threadCmd = false;
  62. m_hThread = 0;
  63. InitializeCriticalSection(&notifyLock);
  64. }
  65. //----------------------------------------------------------------
  66. WbemServiceThread::~WbemServiceThread()
  67. {
  68. m_hr = 0;
  69. m_status = notStarted;
  70. m_notify.RemoveAll();
  71. if(m_hThread)
  72. {
  73. m_threadCmd = CT_EXIT;
  74. SetEvent(m_doWork);
  75. WaitForSingleObject((HANDLE)m_hThread, 5000);
  76. }
  77. if(m_doWork)
  78. {
  79. CloseHandle(m_doWork);
  80. m_doWork = 0;
  81. }
  82. if(m_ptrReady)
  83. {
  84. CloseHandle(m_ptrReady);
  85. m_ptrReady = 0;
  86. }
  87. if (m_credentials)
  88. {
  89. WbemFreeAuthIdentity(m_credentials->authIdent);
  90. m_credentials->authIdent = 0;
  91. };
  92. DeleteCriticalSection(&notifyLock);
  93. if (m_pStream)
  94. m_pStream->Release();
  95. }
  96. //----------------------------------------------------------------
  97. typedef struct
  98. {
  99. wchar_t t[MAXCOMPUTER_NAME + 1];
  100. } test;
  101. void WbemServiceThread::MachineName(IDataObject *_pDataObject, bstr_t *name)
  102. {
  103. HGLOBAL hMem = GlobalAlloc(GMEM_SHARE,sizeof(test));
  104. wchar_t *pRet = NULL;
  105. HRESULT hr = 0;
  106. if(hMem != NULL)
  107. {
  108. STGMEDIUM stgmedium = { TYMED_HGLOBAL, (HBITMAP) hMem};
  109. FORMATETC formatetc = { MACHINE_NAME,
  110. NULL,
  111. DVASPECT_CONTENT,
  112. -1,
  113. TYMED_HGLOBAL };
  114. if((hr = _pDataObject->GetDataHere(&formatetc, &stgmedium)) == S_OK )
  115. {
  116. *name = bstr_t((wchar_t *)hMem);
  117. }
  118. GlobalFree(hMem);
  119. }
  120. }
  121. //----------------------------------------------------------
  122. HRESULT WbemServiceThread::EnsureThread(void)
  123. {
  124. HRESULT retval = S_OK;
  125. if(m_hThread == 0)
  126. {
  127. // let the thread do the connect. The CWbemService class will
  128. // handle marshalling as its used by other threads.
  129. if((m_hThread = _beginthread(WbemServiceConnectThread, 0,
  130. (LPVOID)this)) == -1)
  131. {
  132. m_status = threadError;
  133. retval = E_FAIL;
  134. }
  135. }
  136. return retval;
  137. }
  138. //----------------------------------------------------------
  139. HRESULT WbemServiceThread::Connect(bstr_t machineName,
  140. bstr_t ns,
  141. bool threaded /* = true */,
  142. LOGIN_CREDENTIALS *credentials, HWND notifiedWnd)
  143. {
  144. if(ns.length() == 0)
  145. {
  146. ns = _T(""); //this allocates...
  147. if (&ns == NULL)
  148. return E_FAIL;
  149. }
  150. m_nameSpace = ns;
  151. if((m_credentials != credentials) &&
  152. m_credentials && m_credentials->authIdent)
  153. {
  154. WbemFreeAuthIdentity(m_credentials->authIdent);
  155. m_credentials->authIdent = 0;
  156. }
  157. if(machineName.length() > 0)
  158. {
  159. m_credentials = credentials;
  160. }
  161. else
  162. {
  163. m_credentials = 0;
  164. m_WbemServices.m_authIdent = 0;
  165. m_realServices.m_authIdent = 0;
  166. }
  167. m_hr = 0;
  168. if(credentials)
  169. {
  170. m_machineName = _T("AGAINWITHTEKLINGONS"); // force a reconnect to
  171. // the same machine.
  172. }
  173. // put the name together.
  174. bstr_t newMachine;
  175. // if reconnecting to another machine...
  176. //if(machineName != m_machineName)
  177. {
  178. // disconnect from the old machine.
  179. DisconnectServer();
  180. m_machineName = machineName;
  181. int x;
  182. // if machine is whacked already...
  183. if(_tcsncmp(m_machineName, _T("\\"), 1) == 0)
  184. {
  185. // use it.
  186. m_nameSpace = m_machineName;
  187. if(ns.length() > 0)
  188. {
  189. if(((LPCTSTR)ns)[0] != _T('\\')) // namespace is whacked.
  190. {
  191. m_nameSpace += _T("\\");
  192. }
  193. }
  194. m_nameSpace += ns;
  195. }
  196. else if(((x = m_machineName.length()) > 0))
  197. {
  198. // whack it myself.
  199. m_nameSpace = "\\\\";
  200. m_nameSpace += m_machineName;
  201. if(((LPCTSTR)ns)[0] != _T('\\')) // namespace is whacked.
  202. {
  203. m_nameSpace += _T("\\");
  204. }
  205. m_nameSpace += ns;
  206. }
  207. EnsureThread();
  208. NotifyWhenDone(notifiedWnd);
  209. m_threadCmd = CT_CONNECT;
  210. SetEvent(m_doWork);
  211. }
  212. // else
  213. // {
  214. // // reconnecting to the same machine-- lie!!
  215. // return WBEM_S_SAME;
  216. // }
  217. return E_FAIL;
  218. }
  219. //----------------------------------------------------------
  220. // TODO: merge the Connects()
  221. bool WbemServiceThread::Connect(IDataObject *_pDataObject, HWND hWnd )
  222. {
  223. m_nameSpace = "root\\cimv2";
  224. // put the name together.
  225. bstr_t newMachine;
  226. MachineName(_pDataObject, &newMachine);
  227. if(!newMachine) return false;
  228. // if reconnecting to another machine...
  229. if(newMachine != m_machineName)
  230. {
  231. // disconnect from the old machine.
  232. DisconnectServer();
  233. m_machineName = newMachine;
  234. int x;
  235. // if its whacked already...
  236. if(_tcsncmp((LPCTSTR)m_machineName, _T("\\"), 1) == 0)
  237. {
  238. // use it.
  239. m_nameSpace = m_machineName;
  240. m_nameSpace += "\\root\\cimv2";
  241. }
  242. else if(((x = m_machineName.length()) > 0))
  243. {
  244. // whack it myself.
  245. m_nameSpace = "\\\\";
  246. m_nameSpace += m_machineName;
  247. m_nameSpace += "\\root\\cimv2";
  248. }
  249. EnsureThread();
  250. NotifyWhenDone(hWnd);
  251. m_threadCmd = CT_CONNECT;
  252. SetEvent(m_doWork);
  253. }
  254. else
  255. {
  256. // reconnecting to the same machine-- lie!!
  257. return true;
  258. }
  259. return false;
  260. }
  261. //----------------------------------------------------------
  262. // Returns true if a msg will be sent.
  263. // Returns false if its already over.
  264. bool WbemServiceThread::NotifyWhenDone(HWND dlg)
  265. {
  266. CCheckedInCritSec autoLock(&notifyLock);
  267. for (int i=0;i<m_notify.GetSize();i++)
  268. {
  269. if (dlg==m_notify[i]) { return false;}
  270. }
  271. switch(m_status)
  272. {
  273. case notStarted:
  274. case locating:
  275. case connecting:
  276. m_notify.Add(dlg);
  277. return true;
  278. case error:
  279. case ready:
  280. case cancelled:
  281. return false;
  282. }; // endswitch
  283. return false;
  284. }
  285. //------------------------------------------------
  286. bool WbemServiceThread::LocalConnection(void)
  287. {
  288. return (m_machineName.length() == 0);
  289. }
  290. //------------------------------------------------
  291. void WbemServiceThread::Cancel(void)
  292. {
  293. m_status = cancelled;
  294. m_hr = WBEM_S_OPERATION_CANCELLED;
  295. Notify(0);
  296. m_machineName = L"AGAINWITHTEKLINGONS";
  297. }
  298. //------------------------------------------------
  299. void WbemServiceThread::DisconnectServer(void)
  300. {
  301. m_status = notStarted;
  302. m_notify.RemoveAll();
  303. m_machineName = L"AGAINWITHTEKLINGONS";
  304. m_WbemServices.DisconnectServer();
  305. }
  306. //------------------------------------------------
  307. void WbemServiceThread::Notify(IWbemServices *service)
  308. {
  309. CCheckedInCritSec autoLock(&notifyLock);
  310. HWND hwnd;
  311. for(int i = 0; i < m_notify.GetSize(); i++)
  312. {
  313. hwnd = m_notify[i];
  314. if(hwnd)
  315. {
  316. IStream* pStream = 0;
  317. autoLock.Leave();
  318. if (service!=0) CoMarshalInterThreadInterfaceInStream(IID_IWbemServices,service, &pStream);
  319. PostMessage(hwnd, WM_ASYNC_CIMOM_CONNECTED, 0, (LPARAM)pStream);
  320. autoLock.Enter();
  321. }
  322. }
  323. m_notify.RemoveAll();
  324. }
  325. //------------------------------------------------
  326. void WbemServiceThread::NotifyError(void)
  327. {
  328. IWbemServices * nullPtr = 0;
  329. Notify(nullPtr);
  330. }
  331. //-----------------------------------------------------------------
  332. HRESULT WbemServiceThread::ConnectNow(bool real)
  333. {
  334. HRESULT retval = E_FAIL;
  335. m_status = connecting;
  336. ATLTRACE(_T("ConnectServer() starting\n"));
  337. try
  338. {
  339. if(real)
  340. {
  341. m_hr = m_realServices.ConnectServer(m_nameSpace, m_credentials);
  342. }
  343. else
  344. {
  345. m_hr = m_WbemServices.ConnectServer(m_nameSpace, m_credentials);
  346. }
  347. }
  348. catch(CWbemException &e)
  349. {
  350. m_status = error;
  351. m_hr = e.GetErrorCode();
  352. }
  353. if(SUCCEEDED(m_hr))
  354. {
  355. if(m_status == cancelled)
  356. {
  357. }
  358. else
  359. {
  360. m_status = ready;
  361. retval = S_OK;
  362. }
  363. ATLTRACE(_T("ConnectServer() done\n"));
  364. }
  365. else
  366. {
  367. m_status = error;
  368. ATLTRACE(_T("ConnectServer() failed\n"));
  369. }
  370. return retval;
  371. }
  372. //-----------------------------------------------------------------
  373. void WbemServiceThread::SendPtr(HWND hwnd)
  374. {
  375. EnsureThread();
  376. m_hWndGetPtr = hwnd;
  377. m_threadCmd = CT_SEND_PTR;
  378. SetEvent(m_doWork);
  379. }
  380. //-----------------------------------------------------
  381. void __cdecl WbemServiceConnectThread(LPVOID lpParameter)
  382. {
  383. WbemServiceThread *me = (WbemServiceThread *)lpParameter;
  384. me->AddRef();
  385. IStream *pStream = 0;
  386. HRESULT hr = S_OK;
  387. HRESULT retval = E_FAIL;
  388. CWbemServices pServices;
  389. CoInitialize(NULL);
  390. MSG msg;
  391. while(true)
  392. {
  393. DWORD res = MsgWaitForMultipleObjects (1,&me->m_doWork,
  394. FALSE, -1, QS_ALLINPUT);
  395. if (res == WAIT_OBJECT_0 + 1)
  396. {
  397. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  398. {
  399. DispatchMessage(&msg);
  400. }
  401. continue;
  402. }
  403. switch(me->m_threadCmd)
  404. {
  405. case CT_CONNECT:
  406. pStream = 0;
  407. /****************** VINOTH *****************************/
  408. me->m_status = WbemServiceThread::connecting;
  409. try
  410. {
  411. me->m_hr = pServices.ConnectServer(me->m_nameSpace, me->m_credentials);
  412. }
  413. catch(CWbemException &e)
  414. {
  415. me->m_status = WbemServiceThread::error;
  416. me->m_hr = e.GetErrorCode();
  417. }
  418. if(SUCCEEDED(me->m_hr))
  419. {
  420. if(me->m_status == WbemServiceThread::cancelled)
  421. {
  422. }
  423. else
  424. {
  425. me->m_status = WbemServiceThread::ready;
  426. retval = S_OK;
  427. }
  428. }
  429. else
  430. {
  431. me->m_status = WbemServiceThread::error;
  432. }
  433. /*************** END VINOTH ************************/
  434. if(SUCCEEDED(me->m_hr))
  435. {
  436. IWbemServices *service = 0;
  437. pServices.GetServices(&service);
  438. me->Notify(service);
  439. service->Release();
  440. }
  441. else
  442. {
  443. me->NotifyError();
  444. }
  445. break;
  446. case CT_SEND_PTR:
  447. if((bool)pServices)
  448. {
  449. IWbemServices *service = 0;
  450. pServices.GetServices(&service);
  451. if(me->m_threadCmd == CT_SEND_PTR)
  452. {
  453. hr = CoMarshalInterThreadInterfaceInStream(IID_IWbemServices,
  454. service, &pStream);
  455. PostMessage(me->m_hWndGetPtr,
  456. WM_ASYNC_CIMOM_CONNECTED,
  457. 0, (LPARAM)pStream);
  458. }
  459. service->Release();
  460. }
  461. break;
  462. case CT_EXIT:
  463. pServices = (IWbemServices *)NULL;
  464. break;
  465. } //endswitch
  466. } //endwhile
  467. pServices = (IUnknown *)NULL;
  468. me->Release();
  469. CoUninitialize();
  470. }