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.

435 lines
12 KiB

  1. /*++
  2. Copyright (C) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. PropBag.cpp
  5. Abstract:
  6. Implementation of the private IPropertyBag interface used by
  7. the Performance Log Manager.
  8. --*/
  9. #include "logman.h"
  10. #include "stdafx.h"
  11. #include "unihelpr.h"
  12. #include "strings.h"
  13. #include "propbag.h"
  14. #define MAX_GUID_STRING_LENGTH 39
  15. /*
  16. * CPropertyBag::CPropertyBag
  17. *
  18. * Purpose:
  19. * Constructor.
  20. *
  21. * Return Value:
  22. */
  23. CPropertyBag::CPropertyBag ( void )
  24. : m_pszData ( NULL ),
  25. m_dwCurrentDataLength ( 0 ),
  26. m_plistData ( NULL )
  27. {
  28. return;
  29. }
  30. /*
  31. * CPropertyBag::~CPropertyBag
  32. *
  33. * Purpose:
  34. * Destructor.
  35. *
  36. * Return Value:
  37. */
  38. CPropertyBag::~CPropertyBag ( void )
  39. {
  40. if ( NULL != m_pszData ) {
  41. delete m_pszData;
  42. }
  43. while ( NULL != m_plistData ) {
  44. PPARAM_DATA pData = DataListRemoveHead();
  45. VariantClear ( &pData->vValue );
  46. delete pData;
  47. }
  48. return;
  49. }
  50. /*
  51. * CPropertyBag::Read
  52. *
  53. * Purpose:
  54. *
  55. * This function is called to read a property from the property bag.
  56. *
  57. * Parameters:
  58. * pszPropName Pointer to name of property to be read
  59. * pVar Pointer to the VARIANT to receive the property value
  60. * pIErrorLog Pointer to the caller's error log
  61. */
  62. HRESULT
  63. CPropertyBag::Read (
  64. LPCWSTR pszPropName, //Pointer to the property to be read
  65. VARIANT* pVar ) //Pointer to the VARIANT to receive the
  66. //property value
  67. {
  68. HRESULT hr = NOERROR;
  69. PPARAM_DATA pData = NULL;
  70. assert ( NULL != pszPropName );
  71. assert ( NULL != pVar );
  72. if ( NULL == pszPropName )
  73. return ResultFromScode ( E_POINTER );
  74. if ( NULL == pVar )
  75. return ResultFromScode ( E_POINTER );
  76. //Read the specified data into the passed variant.
  77. pData = FindProperty ( pszPropName );
  78. if ( NULL != pData ) {
  79. hr = VariantChangeType ( pVar, &pData->vValue, NULL, pVar->vt );
  80. } else {
  81. hr = E_INVALIDARG;
  82. }
  83. return hr;
  84. }
  85. /*
  86. * CPropertyBag::Write
  87. *
  88. * Purpose:
  89. *
  90. * This function is called to write a property to the property bag.
  91. *
  92. * Parameters:
  93. * pszPropName Pointer to name of property to be written
  94. * pVar Pointer to the VARIANT containing the property value
  95. */
  96. HRESULT
  97. CPropertyBag::Write (
  98. LPCWSTR pszPropName, //Pointer to the property to be written
  99. VARIANT* pVar ) //Pointer to the VARIANT containing the
  100. //property value and type
  101. {
  102. HRESULT hr = S_OK;
  103. VARIANT vValueBstr;
  104. DWORD dwNameLength;
  105. DWORD dwDataLength;
  106. static DWORD dwDelimiterLength = 0;
  107. static DWORD dwParamNameLength = 0;
  108. static DWORD dwEolTagLength = 0;
  109. static DWORD dwValueTagLength = 0;
  110. HRESULT hrConvert;
  111. LPWSTR pszNextField = m_pszData;
  112. DWORD dwCurrentDataUsedLength;
  113. assert ( NULL != pszPropName );
  114. assert ( NULL != pVar );
  115. if ( NULL == pszPropName )
  116. return ResultFromScode ( E_POINTER );
  117. if ( NULL == pVar )
  118. return ResultFromScode ( E_POINTER );
  119. USES_CONVERSION
  120. VariantInit ( &vValueBstr );
  121. hrConvert = VariantChangeType ( &vValueBstr, pVar, NULL, VT_BSTR );
  122. // All length values calculated number of WCHARs.
  123. if ( 0 == dwDelimiterLength ) {
  124. // Initialize static values
  125. dwParamNameLength = lstrlenW (cwszHtmlParamTag);
  126. dwValueTagLength = lstrlenW ( cwszHtmlValueTag );
  127. dwEolTagLength = lstrlenW ( cwszHtmlValueEolTag );
  128. dwDelimiterLength = dwParamNameLength + dwValueTagLength + dwEolTagLength;
  129. }
  130. if ( SUCCEEDED ( hr ) ) {
  131. hr = E_NOTIMPL;
  132. // Todo: Implement
  133. dwNameLength = lstrlenW ( pszPropName );
  134. dwDataLength = lstrlenW ( vValueBstr.bstrVal );
  135. dwCurrentDataUsedLength = lstrlenW ( m_pszData );
  136. // Add 1 to size calculation for NULL buffer terminator.
  137. if ( m_dwCurrentDataLength
  138. < dwCurrentDataUsedLength + dwNameLength + dwDataLength + dwDelimiterLength + 1 ) {
  139. LPWSTR pszNewBuffer;
  140. if ( 0 == m_dwCurrentDataLength ) {
  141. m_dwCurrentDataLength += eDefaultBufferLength;
  142. } else {
  143. m_dwCurrentDataLength *= 2;
  144. }
  145. pszNewBuffer = new WCHAR[m_dwCurrentDataLength];
  146. if ( NULL == pszNewBuffer )
  147. return E_OUTOFMEMORY;
  148. if ( NULL != m_pszData ) {
  149. memcpy ( pszNewBuffer, m_pszData, dwCurrentDataUsedLength * sizeof(WCHAR) );
  150. delete m_pszData;
  151. }
  152. m_pszData = pszNewBuffer;
  153. }
  154. // Build the new string and add it to the current data.
  155. pszNextField = m_pszData + dwCurrentDataUsedLength;
  156. memcpy ( pszNextField, cwszHtmlParamTag, dwParamNameLength * sizeof(WCHAR) );
  157. pszNextField += dwParamNameLength;
  158. memcpy ( pszNextField, pszPropName, dwNameLength * sizeof(WCHAR) );
  159. pszNextField += dwNameLength;
  160. memcpy ( pszNextField, cwszHtmlValueTag, dwValueTagLength * sizeof(WCHAR) );
  161. pszNextField += dwValueTagLength;
  162. memcpy ( pszNextField, W2T(vValueBstr.bstrVal), dwDataLength * sizeof(WCHAR) );
  163. pszNextField += dwDataLength;
  164. memcpy ( pszNextField, cwszHtmlValueEolTag, dwEolTagLength * sizeof(WCHAR) );
  165. pszNextField += dwEolTagLength;
  166. lstrcpyW ( pszNextField, cwszNull );
  167. }
  168. return hr;
  169. }
  170. /*
  171. * CPropertyBag::GetData
  172. *
  173. * Purpose:
  174. * Return pointer to the data buffer.
  175. *
  176. * Return Value:
  177. * Pointer to the data buffer.
  178. */
  179. LPWSTR
  180. CPropertyBag::GetData ( void )
  181. {
  182. return m_pszData;
  183. }
  184. /*
  185. * CPropertyBag::LoadData
  186. *
  187. * Purpose:
  188. * Load data from the supplied buffer into internal data structures.
  189. *
  190. * Return Value:
  191. * Status.
  192. */
  193. DWORD
  194. CPropertyBag::LoadData (
  195. LPCTSTR pszData,
  196. LPTSTR& rpszNextData )
  197. {
  198. DWORD dwStatus = ERROR_SUCCESS;
  199. LPWSTR szNextEoo = NULL;
  200. BOOL bUnicode = TRUE;
  201. USES_CONVERSION
  202. assert ( NULL != pszData );
  203. rpszNextData = NULL;
  204. if ( NULL != pszData ) {
  205. LPWSTR pszDataW = NULL;
  206. LPWSTR pszDataAllocW = NULL;
  207. LPWSTR pszCurrentPos;
  208. LPWSTR pszGuid;
  209. // Unicode search: Begin the search after the first instance
  210. // of the System Monitor class id.
  211. pszGuid = wcstok ( const_cast<LPWSTR>(cwszHtmlObjectClassId), L"{} " );
  212. pszCurrentPos = wcsstr( (LPWSTR) pszData, pszGuid );
  213. // Handle wide vs ansi.
  214. if ( NULL != pszCurrentPos ) {
  215. pszDataW = (LPWSTR)pszData;
  216. bUnicode = TRUE;
  217. } else {
  218. // Check for ANSI version:
  219. LPSTR pszGuidA = NULL;
  220. LPSTR pszCurrentPosA = NULL;
  221. LPSTR pszDataA = (CHAR*) pszData;
  222. pszGuidA = W2A( pszGuid );
  223. pszCurrentPosA = strstr ( pszDataA, pszGuidA );
  224. if ( NULL != pszCurrentPosA ) {
  225. pszDataAllocW = A2W ( pszDataA );
  226. pszDataW = pszDataAllocW;
  227. bUnicode = FALSE;
  228. pszCurrentPos = wcsstr(pszDataW, pszGuid );
  229. }
  230. }
  231. if ( NULL != pszCurrentPos ) {
  232. LPWSTR szEoo;
  233. // End of object is the first object footer tag after the first sysmon
  234. // class id found. If multiple objects in the data block, only parse the first sysmon.
  235. szEoo = wcsstr(pszCurrentPos, cwszHtmlObjectFooter );
  236. if ( NULL != szEoo ) {
  237. // Find first parameter tag.
  238. pszCurrentPos = wcsstr(pszCurrentPos, cwszHtmlParamSearchTag );
  239. while ( NULL != pszCurrentPos && pszCurrentPos < szEoo ) {
  240. LPWSTR pszNextPos;
  241. INT lStrLength;
  242. PPARAM_DATA pParamData;
  243. LPWSTR szTemp;
  244. // Store parameter/property name.
  245. // Find one past first quote.
  246. pszCurrentPos = wcsstr(pszCurrentPos, cwszQuote ) + 1;
  247. // The param name is between first and second quote.
  248. pszNextPos = wcsstr(pszCurrentPos, cwszQuote );
  249. lStrLength = ( (INT)((UINT_PTR)pszNextPos - (UINT_PTR)pszCurrentPos) ) / sizeof ( WCHAR ) ;
  250. pParamData = new PARAM_DATA;
  251. if ( NULL != pParamData ) {
  252. pParamData->pNextParam = NULL;
  253. VariantInit ( &pParamData->vValue );
  254. pParamData->vValue.vt = VT_BSTR;
  255. } else {
  256. dwStatus = ERROR_OUTOFMEMORY;
  257. break;
  258. }
  259. wcsncpy ( pParamData->pszPropertyName, pszCurrentPos, lStrLength );
  260. pParamData->pszPropertyName[lStrLength] = TEXT ('\0');
  261. // Find value tag and store parameter/property value.
  262. // Find value tag
  263. pszCurrentPos = wcsstr ( pszCurrentPos, cwszHtmlValueSearchTag );
  264. // Find one past first quote
  265. pszCurrentPos = wcsstr ( pszCurrentPos, cwszQuote ) + 1;
  266. // The value is between first and second quote.
  267. pszNextPos = wcsstr ( pszCurrentPos, cwszQuote );
  268. lStrLength = ( (INT)((UINT_PTR)pszNextPos - (UINT_PTR)pszCurrentPos) ) / sizeof ( WCHAR );
  269. szTemp = new WCHAR[lStrLength+1];
  270. if (szTemp != NULL) {
  271. wcsncpy ( szTemp, pszCurrentPos, lStrLength );
  272. szTemp[lStrLength] = TEXT('\0');
  273. pParamData->vValue.bstrVal =
  274. SysAllocString ( szTemp );
  275. delete szTemp;
  276. DataListAddHead ( pParamData );
  277. // Find next parameter/property tag.
  278. pszCurrentPos = wcsstr(pszCurrentPos, cwszHtmlParamSearchTag );
  279. } else {
  280. delete pParamData;
  281. dwStatus = ERROR_OUTOFMEMORY;
  282. break;
  283. }
  284. } // While parameter tags exist for a single object.
  285. // Search for next object
  286. // Start after current object footer
  287. szEoo += lstrlenW ( cwszHtmlObjectFooter );
  288. szNextEoo = wcsstr(szEoo, cwszHtmlObjectFooter);
  289. // Successful. Return pointer to end of the current object, or NULL if all
  290. // objects have been processed.
  291. if ( NULL != szNextEoo ) {
  292. if ( bUnicode ) {
  293. rpszNextData = (LPTSTR)szEoo;
  294. } else {
  295. INT lStrLength;
  296. lStrLength = ( (INT)((UINT_PTR)szEoo - (UINT_PTR)pszDataW) ) / sizeof ( WCHAR ) ;
  297. // Add string length to original buffer pointer
  298. rpszNextData = (LPTSTR)((LPSTR)pszData + lStrLength);
  299. }
  300. }
  301. } else {
  302. dwStatus = LOGMAN_NO_SYSMON_OBJECT;
  303. }
  304. } else {
  305. dwStatus = LOGMAN_NO_SYSMON_OBJECT;
  306. }
  307. } else {
  308. dwStatus = ERROR_INVALID_PARAMETER;
  309. }
  310. return dwStatus;
  311. }
  312. void
  313. CPropertyBag::DataListAddHead ( PPARAM_DATA pData )
  314. {
  315. assert ( NULL != pData );
  316. pData->pNextParam = m_plistData;
  317. m_plistData = pData;
  318. return;
  319. }
  320. CPropertyBag::PPARAM_DATA
  321. CPropertyBag::DataListRemoveHead ( )
  322. {
  323. PPARAM_DATA pReturnData;
  324. pReturnData = m_plistData;
  325. if ( NULL != m_plistData )
  326. m_plistData = m_plistData->pNextParam;
  327. return pReturnData;
  328. }
  329. CPropertyBag::PPARAM_DATA
  330. CPropertyBag::FindProperty ( LPCWSTR pszPropName )
  331. {
  332. PPARAM_DATA pReturnData;
  333. pReturnData = m_plistData;
  334. while ( NULL != pReturnData ) {
  335. if ( 0 == lstrcmpiW ( pszPropName, pReturnData->pszPropertyName ) )
  336. break;
  337. pReturnData = pReturnData->pNextParam;
  338. }
  339. return pReturnData;
  340. }