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.

528 lines
14 KiB

  1. /*++
  2. Copyright (C) 1993-1999 Microsoft Corporation
  3. Module Name:
  4. ipropbag.cpp
  5. Abstract:
  6. Implementation of the private IPropertyBag interface used by
  7. the Performance Logs and Alerts MMC snap-in.
  8. --*/
  9. #include "stdafx.h"
  10. #include "smcfgmsg.h"
  11. #include "ipropbag.h"
  12. USE_HANDLE_MACROS("SMLOGCFG(ipropbag.cpp)");
  13. /*
  14. * CImpIPropertyBag interface implementation
  15. */
  16. /*
  17. * CImpIPropertyBag::CImpIPropertyBag
  18. *
  19. * Purpose:
  20. * Constructor.
  21. *
  22. * Return Value:
  23. */
  24. CImpIPropertyBag::CImpIPropertyBag ()
  25. : m_cRef ( 0 ),
  26. m_pszData ( NULL ),
  27. m_dwCurrentDataLength ( 0 ),
  28. m_plistData ( NULL )
  29. {
  30. m_hModule = (HINSTANCE)GetModuleHandleW (_CONFIG_DLL_NAME_W_);
  31. return;
  32. }
  33. /*
  34. * CImpIPropertyBag::~CImpIPropertyBag
  35. *
  36. * Purpose:
  37. * Destructor.
  38. *
  39. * Return Value:
  40. */
  41. CImpIPropertyBag::~CImpIPropertyBag ( void )
  42. {
  43. if ( NULL != m_pszData ) {
  44. delete m_pszData;
  45. }
  46. while ( NULL != m_plistData ) {
  47. PPARAM_DATA pData = DataListRemoveHead();
  48. VariantClear ( &pData->vValue );
  49. delete pData;
  50. }
  51. return;
  52. }
  53. /*
  54. * CImpIPropertyBag::Read
  55. *
  56. * Purpose:
  57. *
  58. * This function is called to read a property from the property bag.
  59. *
  60. * Parameters:
  61. * pszPropName Pointer to name of property to be read
  62. * pVar Pointer to the VARIANT to receive the property value
  63. * pIErrorLog Pointer to the caller's error log
  64. */
  65. STDMETHODIMP
  66. CImpIPropertyBag::Read (
  67. LPCOLESTR pszPropName, //Pointer to the property to be read
  68. VARIANT* pVar, //Pointer to the VARIANT to receive the
  69. //property value
  70. IErrorLog* pIErrorLog ) //Pointer to the caller's error log // can be null
  71. {
  72. HRESULT hr = S_OK;
  73. PPARAM_DATA pData;
  74. if (NULL==pszPropName)
  75. return ResultFromScode(E_POINTER);
  76. if (NULL==pVar)
  77. return ResultFromScode(E_POINTER);
  78. // Currently don't handle error log.
  79. ASSERT ( NULL == pIErrorLog );
  80. pIErrorLog; // Avoid compiler warning
  81. //Read the specified data into the passed variant.
  82. pData = FindProperty ( pszPropName );
  83. if ( NULL != pData ) {
  84. //VARTYPE vtTarget = vValue.vt;
  85. hr = VariantChangeType ( pVar, &pData->vValue, NULL, pVar->vt );
  86. } else {
  87. hr = E_INVALIDARG;
  88. }
  89. return hr;
  90. }
  91. /*
  92. * CImpIPropertyBag::Write
  93. *
  94. * Purpose:
  95. *
  96. * This function is called to write a property to the property bag.
  97. *
  98. * Parameters:
  99. * pszPropName Pointer to name of property to be written
  100. * pVar Pointer to the VARIANT containing the property value
  101. */
  102. STDMETHODIMP
  103. CImpIPropertyBag::Write (
  104. LPCOLESTR pszPropName, //Pointer to the property to be written
  105. VARIANT* pVar ) //Pointer to the VARIANT containing the
  106. //property value and type
  107. {
  108. HRESULT hr = S_OK;
  109. VARIANT vValueBstr;
  110. DWORD dwNameLength;
  111. DWORD dwDataLength;
  112. DWORD dwDelimiterLength;
  113. CString strParamTag;
  114. CString strValueTag;
  115. CString strEolTag;
  116. LPTSTR pszNewBuffer = NULL;
  117. ResourceStateManager rsm;
  118. if ( NULL != pszPropName && NULL != pVar ) {
  119. VariantInit ( &vValueBstr );
  120. hr = VariantChangeType ( &vValueBstr, pVar, NULL, VT_BSTR );
  121. if ( SUCCEEDED ( hr ) ) {
  122. MFC_TRY
  123. strParamTag.LoadString(IDS_HTML_PARAM_TAG);
  124. strValueTag.LoadString(IDS_HTML_VALUE_TAG);
  125. strEolTag.LoadString(IDS_HTML_VALUE_EOL_TAG);
  126. dwDelimiterLength = strParamTag.GetLength() + strValueTag.GetLength() + strEolTag.GetLength();
  127. dwNameLength = lstrlen ( pszPropName );
  128. dwDataLength = lstrlen ( W2T ( vValueBstr.bstrVal ) );
  129. // Include 1 for the ending NULL character in the length check.
  130. if ( m_dwCurrentDataLength
  131. < lstrlen ( m_pszData ) + dwNameLength + dwDataLength + dwDelimiterLength + 1 ) {
  132. m_dwCurrentDataLength += eDefaultBufferLength;
  133. pszNewBuffer = new TCHAR[m_dwCurrentDataLength];
  134. lstrcpy ( pszNewBuffer, L"");
  135. if ( NULL != m_pszData ) {
  136. lstrcpy ( pszNewBuffer, m_pszData );
  137. delete m_pszData;
  138. }
  139. m_pszData = pszNewBuffer;
  140. pszNewBuffer = NULL;
  141. }
  142. // Build the new string and add it to the current data.
  143. lstrcat ( m_pszData, strParamTag.GetBufferSetLength(strParamTag.GetLength()) );
  144. lstrcat ( m_pszData, pszPropName );
  145. lstrcat ( m_pszData, strValueTag.GetBufferSetLength(strValueTag.GetLength()) );
  146. lstrcat ( m_pszData, W2T(vValueBstr.bstrVal) );
  147. lstrcat ( m_pszData, strEolTag.GetBufferSetLength(strEolTag.GetLength()) );
  148. MFC_CATCH_HR_RETURN;
  149. if ( NULL != pszNewBuffer ) {
  150. delete pszNewBuffer;
  151. }
  152. }
  153. } else {
  154. hr = E_POINTER;
  155. }
  156. return hr;
  157. }
  158. /*
  159. * CImpIPropertyBag::GetData
  160. *
  161. * Purpose:
  162. * Return pointer to the data buffer.
  163. *
  164. * Return Value:
  165. * Pointer to the data buffer.
  166. */
  167. LPTSTR
  168. CImpIPropertyBag::GetData ( void )
  169. {
  170. return m_pszData;
  171. }
  172. /*
  173. * CImpIPropertyBag::LoadData
  174. *
  175. * Purpose:
  176. * Load data from the supplied buffer into internal data structures.
  177. * Return pointer to the next object, or NULL if no more objects.
  178. *
  179. * Return Value:
  180. * Status.
  181. */
  182. DWORD
  183. CImpIPropertyBag::LoadData ( LPTSTR pszData, LPTSTR* ppszNextData )
  184. {
  185. DWORD dwStatus = ERROR_SUCCESS;
  186. BOOL bUnicode = TRUE;
  187. LPWSTR pszDataW = NULL;
  188. LPWSTR pszDataAllocW = NULL;
  189. LPWSTR pszCurrentPos = NULL;
  190. WCHAR szGuid[uiSmLogGuidStringBufLen];
  191. WCHAR szParamSearchTag[MAX_PATH];
  192. WCHAR szValueSearchTag[MAX_PATH];
  193. WCHAR szEooSearchTag[MAX_PATH];
  194. INT iLength;
  195. USES_CONVERSION;
  196. szGuid[0] = L'\0';
  197. szParamSearchTag[0] = L'\0';
  198. szValueSearchTag[0] = L'\0';
  199. szEooSearchTag[0] = L'\0';
  200. if ( NULL != pszData ) {
  201. // Unicode search: Begin the search after the first instance
  202. // of the System Monitor class id.
  203. iLength = ::LoadString ( m_hModule, IDS_HTML_OBJECT_CLASSID, szGuid, uiSmLogGuidStringBufLen );
  204. if ( 0 < iLength ) {
  205. ::LoadString ( m_hModule, IDS_HTML_PARAM_SEARCH_TAG, szParamSearchTag, MAX_PATH );
  206. }
  207. if ( 0 < iLength ) {
  208. ::LoadString ( m_hModule, IDS_HTML_VALUE_SEARCH_TAG, szValueSearchTag, MAX_PATH );
  209. }
  210. if ( 0 < iLength ) {
  211. ::LoadString ( m_hModule, IDS_HTML_OBJECT_FOOTER, szEooSearchTag, MAX_PATH );
  212. }
  213. ASSERT ( sizeof(TCHAR) == sizeof(WCHAR) );
  214. if ( 0 < iLength ) {
  215. pszCurrentPos = wcsstr(pszData, szGuid );
  216. } else {
  217. dwStatus = ERROR_OUTOFMEMORY;
  218. }
  219. if ( NULL != pszCurrentPos ) {
  220. pszDataW = pszData;
  221. bUnicode = TRUE;
  222. } else {
  223. // Check for ANSI version:
  224. LPSTR pszGuidA = NULL;
  225. LPSTR pszCurrentPosA = NULL;
  226. LPSTR pszDataA = (CHAR*) pszData;
  227. pszGuidA = W2A( szGuid );
  228. pszCurrentPosA = strstr ( pszDataA, pszGuidA );
  229. if ( NULL != pszCurrentPosA ) {
  230. pszDataAllocW = A2W ( pszDataA );
  231. pszDataW = pszDataAllocW;
  232. bUnicode = FALSE;
  233. pszCurrentPos = wcsstr(pszDataW, szGuid );
  234. }
  235. }
  236. if ( NULL != pszCurrentPos ) {
  237. WCHAR szQuote[2];
  238. LPWSTR pszEoo;
  239. wcscpy ( szQuote, L"\"" );
  240. // End of object is the first object footer tag after the first sysmon
  241. // class id found. If multiple objects in the data block, only parse the first sysmon.
  242. pszEoo = wcsstr(pszCurrentPos, szEooSearchTag);
  243. if ( NULL != pszEoo ) {
  244. // Find first parameter tag.
  245. pszCurrentPos = wcsstr(pszCurrentPos, szParamSearchTag );
  246. while ( NULL != pszCurrentPos && pszCurrentPos < pszEoo ) {
  247. LPWSTR pszNextPos;
  248. INT lStrLength;
  249. PPARAM_DATA pParamData;
  250. LPWSTR pszTemp;
  251. // Store parameter/property name.
  252. // Find one past first quote.
  253. pszCurrentPos = wcsstr(pszCurrentPos, szQuote ) + 1;
  254. // The param name is between first and second quote.
  255. pszNextPos = wcsstr(pszCurrentPos, szQuote );
  256. lStrLength = ( (INT)((UINT_PTR)pszNextPos - (UINT_PTR)pszCurrentPos) ) / sizeof ( WCHAR ) ;
  257. try {
  258. pParamData = new PARAM_DATA;
  259. pParamData->pNextParam = NULL;
  260. VariantInit ( &pParamData->vValue );
  261. pParamData->vValue.vt = VT_BSTR;
  262. } catch ( ... ) {
  263. dwStatus = ERROR_OUTOFMEMORY;
  264. break;
  265. }
  266. wcsncpy ( pParamData->pszPropertyName, pszCurrentPos, lStrLength );
  267. pParamData->pszPropertyName[lStrLength] = TEXT ('\0');
  268. // Find value tag and store parameter/property value.
  269. // Find value tag
  270. pszCurrentPos = wcsstr ( pszCurrentPos, szValueSearchTag );
  271. // Find one past first quote
  272. pszCurrentPos = wcsstr ( pszCurrentPos, szQuote ) + 1;
  273. // The value is between first and second quote.
  274. pszNextPos = wcsstr ( pszCurrentPos, szQuote );
  275. lStrLength = ( (INT)((UINT_PTR)pszNextPos - (UINT_PTR)pszCurrentPos) ) / sizeof ( WCHAR );
  276. try {
  277. pszTemp = new WCHAR[lStrLength+1];
  278. wcsncpy ( pszTemp, pszCurrentPos, lStrLength );
  279. pszTemp[lStrLength] = TEXT('\0');
  280. pParamData->vValue.bstrVal =
  281. SysAllocString ( pszTemp );
  282. delete pszTemp;
  283. DataListAddHead ( pParamData );
  284. // Find next parameter/property tag.
  285. pszCurrentPos = wcsstr(pszCurrentPos, szParamSearchTag );
  286. } catch ( ... ) {
  287. delete pParamData;
  288. dwStatus = ERROR_OUTOFMEMORY;
  289. break;
  290. }
  291. } // While parameter tags exist for a single object.
  292. if ( NULL != ppszNextData ) {
  293. LPWSTR pszNextEoo = NULL;
  294. pszEoo += lstrlenW ( szEooSearchTag );
  295. pszNextEoo = wcsstr(pszEoo, szEooSearchTag);
  296. // Successful. Return pointer to end of the current object, or NULL if all
  297. // objects have been processed.
  298. if ( NULL != pszNextEoo ) {
  299. if ( bUnicode ) {
  300. *ppszNextData = pszEoo;
  301. } else {
  302. INT lStrLength;
  303. lStrLength = ( (INT)((UINT_PTR)pszEoo - (UINT_PTR)pszDataW) ) / sizeof ( WCHAR ) ;
  304. *(CHAR**)ppszNextData = (CHAR*)pszData + lStrLength;
  305. }
  306. } else {
  307. *ppszNextData = NULL;
  308. }
  309. }
  310. } else {
  311. if ( NULL != ppszNextData ) {
  312. *ppszNextData = NULL;
  313. }
  314. dwStatus = SMCFG_NO_HTML_SYSMON_OBJECT;
  315. }
  316. } else {
  317. if ( NULL != ppszNextData ) {
  318. *ppszNextData = NULL;
  319. }
  320. dwStatus = SMCFG_NO_HTML_SYSMON_OBJECT;
  321. }
  322. } else {
  323. if ( NULL != ppszNextData ) {
  324. *ppszNextData = NULL;
  325. }
  326. dwStatus = SMCFG_NO_HTML_SYSMON_OBJECT;
  327. }
  328. return dwStatus;
  329. }
  330. void
  331. CImpIPropertyBag::DataListAddHead ( PPARAM_DATA pData )
  332. {
  333. pData->pNextParam = m_plistData;
  334. m_plistData = pData;
  335. return;
  336. }
  337. CImpIPropertyBag::PPARAM_DATA
  338. CImpIPropertyBag::DataListRemoveHead ( )
  339. {
  340. PPARAM_DATA pReturnData;
  341. pReturnData = m_plistData;
  342. if ( NULL != m_plistData )
  343. m_plistData = m_plistData->pNextParam;
  344. return pReturnData;
  345. }
  346. CImpIPropertyBag::PPARAM_DATA
  347. CImpIPropertyBag::FindProperty ( LPCTSTR pszPropName )
  348. {
  349. PPARAM_DATA pReturnData;
  350. pReturnData = m_plistData;
  351. while ( NULL != pReturnData ) {
  352. if ( 0 == lstrcmpi ( pszPropName, pReturnData->pszPropertyName ) )
  353. break;
  354. pReturnData = pReturnData->pNextParam;
  355. }
  356. return pReturnData;
  357. }
  358. /////////////////////////////////////////////////////////////////////////////
  359. // IUnknown implementation
  360. //
  361. //---------------------------------------------------------------------------
  362. // Standard implementation
  363. //
  364. STDMETHODIMP
  365. CImpIPropertyBag::QueryInterface
  366. (
  367. REFIID riid,
  368. LPVOID *ppvObj
  369. )
  370. {
  371. HRESULT hr = S_OK;
  372. do
  373. {
  374. if( NULL == ppvObj )
  375. {
  376. hr = E_INVALIDARG;
  377. break;
  378. }
  379. if (IsEqualIID(riid, IID_IUnknown))
  380. {
  381. *ppvObj = (IUnknown *)(IDataObject *)this;
  382. }
  383. else if (IsEqualIID(riid, IID_IDataObject))
  384. {
  385. *ppvObj = (IUnknown *)(IPropertyBag *)this;
  386. }
  387. else
  388. {
  389. hr = E_NOINTERFACE;
  390. *ppvObj = NULL;
  391. break;
  392. }
  393. // If we got this far we are handing out a new interface pointer on
  394. // this object, so addref it.
  395. AddRef();
  396. } while (0);
  397. return hr;
  398. } // end QueryInterface()
  399. //---------------------------------------------------------------------------
  400. // Standard implementation
  401. //
  402. STDMETHODIMP_(ULONG)
  403. CImpIPropertyBag::AddRef()
  404. {
  405. return InterlockedIncrement((LONG*) &m_cRef);
  406. }
  407. //---------------------------------------------------------------------------
  408. // Standard implementation
  409. //
  410. STDMETHODIMP_(ULONG)
  411. CImpIPropertyBag::Release()
  412. {
  413. ULONG cRefTemp;
  414. cRefTemp = InterlockedDecrement((LONG *)&m_cRef);
  415. if( 0 == cRefTemp )
  416. {
  417. delete this;
  418. }
  419. return cRefTemp;
  420. } // end Release()