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.

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