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.

278 lines
6.8 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. // Tell the Diagnostics object that we are accessing it though COM not netsh
  30. //
  31. pDglogsCom->m_Diagnostics.SetInterface(COM_INTERFACE);
  32. // Tell the Diagnostics object to send status reports to the client
  33. //
  34. pDglogsCom->m_Diagnostics.RequestStatusReport(TRUE,pDglogsCom);
  35. // Execute the clients query
  36. //
  37. pDglogsCom->m_Diagnostics.ExecQuery();
  38. // Uniniatlize COM
  39. //
  40. CoUninitialize();
  41. }
  42. // do not know how to describe this (yet)
  43. //
  44. SetEvent(pDglogsCom->m_hThreadTerminated);
  45. // There are 0 local threads.
  46. //
  47. pDglogsCom->m_lThreadCount = 0;
  48. // The thread has completed its work. Thus the thread count is 0 again. (Only one thread at a time
  49. //
  50. InterlockedExchange(&g_lThreadCount,0);
  51. ExitThread(0);
  52. return 0;
  53. }
  54. /*++
  55. Routine Description
  56. Initialize the COM object and the Diagnostics object
  57. Arguments
  58. pbstrResult -- Not used
  59. Return Value
  60. HRESULT
  61. --*/
  62. STDMETHODIMP CDglogsCom::Initialize(BSTR *pbstrResult)
  63. {
  64. if( _Module.GetLockCount() > 1)
  65. {
  66. }
  67. return S_OK;
  68. }
  69. /*++
  70. Routine Description
  71. Process the clients request by creating a thread to collect the data,
  72. Arguments
  73. bstrCatagory -- List of the catagories to collect divided by semicollens i.e. "ieproxy;mail;news;adapter"
  74. bFlag -- The actions to perform i.e. PING, SHOW, CONNECT
  75. pbstrResult -- Stores the result as an XML string
  76. Return Value
  77. HRESULT
  78. --*/
  79. STDMETHODIMP CDglogsCom::ExecQuery(BSTR bstrCatagory, LONG bFlag, BSTR *pbstrResult)
  80. {
  81. HANDLE hThread;
  82. WCHAR szFilename[MAX_PATH+1];
  83. *pbstrResult = NULL;
  84. // For security reason we can not run inside of internet explorer. Otherwise
  85. // someone could create a web page using this active X component and collect
  86. // the clients info. If IE is renamed to something else other than explorer,exe
  87. // IE will not run Active X controls or scripts
  88. if( GetModuleFileName(NULL,szFilename,MAX_PATH) )
  89. {
  90. LPWSTR ExeName;
  91. LONG len = wcslen(szFilename) - wcslen(L"helpctr.exe");
  92. if( len <= 0 || _wcsicmp(&szFilename[len], L"helpctr.exe") != 0 )
  93. {
  94. // The name of process is not helpctr, refuse to run but do not tell the
  95. // user why.
  96. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  97. //return E_FAIL;
  98. return S_FALSE;
  99. }
  100. }
  101. else
  102. {
  103. // Unable to get process name, fail and abort. Do not provide rason for
  104. // failure.
  105. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  106. //return E_FAIL;
  107. return S_FALSE;
  108. }
  109. // Check if an other thread is already in this function
  110. //
  111. if( InterlockedCompareExchange(&g_lThreadCount,1,0) == 0 )
  112. {
  113. m_lThreadCount = 1;
  114. // The information is passed to the thread via gloabl parameters. In the near future it will be passed
  115. // as parameters.
  116. //
  117. m_Diagnostics.SetQuery((WCHAR *)bstrCatagory,bFlag);
  118. // In order to cancel the thread we set events. The worker thread checks to see if the main thread
  119. // has set the cancel event
  120. //
  121. m_hThreadTerminated = CreateEvent(NULL, TRUE, FALSE, NULL);
  122. m_hTerminateThread = CreateEvent(NULL, TRUE, FALSE, NULL);
  123. // Set the cancel option so the worker thread can be canceled at any time.
  124. //
  125. m_Diagnostics.SetCancelOption(m_hTerminateThread);
  126. // Create a worker thread to collect the information from WMI.
  127. //
  128. hThread = CreateThread(NULL, // Security Attributes
  129. 0, // Stack Size
  130. DiagnosticsThreadProc, // Start Proc
  131. this, // Thread Paramter
  132. 0, // Creation flags
  133. &m_dwThreadId // ID of thethread being created
  134. );
  135. if( hThread )
  136. {
  137. // We are done with the thread. Close it.
  138. //
  139. CloseHandle(hThread);
  140. *pbstrResult = SysAllocString(ids(IDS_PASSED));
  141. return S_OK;
  142. }
  143. else
  144. {
  145. // Could not create the thread. So the thread count is 0 again;
  146. //
  147. InterlockedExchange(&g_lThreadCount,0);
  148. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  149. return E_FAIL;
  150. }
  151. }
  152. *pbstrResult = SysAllocString(ids(IDS_FAILED));
  153. return S_FALSE;
  154. }
  155. /*++
  156. Routine Description
  157. Cancels the worker thread
  158. Arguments
  159. Return Value
  160. HRESULT
  161. --*/
  162. STDMETHODIMP CDglogsCom::StopQuery()
  163. {
  164. // Check if there is a worker thread.
  165. //
  166. if( m_lThreadCount )
  167. {
  168. // There is a worker thread for this instance. Set an event to tell it to stop processing
  169. //
  170. SetEvent(m_hTerminateThread);
  171. // If the worker thread is doing an RPC call send the quit message.
  172. // In theory this should cancel the RPC call
  173. //
  174. PostThreadMessage(m_dwThreadId, WM_QUIT, NULL, NULL);
  175. // Wait until it's terminated
  176. //
  177. if (WAIT_OBJECT_0 == WaitForSingleObject(m_hThreadTerminated, 10000))
  178. {
  179. ResetEvent(m_hThreadTerminated);
  180. }
  181. return S_OK;
  182. }
  183. return S_FALSE;
  184. }
  185. /*++
  186. Routine Description
  187. Inialize the COM object
  188. Arguments
  189. Return Value
  190. HRESULT
  191. --*/
  192. CDglogsCom::CDglogsCom()
  193. {
  194. if( m_Diagnostics.Initialize(COM_INTERFACE) == FALSE )
  195. {
  196. // TODO figure out what error code to return if Inialize fails
  197. //
  198. return;
  199. }
  200. if( _Module.GetLockCount() == 0)
  201. {
  202. g_lThreadCount = 0;
  203. }
  204. }
  205. /*++
  206. Routine Description
  207. Uninialize the COM object
  208. Arguments
  209. Return Value
  210. HRESULT
  211. --*/
  212. CDglogsCom::~CDglogsCom()
  213. {
  214. }