159 lines
3.9 KiB
C++
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;
|
||
|
}
|
||
|
}
|