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.

405 lines
12 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1999 - 1999
  5. *
  6. * File: bookmark.inl
  7. *
  8. * Contents: Implementation file for CBookmark
  9. *
  10. * History: 25-Oct-99 vivekj Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #include "uastrfnc.h" // from $(SHELL_INC_PATH), for unaligned string functions
  14. /*+-------------------------------------------------------------------------*
  15. * UnalignedValueAt
  16. *
  17. * Returns the value at a potentially unaligned address.
  18. *--------------------------------------------------------------------------*/
  19. template<typename T>
  20. T UnalignedValueAt (UNALIGNED T* pT)
  21. {
  22. return (*pT);
  23. }
  24. //############################################################################
  25. //############################################################################
  26. //
  27. // Implementation of class CDynamicPathEntry
  28. //
  29. //############################################################################
  30. //############################################################################
  31. /*+-------------------------------------------------------------------------*
  32. *
  33. * CDynamicPathEntry::ScInitialize
  34. *
  35. * PURPOSE: Initializes the entry from a byte array read in from a console file.
  36. *
  37. * PARAMETERS:
  38. * bool bIs10Path : true if the path entry format is that of MMC1.0.
  39. * I iter: The byte array.
  40. *
  41. * RETURNS:
  42. * inline SC
  43. *
  44. *+-------------------------------------------------------------------------*/
  45. inline SC
  46. CDynamicPathEntry::ScInitialize(bool bIs10Path, /*[IN,OUT]*/ByteVector::iterator &iter)
  47. {
  48. DECLARE_SC(sc, TEXT("CDynamicPathEntry::ScInitialize"));
  49. if(bIs10Path) // an MMC1.0 path entry. Just the display name
  50. {
  51. m_type = NDTYP_STRING;
  52. m_strEntry = reinterpret_cast<LPCWSTR>(iter);
  53. iter += (m_strEntry.length() + 1) *sizeof(WCHAR); // bump up the iterator.
  54. }
  55. else // a 1.1 or 1.2 path. The first byte contains the type.
  56. {
  57. m_type = *iter++; // either NDTYP_STRING or NDTYP_CUSTOM
  58. switch(m_type)
  59. {
  60. default:
  61. sc = E_UNEXPECTED;
  62. break;
  63. case NDTYP_STRING:
  64. {
  65. LPCWSTR pszEntry = reinterpret_cast<LPCWSTR>(iter);
  66. sc = ScCheckPointers(pszEntry);
  67. if(sc)
  68. return sc;
  69. #ifdef ALIGNMENT_MACHINE
  70. /*
  71. * Bug 128010: if our target machine requires data alignment and
  72. * the source is unaligned, make an aligned copy that we can
  73. * pass to std::wstring::operator=, which calls wcs* functions
  74. * expect aligned data
  75. */
  76. if (!IS_ALIGNED (pszEntry))
  77. {
  78. LPWSTR pszNew = (LPWSTR) alloca ((ualstrlenW(pszEntry) + 1) * sizeof(WCHAR));
  79. sc = ScCheckPointers(pszNew);
  80. if(sc)
  81. return sc;
  82. ualstrcpyW (pszNew, pszEntry);
  83. pszEntry = pszNew;
  84. }
  85. #endif
  86. m_strEntry = pszEntry;
  87. // bump the input pointer to the next element
  88. iter += (m_strEntry.length() + 1) * sizeof (WCHAR);
  89. break;
  90. }
  91. case NDTYP_CUSTOM:
  92. const SNodeID* pNodeID = reinterpret_cast<const SNodeID*>(iter); // same binary layout as a SNodeID.
  93. if(!pNodeID)
  94. return (sc = E_UNEXPECTED);
  95. /*
  96. * Bug 177492: pNodeID->cBytes may be unaligned, so make an aligned copy of it
  97. */
  98. const DWORD cBytes = UnalignedValueAt (&pNodeID->cBytes);
  99. m_byteVector.insert(m_byteVector.end(), pNodeID->id, pNodeID->id + cBytes);
  100. /*if(pNodeID->cBytes==0)
  101. m_dwFlags = MMC_NODEID_SLOW_RETRIEVAL; */ // shouldn't need this; should not be able to save such a bookmark.
  102. iter += sizeof (pNodeID->cBytes) + cBytes; // bump up the pointer.
  103. break;
  104. }
  105. }
  106. return sc;
  107. }
  108. inline bool
  109. CDynamicPathEntry::operator ==(const CDynamicPathEntry &rhs) const
  110. {
  111. // check the types
  112. if(!(m_type & rhs.m_type & (NDTYP_CUSTOM | NDTYP_STRING))) // bitwise OR - at least one type must be in common
  113. return false;
  114. // if both types implement NDTYP_CUSTOM, use that preferentially. Else, compare based on display names.
  115. if(m_type & rhs.m_type & NDTYP_CUSTOM)
  116. return (m_byteVector == rhs.m_byteVector);
  117. else // (m_type & rhs.m_type & NDTYP_STRING)
  118. return (m_strEntry == rhs.m_strEntry);
  119. }
  120. inline bool
  121. CDynamicPathEntry::operator < (const CDynamicPathEntry &rhs) const
  122. {
  123. // If both have NDTYP_CUSTOM in common, compare byte vector
  124. // else if both have NDTYP_STRING in common, compare strings.
  125. // Otherwise (have nothing in common), use m_type to impose the ordering
  126. if (rhs.m_type & m_type & NDTYP_CUSTOM)
  127. return std::lexicographical_compare(m_byteVector.begin(),
  128. m_byteVector.end(),
  129. rhs.m_byteVector.begin(),
  130. rhs.m_byteVector.end());
  131. else if (rhs.m_type & m_type & NDTYP_STRING)
  132. return m_strEntry < rhs.m_strEntry;
  133. else
  134. return (m_type < rhs.m_type);
  135. }
  136. /*--------------------------------------------------------------------------*
  137. * InsertScalar
  138. *
  139. * Inserts a scalar value of type T into an output stream as a series of
  140. * the output stream's value_type.
  141. *--------------------------------------------------------------------------*/
  142. template<typename Container, typename T>
  143. void InsertScalar (Container& c, const T& t)
  144. {
  145. Container::const_iterator itFrom = reinterpret_cast<Container::const_iterator>(&t);
  146. std::copy (itFrom, itFrom + sizeof (t), std::back_inserter(c));
  147. }
  148. //############################################################################
  149. //############################################################################
  150. //
  151. // Implementation of class CBookmark
  152. //
  153. //############################################################################
  154. //############################################################################
  155. inline bool
  156. CBookmark::operator ==(const CBookmark& other) const
  157. {
  158. return ((m_idStatic == other.m_idStatic) &&
  159. (m_dynamicPath == other.m_dynamicPath));
  160. }
  161. inline bool
  162. CBookmark::operator!=(const CBookmark& other) const
  163. {
  164. return (!(*this == other));
  165. }
  166. inline bool
  167. CBookmark::operator<(const CBookmark& other) const
  168. {
  169. if (m_idStatic < other.m_idStatic)
  170. return true;
  171. if (m_idStatic == other.m_idStatic)
  172. {
  173. return std::lexicographical_compare( m_dynamicPath.begin(),
  174. m_dynamicPath.end(),
  175. other.m_dynamicPath.begin(),
  176. other.m_dynamicPath.end() );
  177. }
  178. return false;
  179. }
  180. /*+-------------------------------------------------------------------------*
  181. *
  182. * CBookmark::HBOOKMARK
  183. *
  184. * PURPOSE: Casts a bookmark into an HBOOKMARK
  185. *
  186. * RETURNS:
  187. * operator
  188. *
  189. *+-------------------------------------------------------------------------*/
  190. inline
  191. CBookmark:: operator HBOOKMARK() const
  192. {
  193. return reinterpret_cast<HBOOKMARK>(this);
  194. }
  195. /*+-------------------------------------------------------------------------*
  196. *
  197. * CBookmark::GetBookmark
  198. *
  199. * PURPOSE: Converts an HBOOKMARK to a CBookmark.
  200. *
  201. * PARAMETERS:
  202. * HBOOKMARK hbm :
  203. *
  204. * RETURNS:
  205. * CBookmark *
  206. *
  207. *+-------------------------------------------------------------------------*/
  208. inline CBookmark *
  209. CBookmark::GetBookmark(HBOOKMARK hbm)
  210. {
  211. return reinterpret_cast<CBookmark *>(hbm);
  212. }
  213. /*+-------------------------------------------------------------------------*
  214. *
  215. * CBookmark::Load
  216. *
  217. * PURPOSE:
  218. *
  219. * PARAMETERS:
  220. * IStream& stm :
  221. *
  222. * RETURNS:
  223. * inline IStream&
  224. *
  225. *+-------------------------------------------------------------------------*/
  226. inline IStream&
  227. CBookmark::Load(IStream& stm)
  228. {
  229. // loading from a stream. Convert from one of the legacy formats.
  230. // 1. Read the static node ID
  231. stm >> m_idStatic;
  232. m_dynamicPath.clear();
  233. // 2. Read the dynamic path
  234. ByteVector vDynamicPath;
  235. ByteVector::iterator iter;
  236. stm >> vDynamicPath;
  237. // 2a. If the dynamic path is empty, we're done.
  238. if(vDynamicPath.empty())
  239. return (stm);
  240. // 3. Strip out the unnecessary details like the signature, etc.
  241. // 3a. Check for a signature
  242. iter = vDynamicPath.begin();
  243. bool bIs10Path = true;
  244. if(memcmp (iter, BOOKMARK_CUSTOMSTREAMSIGNATURE,
  245. sizeof(BOOKMARK_CUSTOMSTREAMSIGNATURE)) == 0)
  246. {
  247. // throw away the signature and the following version bytes
  248. iter += (sizeof(BOOKMARK_CUSTOMSTREAMSIGNATURE) + sizeof(DWORD));
  249. bIs10Path = false; //is a post-MMC1.0 path.
  250. }
  251. // create new entries for each piece.
  252. while(iter != vDynamicPath.end())
  253. {
  254. CDynamicPathEntry entry;
  255. entry.ScInitialize(bIs10Path, iter); //NOTE: iter is an in/out parameter.
  256. m_dynamicPath.push_back(entry);
  257. }
  258. return (stm);
  259. }
  260. /*+-------------------------------------------------------------------------*
  261. *
  262. * CBookmark::Persist
  263. *
  264. * PURPOSE: Persists the bookmark
  265. *
  266. * PARAMETERS:
  267. * CPersistor & persistor :
  268. *
  269. * RETURNS:
  270. * void
  271. *
  272. *+-------------------------------------------------------------------------*/
  273. inline void
  274. CBookmark::Persist(CPersistor &persistor)
  275. {
  276. DECLARE_SC(sc, TEXT("CBookmark::Persist"));
  277. // check and persist only valid node ids
  278. if (persistor.IsStoring() && (m_idStatic == ID_Unknown))
  279. sc.Throw(E_UNEXPECTED);
  280. persistor.PersistAttribute(XML_ATTR_BOOKMARK_STATIC, m_idStatic);
  281. bool bPersistList = persistor.IsLoading() ? (persistor.HasElement(XML_ATTR_BOOKMARK_DYNAMIC_PATH, NULL)) :
  282. (m_dynamicPath.size() > 0);
  283. if (bPersistList)
  284. persistor.PersistList(XML_ATTR_BOOKMARK_DYNAMIC_PATH, NULL, m_dynamicPath);
  285. }
  286. /*+-------------------------------------------------------------------------*
  287. *
  288. * CDynamicPathEntry::Persist
  289. *
  290. * PURPOSE: Persists the dynamic path entry of the bookmark
  291. *
  292. * PARAMETERS:
  293. * CPersistor & persistor :
  294. *
  295. * RETURNS:
  296. * void
  297. *
  298. *+-------------------------------------------------------------------------*/
  299. inline void
  300. CDynamicPathEntry::Persist(CPersistor &persistor)
  301. {
  302. DECLARE_SC(sc, TEXT("CDynamicPathEntry::Persist"));
  303. if ( (m_type & NDTYP_STRING) || persistor.IsLoading())
  304. persistor.PersistAttribute(XML_ATTR_BOOKMARK_DYN_STRING, m_strEntry, attr_optional);
  305. if ( (m_type & NDTYP_CUSTOM) || persistor.IsLoading())
  306. {
  307. CXMLAutoBinary binData;
  308. if (persistor.IsStoring())
  309. {
  310. if (m_byteVector.size())
  311. {
  312. sc = binData.ScAlloc(m_byteVector.size());
  313. if (sc)
  314. sc.Throw();
  315. CXMLBinaryLock sLock(binData); // unlocks on destructor
  316. LPBYTE pData = NULL;
  317. sc = sLock.ScLock(&pData);
  318. if (sc)
  319. sc.Throw();
  320. std::copy(m_byteVector.begin(), m_byteVector.end(), pData);
  321. }
  322. }
  323. persistor.PersistAttribute(XML_ATTR_BOOKMARK_DYN_CUSTOM, binData, attr_optional);
  324. if (persistor.IsLoading())
  325. {
  326. m_byteVector.clear();
  327. if (binData.GetSize()) // if there is nothing to read it won't be allocated
  328. {
  329. CXMLBinaryLock sLock(binData); // unlocks on destructor
  330. LPBYTE pData = NULL;
  331. sc = sLock.ScLock(&pData);
  332. if (sc)
  333. sc.Throw();
  334. m_byteVector.assign( pData, pData + binData.GetSize() );
  335. }
  336. }
  337. }
  338. if (persistor.IsLoading()) // determine the format(s) available
  339. {
  340. m_type = 0;
  341. if(m_strEntry.size() > 0)
  342. m_type |= NDTYP_STRING;
  343. if(m_byteVector.size())
  344. m_type |= NDTYP_CUSTOM;
  345. }
  346. }