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.

472 lines
9.8 KiB

  1. // File: mrulist.cpp
  2. #include "precomp.h"
  3. #include "mrulist2.h"
  4. typedef struct {
  5. LPTSTR psz1;
  6. LPTSTR psz2;
  7. } SZSZ;
  8. typedef SZSZ * PSZSZ;
  9. typedef struct {
  10. LPTSTR psz1;
  11. LPTSTR psz2;
  12. DWORD dw;
  13. } SZSZDW;
  14. typedef SZSZDW * PSZSZDW;
  15. /* C M R U L I S T */
  16. /*-------------------------------------------------------------------------
  17. %%Function: CMRUList2
  18. -------------------------------------------------------------------------*/
  19. CMRUList2::CMRUList2(const DWSTR * prgDwStr, int cEntryMax, BOOL fReversed) :
  20. m_prgDwStr (prgDwStr),
  21. m_cEntryMax (cEntryMax),
  22. m_fReversed (fReversed),
  23. m_cEntry (0),
  24. m_rgpEntry (NULL),
  25. m_fDirty (FALSE)
  26. {
  27. DBGENTRY(CMRUList2::CMRUList2);
  28. ASSERT(NULL != prgDwStr);
  29. m_cCol = m_prgDwStr[0].dw;
  30. int cb = m_cEntryMax * sizeof(PMRUE);
  31. m_rgpEntry = new PMRUE[cb];
  32. if (NULL == m_rgpEntry)
  33. {
  34. ERROR_OUT(("CMRUList2 - out of memory"));
  35. return;
  36. }
  37. ZeroMemory(m_rgpEntry, cb);
  38. RegEntry re(PszRegKey(), HKEY_CURRENT_USER);
  39. if (ERROR_SUCCESS != re.GetError())
  40. return;
  41. m_cEntry = min(re.GetNumber(REGVAL_MRU_COUNT, 0), m_cEntryMax);
  42. for (int i = 0; i < m_cEntry; i++)
  43. {
  44. m_rgpEntry[i] = LoadEntry(&re, i);
  45. }
  46. }
  47. CMRUList2::~CMRUList2()
  48. {
  49. DBGENTRY(CMRUList2::~CMRUList2);
  50. if (m_fDirty)
  51. {
  52. Save();
  53. }
  54. for (int i = 0; i < m_cEntry; i++)
  55. {
  56. DeleteEntry(m_rgpEntry[i]);
  57. }
  58. delete m_rgpEntry;
  59. }
  60. ///////////////////////////////////////////////////////////////////////////
  61. PMRUE CMRUList2::LoadEntry(RegEntry * pre, int iItem)
  62. {
  63. if (m_fReversed)
  64. {
  65. iItem = (m_cEntry - (iItem+1));
  66. }
  67. PMRUE pEntry = (PMRUE) new PVOID[m_cCol*sizeof(PVOID)];
  68. if (NULL != pEntry)
  69. {
  70. PVOID ** ppv = (PVOID **) pEntry;
  71. for (int iCol = 0; iCol < m_cCol; iCol++, ppv++)
  72. {
  73. TCHAR szKey[MAX_PATH];
  74. wsprintf(szKey, TEXT("%s%d"), PszPrefixForCol(iCol), iItem);
  75. switch (MruTypeForCol(iCol))
  76. {
  77. default:
  78. case MRUTYPE_SZ:
  79. * (LPTSTR *)ppv = PszAlloc(pre->GetString(szKey));
  80. break;
  81. case MRUTYPE_DW:
  82. * (DWORD *) ppv = pre->GetNumber(szKey);
  83. break;
  84. }
  85. }
  86. }
  87. return pEntry;
  88. }
  89. VOID CMRUList2::StoreEntry(RegEntry * pre, int iItem)
  90. {
  91. PVOID ** ppv = (PVOID **) GetEntry(iItem);
  92. if (m_fReversed)
  93. {
  94. iItem = (m_cEntry - (iItem+1));
  95. }
  96. for (int iCol = 0; iCol < m_cCol; iCol++, ppv++)
  97. {
  98. TCHAR szKey[MAX_PATH];
  99. wsprintf(szKey, TEXT("%s%d"), PszPrefixForCol(iCol), iItem);
  100. switch (MruTypeForCol(iCol))
  101. {
  102. default:
  103. case MRUTYPE_SZ:
  104. pre->SetValue(szKey, * (LPCTSTR *)ppv);
  105. break;
  106. case MRUTYPE_DW:
  107. pre->SetValue(szKey, * (ULONG *) ppv);
  108. break;
  109. }
  110. }
  111. }
  112. VOID CMRUList2::DeleteEntry(PMRUE pEntry)
  113. {
  114. PVOID ** ppv = (PVOID **) pEntry;
  115. for (int iCol = 0; iCol < m_cCol; iCol++, ppv++)
  116. {
  117. switch (MruTypeForCol(iCol))
  118. {
  119. default:
  120. case MRUTYPE_SZ:
  121. delete *ppv;
  122. break;
  123. case MRUTYPE_DW:
  124. break;
  125. }
  126. }
  127. delete pEntry;
  128. }
  129. VOID CMRUList2::DeleteEntry(int iItem)
  130. {
  131. if ((iItem < 0) || (iItem >= m_cEntry))
  132. return; // nothing to do
  133. // delete the data
  134. DeleteEntry(m_rgpEntry[iItem]);
  135. // decrement the count
  136. m_cEntry--;
  137. // shift items up
  138. for ( ; iItem < m_cEntry; iItem++)
  139. {
  140. m_rgpEntry[iItem] = m_rgpEntry[iItem+1];
  141. }
  142. // the list has been modified
  143. m_fDirty = TRUE;
  144. }
  145. //--------------------------------------------------------------------------//
  146. // CMRUList2::DeleteEntry. //
  147. // This DeleteEntry() deletes the first entry it finds thats primary //
  148. // string matches the one passed in. //
  149. //--------------------------------------------------------------------------//
  150. void
  151. CMRUList2::DeleteEntry
  152. (
  153. const TCHAR * const primaryString
  154. ){
  155. int items = GetNumEntries();
  156. for( int nn = 0; nn < items; nn++ )
  157. {
  158. if( StrCmpI( primaryString, * ((const TCHAR * const * const) m_rgpEntry[ nn ]) ) == 0 )
  159. {
  160. DeleteEntry( nn );
  161. break;
  162. }
  163. }
  164. } // End of CMRUList2::DeleteEntry.
  165. /* C O M P A R E E N T R Y */
  166. /*-------------------------------------------------------------------------
  167. %%Function: CompareEntry
  168. -------------------------------------------------------------------------*/
  169. int CMRUList2::CompareEntry(int iItem, PMRUE pEntry)
  170. {
  171. ASSERT(NULL != pEntry);
  172. int iRet = 0;
  173. PVOID * ppv1 = (PVOID *) GetEntry(iItem);
  174. PVOID * ppv2 = (PVOID *) pEntry;
  175. for (int iCol = 0; iCol < m_cCol; iCol++, ppv1++, ppv2++)
  176. {
  177. switch (MruTypeForCol(iCol))
  178. {
  179. default:
  180. case MRUTYPE_SZ:
  181. iRet = lstrcmpi(* (LPCTSTR *) ppv1, * (LPCTSTR *) ppv2);
  182. break;
  183. case MRUTYPE_DW:
  184. iRet = (* (int *) ppv1) - (* (int *) ppv2);
  185. break;
  186. }
  187. if (0 != iRet)
  188. break;
  189. }
  190. return iRet;
  191. }
  192. /* F I N D E N T R Y */
  193. /*-------------------------------------------------------------------------
  194. %%Function: FindEntry
  195. Return -1 if the item is not found.
  196. -------------------------------------------------------------------------*/
  197. int CMRUList2::FindEntry(PMRUE pEntry)
  198. {
  199. int cItems = GetNumEntries();
  200. for (int i = 0; i < cItems; i++)
  201. {
  202. if (0 == CompareEntry(i, pEntry))
  203. {
  204. return i;
  205. }
  206. }
  207. return -1; // not found
  208. }
  209. /* S A V E */
  210. /*-------------------------------------------------------------------------
  211. %%Function: Save
  212. -------------------------------------------------------------------------*/
  213. HRESULT CMRUList2::Save(void)
  214. {
  215. DBGENTRY(CMRUList2::Save);
  216. // Retrieve the data from the registry
  217. RegEntry re(PszRegKey(), HKEY_CURRENT_USER);
  218. if (ERROR_SUCCESS != re.GetError())
  219. return E_FAIL;
  220. re.SetValue(REGVAL_MRU_COUNT, m_cEntry);
  221. for (int i = 0; i < m_cEntry; i++)
  222. {
  223. StoreEntry(&re, i);
  224. }
  225. return S_OK;
  226. }
  227. /* S H I F T E N T R I E S D O W N */
  228. /*-------------------------------------------------------------------------
  229. %%Function: ShiftEntriesDown
  230. Shift the entires down by one slot leaving the first position open.
  231. -------------------------------------------------------------------------*/
  232. VOID CMRUList2::ShiftEntriesDown(int cItem)
  233. {
  234. if (cItem < 1)
  235. return; // nothing to do
  236. int iItem;
  237. for (iItem = cItem; iItem > 0; iItem--)
  238. {
  239. m_rgpEntry[iItem] = m_rgpEntry[iItem-1];
  240. }
  241. // the list has been modified
  242. m_fDirty = TRUE;
  243. }
  244. /* M O V E E N T R Y T O T O P */
  245. /*-------------------------------------------------------------------------
  246. %%Function: MoveEntryToTop
  247. -------------------------------------------------------------------------*/
  248. VOID CMRUList2::MoveEntryToTop(int iItem)
  249. {
  250. DBGENTRY(CMRUList2::MoveEntryToTop);
  251. if ((iItem < 1) || (iItem >= m_cEntry))
  252. return; // nothing to do
  253. PMRUE pEntry = GetEntry(iItem);
  254. ShiftEntriesDown(iItem);
  255. m_rgpEntry[0] = pEntry;
  256. }
  257. /* A D D E N T R Y */
  258. /*-------------------------------------------------------------------------
  259. %%Function: AddEntry
  260. Put the entry into the top of the list.
  261. The data is owned by the list after this.
  262. Returns:
  263. S_OK - added to the head of the list
  264. S_FALSE - already in list (item is moved to top)
  265. -------------------------------------------------------------------------*/
  266. HRESULT CMRUList2::AddEntry(PMRUE pEntry)
  267. {
  268. DBGENTRY(CMRUList2::AddEntry);
  269. HRESULT ret = S_OK;
  270. // the list has been modified
  271. m_fDirty = TRUE;
  272. int cShift;
  273. int iItem = FindEntry(pEntry);
  274. if (-1 != iItem)
  275. {
  276. // This entry already exists, delete it so we get the new info
  277. DeleteEntry(m_rgpEntry[iItem]);
  278. cShift = iItem;
  279. ret = S_FALSE; // Success, but already in the list
  280. }
  281. else if (m_cEntryMax == m_cEntry)
  282. {
  283. // drop the last item
  284. DeleteEntry(m_rgpEntry[m_cEntry-1]);
  285. cShift = m_cEntry-1;
  286. }
  287. else
  288. {
  289. cShift = m_cEntry;
  290. m_cEntry++;
  291. }
  292. ShiftEntriesDown(cShift);
  293. // add it to the head of the list
  294. m_rgpEntry[0] = pEntry;
  295. return ret;
  296. }
  297. HRESULT CMRUList2::AddEntry(LPCTSTR pcsz)
  298. {
  299. LPTSTR * ppsz = new LPTSTR;
  300. LPTSTR psz = PszAlloc(pcsz);
  301. if ((NULL == ppsz) || (NULL == psz))
  302. {
  303. delete ppsz;
  304. delete psz;
  305. return E_OUTOFMEMORY;
  306. }
  307. *ppsz = psz;
  308. return AddEntry((PMRUE) ppsz);
  309. }
  310. HRESULT CMRUList2::AddEntry(LPCTSTR pcsz1, LPCTSTR pcsz2)
  311. {
  312. PSZSZ pSzSz = new SZSZ;
  313. if (NULL == pSzSz)
  314. return E_OUTOFMEMORY;
  315. pSzSz->psz1 = PszAlloc(pcsz1);
  316. pSzSz->psz2 = PszAlloc(pcsz2);
  317. if ((NULL == pSzSz->psz1) || (NULL == pSzSz->psz1))
  318. {
  319. // something failed - don't add anything
  320. DeleteEntry(pSzSz);
  321. return E_OUTOFMEMORY;
  322. }
  323. return AddEntry((PMRUE) pSzSz);
  324. }
  325. HRESULT CMRUList2::AddEntry(LPCTSTR pcsz1, LPCTSTR pcsz2, DWORD dw3)
  326. {
  327. PSZSZDW pData = new SZSZDW;
  328. if (NULL == pData)
  329. return E_OUTOFMEMORY;
  330. pData->psz1 = PszAlloc(pcsz1);
  331. pData->psz2 = PszAlloc(pcsz2);
  332. if ((NULL == pData->psz1) || (NULL == pData->psz1))
  333. {
  334. // something failed - don't add anything
  335. DeleteEntry(pData);
  336. return E_OUTOFMEMORY;
  337. }
  338. pData->dw = dw3;
  339. return AddEntry((PMRUE) pData);
  340. }
  341. /*-------------------------------------------------------------------------
  342. %%Function: GetString
  343. Return the data associated with the entry
  344. -------------------------------------------------------------------------*/
  345. LPCTSTR CMRUList2::GetString(int iItem, int iCol)
  346. {
  347. if (!FValidIndex(iItem))
  348. {
  349. return(NULL);
  350. }
  351. return(GetString(GetEntry(iItem), iCol));
  352. }
  353. DWORD CMRUList2::GetDWORD(int iItem, int iCol)
  354. {
  355. if (!FValidIndex(iItem))
  356. {
  357. return(0);
  358. }
  359. return(GetDWORD(GetEntry(iItem), iCol));
  360. }
  361. LPCTSTR CMRUList2::GetString(PMRUE pEntry, int iCol)
  362. {
  363. if (iCol >= m_cCol
  364. || MRUTYPE_SZ != m_prgDwStr[iCol+1].dw
  365. )
  366. {
  367. return(NULL);
  368. }
  369. LPTSTR * ppsz = reinterpret_cast<LPTSTR *>(pEntry);
  370. return * (ppsz+iCol);
  371. }
  372. DWORD CMRUList2::GetDWORD(PMRUE pEntry, int iCol)
  373. {
  374. if (iCol >= m_cCol
  375. || MRUTYPE_DW != m_prgDwStr[iCol+1].dw
  376. )
  377. {
  378. return(0);
  379. }
  380. DWORD * ppdw = reinterpret_cast<DWORD *>(pEntry);
  381. return * (ppdw+iCol);
  382. }