windows-nt/Source/XPSP1/NT/sdktools/tweakui/link.cpp
2020-09-26 16:20:57 +08:00

159 lines
3.9 KiB
C++

/*
* link - The Rundll that turns off "Shortcut to"
*
* This works around a bug in Shell32, where an off-by-one prevented
* the restore of the setting from working.
*/
#include "tweakui.h"
#pragma BEGIN_CONST_DATA
KL c_klLink = { &g_hkCUSMWCV, c_tszExplorer, c_tszLink };
#pragma END_CONST_DATA
/*****************************************************************************
*
* Link_GetShortcutTo
*
* Determine whether the "Shortcut to" prefix is enabled.
*
*****************************************************************************/
BOOL PASCAL
Link_GetShortcutTo(void)
{
return GetDwordPkl(&c_klLink, 1) > 0;
}
/*****************************************************************************
*
* fCreateNil
*
* Create a zero-length file.
*
*****************************************************************************/
BOOL PASCAL
fCreateNil(LPCTSTR cqn)
{
HFILE hf = _lcreat(cqn, 0);
if (hf != -1) {
_lclose(hf);
return 1;
} else {
return 0;
}
}
/*****************************************************************************
*
* Link_Drop -- Create a temp directory, then...
* Link_DropCqn -- create a pidl for the directory, then...
* Link_DropPidlCqn -- bind to the pidl, then...
* Link_DropPsfCqn -- try 20 times to...
* Link_RenameToBang -- rename a scratch pidl to "!"
*
* (Welcome to lisp.)
*
* Keep renaming a file, losing the "Shortcut to", until the shell
* finally gets the point, or we've tried 20 times and give up.
* If the shell doesn't get the point after 20 tries, it'll never
* learn...
*
* Returns 0 if we couldn't do it.
*
* We do this by creating a temporary directory within the temp
* directory. In this temp-temp directory, create a file called
* "Shortcut to !.lnk", then keep renaming it to "!".
*
* By creating it in a brand new temp dir, we are sure we won't
* conflict with any other files.
*
*****************************************************************************/
BOOL PASCAL
Link_RenameToBang(PIDL pidl, LPVOID pv)
{
PSF psf = (PSF)pv;
DeleteFile(c_tszBangLnk); /* So the rename will work */
return SetNameOfPidl(psf, pidl, c_tszBang);
}
BOOL PASCAL
Link_DropPsfCqn(PSF psf, LPVOID pv)
{
LPCTSTR cqn = (LPCTSTR)pv;
if (fCreateNil(c_tszBang)) {
BOOL fRc;
TCH tszLinkToBang[MAX_PATH];
if (mit.SHGetNewLinkInfo(c_tszBang, cqn, tszLinkToBang, &fRc,
SHGNLI_PREFIXNAME)) {
int iter;
for (iter = 0; iter < 20 && Link_GetShortcutTo(); iter++) {
fCreateNil(tszLinkToBang);
WithPidl(psf, ptszFilenameCqn(tszLinkToBang),
Link_RenameToBang, psf);
}
}
}
return !Link_GetShortcutTo();
}
BOOL PASCAL
Link_DropPidlCqn(PIDL pidl, LPVOID cqn)
{
return WithPsf(psfDesktop, pidl, Link_DropPsfCqn, cqn);
}
BOOL PASCAL
Link_DropCqn(LPCTSTR cqn, LPVOID pv)
{
return WithPidl(psfDesktop, cqn, Link_DropPidlCqn, (LPVOID)cqn);
}
Link_Drop(void)
{
return WithTempDirectory(Link_DropCqn, 0);
}
/*****************************************************************************
*
* Link_SetShortcutTo
*
* Set or clear the "prepend "Shortcut to" to new shortcuts" flag.
*
* If we need to set it, then set the registry key and ask the user
* to log off and back on. There is no way to make the count go up.
*
* If we need to clear it, then keep renaming "Shortcut to frob" to
* "frob" until the link count goes to zero.
*
* Returns 0 if the user must log off and back on for the change
* to take effect.
*
*****************************************************************************/
BOOL PASCAL
Link_SetShortcutTo(BOOL fPrefix)
{
if (fPrefix != Link_GetShortcutTo()) {
if (fPrefix) {
DelPkl(&c_klLink);
return 0; /* Must log off and back on */
} else { /* Make the count drop to zero */
if (!g_fNT && Link_Drop()) {
return 1;
} else {
SetDwordPkl(&c_klLink, fPrefix);
/* Oh well */
return 0;
}
}
} else {
return 1;
}
}