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.

592 lines
13 KiB

  1. /*++
  2. Copyright (C) 1996-2000 Microsoft Corporation
  3. Module Name:
  4. logfiles.cpp
  5. Abstract:
  6. Implementation of the ILogFiles interface
  7. --*/
  8. #include "polyline.h"
  9. #include "unkhlpr.h"
  10. #include "unihelpr.h"
  11. #include "smonmsg.h"
  12. #include "logsrc.h"
  13. #include "logfiles.h"
  14. extern ITypeLib *g_pITypeLib;
  15. //Standard IUnknown implementation for contained interface
  16. IMPLEMENT_CONTAINED_CONSTRUCTOR(CPolyline, CImpILogFiles)
  17. IMPLEMENT_CONTAINED_DESTRUCTOR(CImpILogFiles)
  18. IMPLEMENT_CONTAINED_ADDREF(CImpILogFiles)
  19. IMPLEMENT_CONTAINED_RELEASE(CImpILogFiles)
  20. STDMETHODIMP
  21. CImpILogFiles::QueryInterface (
  22. IN REFIID riid,
  23. OUT PPVOID ppv
  24. )
  25. {
  26. HRESULT hr = E_POINTER;
  27. if ( NULL != ppv ) {
  28. *ppv=NULL;
  29. if (!(IID_IUnknown == riid || IID_ILogFiles == riid)) {
  30. hr = E_NOINTERFACE;
  31. } else {
  32. *ppv=(LPVOID)this;
  33. ((LPUNKNOWN)*ppv)->AddRef();
  34. hr = NOERROR;
  35. }
  36. }
  37. return hr;
  38. }
  39. STDMETHODIMP
  40. CImpILogFiles::GetTypeInfoCount (
  41. OUT UINT *pctInfo
  42. )
  43. {
  44. HRESULT hr = E_POINTER;
  45. if ( NULL != pctInfo ) {
  46. *pctInfo = 1;
  47. hr = NOERROR;
  48. }
  49. return hr;
  50. }
  51. STDMETHODIMP
  52. CImpILogFiles::GetTypeInfo (
  53. IN UINT itInfo,
  54. IN LCID /* lcid */,
  55. OUT ITypeInfo** ppITypeInfo
  56. )
  57. {
  58. if (0 != itInfo)
  59. return TYPE_E_ELEMENTNOTFOUND;
  60. if (NULL == ppITypeInfo)
  61. return E_POINTER;
  62. *ppITypeInfo = NULL;
  63. //We ignore the LCID
  64. return g_pITypeLib->GetTypeInfoOfGuid(IID_ILogFiles, ppITypeInfo);
  65. }
  66. STDMETHODIMP
  67. CImpILogFiles::GetIDsOfNames (
  68. IN REFIID riid,
  69. IN OLECHAR **rgszNames,
  70. IN UINT cNames,
  71. IN LCID /* lcid */,
  72. OUT DISPID *rgDispID
  73. )
  74. {
  75. HRESULT hr = E_POINTER;
  76. ITypeInfo *pTI;
  77. if ( NULL != rgDispID
  78. && NULL != rgszNames
  79. && NULL != *rgszNames) {
  80. if (IID_NULL == riid) {
  81. hr = g_pITypeLib->GetTypeInfoOfGuid(IID_ILogFiles, &pTI);
  82. if ( SUCCEEDED ( hr ) ) {
  83. hr = DispGetIDsOfNames(pTI, rgszNames, cNames, rgDispID);
  84. pTI->Release();
  85. }
  86. } else {
  87. hr = DISP_E_UNKNOWNINTERFACE;
  88. }
  89. }
  90. return hr;
  91. }
  92. /*
  93. * CImpIDispatch::Invoke
  94. *
  95. * Purpose:
  96. * Calls a method in the dispatch interface or manipulates a
  97. * property.
  98. *
  99. * Parameters:
  100. * dispID DISPID of the method or property of interest.
  101. * riid REFIID reserved, must be IID_NULL.
  102. * lcid LCID of the locale.
  103. * wFlags USHORT describing the context of the invocation.
  104. * pDispParams DISPPARAMS * to the array of arguments.
  105. * pVarResult VARIANT * in which to store the result. Is
  106. * NULL if the caller is not interested.
  107. * pExcepInfo EXCEPINFO * to exception information.
  108. * puArgErr UINT * in which to store the index of an
  109. * invalid parameter if DISP_E_TYPEMISMATCH
  110. * is returned.
  111. *
  112. * Return Value:
  113. * HRESULT NOERROR or a general error code.
  114. */
  115. STDMETHODIMP
  116. CImpILogFiles::Invoke (
  117. IN DISPID dispID,
  118. IN REFIID riid,
  119. IN LCID /* lcid */,
  120. IN USHORT wFlags,
  121. IN DISPPARAMS *pDispParams,
  122. OUT VARIANT *pVarResult,
  123. OUT EXCEPINFO *pExcepInfo,
  124. OUT UINT *puArgErr
  125. )
  126. {
  127. HRESULT hr = DISP_E_UNKNOWNINTERFACE;
  128. ITypeInfo *pTI = NULL;
  129. if ( IID_NULL == riid ) {
  130. hr = g_pITypeLib->GetTypeInfoOfGuid(IID_ILogFiles, &pTI);
  131. if (SUCCEEDED(hr)) {
  132. hr = pTI->Invoke(this, dispID, wFlags,
  133. pDispParams, pVarResult, pExcepInfo, puArgErr);
  134. pTI->Release();
  135. }
  136. }
  137. return hr;
  138. }
  139. STDMETHODIMP
  140. CImpILogFiles::get_Count (
  141. OUT LONG* pLong )
  142. {
  143. HRESULT hr = E_POINTER;
  144. if (pLong != NULL) {
  145. *pLong = m_pObj->m_pCtrl->NumLogFiles();
  146. hr = NOERROR;
  147. }
  148. return hr;
  149. }
  150. STDMETHODIMP
  151. CImpILogFiles::get__NewEnum (
  152. IUnknown **ppIunk
  153. )
  154. {
  155. HRESULT hr = E_POINTER;
  156. CImpIEnumLogFile *pEnum;
  157. if ( NULL != ppIunk ) {
  158. *ppIunk = NULL;
  159. pEnum = new CImpIEnumLogFile;
  160. if ( NULL != pEnum ) {
  161. hr = pEnum->Init (
  162. m_pObj->m_pCtrl->FirstLogFile(),
  163. m_pObj->m_pCtrl->NumLogFiles() );
  164. if ( SUCCEEDED ( hr ) ) {
  165. pEnum->AddRef();
  166. *ppIunk = pEnum;
  167. hr = NOERROR;
  168. } else {
  169. delete pEnum;
  170. }
  171. } else {
  172. return E_OUTOFMEMORY;
  173. }
  174. }
  175. return hr;
  176. }
  177. STDMETHODIMP
  178. CImpILogFiles::get_Item (
  179. IN VARIANT varIndex,
  180. OUT DILogFileItem **ppI
  181. )
  182. {
  183. HRESULT hr = E_POINTER;
  184. VARIANT varLoc;
  185. INT iIndex = 0;
  186. INT i;
  187. CLogFileItem *pItem = NULL;
  188. if (ppI != NULL) {
  189. *ppI = NULL;
  190. // Try coercing index to I4
  191. VariantInit(&varLoc);
  192. hr = VariantChangeType(&varLoc, &varIndex, 0, VT_I4);
  193. if ( SUCCEEDED (hr) ) {
  194. // Verify index is in range
  195. iIndex = V_I4(&varLoc);
  196. if (iIndex < 1 || iIndex > m_pObj->m_pCtrl->NumLogFiles() ) {
  197. hr = DISP_E_BADINDEX;
  198. } else {
  199. // Traverse log file linked list to indexed item
  200. pItem = m_pObj->m_pCtrl->FirstLogFile ();
  201. i = 1;
  202. while (i++ < iIndex && NULL != pItem ) {
  203. pItem = pItem->Next();
  204. }
  205. // Something wrong with linked list!!
  206. if ( NULL == pItem )
  207. hr = E_FAIL;
  208. }
  209. }
  210. if ( SUCCEEDED (hr) ) {
  211. // Return counter's dispatch interface
  212. hr = pItem->QueryInterface(DIID_DILogFileItem, (PVOID*)ppI);
  213. }
  214. }
  215. return hr;
  216. }
  217. STDMETHODIMP
  218. CImpILogFiles::Add (
  219. IN BSTR bstrPath,
  220. OUT DILogFileItem **ppI
  221. )
  222. {
  223. HRESULT hr = E_POINTER;
  224. eDataSourceTypeConstant eDataSourceType = sysmonCurrentActivity;
  225. PCLogFileItem pItem = NULL;
  226. USES_CONVERSION
  227. // Check data source type. Only add log files
  228. // when the data source is not sysmonLogFiles
  229. hr = m_pObj->m_pCtrl->get_DataSourceType ( eDataSourceType );
  230. if ( SUCCEEDED ( hr ) ) {
  231. if ( sysmonLogFiles != eDataSourceType ) {
  232. if ( NULL != ppI ) {
  233. *ppI = NULL;
  234. // If non-null log file path
  235. if ( NULL != bstrPath && 0 != bstrPath[0] ) {
  236. hr = m_pObj->m_pCtrl->AddSingleLogFile(W2T(bstrPath), &pItem);
  237. if ( SUCCEEDED ( hr ) ) {
  238. hr = pItem->QueryInterface(DIID_DILogFileItem, (PVOID*)ppI);
  239. pItem->Release();
  240. }
  241. } else {
  242. hr = E_INVALIDARG;
  243. }
  244. }
  245. } else {
  246. hr = SMON_STATUS_LOG_FILE_DATA_SOURCE;
  247. }
  248. }
  249. return hr;
  250. }
  251. STDMETHODIMP
  252. CImpILogFiles::Remove (
  253. IN VARIANT varIndex
  254. )
  255. {
  256. HRESULT hr;
  257. eDataSourceTypeConstant eDataSourceType = sysmonCurrentActivity;
  258. DILogFileItem* pDI = NULL;
  259. PCLogFileItem pItem = NULL;
  260. // Check data source type. Only remove log files
  261. // when the data source is not sysmonLogFiles
  262. hr = m_pObj->m_pCtrl->get_DataSourceType ( eDataSourceType );
  263. if ( SUCCEEDED ( hr ) ) {
  264. if ( sysmonLogFiles != eDataSourceType ) {
  265. // Get interface to indexed item
  266. hr = get_Item(varIndex, &pDI);
  267. if ( SUCCEEDED ( hr ) ) {
  268. // Exchange Dispatch interface for direct one
  269. hr = pDI->QueryInterface(IID_ILogFileItem, (PVOID*)&pItem);
  270. pDI->Release();
  271. if ( SUCCEEDED ( hr ) ) {
  272. assert ( NULL != pItem );
  273. // Remove the item from the control's list.
  274. m_pObj->m_pCtrl->RemoveSingleLogFile ( pItem );
  275. // Release the temp interface
  276. pItem->Release();
  277. }
  278. } else {
  279. hr = SMON_STATUS_LOG_FILE_DATA_SOURCE;
  280. }
  281. }
  282. }
  283. return hr;
  284. }
  285. CImpIEnumLogFile::CImpIEnumLogFile (
  286. void )
  287. : m_cItems ( 0 ),
  288. m_uCurrent ( 0 ),
  289. m_cRef ( 0 ),
  290. m_paLogFileItem ( NULL )
  291. {
  292. return;
  293. }
  294. HRESULT
  295. CImpIEnumLogFile::Init (
  296. PCLogFileItem pLogFileItem,
  297. INT cItems )
  298. {
  299. HRESULT hr = NOERROR;
  300. INT i;
  301. if ( cItems > 0 ) {
  302. m_cItems = cItems;
  303. m_paLogFileItem = (PCLogFileItem*)malloc(sizeof(PCLogFileItem) * cItems);
  304. if ( NULL != m_paLogFileItem ) {
  305. for (i=0; i<cItems; i++) {
  306. m_paLogFileItem[i] = pLogFileItem;
  307. pLogFileItem = pLogFileItem->Next();
  308. }
  309. } else {
  310. hr = E_OUTOFMEMORY;
  311. }
  312. } // No error if cItems <= 0
  313. return hr;
  314. }
  315. STDMETHODIMP
  316. CImpIEnumLogFile::QueryInterface (
  317. IN REFIID riid,
  318. OUT PVOID *ppv
  319. )
  320. {
  321. HRESULT hr = E_POINTER;
  322. if ( NULL != ppv ) {
  323. if ((riid == IID_IUnknown) || (riid == IID_IEnumVARIANT)) {
  324. *ppv = this;
  325. AddRef();
  326. hr = NOERROR;
  327. } else {
  328. *ppv = NULL;
  329. hr = E_NOINTERFACE;
  330. }
  331. }
  332. return hr;
  333. }
  334. STDMETHODIMP_(ULONG)
  335. CImpIEnumLogFile::AddRef (
  336. VOID
  337. )
  338. {
  339. return ++m_cRef;
  340. }
  341. STDMETHODIMP_(ULONG)
  342. CImpIEnumLogFile::Release(
  343. VOID
  344. )
  345. {
  346. if (--m_cRef == 0) {
  347. if (m_paLogFileItem != NULL)
  348. free(m_paLogFileItem);
  349. delete this;
  350. return 0;
  351. }
  352. return m_cRef;
  353. }
  354. STDMETHODIMP
  355. CImpIEnumLogFile::Next(
  356. IN ULONG cItems,
  357. OUT VARIANT *varItem,
  358. OUT ULONG *pcReturned)
  359. {
  360. HRESULT hr = E_POINTER;
  361. ULONG i;
  362. ULONG cRet;
  363. if ( NULL != varItem ) {
  364. hr = NOERROR;
  365. // Clear the return variants
  366. for (i = 0; i < cItems; i++)
  367. VariantInit(&varItem[i]);
  368. // Try to fill the caller's array
  369. for (cRet = 0; cRet < cItems; cRet++) {
  370. // No more, return success with false
  371. if (m_uCurrent == m_cItems) {
  372. hr = S_FALSE;
  373. break;
  374. }
  375. // Get a dispatch interface for the item
  376. hr = m_paLogFileItem[m_uCurrent]->QueryInterface(DIID_DILogFileItem,
  377. (PVOID*)&V_DISPATCH(&varItem[cRet]));
  378. if (FAILED(hr))
  379. break;
  380. V_VT(&varItem[cRet]) = VT_DISPATCH;
  381. m_uCurrent++;
  382. }
  383. // If failed, clear out the variants
  384. if (FAILED(hr)) {
  385. for (i = 0; i < cItems; i++)
  386. VariantClear(&varItem[i]);
  387. cRet = 0;
  388. }
  389. // If desired, return number of items fetched
  390. if (pcReturned != NULL)
  391. *pcReturned = cRet;
  392. }
  393. return hr;
  394. }
  395. /***
  396. *HRESULT CEnumPoint::Skip(unsigned long)
  397. *Purpose:
  398. * Attempt to skip over the next 'celt' elements in the enumeration
  399. * sequence.
  400. *
  401. *Entry:
  402. * celt = the count of elements to skip
  403. *
  404. *Exit:
  405. * return value = HRESULT
  406. * S_OK
  407. * S_FALSE - the end of the sequence was reached
  408. *
  409. ***********************************************************************/
  410. STDMETHODIMP
  411. CImpIEnumLogFile::Skip(
  412. IN ULONG cItems
  413. )
  414. {
  415. m_uCurrent += cItems;
  416. if (m_uCurrent > m_cItems)
  417. m_uCurrent = m_cItems;
  418. return (m_uCurrent == m_cItems) ? S_FALSE : S_OK;
  419. }
  420. /***
  421. *HRESULT CEnumPoint::Reset(void)
  422. *Purpose:
  423. * Reset the enumeration sequence back to the beginning.
  424. *
  425. *Entry:
  426. * None
  427. *
  428. *Exit:
  429. * return value = SHRESULT CODE
  430. * S_OK
  431. *
  432. ***********************************************************************/
  433. STDMETHODIMP
  434. CImpIEnumLogFile::Reset(
  435. VOID
  436. )
  437. {
  438. m_uCurrent = 0;
  439. return S_OK;
  440. }
  441. /***
  442. *HRESULT CEnumPoint::Clone(IEnumVARIANT**)
  443. *Purpose:
  444. * Retrun a CPoint enumerator with exactly the same state as the
  445. * current one.
  446. *
  447. *Entry:
  448. * None
  449. *
  450. *Exit:
  451. * return value = HRESULT
  452. * S_OK
  453. * E_OUTOFMEMORY
  454. *
  455. ***********************************************************************/
  456. STDMETHODIMP
  457. CImpIEnumLogFile::Clone (
  458. OUT IEnumVARIANT **ppEnum
  459. )
  460. {
  461. HRESULT hr = E_POINTER;
  462. ULONG i;
  463. CImpIEnumLogFile *pNewEnum;
  464. if ( NULL != ppEnum ) {
  465. *ppEnum = NULL;
  466. // Create new enumerator
  467. pNewEnum = new CImpIEnumLogFile;
  468. if ( NULL != pNewEnum ) {
  469. // Init, copy item list and current position
  470. pNewEnum->m_cItems = m_cItems;
  471. pNewEnum->m_uCurrent = m_uCurrent;
  472. pNewEnum->m_paLogFileItem = (PCLogFileItem*)malloc(sizeof(PCLogFileItem) * m_cItems);
  473. if ( NULL != pNewEnum->m_paLogFileItem ) {
  474. for (i=0; i<m_cItems; i++) {
  475. pNewEnum->m_paLogFileItem[i] = m_paLogFileItem[i];
  476. }
  477. *ppEnum = pNewEnum;
  478. hr = NOERROR;
  479. } else {
  480. delete pNewEnum;
  481. hr = E_OUTOFMEMORY;
  482. }
  483. } else {
  484. hr = E_OUTOFMEMORY;
  485. }
  486. }
  487. return hr;
  488. }