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.

321 lines
8.6 KiB

  1. // DglogsCom.cpp : Implementation of CDglogsCom
  2. #include "stdafx.h"
  3. #include "Dglogs.h"
  4. #include "DglogsCom.h"
  5. #include "Commdlg.h"
  6. // Counts the total number of worker threads running.
  7. //
  8. LONG g_lThreadCount;
  9. /*++
  10. Routine Description
  11. Collects the diagnostics information that the client requested. A worker thread is spawened so
  12. the UI (webpage) does not have to wait for the diagnostics to complete. If the UI waits
  13. the web page freezes.
  14. Arguments
  15. lpParameter -- Pointer to the DglogsCom Object
  16. Return Value
  17. error code
  18. --*/
  19. DWORD WINAPI DiagnosticsThreadProc(LPVOID lpParameter)
  20. {
  21. BSTR bstrResult;
  22. CDglogsCom *pDglogsCom = (CDglogsCom *)lpParameter;
  23. HRESULT hr;
  24. // Every thread in COM needs to initialize COM in order to use COM
  25. //
  26. hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
  27. if( SUCCEEDED(hr) )
  28. {
  29. // Each thread needs to reference the class
  30. //
  31. pDglogsCom->AddRef();
  32. // Tell the Diagnostics object that we are accessing it though COM not netsh
  33. //
  34. pDglogsCom->m_Diagnostics.SetInterface(COM_INTERFACE);
  35. // Tell the Diagnostics object to send status reports to the client
  36. //
  37. pDglogsCom->m_Diagnostics.RequestStatusReport(TRUE,pDglogsCom);
  38. // Execute the clients query
  39. //
  40. pDglogsCom->m_Diagnostics.ExecQuery();
  41. // We are done referencing the Class, dec the ref count
  42. //
  43. pDglogsCom->Release();
  44. // Uniniatlize COM
  45. //
  46. CoUninitialize();
  47. }
  48. else
  49. {
  50. // We no longer need the class
  51. pDglogsCom->Release();
  52. }
  53. // Tell the main thread that the worker thread has completed
  54. //
  55. SetEvent(pDglogsCom->m_hThreadTerminated);
  56. // There are 0 local threads. (Only one thread can be in here at any given time)
  57. //
  58. pDglogsCom->m_lThreadCount = 0;
  59. // The thread has completed its work. Thus the thread count is 0 again. (Only one thread at a time)
  60. //
  61. InterlockedExchange(&g_lThreadCount,0);
  62. ExitThread(0);
  63. return 0;
  64. }
  65. /*++
  66. Routine Description
  67. Initialize the COM object and the Diagnostics object
  68. Arguments
  69. pbstrResult -- Not used
  70. Return Value
  71. HRESULT
  72. --*/
  73. STDMETHODIMP CDglogsCom::Initialize(BSTR *pbstrResult)
  74. {
  75. if( _Module.GetLockCount() > 1)
  76. {
  77. }
  78. return S_OK;
  79. }
  80. /*++
  81. Routine Description
  82. Process the clients request by creating a thread to collect the data,
  83. Arguments
  84. bstrCatagory -- List of the catagories to collect divided by semicollens i.e. "ieproxy;mail;news;adapter"
  85. bFlag -- The actions to perform i.e. PING, SHOW, CONNECT
  86. pbstrResult -- Stores the result as an XML string
  87. Return Value
  88. HRESULT
  89. --*/
  90. STDMETHODIMP CDglogsCom::ExecQuery(BSTR bstrCatagory, LONG bFlag, BSTR *pbstrResult)
  91. {
  92. HANDLE hThread;
  93. WCHAR szFilename[MAX_PATH+1];
  94. *pbstrResult = NULL;
  95. // For security reason we can not run inside of internet explorer. Otherwise
  96. // someone could create a web page using this active X component and collect
  97. // the clients info. If IE is renamed to something else other than explorer,exe
  98. // IE will not run Active X controls or scripts
  99. if( GetModuleFileName(NULL,szFilename,MAX_PATH) )
  100. {
  101. LPWSTR ExeName;
  102. LONG len = wcslen(szFilename) - wcslen(L"helpctr.exe");
  103. if( len <= 0 || _wcsicmp(&szFilename[len], L"helpctr.exe") != 0 )
  104. {
  105. // The name of process is not helpctr, refuse to run but do not tell the
  106. // user why.
  107. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  108. //return E_FAIL;
  109. return S_FALSE;
  110. }
  111. }
  112. else
  113. {
  114. // Unable to get process name, fail and abort. Do not provide rason for
  115. // failure.
  116. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  117. return S_FALSE;
  118. }
  119. // Check if an other thread is already in this function
  120. //
  121. if( InterlockedCompareExchange(&g_lThreadCount,1,0) == 0 )
  122. {
  123. // Need to make sure that CDiagnostics Initialized correctly in the CDglogsCom constructor
  124. if( !m_Diagnostics.m_bDiagInit )
  125. {
  126. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  127. InterlockedExchange(&g_lThreadCount,0);
  128. return S_FALSE;
  129. }
  130. m_lThreadCount = 1;
  131. // The information is passed to the thread via gloabl parameters. In the near future it will be passed
  132. // as parameters.
  133. //
  134. m_Diagnostics.SetQuery((WCHAR *)bstrCatagory,bFlag);
  135. // In order to cancel the thread we set events. The worker thread checks to see if the main thread
  136. // has set the cancel event
  137. //
  138. m_hThreadTerminated = CreateEvent(NULL, TRUE, FALSE, NULL);
  139. m_hTerminateThread = CreateEvent(NULL, TRUE, FALSE, NULL);
  140. // Set the cancel option so the worker thread can be canceled at any time.
  141. //
  142. m_Diagnostics.SetCancelOption(m_hTerminateThread);
  143. // Add the ref count to the thread so the class does not dissappear underneath it
  144. AddRef();
  145. // Create a worker thread to collect the information from WMI.
  146. //
  147. hThread = CreateThread(NULL, // Security Attributes
  148. 0, // Stack Size
  149. DiagnosticsThreadProc, // Start Proc
  150. this, // Thread Paramter
  151. 0, // Creation flags
  152. &m_dwThreadId // ID of thethread being created
  153. );
  154. if( hThread )
  155. {
  156. // We are done with the thread. Close it.
  157. //
  158. CloseHandle(hThread);
  159. *pbstrResult = SysAllocString(ids(IDS_PASSED));
  160. // Do not do a release cause the thread succeeded and is referencing the class now
  161. return S_OK;
  162. }
  163. else
  164. {
  165. // Could not create the thread. So the thread count is 0 again;
  166. //
  167. InterlockedExchange(&g_lThreadCount,0);
  168. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  169. // The thread failed to be created not referencing the class.
  170. Release();
  171. return E_FAIL;
  172. }
  173. }
  174. // Another instance is already running. We only allow one instance at a time.
  175. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  176. return S_FALSE;
  177. }
  178. /*++
  179. Routine Description
  180. Cancels the worker thread
  181. Arguments
  182. Return Value
  183. HRESULT
  184. --*/
  185. STDMETHODIMP CDglogsCom::StopQuery()
  186. {
  187. // Check if there is a worker thread.
  188. //
  189. if( m_lThreadCount )
  190. {
  191. // There is a worker thread for this instance. Set an event to tell it to stop processing
  192. //
  193. SetEvent(m_hTerminateThread);
  194. // If the worker thread is doing an RPC call send the quit message.
  195. // In theory this should cancel the RPC call
  196. //
  197. PostThreadMessage(m_dwThreadId, WM_QUIT, NULL, NULL);
  198. // Wait until it's terminated
  199. //
  200. if (WAIT_OBJECT_0 == WaitForSingleObject(m_hThreadTerminated, 10000))
  201. {
  202. ResetEvent(m_hThreadTerminated);
  203. }
  204. return S_OK;
  205. }
  206. return S_FALSE;
  207. }
  208. /*++
  209. Routine Description
  210. Inialize the COM object
  211. Arguments
  212. Return Value
  213. HRESULT
  214. --*/
  215. CDglogsCom::CDglogsCom()
  216. {
  217. if( m_Diagnostics.Initialize(COM_INTERFACE) == FALSE )
  218. {
  219. // If m_Diagnostics.Initialize fails it sets m_bDiagInit to false. Need to check if this
  220. // value is TRUE inorder to execute anyfunctions in CDiagnostics
  221. return;
  222. }
  223. if( _Module.GetLockCount() == 0)
  224. {
  225. // Reset globals only for the first instance of the object
  226. //
  227. g_lThreadCount = 0;
  228. }
  229. }
  230. /*++
  231. Routine Description
  232. Uninialize the COM object
  233. Arguments
  234. Return Value
  235. HRESULT
  236. --*/
  237. CDglogsCom::~CDglogsCom()
  238. {
  239. if( m_hThreadTerminated )
  240. {
  241. CloseHandle(m_hThreadTerminated);
  242. m_hThreadTerminated = NULL;
  243. }
  244. if( m_hTerminateThread )
  245. {
  246. CloseHandle(m_hTerminateThread);
  247. m_hTerminateThread = NULL;
  248. }
  249. }