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.

799 lines
21 KiB

  1. /*
  2. * mycomp - Dialog box property sheet for "My Computer"
  3. *
  4. * For now, we display only Drives.
  5. */
  6. #include "tweakui.h"
  7. #pragma BEGIN_CONST_DATA
  8. const static DWORD CODESEG rgdwHelp[] = {
  9. IDC_ICONLVTEXT, IDH_GROUP,
  10. IDC_ICONLVTEXT2, IDH_MYCOMP,
  11. IDC_ICONLV, IDH_MYCOMP,
  12. IDC_FLDGROUP, IDH_GROUP,
  13. IDC_FLDNAMETXT, IDH_FOLDERNAME,
  14. IDC_FLDNAMELIST, IDH_FOLDERNAME,
  15. IDC_FLDLOCTXT, IDH_FOLDERNAME,
  16. IDC_FLDLOC, IDH_FOLDERNAME,
  17. IDC_FLDCHG, IDH_FOLDERNAME,
  18. 0, 0,
  19. };
  20. #pragma END_CONST_DATA
  21. /*****************************************************************************
  22. *
  23. * CFolderDesc - Describes a single special folder
  24. *
  25. *****************************************************************************/
  26. #define MAKEKL(nm) \
  27. KL const c_kl##nm = { &pcdii->hkCUExplorer, \
  28. c_tszUserShellFolders, c_tsz##nm }
  29. MAKEKL(Desktop);
  30. MAKEKL(Programs);
  31. MAKEKL(Personal);
  32. MAKEKL(Favorites);
  33. MAKEKL(Startup);
  34. MAKEKL(Recent);
  35. MAKEKL(SendTo);
  36. MAKEKL(StartMenu);
  37. MAKEKL(Templates);
  38. KL const c_klMyMusic = { &pcdii->hkCUExplorer, c_tszUserShellFolders, TEXT("My Music") };
  39. KL const c_klMyVideo = { &pcdii->hkCUExplorer, c_tszUserShellFolders, TEXT("My Video") };
  40. KL const c_klMyPictures = { &pcdii->hkCUExplorer, c_tszUserShellFolders, TEXT("My Pictures") };
  41. #undef MAKEKL
  42. KL const c_klProgramFiles = { &g_hkLMSMWCV, 0, c_tszProgramFilesDir };
  43. KL const c_klCommonFiles = { &g_hkLMSMWCV, 0, c_tszCommonFilesDir };
  44. KL const c_klSourcePath = { &g_hkLMSMWCV, c_tszSetup, c_tszSourcePath };
  45. /*
  46. * HACKHACK - Fake some private CSIDL's
  47. * by stealing the various CSIDL_COMMON_* values.
  48. */
  49. enum {
  50. CSIDL_SOURCEPATH = CSIDL_COMMON_STARTUP,
  51. };
  52. /*
  53. * Declare as a struct so you can initialize it statically.
  54. */
  55. struct CFolderDesc { /* fldd */
  56. PIDL GetPidl() const;
  57. BOOL SetValue(LPTSTR ptsz) const; /* returns fNeedLogoff */
  58. inline int GetFriendlyName(LPTSTR pszBuf, int cch) const
  59. {
  60. return LoadString(hinstCur, _csidl + IDS_FOLDER_BASE, pszBuf, cch);
  61. }
  62. UINT _csidl;
  63. PKL _pkl;
  64. /*
  65. * These are really private members, but you can't say "private"
  66. * in a struct definition if you want it to be statically initializable.
  67. */
  68. static BOOL _UnexpandEnvironmentString(LPTSTR ptsz, LPCTSTR ptszEnv);
  69. static void _SetUserShellFolder(LPTSTR ptsz, LPCTSTR ptszSubkey);
  70. };
  71. /*****************************************************************************
  72. *
  73. * CFolderDesc::GetPidl
  74. *
  75. * Wrapper around SHGetSpecialFolderLocation that also knows how
  76. * to read our hacky values.
  77. *
  78. *****************************************************************************/
  79. PIDL
  80. CFolderDesc::GetPidl() const
  81. {
  82. HRESULT hres;
  83. PIDL pidl;
  84. TCHAR tszPath[MAX_PATH];
  85. switch (_csidl) {
  86. case CSIDL_PROGRAM_FILES:
  87. case CSIDL_PROGRAM_FILES_COMMON:
  88. case CSIDL_SOURCEPATH:
  89. if (GetStrPkl(tszPath, cbX(tszPath), _pkl)) {
  90. pidl = pidlSimpleFromPath(tszPath);
  91. } else {
  92. pidl = NULL;
  93. }
  94. break;
  95. default:
  96. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, _csidl, &pidl))) {
  97. } else {
  98. pidl = NULL;
  99. }
  100. break;
  101. }
  102. return pidl;
  103. }
  104. /*****************************************************************************
  105. *
  106. * CFolderDesc::_UnexpandEnvironmentString
  107. *
  108. * If the string begins with the value of the environment string,
  109. * then change it to said string.
  110. *
  111. * Example:
  112. * In: "C:\WINNT\SYSTEM32\FOO.TXT", "%SystemRoot%"
  113. * Out: "%SystemRoot%\SYSTEM32\FOO.TXT"
  114. *
  115. *****************************************************************************/
  116. BOOL
  117. CFolderDesc::_UnexpandEnvironmentString(LPTSTR ptsz, LPCTSTR ptszEnv)
  118. {
  119. TCHAR tszEnv[MAX_PATH];
  120. DWORD ctch;
  121. BOOL fRc;
  122. /*
  123. * Note that NT ExpandEnvironmentStrings returns the wrong
  124. * value, so we can't rely on it.
  125. */
  126. ExpandEnvironmentStrings(ptszEnv, tszEnv, cA(tszEnv));
  127. ctch = lstrlen(tszEnv);
  128. /*
  129. * Source must be at least as long as the env string for
  130. * us to have a chance of succeeding. This check avoids
  131. * accidentally reading past the end of the source.
  132. */
  133. if ((DWORD)lstrlen(ptsz) >= ctch) {
  134. if (CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
  135. tszEnv, ctch, ptsz, ctch) == 2) {
  136. int ctchEnv = lstrlen(ptszEnv);
  137. /*
  138. * Must use hmemcpy to avoid problems with overlap.
  139. */
  140. hmemcpy(ptsz + ctchEnv, ptsz + ctch,
  141. cbCtch(1 + lstrlen(ptsz + ctch)));
  142. hmemcpy(ptsz, ptszEnv, ctchEnv);
  143. fRc = 1;
  144. } else {
  145. fRc = 0;
  146. }
  147. } else {
  148. fRc = 0;
  149. }
  150. return fRc;
  151. }
  152. /*****************************************************************************
  153. *
  154. * CFolderDesc::_SetUserShellFolder
  155. *
  156. * Don't use REG_EXPAND_SZ if the shell doesn't support it.
  157. *
  158. *****************************************************************************/
  159. void
  160. CFolderDesc::_SetUserShellFolder(LPTSTR ptsz, LPCTSTR ptszSubkey)
  161. {
  162. HKEY hk;
  163. if (g_fShellSz) {
  164. if (!_UnexpandEnvironmentString(ptsz, TEXT("%USERPROFILE%")) &&
  165. !_UnexpandEnvironmentString(ptsz, TEXT("%SystemRoot%"))) {
  166. }
  167. }
  168. if (RegCreateKey(pcdii->hkCUExplorer, c_tszUserShellFolders, &hk) == 0) {
  169. RegSetValueEx(hk, ptszSubkey, 0, g_fShellSz ? REG_EXPAND_SZ
  170. : REG_SZ, (LPBYTE)ptsz,
  171. cbCtch(1 + lstrlen(ptsz)));
  172. RegCloseKey(hk);
  173. }
  174. }
  175. /*****************************************************************************
  176. *
  177. * CFolderDesc::SetValue
  178. *
  179. * Stash the puppy.
  180. *
  181. * Returns nonzero if logoff required.
  182. *
  183. *****************************************************************************/
  184. BOOL
  185. CFolderDesc::SetValue(LPTSTR ptsz) const
  186. {
  187. TCHAR tszDefault[MAX_PATH];
  188. UINT ctch;
  189. BOOL fNeedLogoff = FALSE;
  190. /*
  191. * Is it already in the default location?
  192. *
  193. * Note that the special gizmos don't have default
  194. * locations.
  195. */
  196. ctch = GetWindowsDirectory(tszDefault, cA(tszDefault));
  197. if (ctch && tszDefault[ctch - 1] != TEXT('\\')) {
  198. tszDefault[ctch++] = TEXT('\\');
  199. }
  200. if (LoadString(hinstCur, _csidl + IDS_DEFAULT_BASE,
  201. &tszDefault[ctch], cA(tszDefault) - ctch)) {
  202. if (lstrcmpi(tszDefault, ptsz) == 0) {
  203. /*
  204. * In default location.
  205. */
  206. DelPkl(_pkl);
  207. } else {
  208. /*
  209. * In other location.
  210. *
  211. * Note that we cannot use SetStrPkl here, because
  212. * we need to set the value type to REG_EXPAND_SZ.
  213. *
  214. */
  215. _SetUserShellFolder(ptsz, _pkl->ptszSubkey);
  216. }
  217. fNeedLogoff = TRUE;
  218. } else {
  219. SetStrPkl(_pkl, ptsz);
  220. /*
  221. * On NT5, Program Files and Common Files are CSIDLs,
  222. * and Program Files is an environment variable!
  223. */
  224. if (g_fNT5 && (_csidl == CSIDL_PROGRAM_FILES ||
  225. _csidl == CSIDL_PROGRAM_FILES_COMMON)) {
  226. fNeedLogoff = TRUE;
  227. }
  228. }
  229. return fNeedLogoff;
  230. }
  231. /*****************************************************************************
  232. *
  233. * CSpecialFolders -- Wangle the "special folders" combobox
  234. *
  235. *****************************************************************************/
  236. static const CFolderDesc c_rgfldd[] = {
  237. { CSIDL_DESKTOPDIRECTORY, &c_klDesktop },
  238. { CSIDL_PROGRAMS, &c_klPrograms },
  239. { CSIDL_PERSONAL, &c_klPersonal },
  240. { CSIDL_FAVORITES, &c_klFavorites },
  241. { CSIDL_STARTUP, &c_klStartup },
  242. { CSIDL_RECENT, &c_klRecent },
  243. { CSIDL_SENDTO, &c_klSendTo },
  244. { CSIDL_STARTMENU, &c_klStartMenu },
  245. { CSIDL_TEMPLATES, &c_klTemplates },
  246. { CSIDL_MYMUSIC, &c_klMyMusic },
  247. { CSIDL_MYVIDEO, &c_klMyVideo },
  248. { CSIDL_MYPICTURES, &c_klMyPictures },
  249. { CSIDL_PROGRAM_FILES, &c_klProgramFiles },
  250. { CSIDL_PROGRAM_FILES_COMMON, &c_klCommonFiles },
  251. { CSIDL_SOURCEPATH, &c_klSourcePath },
  252. };
  253. #define cfldd cA(c_rgfldd)
  254. class CSpecialFolders {
  255. public:
  256. void Init(HWND hwndCombo, HWND hwndText);
  257. void Resync();
  258. void Destroy();
  259. BOOL Apply(); /* returns fNeedLogoff */
  260. void ChangeFolder(HWND hdlg);
  261. private:
  262. typedef struct FOLDERINSTANCE {
  263. BOOL fEdited;
  264. PIDL pidl;
  265. } FINST, *PFINST;
  266. static int CALLBACK _ChangeFolder_Callback(HWND hwnd, UINT wm, LPARAM lp, LPARAM lpRef);
  267. HWND _hwndCombo;
  268. HWND _hwndText; /* IDC_FLDLOC */
  269. BOOL _fWarned; /* Did we warn about changing folders? */
  270. PIDL _pidlEditing; /* Which one is the user editing? */
  271. FINST _rgfinst[cfldd];
  272. };
  273. /*****************************************************************************
  274. *
  275. * CSpecialFolders::Destroy
  276. *
  277. * Free the memory.
  278. *
  279. *****************************************************************************/
  280. void
  281. CSpecialFolders::Destroy()
  282. {
  283. UINT i;
  284. for (i = 0; i < cfldd; i++) {
  285. _rgfinst[i].fEdited = 0;
  286. if (_rgfinst[i].pidl) {
  287. Ole_Free(_rgfinst[i].pidl);
  288. _rgfinst[i].pidl = 0;
  289. }
  290. }
  291. }
  292. /*****************************************************************************
  293. *
  294. * CSpecialFolders::Reset
  295. *
  296. *****************************************************************************/
  297. void
  298. CSpecialFolders::Init(HWND hwndCombo, HWND hwndText)
  299. {
  300. _hwndCombo = hwndCombo;
  301. _hwndText = hwndText;
  302. /*
  303. * Free the old memory, if any.
  304. */
  305. Destroy();
  306. /*
  307. * Set up the new combobox.
  308. */
  309. ComboBox_ResetContent(_hwndCombo);
  310. UINT i;
  311. for (i = 0; i < cfldd; i++) {
  312. _rgfinst[i].pidl = c_rgfldd[i].GetPidl();
  313. if (_rgfinst[i].pidl) {
  314. TCHAR tsz[MAX_PATH];
  315. c_rgfldd[i].GetFriendlyName(tsz, cA(tsz));
  316. int iItem = ComboBox_AddString(_hwndCombo, tsz);
  317. ComboBox_SetItemData(_hwndCombo, iItem, i);
  318. }
  319. }
  320. ComboBox_SetCurSel(_hwndCombo, 0);
  321. Resync();
  322. }
  323. /*****************************************************************************
  324. *
  325. * CSpecialFolders::Resync
  326. *
  327. * Update goo since the combo box changed.
  328. *
  329. *****************************************************************************/
  330. void
  331. CSpecialFolders::Resync()
  332. {
  333. LRESULT icsidl = Misc_Combo_GetCurItemData(_hwndCombo);
  334. TCHAR tsz[MAX_PATH];
  335. tsz[0] = TEXT('\0');
  336. SHGetPathFromIDList(_rgfinst[icsidl].pidl, tsz);
  337. SetWindowText(_hwndText, tsz);
  338. }
  339. /*****************************************************************************
  340. *
  341. * CSpecialFolders::Apply
  342. *
  343. * Updating the Folder locations is really annoying, thanks
  344. * to NT's roving profiles.
  345. *
  346. *****************************************************************************/
  347. BOOL
  348. CSpecialFolders::Apply()
  349. {
  350. UINT i;
  351. BOOL fNeedLogoff = FALSE;
  352. for (i = 0; i < cfldd; i++) {
  353. if (_rgfinst[i].fEdited) {
  354. TCHAR tsz[MAX_PATH];
  355. SHGetPathFromIDList(_rgfinst[i].pidl, tsz);
  356. BOOL fNeedLogoffT = c_rgfldd[i].SetValue(tsz);
  357. fNeedLogoff |= fNeedLogoffT;
  358. }
  359. }
  360. return fNeedLogoff;
  361. }
  362. /*****************************************************************************
  363. *
  364. * CSpecialFolders::_ChangeFolder_Callback
  365. *
  366. * Start the user at the old location, and don't let the user pick
  367. * something that collides with something else.
  368. *
  369. *****************************************************************************/
  370. int CALLBACK
  371. CSpecialFolders::_ChangeFolder_Callback(HWND hwnd, UINT wm, LPARAM lp, LPARAM lpRef)
  372. {
  373. CSpecialFolders *self = (CSpecialFolders *)lpRef;
  374. int icsidl;
  375. TCHAR tsz[MAX_PATH];
  376. switch (wm) {
  377. case BFFM_INITIALIZED:
  378. SendMessage(hwnd, BFFM_SETSELECTION, 0, (LPARAM)self->_pidlEditing);
  379. break;
  380. case BFFM_SELCHANGED:
  381. /* Picking nothing is bad */
  382. if (!lp) goto bad;
  383. /* Picking yourself is okay; just don't pick somebody else */
  384. if (ComparePidls((PIDL)lp, self->_pidlEditing) == 0) goto done;
  385. for (icsidl = 0; icsidl < cfldd; icsidl++) {
  386. if (self->_rgfinst[icsidl].pidl &&
  387. ComparePidls(self->_rgfinst[icsidl].pidl, (PIDL)lp) == 0) {
  388. bad:;
  389. SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);
  390. goto done;
  391. }
  392. }
  393. /* Don't allow a removable drive */
  394. tsz[1] = TEXT('\0'); /* Not a typo */
  395. SHGetPathFromIDList((PIDL)lp, tsz);
  396. if (tsz[1] == TEXT(':')) {
  397. tsz[3] = TEXT('\0');
  398. if (GetDriveType(tsz) == DRIVE_REMOVABLE) {
  399. goto bad;
  400. }
  401. }
  402. break;
  403. }
  404. done:;
  405. return 0;
  406. }
  407. /*****************************************************************************
  408. *
  409. * CSpecialFolders::ChangeFolder
  410. *
  411. *****************************************************************************/
  412. void
  413. CSpecialFolders::ChangeFolder(HWND hdlg)
  414. {
  415. if (_fWarned ||
  416. MessageBoxId(hdlg, IDS_WARNFOLDERCHANGE, g_tszName,
  417. MB_YESNO | MB_DEFBUTTON2) == IDYES) {
  418. int iItem;
  419. int icsidl;
  420. BROWSEINFO bi;
  421. LPITEMIDLIST pidl;
  422. TCHAR tsz[MAX_PATH];
  423. TCHAR tszTitle[MAX_PATH];
  424. TCHAR tszName[MAX_PATH];
  425. _fWarned = TRUE;
  426. iItem = ComboBox_GetCurSel(_hwndCombo);
  427. ComboBox_GetLBText(_hwndCombo, iItem, tszName);
  428. LoadString(hinstCur, IDS_FOLDER_PATTERN, tsz, cA(tsz));
  429. wsprintf(tszTitle, tsz, tszName);
  430. bi.hwndOwner = hdlg;
  431. bi.pidlRoot = 0;
  432. bi.pszDisplayName = tsz; /* Garbage */
  433. bi.lpszTitle = tszTitle;
  434. bi.ulFlags = BIF_RETURNONLYFSDIRS;
  435. bi.lpfn = _ChangeFolder_Callback;
  436. icsidl = (int)ComboBox_GetItemData(_hwndCombo, iItem);
  437. _pidlEditing = _rgfinst[icsidl].pidl;
  438. bi.lParam = (LPARAM)this;
  439. pidl = SHBrowseForFolder(&bi);
  440. if (pidl) {
  441. if (ComparePidls(pidl, _rgfinst[icsidl].pidl) != 0) {
  442. Ole_Free(_rgfinst[icsidl].pidl);
  443. _rgfinst[icsidl].pidl = (PIDL)pidl;
  444. _rgfinst[icsidl].fEdited = TRUE;
  445. Common_SetDirty(hdlg);
  446. Resync();
  447. } else {
  448. Ole_Free(pidl);
  449. }
  450. }
  451. }
  452. }
  453. /*****************************************************************************
  454. *
  455. * My Computer Dialog Info
  456. *
  457. *****************************************************************************/
  458. typedef class _MDI { /* mdi = my computer dialog info */
  459. public:
  460. DWORD dwNoDrives;
  461. DWORD dwValidDrives;
  462. CSpecialFolders _sf;
  463. } MDI, *PMDI;
  464. MDI mdi;
  465. #define pdmi (&mdi)
  466. /*****************************************************************************
  467. *
  468. * MyComp_BuildRoot
  469. *
  470. * Build the root directory of a drive. The buffer must be 4 chars.
  471. *
  472. *****************************************************************************/
  473. LPTSTR PASCAL
  474. MyComp_BuildRoot(LPTSTR ptsz, UINT uiDrive)
  475. {
  476. ptsz[0] = uiDrive + TEXT('A');
  477. ptsz[1] = TEXT(':');
  478. ptsz[2] = TEXT('\\');
  479. ptsz[3] = TEXT('\0');
  480. return ptsz;
  481. }
  482. /*****************************************************************************
  483. *
  484. * MyComp_LV_GetIcon
  485. *
  486. * Produce the icon associated with an item. This is called when
  487. * we need to rebuild the icon list after the icon cache has been
  488. * purged.
  489. *
  490. *****************************************************************************/
  491. #define idiPhantom -11 /* Magic index for disconnected drive */
  492. int PASCAL
  493. MyComp_LV_GetIcon(LPARAM insi)
  494. {
  495. if (pdmi->dwValidDrives & (1 << insi)) {
  496. SHFILEINFO sfi;
  497. TCHAR tszRoot[4]; /* Root directory thing */
  498. SHGetFileInfo(MyComp_BuildRoot(tszRoot, (UINT)insi), 0, &sfi, cbX(sfi),
  499. SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  500. return sfi.iIcon;
  501. } else {
  502. if (g_fNT) {
  503. UnicodeFromPtsz(wsz, g_tszPathShell32);
  504. return mit.Shell_GetCachedImageIndex(wsz, idiPhantom, 0);
  505. } else {
  506. return mit.Shell_GetCachedImageIndex(g_tszPathShell32,
  507. idiPhantom, 0);
  508. }
  509. }
  510. }
  511. /*****************************************************************************
  512. *
  513. * MyComp_OnInitDialog
  514. *
  515. * For now, just populate with each physical local drive.
  516. *
  517. *****************************************************************************/
  518. BOOL PASCAL
  519. MyComp_OnInitDialog(HWND hwnd)
  520. {
  521. UINT ui;
  522. TCHAR tszDrive[3];
  523. tszDrive[1] = TEXT(':');
  524. tszDrive[2] = TEXT('\0');
  525. pdmi->dwNoDrives = GetRegDword(g_hkCUSMWCV, c_tszRestrictions,
  526. c_tszNoDrives, 0);
  527. pdmi->dwValidDrives = GetLogicalDrives();
  528. for (ui = 0; ui < 26; ui++) {
  529. int iIcon = MyComp_LV_GetIcon(ui);
  530. tszDrive[0] = ui + TEXT('A');
  531. LV_AddItem(hwnd, ui, tszDrive, iIcon, !(pdmi->dwNoDrives & (1 << ui)));
  532. }
  533. /*
  534. * And initialize the special folders stuff.
  535. */
  536. HWND hdlg = GetParent(hwnd);
  537. pdmi->_sf.Init(GetDlgItem(hdlg, IDC_FLDNAMELIST),
  538. GetDlgItem(hdlg, IDC_FLDLOC));
  539. return 1;
  540. }
  541. /*****************************************************************************
  542. *
  543. * MyComp_OnDestroy
  544. *
  545. * Free the memory we allocated.
  546. *
  547. *****************************************************************************/
  548. void PASCAL
  549. MyComp_OnDestroy(HWND hdlg)
  550. {
  551. /*
  552. * Destroy the special folders stuff.
  553. */
  554. pdmi->_sf.Destroy();
  555. }
  556. #if 0
  557. /*****************************************************************************
  558. *
  559. * MyComp_FactoryReset
  560. *
  561. * This is scary and un-undoable, so let's do extra confirmation.
  562. *
  563. *****************************************************************************/
  564. void PASCAL
  565. MyComp_FactoryReset(HWND hdlg)
  566. {
  567. if (MessageBoxId(hdlg, IDS_MyCompRESETOK,
  568. tszName, MB_YESNO + MB_DEFBUTTON2) == IDYES) {
  569. pcdii->fRunShellInf = 1;
  570. Common_NeedLogoff(hdlg);
  571. PropSheet_Apply(GetParent(hdlg));
  572. }
  573. }
  574. #endif
  575. /*****************************************************************************
  576. *
  577. * MyComp_OnApply
  578. *
  579. * Write the changes to the registry.
  580. *
  581. *****************************************************************************/
  582. void PASCAL
  583. MyComp_OnApply(HWND hdlg)
  584. {
  585. HWND hwnd = GetDlgItem(hdlg, IDC_ICONLV);
  586. DWORD dwDrives = 0;
  587. LV_ITEM lvi;
  588. for (lvi.iItem = 0; lvi.iItem < 26; lvi.iItem++) {
  589. lvi.stateMask = LVIS_STATEIMAGEMASK;
  590. Misc_LV_GetItemInfo(hwnd, &lvi, lvi.iItem, LVIF_STATE);
  591. if (!LV_IsChecked(&lvi)) {
  592. dwDrives |= 1 << lvi.iItem;
  593. }
  594. }
  595. if (pdmi->dwNoDrives != dwDrives) {
  596. DWORD dwChanged;
  597. UINT ui;
  598. TCHAR tszRoot[4];
  599. SetRegDword(g_hkCUSMWCV, c_tszRestrictions, c_tszNoDrives, dwDrives);
  600. /* Recompute GetLogicalDrives() in case new drives are here */
  601. dwChanged = (pdmi->dwNoDrives ^ dwDrives) & GetLogicalDrives();
  602. pdmi->dwNoDrives = dwDrives;
  603. /*
  604. * SHCNE_UPDATEDIR doesn't work for CSIDL_DRIVES because
  605. * Drivesx.c checks the restrictions only in response to a
  606. * SHCNE_ADDDRIVE. So walk through every drive that changed
  607. * and send a SHCNE_DRIVEADD or SHCNE_DRIVEREMOVED for it.
  608. */
  609. for (ui = 0; ui < 26; ui++) {
  610. DWORD dwMask = 1 << ui;
  611. if (dwChanged & dwMask) {
  612. MyComp_BuildRoot(tszRoot, ui);
  613. SHChangeNotify((dwDrives & dwMask) ? SHCNE_DRIVEREMOVED
  614. : SHCNE_DRIVEADD,
  615. SHCNF_PATH, tszRoot, 0L);
  616. }
  617. }
  618. }
  619. /*
  620. * And update the special folders, too.
  621. */
  622. BOOL fNeedLogoff = pdmi->_sf.Apply();
  623. if (fNeedLogoff) {
  624. Common_NeedLogoff(hdlg);
  625. }
  626. }
  627. /*****************************************************************************
  628. *
  629. * MyComp_OnCommand
  630. *
  631. * Ooh, we got a command.
  632. *
  633. *****************************************************************************/
  634. void PASCAL
  635. MyComp_OnCommand(HWND hdlg, int id, UINT codeNotify)
  636. {
  637. switch (id) {
  638. case IDC_FLDNAMELIST:
  639. if (codeNotify == CBN_SELCHANGE) pdmi->_sf.Resync();
  640. break;
  641. case IDC_FLDCHG:
  642. if (codeNotify == BN_CLICKED) pdmi->_sf.ChangeFolder(hdlg);
  643. break;
  644. }
  645. }
  646. /*****************************************************************************
  647. *
  648. * Oh yeah, we need this too.
  649. *
  650. *****************************************************************************/
  651. #pragma BEGIN_CONST_DATA
  652. LVV lvvMyComp = {
  653. MyComp_OnCommand,
  654. 0,
  655. 0, /* MyComp_LV_Dirtify */
  656. MyComp_LV_GetIcon,
  657. MyComp_OnInitDialog,
  658. MyComp_OnApply,
  659. MyComp_OnDestroy,
  660. 0,
  661. 4, /* iMenu */
  662. rgdwHelp,
  663. 0, /* Double-click action */
  664. lvvflIcons | /* We need icons */
  665. lvvflCanCheck, /* And check boxes */
  666. NULL,
  667. };
  668. #pragma END_CONST_DATA
  669. /*****************************************************************************
  670. *
  671. * Our window procedure.
  672. *
  673. *****************************************************************************/
  674. INT_PTR EXPORT
  675. MyComp_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  676. {
  677. return LV_DlgProc(&lvvMyComp, hdlg, wm, wParam, lParam);
  678. }