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.

736 lines
21 KiB

  1. /*
  2. * desktop - Dialog box property sheet for "desktop customization"
  3. */
  4. #include "tweakui.h"
  5. #pragma BEGIN_CONST_DATA
  6. #define c_tszCLSIDMyDocs TEXT("CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}")
  7. #define c_tszParseMyDocs TEXT("::{450D8FBA-AD25-11D0-98A8-0800361B1103}")
  8. #define c_tszParseMyComp TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}")
  9. KL const c_klMyDocsOrder = { &c_hkCR, c_tszCLSIDMyDocs, TEXT("SortOrderIndex") };
  10. #define ORDER_BEFOREMYCOMP 0x48
  11. #define ORDER_AFTERMYCOMP 0x54
  12. const static DWORD CODESEG rgdwHelp[] = {
  13. IDC_ICONLVTEXT, IDH_GROUP,
  14. IDC_ICONLVTEXT2, IDH_ICONLV,
  15. IDC_ICONLV, IDH_ICONLV,
  16. IDC_CREATENOWTEXT, IDH_GROUP,
  17. IDC_CREATENOW, IDH_CREATENOW,
  18. IDC_ENUMFIRSTTEXT, IDH_DESKFIRSTICON,
  19. IDC_ENUMFIRST, IDH_DESKFIRSTICON,
  20. #if 0
  21. IDC_RESET, IDH_RESET,
  22. #endif
  23. 0, 0,
  24. };
  25. #pragma END_CONST_DATA
  26. /*
  27. * cchFriendlyMax should be at least MAX_PATH, because we also use it
  28. * to hold icon file names.
  29. */
  30. #define cchFriendlyMax 256
  31. /*
  32. * Evil hack! Since the ::{guid} hack doesn't work unless the object
  33. * really exists in the name space, we pull an evil trick and just
  34. * create the idlist that the shell would've made if you had asked for
  35. * it...
  36. */
  37. typedef struct RIDL {
  38. USHORT cb; /* Must be 20 */
  39. BYTE bFlags; /* Must be 0x1F */
  40. BYTE bOrder; /* Sorting order */
  41. CLSID clsid; /* Guid goes here */
  42. USHORT zero; /* Must be zero */
  43. } RIDL, *PRIDL;
  44. #define pidlPnsi(pnsi) ((PIDL)&(pnsi)->ridl)
  45. /*
  46. * The only abnormal key is Network Neighborhood, since its presence
  47. * is controlled by a system policy...
  48. *
  49. * You need to set nsiflNever if something should not have a check
  50. * box next to it because it cannot be added to the namespace.
  51. *
  52. * You need to set nsiflDir for things that aren't valid namespace
  53. * items but should be created as directory-like objects.
  54. *
  55. * Briefcase is doubly abnormal, because it doesn't do anything at all!
  56. * So we just exclude him from the enumeration.
  57. */
  58. typedef BYTE NSIFL; /* Random flags */
  59. #define nsiflNormal 1 /* Is a regular thing */
  60. #define nsiflDir 2 /* Is a directory-like object */
  61. #define nsiflNever 4 /* Not a valid namespace item */
  62. #define nsiflEdited 8 /* The name has been edited */
  63. typedef struct NSI { /* namespace item */
  64. NSIFL nsifl; /* Is this a normal regkey? */
  65. TCH tszClsid[ctchClsid]; /* Class id */
  66. RIDL ridl; /* Regitem idlist */
  67. } NSI, *PNSI;
  68. #define insiPlvi(plvi) ((UINT)(plvi)->lParam)
  69. #define pnsiInsi(insi) (&pddii->pnsi[insi])
  70. #define pnsiPlvi(plvi) pnsiInsi(insiPlvi(plvi))
  71. typedef struct DDII {
  72. Declare_Gxa(NSI, nsi);
  73. HKEY hkNS;
  74. int iFirstIcon;
  75. } DDII, *PDDII;
  76. DDII ddii;
  77. #define pddii (&ddii)
  78. /*****************************************************************************
  79. *
  80. * Desktop_GetClsidAttributes
  81. *
  82. * Return the Attributes registry key for a class id.
  83. *
  84. *****************************************************************************/
  85. #define ctchPathShellFolder 21
  86. DWORD PASCAL
  87. Desktop_GetClsidAttributes(PCTSTR ptszClsid)
  88. {
  89. TCH tsz[ctchPathShellFolder + ctchClsid];
  90. wsprintf(tsz, c_tszPathShellFolder, ptszClsid);
  91. return GetRegDword(hhkCR, tsz, c_tszAttributes, 0);
  92. }
  93. /*****************************************************************************
  94. *
  95. * Desktop_HasSubkey
  96. *
  97. * Return whether the key has a child key with the specified name.
  98. *
  99. *****************************************************************************/
  100. BOOL PASCAL
  101. Desktop_HasSubkey(HKEY hk, LPCTSTR ptszChild)
  102. {
  103. HKEY hkS;
  104. if (_RegOpenKey(hk, ptszChild, &hkS) == 0) {
  105. RegCloseKey(hkS);
  106. return 1;
  107. } else {
  108. return 0;
  109. }
  110. }
  111. /*****************************************************************************
  112. *
  113. * Desktop_IsNSKey
  114. *
  115. * Determine whether the specified class is in the desktop namespace
  116. * right now.
  117. *
  118. *****************************************************************************/
  119. #define Desktop_IsNSKey(ptszClsid) Desktop_HasSubkey(pddii->hkNS, ptszClsid)
  120. /*****************************************************************************
  121. *
  122. * Desktop_GetNetHood
  123. *
  124. * Determine whether the network neighborhood is visible now.
  125. *
  126. *****************************************************************************/
  127. #define Desktop_GetNetHood() GetRestriction(c_tszNoNetHood)
  128. /*****************************************************************************
  129. *
  130. * Desktop_SetNetHood
  131. *
  132. * Set the new network neighborhood visibility.
  133. *
  134. *****************************************************************************/
  135. #define Desktop_SetNetHood(f) SetRestriction(c_tszNoNetHood, f)
  136. /*****************************************************************************
  137. *
  138. * Desktop_IsHereNow
  139. *
  140. * Determine the state of the object as it is in the world today.
  141. *
  142. *****************************************************************************/
  143. #define Desktop_IsHereNow(pnsi, ptszClsid) \
  144. ((pnsi->nsifl & nsiflNormal) ? Desktop_IsNSKey(ptszClsid) \
  145. : Desktop_GetNetHood())
  146. /*****************************************************************************
  147. *
  148. * Desktop_AddNSKey
  149. *
  150. * Okay, we've committed ourselves to adding the key to the listview.
  151. * No turning back now!
  152. *
  153. * We default to the shared desktop, so set the initial state accordingly.
  154. *
  155. *****************************************************************************/
  156. void PASCAL
  157. Desktop_AddNSKey(HWND hwnd, PNSI pnsi, LPCTSTR ptszClsid,
  158. LPCTSTR ptszFriendly, int iImage, NSIFL nsifl)
  159. {
  160. pnsi->nsifl = nsifl;
  161. lstrcpy(pnsi->tszClsid, ptszClsid);
  162. LV_AddItem(hwnd, pddii->cnsi++, ptszFriendly, iImage,
  163. (nsifl & nsiflNever) ? -1 : Desktop_IsHereNow(pnsi, ptszClsid));
  164. }
  165. /*****************************************************************************
  166. *
  167. * Desktop_MakeRidl
  168. *
  169. * Initialize a RIDL from a GUID display name.
  170. *
  171. *****************************************************************************/
  172. HRESULT PASCAL
  173. Desktop_MakeRidl(PNSI pnsi, LPCTSTR ptszClsid)
  174. {
  175. pnsi->ridl.cb = 20; /* Always */
  176. pnsi->ridl.bFlags = 0x1F; /* Always */
  177. pnsi->ridl.bOrder = 0; /* Unsorted */
  178. pnsi->ridl.zero = 0; /* Always */
  179. return Ole_ClsidFromString(ptszClsid, &pnsi->ridl.clsid);
  180. }
  181. /*****************************************************************************
  182. *
  183. * Desktop_ShouldUseNSClsid
  184. *
  185. * Check if this is a CLSID we should bother showing.
  186. *
  187. *****************************************************************************/
  188. const GUID c_rgguidExclude[] = {
  189. /*
  190. * These must be rooted on a filesystem object.
  191. */
  192. { 0x85BBD920, 0x42A0, 0x1069, { 0xA2, 0xE4, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D} }, /* Briefcase */
  193. { 0x1A9BA3A0, 0x143A, 0x11CF, { 0x83, 0x50, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} }, /* Shell Favorites */
  194. { 0xAFDB1F70, 0x2A4C, 0x11d2, { 0x90, 0x39, 0x00, 0xC0, 0x4F, 0x8E, 0xEB, 0x3E} }, /* Offline Files Folder */
  195. { 0x0CD7A5C0, 0x9F37, 0x11CE, { 0xAE, 0x65, 0x08, 0x00, 0x2B, 0x2E, 0x12, 0x62} }, /* Cabinet File */
  196. { 0x88C6C381, 0x2E85, 0x11d0, { 0x94, 0xDE, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} }, /* ActiveX Cache Folder */
  197. { 0xE88DCCE0, 0xB7B3, 0x11d1, { 0xA9, 0xF0, 0x00, 0xAA, 0x00, 0x60, 0xFA, 0x31} }, /* Compressed Folder (Zip) */
  198. /*
  199. * These simply weren't meant to be seen.
  200. */
  201. { 0x1f4de370, 0xd627, 0x11d1, { 0xba, 0x4f, 0x00, 0xa0, 0xc9, 0x1e, 0xed, 0xba} }, /* Search Results - Computers */
  202. { 0x63da6ec0, 0x2e98, 0x11cf, { 0x8d, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} }, /* Microsoft FTP Folder */
  203. /*
  204. * These have other ways of being hidden.
  205. */
  206. { 0x450D8FBA, 0xAD25, 0x11D0, { 0x98, 0xA8, 0x08, 0x00, 0x36, 0x1B, 0x11, 0x03} }, /* My Documents */
  207. };
  208. /*
  209. * The Win98 "Networking and Dial-Up Connections" CLSID is excluded on NT5.
  210. * (They leave it around for back compat reasons but it shouldn't be
  211. * exposed to the user.)
  212. */
  213. const GUID c_clsidDUN98 =
  214. { 0x992CFFA0, 0xF557, 0x101A, { 0x88, 0xEC, 0x00, 0xDD, 0x01, 0x0C, 0xCC, 0x48} };
  215. const GUID c_clsidIE =
  216. { 0x871C5380, 0x42A0, 0x1069, { 0xA2, 0xEA, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D} };
  217. BOOL PASCAL
  218. Desktop_ShouldUseNSClsid(PNSI pnsi)
  219. {
  220. int i;
  221. for (i = 0; i < cA(c_rgguidExclude); i++) {
  222. if (IsEqualGUID(pnsi->ridl.clsid, c_rgguidExclude[i])) {
  223. return FALSE;
  224. }
  225. }
  226. if (g_fNT5 && IsEqualGUID(pnsi->ridl.clsid, c_clsidDUN98)) {
  227. return FALSE;
  228. }
  229. /*
  230. * If IE5 is installed, then it already has the "Show IE on desktop"
  231. * setting in its Advanced dialog. Don't need one here.
  232. */
  233. if (IsEqualGUID(pnsi->ridl.clsid, c_clsidIE) &&
  234. (g_fShell5 || RegKeyExists(g_hkLMSMIE, TEXT("AdvancedOptions\\BROWSEE\\IEONDESKTOP")))) {
  235. return FALSE;
  236. }
  237. return TRUE;
  238. }
  239. /*****************************************************************************
  240. *
  241. * Desktop_CheckNSKey
  242. *
  243. * Check and possibly add a new namespace key. My Computer is
  244. * excluded because you can't get rid of it. Network Neighborhood
  245. * is here, although it is somewhat weird. We handle the weirdness
  246. * as it arises...
  247. *
  248. * All that has been validated so far is that the key exists, it
  249. * has a ShellEx subkey, and it has nonzero attributes.
  250. *
  251. * We haven't yet validated that it has an icon. We'll notice that
  252. * when we try to build up the listview info.
  253. *
  254. * And people complain that lisp has too many levels of nesting...
  255. *
  256. *****************************************************************************/
  257. void PASCAL
  258. Desktop_CheckNSKey(HWND hwnd, HKEY hk, LPCTSTR ptszClsid, NSIFL nsifl)
  259. {
  260. PNSI pnsi = (PNSI)Misc_AllocPx(&pddii->gxa);
  261. if (pnsi) {
  262. if (SUCCEEDED(Desktop_MakeRidl(pnsi, ptszClsid)) &&
  263. Desktop_ShouldUseNSClsid(pnsi)) {
  264. SHFILEINFO sfi;
  265. if (SHGetFileInfo((LPCSTR)pidlPnsi(pnsi), 0, &sfi, cbX(sfi),
  266. SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_SYSICONINDEX |
  267. SHGFI_SMALLICON)) {
  268. /*
  269. * gacky Net Hood hack. Shell won't give me a name
  270. * if I don't have one in the registry.
  271. */
  272. if (sfi.szDisplayName[0] == 0 && !(nsifl & nsiflNormal)) {
  273. LoadString(hinstCur, IDS_NETHOOD,
  274. sfi.szDisplayName, cA(sfi.szDisplayName));
  275. }
  276. /*
  277. * It must have a name and must have a custom icon.
  278. */
  279. if (sfi.szDisplayName[0] && sfi.iIcon != 3) {
  280. Desktop_AddNSKey(hwnd, pnsi, ptszClsid, sfi.szDisplayName,
  281. sfi.iIcon, nsifl);
  282. }
  283. } /* couldn't get file info */
  284. } /* not a valid guid */
  285. } /* else no memory to store this entry */
  286. }
  287. /*****************************************************************************
  288. *
  289. * Desktop_AddSpecialNSKey
  290. *
  291. * Add some special namespace keys, which eluded our enumeration.
  292. *
  293. *****************************************************************************/
  294. void PASCAL
  295. Desktop_AddSpecialNSKey(HWND hwnd, LPCTSTR ptszClsid, NSIFL nsifl)
  296. {
  297. int insi;
  298. HKEY hk;
  299. for (insi = 0; insi < pddii->cnsi; insi++) {
  300. if (lstrcmpi(pddii->pnsi[insi].tszClsid, ptszClsid) == 0) {
  301. goto found;
  302. }
  303. }
  304. hk = hkOpenClsid(ptszClsid);
  305. if (hk) {
  306. Desktop_CheckNSKey(hwnd, hk, ptszClsid, nsifl);
  307. RegCloseKey(hk);
  308. }
  309. found:;
  310. }
  311. /*****************************************************************************
  312. *
  313. * Desktop_EnumClasses
  314. *
  315. * Locate all the classes that are possible namespace keys.
  316. *
  317. *****************************************************************************/
  318. void PASCAL
  319. Desktop_EnumClasses(HWND hwnd)
  320. {
  321. int ihk;
  322. TCH tsz[ctchClsid];
  323. for (ihk = 0; RegEnumKey(pcdii->hkClsid, ihk, tsz, cA(tsz)) == 0; ihk++) {
  324. HKEY hk = hkOpenClsid(tsz);
  325. if (hk) {
  326. if (Desktop_GetClsidAttributes(tsz)) {
  327. Desktop_CheckNSKey(hwnd, hk, tsz, nsiflNormal);
  328. }
  329. RegCloseKey(hk);
  330. }
  331. }
  332. Desktop_AddSpecialNSKey(hwnd, c_tszClsidNetHood, nsiflDir);
  333. Desktop_AddSpecialNSKey(hwnd, c_tszClsidCpl,
  334. nsiflNormal | nsiflNever | nsiflDir);
  335. Desktop_AddSpecialNSKey(hwnd, c_tszClsidPrint,
  336. nsiflNormal | nsiflNever | nsiflDir);
  337. Misc_LV_SetCurSel(hwnd, 0); /* Default to top of list */
  338. }
  339. /*****************************************************************************
  340. *
  341. * Desktop_OnInitDialog
  342. *
  343. * We have much nontrivial work to do. Fill all the list boxes with
  344. * defaults.
  345. *
  346. *****************************************************************************/
  347. BOOL PASCAL
  348. Desktop_OnInitDialog(HWND hwnd)
  349. {
  350. ZeroMemory(pddii, cbX(*pddii));
  351. CWaitCursor wc;
  352. if (Misc_InitPgxa(&pddii->gxa, cbX(NSI))) {
  353. if (RegCreateKey(pcdii->hkLMExplorer, c_tszDesktopNameSpace,
  354. &pddii->hkNS) == 0) {
  355. Desktop_EnumClasses(hwnd);
  356. }
  357. }
  358. /*
  359. * Set the order for My Documents if it exists.
  360. */
  361. HWND hdlg = GetParent(hwnd);
  362. PRIDL pridl = (PRIDL)pidlFromPath(psfDesktop, c_tszParseMyDocs);
  363. if (pridl && (pridl->bOrder == ORDER_BEFOREMYCOMP ||
  364. pridl->bOrder == ORDER_AFTERMYCOMP))
  365. {
  366. SHFILEINFO sfi;
  367. HWND hwndCombo = GetDlgItem(hdlg, IDC_ENUMFIRST);
  368. /* Item 0 = My Documents */
  369. SHGetFileInfo((LPCSTR)pridl, 0, &sfi, cbX(sfi), SHGFI_PIDL | SHGFI_DISPLAYNAME);
  370. ComboBox_AddString(hwndCombo, sfi.szDisplayName);
  371. /* Item 1 = My Computer */
  372. SHGetFileInfo(c_tszParseMyComp, 0, &sfi, cbX(sfi), SHGFI_DISPLAYNAME);
  373. ComboBox_AddString(hwndCombo, sfi.szDisplayName);
  374. pddii->iFirstIcon = pridl->bOrder == ORDER_AFTERMYCOMP;
  375. ComboBox_SetCurSel(hwndCombo, pddii->iFirstIcon);
  376. } else {
  377. DestroyDlgItems(hdlg, IDC_ENUMFIRSTTEXT, IDC_ENUMFIRST);
  378. }
  379. return 1;
  380. }
  381. /*****************************************************************************
  382. *
  383. * Desktop_OnDestroy
  384. *
  385. * Free the memory we allocated.
  386. *
  387. * We also destroy the imagelist, because listview gets confused if
  388. * it gets two image lists which are the same.
  389. *
  390. *****************************************************************************/
  391. void PASCAL
  392. Desktop_OnDestroy(HWND hdlg)
  393. {
  394. Misc_FreePgxa(&pddii->gxa);
  395. if (pddii->hkNS) {
  396. RegCloseKey(pddii->hkNS);
  397. }
  398. }
  399. #if 0
  400. /*****************************************************************************
  401. *
  402. * Desktop_FactoryReset
  403. *
  404. * This is scary and un-undoable, so let's do extra confirmation.
  405. *
  406. *****************************************************************************/
  407. void PASCAL
  408. Desktop_FactoryReset(HWND hdlg)
  409. {
  410. if (MessageBoxId(hdlg, IDS_DESKTOPRESETOK,
  411. tszName, MB_YESNO + MB_DEFBUTTON2) == IDYES) {
  412. pcdii->fRunShellInf = 1;
  413. Common_NeedLogoff(hdlg);
  414. PropSheet_Apply(GetParent(hdlg));
  415. }
  416. }
  417. #endif
  418. /*****************************************************************************
  419. *
  420. * Desktop_OnCreateNow
  421. *
  422. * Somebody asked to create another one...
  423. *
  424. * Use common dialogs to do the work.
  425. *
  426. *****************************************************************************/
  427. void PASCAL
  428. Desktop_OnCreateNow(HWND hwnd, int iItem)
  429. {
  430. LV_ITEM lvi;
  431. COFN cofn;
  432. lvi.pszText = cofn.tsz;
  433. lvi.cchTextMax = cA(cofn.tsz);
  434. Misc_LV_GetItemInfo(hwnd, &lvi, iItem, LVIF_PARAM | LVIF_TEXT);
  435. InitOpenFileName(GetParent(hwnd), &cofn, IDS_ALLFILES, cofn.tsz);
  436. cofn.ofn.nMaxFile -= ctchClsid + 1; /* Leave room for dot and clsid */
  437. cofn.ofn.Flags |= OFN_NOREADONLYRETURN;
  438. if (GetSaveFileName(&cofn.ofn)) {
  439. PNSI pnsi;
  440. lstrcat(cofn.tsz, c_tszDot);
  441. pnsi = pnsiPlvi(&lvi);
  442. lstrcat(cofn.tsz, pnsi->tszClsid);
  443. if ((pnsi->nsifl & nsiflDir) ||
  444. Desktop_GetClsidAttributes(pnsi->tszClsid) & SFGAO_FOLDER) {
  445. CreateDirectory(cofn.tsz, 0);
  446. } else {
  447. fCreateNil(cofn.tsz);
  448. }
  449. }
  450. }
  451. /*****************************************************************************
  452. *
  453. * Desktop_OnCommand
  454. *
  455. *****************************************************************************/
  456. void PASCAL
  457. Desktop_OnCommand(HWND hdlg, int id, UINT codeNotify)
  458. {
  459. switch (id) {
  460. #if 0
  461. case IDC_RESET:
  462. if (codeNotify == BN_CLICKED) {
  463. Desktop_FactoryReset(hdlg);
  464. }
  465. break;
  466. #endif
  467. case IDC_ENUMFIRST:
  468. if (codeNotify == CBN_SELCHANGE) {
  469. Common_SetDirty(hdlg);
  470. }
  471. break;
  472. }
  473. }
  474. /*****************************************************************************
  475. *
  476. * Desktop_LV_Dirtify
  477. *
  478. * Mark this item as having been renamed during the property sheet
  479. * page's lifetime.
  480. *
  481. *****************************************************************************/
  482. void PASCAL
  483. Desktop_LV_Dirtify(LPARAM insi)
  484. {
  485. pddii->pnsi[insi].nsifl |= nsiflEdited;
  486. }
  487. /*****************************************************************************
  488. *
  489. * Desktop_LV_GetIcon
  490. *
  491. * Produce the icon associated with an item. This is called when
  492. * we need to rebuild the icon list after the icon cache has been
  493. * purged.
  494. *
  495. *****************************************************************************/
  496. int PASCAL
  497. Desktop_LV_GetIcon(LPARAM insi)
  498. {
  499. SHFILEINFO sfi;
  500. sfi.iIcon = 0;
  501. SHGetFileInfo((LPCSTR)pidlPnsi(pnsiInsi(insi)), 0, &sfi, cbX(sfi),
  502. SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  503. return sfi.iIcon;
  504. }
  505. /*****************************************************************************
  506. *
  507. * Desktop_OnSelChange
  508. *
  509. * Disable the "Create as File" button if we are on Net Hood.
  510. *
  511. *****************************************************************************/
  512. void PASCAL
  513. Desktop_OnSelChange(HWND hwnd, int iItem)
  514. {
  515. PNSI pnsi = pnsiInsi(Misc_LV_GetParam(hwnd, iItem));
  516. EnableWindow(GetDlgItem(GetParent(hwnd), IDC_CREATENOW),
  517. pnsi->nsifl & nsiflNormal);
  518. }
  519. /*****************************************************************************
  520. *
  521. * Desktop_OnApply
  522. *
  523. * Write the changes to the registry.
  524. *
  525. *****************************************************************************/
  526. void PASCAL
  527. Desktop_OnApply(HWND hdlg)
  528. {
  529. HWND hwnd = GetDlgItem(hdlg, IDC_ICONLV);
  530. int cItems = ListView_GetItemCount(hwnd);
  531. BOOL fChanged = 0;
  532. LV_ITEM lvi;
  533. TCH tsz[cchFriendlyMax];
  534. lvi.pszText = tsz;
  535. lvi.cchTextMax = cA(tsz);
  536. for (lvi.iItem = 0; lvi.iItem < cItems; lvi.iItem++) {
  537. PNSI pnsi;
  538. lvi.stateMask = LVIS_STATEIMAGEMASK;
  539. Misc_LV_GetItemInfo(hwnd, &lvi, lvi.iItem,
  540. LVIF_PARAM | LVIF_TEXT | LVIF_STATE);
  541. pnsi = pnsiPlvi(&lvi);
  542. if (Desktop_IsHereNow(pnsi, pnsi->tszClsid) != LV_IsChecked(&lvi)) {
  543. fChanged = 1;
  544. if (pnsi->nsifl & nsiflNormal) {
  545. if (LV_IsChecked(&lvi)) {
  546. HKEY hk;
  547. if (RegCreateKey(pddii->hkNS, pnsi->tszClsid, &hk) == 0) {
  548. RegSetValuePtsz(hk, 0, lvi.pszText);
  549. RegCloseKey(hk);
  550. }
  551. } else {
  552. RegDeleteTree(pddii->hkNS, pnsi->tszClsid);
  553. }
  554. } else { /* Ah, the Net Hood... */
  555. Desktop_SetNetHood(LV_IsChecked(&lvi));
  556. Common_NeedLogoff(hdlg);
  557. if (!LV_IsChecked(&lvi)) {
  558. if (MessageBoxId(hdlg, IDS_NONETHOOD, g_tszName, MB_YESNO)
  559. == IDYES) {
  560. WinHelp(hdlg, c_tszMyHelp, HELP_CONTEXT, IDH_NONETHOOD);
  561. }
  562. }
  563. }
  564. }
  565. /* Not worth cacheing this */
  566. if (pnsi->nsifl & nsiflEdited) {
  567. SetNameOfPidl(psfDesktop, pidlPnsi(pnsi), lvi.pszText);
  568. SHChangeNotify(SHCNE_UPDATEIMAGE, SHCNF_DWORD,
  569. IntToPtr(lvi.iImage), 0L);
  570. }
  571. }
  572. HWND hwndCombo = GetDlgItem(hdlg, IDC_ENUMFIRST);
  573. int iFirstIcon = ComboBox_GetCurSel(hwndCombo);
  574. if (iFirstIcon != pddii->iFirstIcon) {
  575. SetDwordPkl2(&c_klMyDocsOrder, iFirstIcon ? ORDER_AFTERMYCOMP : ORDER_BEFOREMYCOMP);
  576. pddii->iFirstIcon = iFirstIcon;
  577. MessageBoxId(hdlg, IDS_REORDERDESKTOP, g_tszName, MB_OK);
  578. fChanged = TRUE;
  579. }
  580. if (fChanged) {
  581. SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_DWORD, 0L, 0L);
  582. }
  583. }
  584. /*****************************************************************************
  585. *
  586. * Desktop_LV_OnInitContextMenu
  587. *
  588. * Propagate the status of the Create Now button.
  589. *
  590. *****************************************************************************/
  591. void PASCAL
  592. Desktop_LV_OnInitContextMenu(HWND hwnd, int iItem, HMENU hmenu)
  593. {
  594. Misc_EnableMenuFromHdlgId(hmenu, GetParent(hwnd), IDC_CREATENOW);
  595. }
  596. /*****************************************************************************
  597. *
  598. * Oh yeah, we need this too.
  599. *
  600. *****************************************************************************/
  601. #pragma BEGIN_CONST_DATA
  602. LVCI lvciDesktop[] = {
  603. { IDC_CREATENOW, Desktop_OnCreateNow },
  604. { 0, 0 },
  605. };
  606. LVV lvvDesktop = {
  607. Desktop_OnCommand,
  608. Desktop_LV_OnInitContextMenu,
  609. Desktop_LV_Dirtify,
  610. Desktop_LV_GetIcon,
  611. Desktop_OnInitDialog,
  612. Desktop_OnApply,
  613. Desktop_OnDestroy,
  614. Desktop_OnSelChange,
  615. 1, /* iMenu */
  616. rgdwHelp,
  617. 0, /* Double-click action */
  618. lvvflIcons | /* We need icons */
  619. lvvflCanCheck | /* And check boxes */
  620. lvvflCanRename, /* and you can rename by clicking */
  621. lvciDesktop,
  622. };
  623. #pragma END_CONST_DATA
  624. /*****************************************************************************
  625. *
  626. * Our window procedure.
  627. *
  628. *****************************************************************************/
  629. INT_PTR EXPORT
  630. Desktop_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  631. {
  632. return LV_DlgProc(&lvvDesktop, hdlg, wm, wParam, lParam);
  633. }