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.

490 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 System Monitor control.
  8. --*/
  9. #include <assert.h>
  10. #include "polyline.h"
  11. #include "unkhlpr.h"
  12. #include "unihelpr.h"
  13. #include "globals.h"
  14. #include "smonmsg.h"
  15. #include "strnoloc.h"
  16. #include "ipropbag.h"
  17. #define MAX_GUID_STRING_LENGTH 39
  18. /*
  19. * CImpIPropertyBag interface implementation
  20. */
  21. IMPLEMENT_CONTAINED_IUNKNOWN(CImpIPropertyBag)
  22. /*
  23. * CImpIPropertyBag::CImpIPropertyBag
  24. *
  25. * Purpose:
  26. * Constructor.
  27. *
  28. * Return Value:
  29. */
  30. CImpIPropertyBag::CImpIPropertyBag ( LPUNKNOWN pUnkOuter)
  31. : m_cRef ( 0 ),
  32. m_pUnkOuter ( pUnkOuter ),
  33. m_pszData ( NULL ),
  34. m_dwCurrentDataLength ( 0 ),
  35. m_plistData ( NULL )
  36. {
  37. return;
  38. }
  39. /*
  40. * CImpIPropertyBag::~CImpIPropertyBag
  41. *
  42. * Purpose:
  43. * Destructor.
  44. *
  45. * Return Value:
  46. */
  47. CImpIPropertyBag::~CImpIPropertyBag ( void )
  48. {
  49. if ( NULL != m_pszData ) {
  50. delete [] m_pszData;
  51. }
  52. while ( NULL != m_plistData ) {
  53. PPARAM_DATA pData;
  54. pData = DataListRemoveHead();
  55. VariantClear ( &pData->vValue );
  56. delete [] pData;
  57. }
  58. }
  59. /*
  60. * CImpIPropertyBag::Read
  61. *
  62. * Purpose:
  63. *
  64. * This function is called to read a property from the property bag.
  65. *
  66. * Parameters:
  67. * pszPropName Pointer to name of property to be read
  68. * pVar Pointer to the VARIANT to receive the property value
  69. * pIErrorLog Pointer to the caller's error log
  70. */
  71. STDMETHODIMP
  72. CImpIPropertyBag::Read (
  73. LPCOLESTR pszPropName, //Pointer to the property to be read
  74. VARIANT* pVar, //Pointer to the VARIANT to receive the
  75. //property value
  76. IErrorLog* pIErrorLog ) //Pointer to the caller's error log // can be null
  77. {
  78. HRESULT hr = S_OK;
  79. PPARAM_DATA pData;
  80. if (NULL == pszPropName || NULL == pVar) {
  81. return (E_POINTER);
  82. }
  83. // Currently don't handle error log.
  84. assert ( NULL == pIErrorLog );
  85. pIErrorLog; // Eliminate compiler warning.
  86. try {
  87. //Read the specified data into the passed variant.
  88. pData = FindProperty ( pszPropName );
  89. if ( NULL != pData ) {
  90. if ( pVar->vt != VT_BSTR ) {
  91. hr = VariantChangeTypeEx( pVar,
  92. &pData->vValue,
  93. LCID_SCRIPT,
  94. VARIANT_NOUSEROVERRIDE,
  95. pVar->vt );
  96. }
  97. else {
  98. hr = VariantChangeType ( pVar,
  99. &pData->vValue,
  100. NULL,
  101. pVar->vt );
  102. }
  103. } else {
  104. hr = E_INVALIDARG;
  105. }
  106. } catch (...) {
  107. hr = E_POINTER;
  108. }
  109. return hr;
  110. }
  111. /*
  112. * CImpIPropertyBag::Write
  113. *
  114. * Purpose:
  115. *
  116. * This function is called to write a property to the property bag.
  117. *
  118. * Parameters:
  119. * pszPropName Pointer to name of property to be written
  120. * pVar Pointer to the VARIANT containing the property value
  121. */
  122. STDMETHODIMP
  123. CImpIPropertyBag::Write (
  124. LPCOLESTR pszPropName, //Pointer to the property to be written
  125. VARIANT* pVar ) //Pointer to the VARIANT containing the
  126. //property value and type
  127. {
  128. HRESULT hr = S_OK;
  129. VARIANT vValueBstr;
  130. DWORD dwNameLength;
  131. DWORD dwDataLength;
  132. //
  133. // Special purpost to use static instead of dynamic
  134. //
  135. static DWORD dwDelimiterLength = 0;
  136. static DWORD dwParamNameLength = 0;
  137. static DWORD dwEolTagLength = 0;
  138. static DWORD dwValueTagLength = 0;
  139. LPWSTR pszNextField = m_pszData;
  140. DWORD dwCurrentDataUsedLength;
  141. if (NULL==pszPropName || NULL==pVar) {
  142. return (E_POINTER);
  143. }
  144. VariantInit ( &vValueBstr );
  145. try {
  146. //
  147. // Use do{}while(0) here to act like a switch statement
  148. //
  149. do {
  150. if( pVar->vt != VT_BSTR ){
  151. hr = VariantChangeTypeEx( &vValueBstr,
  152. pVar,
  153. LCID_SCRIPT,
  154. VARIANT_NOUSEROVERRIDE,
  155. VT_BSTR);
  156. } else {
  157. hr = VariantChangeType ( &vValueBstr,
  158. pVar,
  159. NULL,
  160. VT_BSTR);
  161. }
  162. if (!SUCCEEDED(hr)) {
  163. break;
  164. }
  165. //
  166. // All length values calculated number of WCHARs.
  167. //
  168. if ( 0 == dwDelimiterLength ) {
  169. // Initialize static values
  170. dwParamNameLength = lstrlen ( CGlobalString::m_cszHtmlParamTag );
  171. dwValueTagLength = lstrlen ( CGlobalString::m_cszHtmlValueTag );
  172. dwEolTagLength = lstrlen ( CGlobalString::m_cszHtmlValueEolTag );
  173. dwDelimiterLength = dwParamNameLength + dwValueTagLength + dwEolTagLength;
  174. }
  175. dwNameLength = lstrlen ( pszPropName );
  176. dwDataLength = lstrlen ( vValueBstr.bstrVal );
  177. dwCurrentDataUsedLength = lstrlen ( m_pszData );
  178. // Add 1 to size calculation for NULL buffer terminator.
  179. if ( m_dwCurrentDataLength
  180. < dwCurrentDataUsedLength + dwNameLength + dwDataLength + dwDelimiterLength + 1 ) {
  181. LPWSTR pszNewBuffer;
  182. if ( 0 == m_dwCurrentDataLength ) {
  183. m_dwCurrentDataLength += eDefaultBufferLength;
  184. } else {
  185. m_dwCurrentDataLength *= 2;
  186. }
  187. pszNewBuffer = new WCHAR[m_dwCurrentDataLength];
  188. if ( NULL == pszNewBuffer) {
  189. hr = E_OUTOFMEMORY;
  190. break;
  191. }
  192. if ( NULL != m_pszData ) {
  193. memcpy ( pszNewBuffer, m_pszData, dwCurrentDataUsedLength * sizeof(WCHAR) );
  194. delete [] m_pszData;
  195. }
  196. m_pszData = pszNewBuffer;
  197. }
  198. // Build the new string and add it to the current data.
  199. pszNextField = m_pszData + dwCurrentDataUsedLength;
  200. memcpy ( pszNextField, CGlobalString::m_cszHtmlParamTag, dwParamNameLength * sizeof(WCHAR) );
  201. pszNextField += dwParamNameLength;
  202. memcpy ( pszNextField, pszPropName, dwNameLength * sizeof(WCHAR) );
  203. pszNextField += dwNameLength;
  204. memcpy ( pszNextField, CGlobalString::m_cszHtmlValueTag, dwValueTagLength * sizeof(WCHAR) );
  205. pszNextField += dwValueTagLength;
  206. memcpy ( pszNextField, vValueBstr.bstrVal, dwDataLength * sizeof(WCHAR) );
  207. pszNextField += dwDataLength;
  208. memcpy ( pszNextField, CGlobalString::m_cszHtmlValueEolTag, dwEolTagLength * sizeof(WCHAR) );
  209. pszNextField += dwEolTagLength;
  210. *pszNextField = L'\0';
  211. } while (0);
  212. } catch (...) {
  213. hr = E_POINTER;
  214. }
  215. VariantClear(&vValueBstr);
  216. return hr;
  217. }
  218. /*
  219. * CImpIPropertyBag::GetData
  220. *
  221. * Purpose:
  222. * Return pointer to the data buffer.
  223. *
  224. * Return Value:
  225. * Pointer to the data buffer.
  226. */
  227. LPWSTR
  228. CImpIPropertyBag::GetData ( void )
  229. {
  230. return m_pszData;
  231. }
  232. /*
  233. * CImpIPropertyBag::LoadData
  234. *
  235. * Purpose:
  236. * Load data from the supplied buffer into internal data structures.
  237. *
  238. * Return Value:
  239. * Status.
  240. */
  241. HRESULT
  242. CImpIPropertyBag::LoadData (
  243. LPWSTR pszData
  244. )
  245. {
  246. HRESULT hr = S_OK;
  247. LPWSTR pszDataAllocW = NULL;
  248. LPWSTR pszCurrentPos = NULL;
  249. LPSTR pszGuidA = NULL;
  250. LPSTR pszCurrentPosA = NULL;
  251. LPSTR pszDataA = NULL;
  252. OLECHAR szGuidW[MAX_GUID_STRING_LENGTH];
  253. LPWSTR pszGuidW = NULL;
  254. INT iStatus;
  255. INT iBufLen;
  256. USES_CONVERSION
  257. if ( NULL == pszData ) {
  258. assert ( FALSE );
  259. hr = E_POINTER;
  260. } else {
  261. // Unicode search: Begin the search after the first instance
  262. // of the System Monitor class id.
  263. iStatus = StringFromGUID2(CLSID_SystemMonitor, szGuidW, sizeof(szGuidW)/sizeof(OLECHAR));
  264. if ( 0 < iStatus ) {
  265. pszGuidW = wcstok ( szGuidW, L"{} " );
  266. if ( NULL != pszGuidW ) {
  267. pszCurrentPos = wcsstr(pszData, pszGuidW );
  268. // Handle wide vs ansi.
  269. if ( NULL == pszCurrentPos ) {
  270. // Check for ANSI version:
  271. pszDataA = (CHAR*) pszData;
  272. try {
  273. pszGuidA = W2A( pszGuidW );
  274. } catch (...) {
  275. pszGuidA = NULL;
  276. hr = E_OUTOFMEMORY;
  277. }
  278. if ( NULL != pszGuidA ) {
  279. pszCurrentPosA = strstr ( pszDataA, pszGuidA );
  280. if ( NULL != pszCurrentPosA ) {
  281. iBufLen = lstrlenA (pszDataA) + 1;
  282. pszDataAllocW = new WCHAR [iBufLen * sizeof(WCHAR)];
  283. if ( NULL != pszDataAllocW ) {
  284. _MbToWide ( pszDataAllocW, pszDataA, iBufLen );
  285. pszCurrentPos = wcsstr(pszDataAllocW, pszGuidW );
  286. } else {
  287. hr = E_OUTOFMEMORY;
  288. }
  289. }
  290. }
  291. }
  292. }
  293. } else {
  294. hr = E_UNEXPECTED;
  295. }
  296. if ( NULL != pszCurrentPos ) {
  297. WCHAR szQuote[2];
  298. LPWSTR pszEoo;
  299. szQuote[0] = L'\"';
  300. szQuote[1] = L'\0';
  301. // End of object is the first object footer tag after the first sysmon
  302. // class id found. If multiple objects in the data block, only parse the first sysmon.
  303. pszEoo = wcsstr(pszCurrentPos, CGlobalString::m_cszHtmlObjectFooter );
  304. if ( NULL != pszEoo ) {
  305. // Find first parameter tag.
  306. pszCurrentPos = wcsstr(pszCurrentPos, CGlobalString::m_cszHtmlParamSearchTag );
  307. while ( NULL != pszCurrentPos && pszCurrentPos < pszEoo ) {
  308. LPWSTR pszNextPos;
  309. INT lStrLength;
  310. PPARAM_DATA pParamData;
  311. LPWSTR pszTemp;
  312. LONG lCopyLen;
  313. // Store parameter/property name.
  314. // Find one past first quote.
  315. pszCurrentPos = wcsstr(pszCurrentPos, szQuote ) + 1;
  316. // The param name is between first and second quote.
  317. pszNextPos = wcsstr(pszCurrentPos, szQuote );
  318. lStrLength = ( (INT)((UINT_PTR)pszNextPos - (UINT_PTR)pszCurrentPos) ) / sizeof ( WCHAR ) ;
  319. pParamData = new PARAM_DATA;
  320. if ( NULL != pParamData ) {
  321. pParamData->pNextParam = NULL;
  322. VariantInit ( &pParamData->vValue );
  323. pParamData->vValue.vt = VT_BSTR;
  324. } else {
  325. hr = E_OUTOFMEMORY;
  326. break;
  327. }
  328. lCopyLen = min(lStrLength, MAX_PATH);
  329. wcsncpy(pParamData->pszPropertyName, pszCurrentPos, lCopyLen);
  330. pParamData->pszPropertyName[lCopyLen] = L'\0';
  331. // Find value tag and store parameter/property value.
  332. // Find value tag and store parameter/property value.
  333. // Find value tag
  334. pszCurrentPos = wcsstr ( pszCurrentPos, CGlobalString::m_cszHtmlValueSearchTag );
  335. // Find one past first quote
  336. pszCurrentPos = wcsstr ( pszCurrentPos, szQuote ) + 1;
  337. // The value is between first and second quote.
  338. pszNextPos = wcsstr ( pszCurrentPos, szQuote );
  339. lStrLength = ( (INT)((UINT_PTR)pszNextPos - (UINT_PTR)pszCurrentPos) ) / sizeof ( WCHAR );
  340. pszTemp = new WCHAR[lStrLength+1];
  341. if (pszTemp != NULL) {
  342. wcsncpy ( pszTemp, pszCurrentPos, lStrLength );
  343. pszTemp[lStrLength] = L'\0';
  344. pParamData->vValue.bstrVal = SysAllocString ( pszTemp );
  345. delete [] pszTemp;
  346. DataListAddHead ( pParamData );
  347. // Find next parameter/property tag.
  348. pszCurrentPos = wcsstr(pszCurrentPos, CGlobalString::m_cszHtmlParamSearchTag );
  349. } else {
  350. delete pParamData;
  351. hr = E_OUTOFMEMORY;
  352. break;
  353. }
  354. } // While parameter tags exist for a single object.
  355. } else {
  356. hr = SMON_STATUS_NO_SYSMON_OBJECT;
  357. }
  358. } else {
  359. hr = SMON_STATUS_NO_SYSMON_OBJECT;
  360. }
  361. }
  362. if ( NULL != pszDataAllocW ) {
  363. delete [] pszDataAllocW;
  364. }
  365. return hr;
  366. }
  367. void
  368. CImpIPropertyBag::DataListAddHead ( PPARAM_DATA pData )
  369. {
  370. pData->pNextParam = m_plistData;
  371. m_plistData = pData;
  372. return;
  373. }
  374. CImpIPropertyBag::PPARAM_DATA
  375. CImpIPropertyBag::DataListRemoveHead ( )
  376. {
  377. PPARAM_DATA pReturnData;
  378. pReturnData = m_plistData;
  379. if ( NULL != m_plistData )
  380. m_plistData = m_plistData->pNextParam;
  381. return pReturnData;
  382. }
  383. CImpIPropertyBag::PPARAM_DATA
  384. CImpIPropertyBag::FindProperty ( LPCWSTR pszPropName )
  385. {
  386. PPARAM_DATA pReturnData;
  387. pReturnData = m_plistData;
  388. while ( NULL != pReturnData ) {
  389. if ( 0 == lstrcmpi ( pszPropName, pReturnData->pszPropertyName ) )
  390. break;
  391. pReturnData = pReturnData->pNextParam;
  392. }
  393. return pReturnData;
  394. }