/*
 * 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;
    }
}
