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.

158 lines
3.9 KiB

  1. /*
  2. * link - The Rundll that turns off "Shortcut to"
  3. *
  4. * This works around a bug in Shell32, where an off-by-one prevented
  5. * the restore of the setting from working.
  6. */
  7. #include "tweakui.h"
  8. #pragma BEGIN_CONST_DATA
  9. KL c_klLink = { &g_hkCUSMWCV, c_tszExplorer, c_tszLink };
  10. #pragma END_CONST_DATA
  11. /*****************************************************************************
  12. *
  13. * Link_GetShortcutTo
  14. *
  15. * Determine whether the "Shortcut to" prefix is enabled.
  16. *
  17. *****************************************************************************/
  18. BOOL PASCAL
  19. Link_GetShortcutTo(void)
  20. {
  21. return GetDwordPkl(&c_klLink, 1) > 0;
  22. }
  23. /*****************************************************************************
  24. *
  25. * fCreateNil
  26. *
  27. * Create a zero-length file.
  28. *
  29. *****************************************************************************/
  30. BOOL PASCAL
  31. fCreateNil(LPCTSTR cqn)
  32. {
  33. HFILE hf = _lcreat(cqn, 0);
  34. if (hf != -1) {
  35. _lclose(hf);
  36. return 1;
  37. } else {
  38. return 0;
  39. }
  40. }
  41. /*****************************************************************************
  42. *
  43. * Link_Drop -- Create a temp directory, then...
  44. * Link_DropCqn -- create a pidl for the directory, then...
  45. * Link_DropPidlCqn -- bind to the pidl, then...
  46. * Link_DropPsfCqn -- try 20 times to...
  47. * Link_RenameToBang -- rename a scratch pidl to "!"
  48. *
  49. * (Welcome to lisp.)
  50. *
  51. * Keep renaming a file, losing the "Shortcut to", until the shell
  52. * finally gets the point, or we've tried 20 times and give up.
  53. * If the shell doesn't get the point after 20 tries, it'll never
  54. * learn...
  55. *
  56. * Returns 0 if we couldn't do it.
  57. *
  58. * We do this by creating a temporary directory within the temp
  59. * directory. In this temp-temp directory, create a file called
  60. * "Shortcut to !.lnk", then keep renaming it to "!".
  61. *
  62. * By creating it in a brand new temp dir, we are sure we won't
  63. * conflict with any other files.
  64. *
  65. *****************************************************************************/
  66. BOOL PASCAL
  67. Link_RenameToBang(PIDL pidl, LPVOID pv)
  68. {
  69. PSF psf = (PSF)pv;
  70. DeleteFile(c_tszBangLnk); /* So the rename will work */
  71. return SetNameOfPidl(psf, pidl, c_tszBang);
  72. }
  73. BOOL PASCAL
  74. Link_DropPsfCqn(PSF psf, LPVOID pv)
  75. {
  76. LPCTSTR cqn = (LPCTSTR)pv;
  77. if (fCreateNil(c_tszBang)) {
  78. BOOL fRc;
  79. TCH tszLinkToBang[MAX_PATH];
  80. if (mit.SHGetNewLinkInfo(c_tszBang, cqn, tszLinkToBang, &fRc,
  81. SHGNLI_PREFIXNAME)) {
  82. int iter;
  83. for (iter = 0; iter < 20 && Link_GetShortcutTo(); iter++) {
  84. fCreateNil(tszLinkToBang);
  85. WithPidl(psf, ptszFilenameCqn(tszLinkToBang),
  86. Link_RenameToBang, psf);
  87. }
  88. }
  89. }
  90. return !Link_GetShortcutTo();
  91. }
  92. BOOL PASCAL
  93. Link_DropPidlCqn(PIDL pidl, LPVOID cqn)
  94. {
  95. return WithPsf(psfDesktop, pidl, Link_DropPsfCqn, cqn);
  96. }
  97. BOOL PASCAL
  98. Link_DropCqn(LPCTSTR cqn, LPVOID pv)
  99. {
  100. return WithPidl(psfDesktop, cqn, Link_DropPidlCqn, (LPVOID)cqn);
  101. }
  102. Link_Drop(void)
  103. {
  104. return WithTempDirectory(Link_DropCqn, 0);
  105. }
  106. /*****************************************************************************
  107. *
  108. * Link_SetShortcutTo
  109. *
  110. * Set or clear the "prepend "Shortcut to" to new shortcuts" flag.
  111. *
  112. * If we need to set it, then set the registry key and ask the user
  113. * to log off and back on. There is no way to make the count go up.
  114. *
  115. * If we need to clear it, then keep renaming "Shortcut to frob" to
  116. * "frob" until the link count goes to zero.
  117. *
  118. * Returns 0 if the user must log off and back on for the change
  119. * to take effect.
  120. *
  121. *****************************************************************************/
  122. BOOL PASCAL
  123. Link_SetShortcutTo(BOOL fPrefix)
  124. {
  125. if (fPrefix != Link_GetShortcutTo()) {
  126. if (fPrefix) {
  127. DelPkl(&c_klLink);
  128. return 0; /* Must log off and back on */
  129. } else { /* Make the count drop to zero */
  130. if (!g_fNT && Link_Drop()) {
  131. return 1;
  132. } else {
  133. SetDwordPkl(&c_klLink, fPrefix);
  134. /* Oh well */
  135. return 0;
  136. }
  137. }
  138. } else {
  139. return 1;
  140. }
  141. }