Vista Does Not Virtualize Creation Of Shell Links

Windows Vista developers beware: Vista does not perform file virtualization on the creation of shell links. Consider the following code:

// Creates a shell link (a.k.a. shortcut) located at swzLinkFile that points to
// szTargetFile with a description of szDescription.
BOOL CreateLink(LPCTSTR szTargetFile, LPCTSTR szDescription, LPCOLESTR swzLinkFile)
{
    BOOL bRet = FALSE;

    IShellLink* psl;
    HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                                    IID_IShellLink, (void**) &psl);
    if (SUCCEEDED(hr))
    {
        IPersistFile* ppf;
        hr = psl->QueryInterface(IID_IPersistFile, (void**) &ppf);
        if (SUCCEEDED(hr))
        {
            hr = psl->SetPath(szTargetFile);
            if (SUCCEEDED(hr))
            {
                hr = psl->SetDescription(szDescription);
                if (SUCCEEDED(hr))
                {
                    hr = ppf->Save(swzLinkFile, TRUE);
                    if (SUCCEEDED(hr))
                    {
                        bSuccess = TRUE;
                    }
                }
            }
            ppf->Release();
        }
        psl->Release();
    }
    return bSuccess;
}

// NOTE: Hardcoding C:\WINDOWS and C:\Program Files is a bad practice.  Use
// something like ::SHGetFolderPath().
BOOL bSuccess = CreateLink
    (
    _T("C:\\WINDOWS\\SYSTEM32\\SOL.EXE"),
    _T("Shortcut to SOL.EXE"),
    L"C:\\Program Files\\sol.lnk")
    );

One might expect that the creation of the file C:\Program Files\sol.lnk would be silently redirected by Vista using file virtualization and CreateLink() would succeed, but it doesn’t — the call to IPersistFile::Save() returns E_ACCESSDENIED.

For more information about developing on Vista, see the document Windows Vista Application Development Requirements for User Account Control Compatibility.

Advertisements