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.

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