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.

531 lines
13 KiB

  1. /*
  2. * misc - misc stuff
  3. */
  4. #include "tweakui.h"
  5. /*****************************************************************************
  6. *
  7. * Eschew the C runtime
  8. *
  9. *****************************************************************************/
  10. void * __cdecl operator new(size_t nSize)
  11. {
  12. // Zero init just to save some headaches
  13. return((LPVOID)LocalAlloc(LPTR, nSize));
  14. }
  15. void __cdecl operator delete(void *pv)
  16. {
  17. LocalFree((HLOCAL)pv);
  18. }
  19. /*****************************************************************************
  20. *
  21. * Misc_NextPx
  22. *
  23. * Allocate another slot in the growable X array, returning its index.
  24. * The slot is not eaten, however.
  25. *
  26. * The array may move as a result of this call; the caller promises
  27. * not to use the resulting pointer after the next alloc call.
  28. *
  29. *****************************************************************************/
  30. PV PASCAL
  31. Misc_AllocPx(PGXA pgxa)
  32. {
  33. if (pgxa->cx >= pgxa->cxAlloc) {
  34. PV pv = lReAlloc(pgxa->pv, pgxa->cbx * (pgxa->cxAlloc + 5));
  35. if (pv) {
  36. pgxa->pv = pv;
  37. pgxa->cxAlloc += 5;
  38. } else {
  39. return 0;
  40. }
  41. }
  42. return (PBYTE)pgxa->pv + pgxa->cbx * pgxa->cx;
  43. }
  44. /*****************************************************************************
  45. *
  46. * Misc_InitPgxa
  47. *
  48. *****************************************************************************/
  49. BOOL PASCAL
  50. Misc_InitPgxa(PGXA pgxa, int cbx)
  51. {
  52. pgxa->cbx = cbx;
  53. pgxa->cxAlloc = 5;
  54. pgxa->cx = 0;
  55. pgxa->pv = lAlloc(pgxa->cbx * pgxa->cxAlloc);
  56. return pgxa->pv ? TRUE : FALSE;
  57. }
  58. /*****************************************************************************
  59. *
  60. * Misc_FreePgxa
  61. *
  62. *****************************************************************************/
  63. void PASCAL
  64. Misc_FreePgxa(PGXA pgxa)
  65. {
  66. if (pgxa->pv) {
  67. lFree(pgxa->pv);
  68. }
  69. }
  70. /*****************************************************************************
  71. *
  72. * Misc_EnableMenuFromHdlgId
  73. *
  74. * Enable or disable a menu item based on a dialog item.
  75. *
  76. *****************************************************************************/
  77. void PASCAL
  78. Misc_EnableMenuFromHdlgId(HMENU hmenu, HWND hdlg, UINT idc)
  79. {
  80. EnableMenuItem(hmenu, idc, MF_BYCOMMAND | (
  81. IsWindowEnabled(GetDlgItem(hdlg, idc)) ? 0 : MFS_GRAYED));
  82. }
  83. /*****************************************************************************
  84. *
  85. * Misc_LV_GetCurSel
  86. *
  87. * Return the selection index.
  88. *
  89. *****************************************************************************/
  90. int PASCAL
  91. Misc_LV_GetCurSel(HWND hwnd)
  92. {
  93. return ListView_GetNextItem(hwnd, -1, LVNI_FOCUSED);
  94. }
  95. /*****************************************************************************
  96. *
  97. * Misc_LV_SetCurSel
  98. *
  99. * Set the selection index.
  100. *
  101. *****************************************************************************/
  102. void PASCAL
  103. Misc_LV_SetCurSel(HWND hwnd, int iIndex)
  104. {
  105. ListView_SetItemState(hwnd, iIndex, LVIS_FOCUSED | LVIS_SELECTED,
  106. LVIS_FOCUSED | LVIS_SELECTED);
  107. }
  108. /*****************************************************************************
  109. *
  110. * Misc_LV_EnsureSel
  111. *
  112. * Make sure *something* is selected. Try to make it iItem.
  113. *
  114. *****************************************************************************/
  115. void PASCAL
  116. Misc_LV_EnsureSel(HWND hwnd, int iItem)
  117. {
  118. int iItemMax = ListView_GetItemCount(hwnd) - 1;
  119. if (iItem > iItemMax) {
  120. iItem = iItemMax;
  121. }
  122. Misc_LV_SetCurSel(hwnd, iItem);
  123. }
  124. /*****************************************************************************
  125. *
  126. * Misc_LV_GetItemInfo
  127. *
  128. * Grab some info out of an item.
  129. *
  130. * The incoming LV_ITEM should have any fields initialized which are
  131. * required by the mask. (E.g., the state mask.)
  132. *
  133. *****************************************************************************/
  134. void PASCAL
  135. Misc_LV_GetItemInfo(HWND hwnd, LV_ITEM FAR *plvi, int iItem, UINT mask)
  136. {
  137. plvi->iItem = iItem;
  138. plvi->iSubItem = 0;
  139. plvi->mask = mask;
  140. ListView_GetItem(hwnd, plvi);
  141. }
  142. /*****************************************************************************
  143. *
  144. * Misc_LV_GetParam
  145. *
  146. * Convert an iItem into the associated parameter.
  147. *
  148. *****************************************************************************/
  149. LPARAM PASCAL
  150. Misc_LV_GetParam(HWND hwnd, int iItem)
  151. {
  152. LV_ITEM lvi;
  153. Misc_LV_GetItemInfo(hwnd, &lvi, iItem, LVIF_PARAM);
  154. return lvi.lParam;
  155. }
  156. /*****************************************************************************
  157. *
  158. * Misc_LV_HitTest
  159. *
  160. * Perform a hit-test on the listview. The LPARAM parameter is
  161. * the screen coordinates of the message.
  162. *
  163. *****************************************************************************/
  164. void PASCAL
  165. Misc_LV_HitTest(HWND hwnd, LV_HITTESTINFO FAR *phti, LPARAM lpPos)
  166. {
  167. phti->pt.x = (signed short)LOWORD(lpPos);
  168. phti->pt.y = (signed short)HIWORD(lpPos);
  169. MapWindowPoints(HWND_DESKTOP, hwnd, &phti->pt, 1);
  170. ListView_HitTest(hwnd, phti);
  171. }
  172. /*****************************************************************************
  173. *
  174. * Misc_Combo_GetCurItemData
  175. *
  176. * Get the current item data from a combo box.
  177. *
  178. *****************************************************************************/
  179. LRESULT PASCAL
  180. Misc_Combo_GetCurItemData(HWND hwnd)
  181. {
  182. int iItem = ComboBox_GetCurSel(hwnd);
  183. return ComboBox_GetItemData(hwnd, iItem);
  184. }
  185. /*****************************************************************************
  186. *
  187. * Misc_Trim
  188. *
  189. * Trim leading and trailing spaces from a string. Returns a pointer
  190. * to the first non-space character, and slaps a '\0' on top of the
  191. * last trailing space.
  192. *
  193. *****************************************************************************/
  194. LPTSTR PASCAL
  195. Misc_Trim(LPTSTR ptsz)
  196. {
  197. int ctch;
  198. for ( ; (unsigned)(*ptsz - 1) <= ' '; ptsz++);
  199. for (ctch = lstrlen(ptsz); ctch && (unsigned)ptsz[ctch-1] <= ' '; ctch--);
  200. if (ctch) {
  201. ptsz[ctch] = '\0';
  202. }
  203. return ptsz;
  204. }
  205. /*****************************************************************************
  206. *
  207. * Misc_SetDrbSize
  208. *
  209. * Set the size of the buffer in a DRB.
  210. *
  211. *****************************************************************************/
  212. typedef struct DRB { /* dynamically resizable buffer */
  213. PV pv; /* Actual buffer */
  214. UINT cb; /* Size of buffer in bytes */
  215. } DRB, *PDRB;
  216. void PASCAL
  217. Misc_SetDrbSize(PDRB pdrb, UINT cb)
  218. {
  219. if (pdrb->pv) {
  220. LocalFree(pdrb->pv);
  221. pdrb->pv = 0;
  222. pdrb->cb = 0;
  223. }
  224. if (cb) {
  225. pdrb->pv = LocalAlloc(LMEM_FIXED, cb);
  226. if (pdrb->pv) {
  227. pdrb->cb = cb;
  228. }
  229. }
  230. }
  231. /*****************************************************************************
  232. *
  233. * Misc_EnsureDrb
  234. *
  235. * Make sure that the DRB can handle at least cb bytes.
  236. *
  237. * Round up to 4K boundary for convenience.
  238. *
  239. *****************************************************************************/
  240. BOOL PASCAL
  241. Misc_EnsureDrb(PDRB pdrb, UINT cb)
  242. {
  243. if (cb <= pdrb->cb) {
  244. } else {
  245. Misc_SetDrbSize(pdrb, (cb + 1023) & ~1023);
  246. }
  247. return pdrb->pv ? TRUE : FALSE;
  248. }
  249. /*****************************************************************************
  250. *
  251. * Misc_CopyRegWorker
  252. *
  253. * Copy a registry tree from one point to another.
  254. *
  255. * Since this is a recursive routine, don't allocate lots of goo off the
  256. * stack.
  257. *
  258. *****************************************************************************/
  259. typedef struct RCI { /* registry copy info */
  260. DRB drb; /* Data being copied */
  261. TCH tszKey[ctchKeyMax]; /* Key name buffer */
  262. } RCI, *PRCI;
  263. BOOL PASCAL
  264. Misc_CopyRegWorker(PRCI prci, HKEY hkSrcRoot, PCTSTR ptszSrc,
  265. HKEY hkDstRoot, PCTSTR ptszDst)
  266. {
  267. HKEY hkSrc, hkDst;
  268. BOOL fRc;
  269. if (_RegOpenKey(hkSrcRoot, ptszSrc, &hkSrc) == 0) {
  270. if (RegCreateKey(hkDstRoot, ptszDst, &hkDst) == 0) {
  271. int i;
  272. /*
  273. * The first loop copies the values.
  274. */
  275. for (i = 0; ; i++) {
  276. DWORD ctch = cA(prci->tszKey), cb = 0, dwType;
  277. switch (RegEnumValue(hkSrc, i, prci->tszKey, &ctch, 0,
  278. &dwType, 0, &cb)) {
  279. case ERROR_NO_MORE_ITEMS: goto valuesdone;
  280. /*
  281. * We can get an ERROR_SUCCESS if the value length is 0.
  282. */
  283. case ERROR_SUCCESS:
  284. case ERROR_MORE_DATA:
  285. if (Misc_EnsureDrb(&prci->drb, cb)) {
  286. DWORD dwType;
  287. if (RegQueryValueEx(hkSrc, prci->tszKey, 0, &dwType,
  288. (LPBYTE)prci->drb.pv, &cb) == 0 &&
  289. RegSetValueEx(hkDst, prci->tszKey, 0, dwType,
  290. (LPBYTE)prci->drb.pv, cb) == 0) {
  291. } else {
  292. fRc = 0; goto stopkey;
  293. }
  294. } else {
  295. fRc = 0; goto stopkey;
  296. }
  297. break;
  298. default:
  299. fRc = 0; goto stopkey;
  300. }
  301. }
  302. valuesdone:;
  303. /*
  304. * The second loop recurses on each subkey.
  305. */
  306. for (i = 0; ; i++) {
  307. switch (RegEnumKey(hkSrc, i, prci->tszKey, cA(prci->tszKey))) {
  308. case ERROR_NO_MORE_ITEMS: goto keysdone;
  309. /*
  310. * We can get an ERROR_SUCCESS if the subkey length is 0.
  311. * (Thought that might be illegal for other reasons, but
  312. * we'll go along with it anyway.)
  313. */
  314. case ERROR_SUCCESS:
  315. case ERROR_MORE_DATA:
  316. if (Misc_CopyRegWorker(prci, hkSrc, prci->tszKey,
  317. hkDst, prci->tszKey)) {
  318. } else {
  319. fRc = 0; goto stopkey;
  320. }
  321. break;
  322. default:
  323. fRc = 0; goto stopkey;
  324. }
  325. }
  326. keysdone:;
  327. fRc = TRUE;
  328. stopkey:;
  329. RegCloseKey(hkDst);
  330. } else {
  331. fRc = 0;
  332. }
  333. RegCloseKey(hkSrc);
  334. } else {
  335. fRc = 0;
  336. }
  337. return fRc;
  338. }
  339. /*****************************************************************************
  340. *
  341. * Misc_CopyReg
  342. *
  343. * Copy a registry tree from one point to another.
  344. *
  345. *****************************************************************************/
  346. BOOL PASCAL
  347. Misc_CopyReg(HKEY hkSrcRoot, PCTSTR ptszSrc, HKEY hkDstRoot, PCTSTR ptszDst)
  348. {
  349. BOOL fRc;
  350. RCI rci;
  351. rci.drb.pv = 0;
  352. rci.drb.cb = 0;
  353. fRc = Misc_CopyRegWorker(&rci, hkSrcRoot, ptszSrc, hkDstRoot, ptszDst);
  354. Misc_SetDrbSize(&rci.drb, 0);
  355. if (fRc) {
  356. } else {
  357. /* Clean up partial copy */
  358. RegDeleteTree(hkDstRoot, ptszDst);
  359. }
  360. return fRc;
  361. }
  362. /*****************************************************************************
  363. *
  364. * Misc_RenameReg
  365. *
  366. * Rename a registry key by copying it and deleting the original.
  367. *
  368. *****************************************************************************/
  369. BOOL PASCAL
  370. Misc_RenameReg(HKEY hkRoot, PCTSTR ptszKey, PCTSTR ptszSrc, PCTSTR ptszDst)
  371. {
  372. BOOL fRc;
  373. HKEY hk;
  374. if (_RegOpenKey(hkRoot, ptszKey, &hk) == 0) {
  375. if (Misc_CopyReg(hk, ptszSrc, hk, ptszDst)) {
  376. RegDeleteTree(hk, ptszSrc);
  377. fRc = TRUE;
  378. } else {
  379. fRc = FALSE;
  380. }
  381. RegCloseKey(hk);
  382. } else {
  383. fRc = FALSE;
  384. }
  385. return fRc;
  386. }
  387. /*****************************************************************************
  388. *
  389. * lstrcatnBs
  390. *
  391. * Like lstrcatn, but with a backslash stuck in between.
  392. *
  393. *****************************************************************************/
  394. void PASCAL
  395. lstrcatnBs(PTSTR ptszDst, PCTSTR ptszSrc, int ctch)
  396. {
  397. int ctchDst = lstrlen(ptszDst);
  398. ptszDst += ctchDst;
  399. ctch -= ctchDst;
  400. if (ctch > 1) {
  401. ptszDst[0] = TEXT('\\');
  402. lstrcpyn(ptszDst + 1, ptszSrc, ctch - 1);
  403. }
  404. }
  405. /*****************************************************************************
  406. *
  407. * Misc_GetShellIconSize
  408. *
  409. *****************************************************************************/
  410. #pragma BEGIN_CONST_DATA
  411. KL const c_klShellIconSize = { &c_hkCU, c_tszMetrics, c_tszShellIconSize };
  412. #pragma END_CONST_DATA
  413. UINT PASCAL
  414. Misc_GetShellIconSize(void)
  415. {
  416. return GetIntPkl(GetSystemMetrics(SM_CXICON), &c_klShellIconSize);
  417. }
  418. /*****************************************************************************
  419. *
  420. * Misc_SetShellIconSize
  421. *
  422. * Dork the shell icon size and rebuild.
  423. *
  424. *****************************************************************************/
  425. void PASCAL
  426. Misc_SetShellIconSize(UINT ui)
  427. {
  428. SetIntPkl(ui, &c_klShellIconSize);
  429. SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0L);
  430. }
  431. /*****************************************************************************
  432. *
  433. * Misc_RebuildIcoCache
  434. *
  435. * Force the shell to rebuild its icon cache.
  436. *
  437. * Due to the way the shell works, we have to do this by changing
  438. * the icon sizes, then changing it back.
  439. *
  440. *****************************************************************************/
  441. void PASCAL
  442. Misc_RebuildIcoCache(void)
  443. {
  444. UINT cxIcon = Misc_GetShellIconSize();
  445. Misc_SetShellIconSize(cxIcon-1);
  446. Misc_SetShellIconSize(cxIcon);
  447. Explorer_HackPtui();
  448. }
  449. /*****************************************************************************
  450. *
  451. * SetWaitCursor
  452. *
  453. *****************************************************************************/
  454. HCURSOR SetWaitCursor(void)
  455. {
  456. return SetCursor(LoadCursor(0, IDC_WAIT));
  457. }