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.

359 lines
8.4 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. metautil.cpp
  5. Abstract:
  6. Useful functions for dealing with the metabase
  7. Author:
  8. Magnus Hedlund (MagnusH) --
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "smtpcmn.h"
  13. #include "cmultisz.h"
  14. #include "oleutil.h"
  15. #include "metautil.h"
  16. #include "metakey.h"
  17. // Metabase property manipulation:
  18. BOOL StdGetMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, BOOL fDefault, BOOL * pfOut, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
  19. {
  20. TraceQuietEnter ( "StdGetMetabaseProp<BOOL>" );
  21. HRESULT hr;
  22. DWORD dwTemp;
  23. hr = pMB->GetDword ( wszPath, dwID, &dwTemp, dwFlags, dwUserType );
  24. if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
  25. // Couldn't find property, use defaults.
  26. DebugTraceX ( 0, "Using default for ID: %d", dwID );
  27. dwTemp = fDefault;
  28. hr = NOERROR;
  29. }
  30. BAIL_ON_FAILURE(hr);
  31. *pfOut = dwTemp;
  32. Exit:
  33. if ( FAILED(hr) ) {
  34. ErrorTraceX ( 0, "Failed to get metabase property ID: %d, Error: %x", dwID, hr );
  35. SetLastError ( HRESULTTOWIN32 ( hr ) );
  36. }
  37. return SUCCEEDED(hr);
  38. }
  39. BOOL StdGetMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, DWORD dwDefault, DWORD * pdwOut, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
  40. {
  41. TraceQuietEnter ( "StdGetMetabaseProp<DWORD>" );
  42. DWORD dwTemp;
  43. HRESULT hr;
  44. hr = pMB->GetDword ( wszPath, dwID, &dwTemp, dwFlags, dwUserType );
  45. if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
  46. // Couldn't find property, use defaults.
  47. DebugTraceX ( 0, "Using default for ID: %d", dwID );
  48. dwTemp = dwDefault;
  49. hr = NOERROR;
  50. }
  51. BAIL_ON_FAILURE(hr);
  52. *pdwOut = dwTemp;
  53. Exit:
  54. if ( FAILED(hr) ) {
  55. ErrorTraceX ( 0, "Failed to get metabase property ID: %d, Error: %x", dwID, hr );
  56. SetLastError ( HRESULTTOWIN32 ( hr ) );
  57. }
  58. return SUCCEEDED(hr);
  59. }
  60. BOOL StdGetMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, LPCWSTR wszDefault, BSTR * pstrOut, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
  61. {
  62. TraceQuietEnter ( "StdGetMetabaseProp <BSTR>" );
  63. HRESULT hr = NOERROR;
  64. BSTR strNew = NULL;
  65. DWORD cbRequired = 0;
  66. DWORD cchRequired = 0;
  67. BOOL fUseDefault = FALSE;
  68. // Get the length of the string to retrieve:
  69. hr = pMB->GetDataSize ( wszPath, dwID, STRING_METADATA, &cbRequired, dwFlags, dwUserType );
  70. cchRequired = cbRequired / sizeof ( WCHAR );
  71. // Is the value there?
  72. if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
  73. // No, so use the default that was passed in.
  74. DebugTraceX ( 0, "Using default for ID: %d", dwID );
  75. fUseDefault = TRUE;
  76. hr = NOERROR;
  77. }
  78. BAIL_ON_FAILURE(hr);
  79. if ( !fUseDefault ) {
  80. strNew = ::SysAllocStringLen ( NULL, cbRequired );
  81. if ( !strNew ) {
  82. FatalTrace ( 0, "Out of memory" );
  83. BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
  84. }
  85. // Get the metabase string:
  86. hr = pMB->GetString ( wszPath, dwID, strNew, cbRequired, dwFlags, dwUserType );
  87. BAIL_ON_FAILURE(hr);
  88. }
  89. if ( fUseDefault ) {
  90. // Use the default:
  91. DebugTraceX ( 0, "Using default for ID: %d", dwID );
  92. strNew = ::SysAllocString ( wszDefault );
  93. if ( !strNew ) {
  94. FatalTrace ( 0, "Out of memory" );
  95. BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
  96. }
  97. }
  98. SAFE_FREE_BSTR ( *pstrOut );
  99. *pstrOut = strNew;
  100. Exit:
  101. if ( FAILED(hr) ) {
  102. ErrorTraceX ( 0, "Failed to get metabase property ID: %d, Error: %x", dwID, hr );
  103. SetLastError ( HRESULTTOWIN32 ( hr ) );
  104. }
  105. return SUCCEEDED(hr);
  106. }
  107. BOOL StdGetMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, LPCWSTR mszDefault, CMultiSz * pmszOut, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
  108. {
  109. TraceQuietEnter ( "StdGetMetabaseProp <CMultiSz>" );
  110. HRESULT hr = NOERROR;
  111. BSTR strNew = NULL;
  112. DWORD cbRequired = 0;
  113. DWORD cchRequired = 0;
  114. BOOL fUseDefault = FALSE;
  115. LPWSTR msz = NULL;
  116. // Get the length of the string to retrieve:
  117. hr = pMB->GetDataSize ( wszPath, dwID, MULTISZ_METADATA, &cbRequired, dwFlags, dwUserType );
  118. cchRequired = cbRequired / sizeof ( WCHAR );
  119. // Is the value there?
  120. if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
  121. // No, so use the default that was passed in.
  122. DebugTraceX ( 0, "Using default for ID: %d", dwID );
  123. fUseDefault = TRUE;
  124. hr = NOERROR;
  125. }
  126. BAIL_ON_FAILURE(hr);
  127. if ( !fUseDefault ) {
  128. msz = new WCHAR [ cchRequired ];
  129. if ( !msz ) {
  130. FatalTrace ( 0, "Out of memory" );
  131. BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
  132. }
  133. // Get the metabase string:
  134. hr = pMB->GetData ( wszPath, dwID, dwUserType, MULTISZ_METADATA, msz, &cbRequired, dwFlags );
  135. BAIL_ON_FAILURE(hr);
  136. *pmszOut = msz;
  137. }
  138. if ( fUseDefault ) {
  139. // Use the default:
  140. DebugTraceX ( 0, "Using default for ID: %d", dwID );
  141. *pmszOut = mszDefault;
  142. }
  143. if ( !*pmszOut ) {
  144. BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
  145. }
  146. Exit:
  147. delete msz;
  148. if ( FAILED(hr) ) {
  149. ErrorTraceX ( 0, "Failed to get metabase property ID: %d, Error: %x", dwID, hr );
  150. SetLastError ( HRESULTTOWIN32 ( hr ) );
  151. }
  152. return SUCCEEDED(hr);
  153. }
  154. BOOL StdPutMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, BOOL fValue, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
  155. {
  156. TraceQuietEnter ( "StdPutMetabaseProp <BOOL>" );
  157. HRESULT hr;
  158. hr = pMB->SetDword ( wszPath, dwID, fValue, dwFlags, dwUserType );
  159. if ( FAILED(hr) ) {
  160. ErrorTraceX ( 0, "Failed to put metabase property ID: %d, Error: %x", dwID, hr );
  161. SetLastError ( HRESULTTOWIN32 ( hr ) );
  162. }
  163. return SUCCEEDED(hr);
  164. }
  165. BOOL StdPutMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, DWORD dwValue, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
  166. {
  167. TraceQuietEnter ( "StdPutMetabaseProp <DWORD>" );
  168. HRESULT hr;
  169. hr = pMB->SetDword ( wszPath, dwID, dwValue, dwFlags, dwUserType );
  170. if ( FAILED(hr) ) {
  171. ErrorTraceX ( 0, "Failed to put metabase property ID: %d, Error: %x", dwID, hr );
  172. SetLastError ( HRESULTTOWIN32 ( hr ) );
  173. }
  174. return SUCCEEDED(hr);
  175. }
  176. BOOL StdPutMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, BSTR strValue, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
  177. {
  178. TraceQuietEnter ( "StdPutMetabaseProp <BSTR>" );
  179. _ASSERT ( strValue );
  180. HRESULT hr;
  181. if ( !strValue ) {
  182. // Just skip it, but log the trace.
  183. FatalTrace ( 0, "strValue should not be NULL here" );
  184. return TRUE;
  185. }
  186. hr = pMB->SetString ( wszPath, dwID, strValue, dwFlags, dwUserType );
  187. BAIL_ON_FAILURE (hr);
  188. Exit:
  189. if ( FAILED(hr) ) {
  190. ErrorTraceX ( 0, "Failed to put metabase property ID: %d, Error: %x", dwID, hr );
  191. SetLastError ( HRESULTTOWIN32 ( hr ) );
  192. }
  193. return SUCCEEDED(hr);
  194. }
  195. BOOL StdPutMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, CMultiSz * pmszValue, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
  196. {
  197. TraceQuietEnter ( "StdPutMetabaseProp <BSTR>" );
  198. _ASSERT ( pmszValue );
  199. if ( !*pmszValue ) {
  200. // Just skip it, but log the trace.
  201. FatalTrace ( 0, "strValue should not be NULL here" );
  202. return TRUE;
  203. }
  204. HRESULT hr;
  205. DWORD cbMultiSz;
  206. LPCWSTR wszValue;
  207. cbMultiSz = pmszValue->SizeInBytes ();
  208. wszValue = *pmszValue;
  209. hr = pMB->SetData ( wszPath, dwID, dwUserType, MULTISZ_METADATA, (void *) wszValue, cbMultiSz, dwFlags );
  210. BAIL_ON_FAILURE (hr);
  211. Exit:
  212. if ( FAILED(hr) ) {
  213. ErrorTraceX ( 0, "Failed to put metabase property ID: %d, Error: %x", dwID, hr );
  214. SetLastError ( HRESULTTOWIN32 ( hr ) );
  215. }
  216. return SUCCEEDED(hr);
  217. }
  218. BOOL HasKeyChanged ( IMSAdminBase * pMetabase, METADATA_HANDLE hKey, const FILETIME * pftLastChanged, LPCWSTR wszSubKey )
  219. {
  220. TraceFunctEnter ( "HasKeyChanged" );
  221. FILETIME ftNew;
  222. HRESULT hr = NOERROR;
  223. BOOL fResult = FALSE;
  224. if ( pftLastChanged->dwHighDateTime == 0 && pftLastChanged->dwLowDateTime == 0 ) {
  225. ErrorTrace ( 0, "Last changed time is NULL" );
  226. // No setting, so say it hasn't changed:
  227. goto Exit;
  228. }
  229. hr = pMetabase->GetLastChangeTime ( hKey, wszSubKey, &ftNew, FALSE );
  230. if ( FAILED (hr) ) {
  231. ErrorTrace ( 0, "Failed to get last change time: %x", hr );
  232. // This is an unexpected error. Ignore it.
  233. goto Exit;
  234. }
  235. // Has the metabase been changed since last time?
  236. // Time can't go backwards:
  237. _ASSERT ( ftNew.dwHighDateTime >= pftLastChanged->dwHighDateTime );
  238. _ASSERT ( ftNew.dwLowDateTime >= pftLastChanged->dwLowDateTime ||
  239. ftNew.dwHighDateTime > pftLastChanged->dwHighDateTime );
  240. if ( ftNew.dwHighDateTime != pftLastChanged->dwHighDateTime ||
  241. ftNew.dwLowDateTime != pftLastChanged->dwLowDateTime ) {
  242. fResult = TRUE;
  243. }
  244. Exit:
  245. TraceFunctLeave ();
  246. return FALSE;
  247. }
  248. BOOL IsValidIntegerSubKey ( LPCWSTR wszSubKey )
  249. {
  250. TraceQuietEnter ( "IsValidIntegerSubKey" );
  251. WCHAR wszIntegerKey [ METADATA_MAX_NAME_LEN ];
  252. DWORD dwItemValue;
  253. dwItemValue = _wtoi ( wszSubKey );
  254. wsprintf ( wszIntegerKey, _T("%d"), dwItemValue );
  255. // If the key is nonzero AND
  256. // The key is just the itoa value of the number:
  257. if ( dwItemValue != 0 &&
  258. lstrcmp ( wszIntegerKey, wszSubKey ) == 0 ) {
  259. return TRUE;
  260. }
  261. else {
  262. return FALSE;
  263. }
  264. }