//TODO: Expand this function to allow for artificially elevated limited users.
        //      For example, a limited user given the permission to write to HKLM
        //      (something that is normally forbidden).
        bool OnlyUpdatingLocalUser()
        {
            // if installing
            //         - system folders
            //         - non-user registry
            //         - Windows Services
            //         - COM files
            // then return false
            // Also note how we're excluding the "BaseDir".
            // This is because the base directory may or may not be in the userprofile
            // directory (or otherwise writable by the user), thus it needs a separate check.
            // Ditto for the "client.wyc" file.
            if (((updateFrom.InstallingTo | InstallingTo.BaseDir) ^ InstallingTo.BaseDir) != 0)
            {
                return(false);
            }

            string userProfileFolder = SystemFolders.GetUserProfile();

            // if the basedir isn't in the userprofile folder (C:\Users\UserName)
            // OR
            // if the folder isn't in the full control of the current user
            // THEN
            // we're not "only updating the local user
            if ((updateFrom.InstallingTo & InstallingTo.BaseDir) != 0 && !(SystemFolders.IsDirInDir(userProfileFolder, baseDirectory) || HaveFolderPermissions(baseDirectory)))
            {
                return(false);
            }

            return(true);
        }
Exemple #2
0
        //TODO: Expand this function to allow for artificially elevated limited users.
        //      For example, a limited user given the permission to write to HKLM
        //      (something that is normally forbidden).
        bool OnlyUpdatingLocalUser()
        {
            // if installing
            //         - system folders
            //         - non-user registry
            //         - Windows Services
            //         - COM files
            // then return false
            // Also note how we're excluding the "BaseDir".
            // This is because the base directory may or may not be in the userprofile
            // directory (or otherwise writable by the user), thus it needs a separate check.
            // Ditto for the "client.wyc" file.
            if (((updateFrom.InstallingTo | InstallingTo.BaseDir) ^ InstallingTo.BaseDir) != 0)
            {
                return(false);
            }

            string userProfileFolder = SystemFolders.GetUserProfile();

            // if the basedir isn't in the userprofile folder (C:\Users\UserName)
            // OR
            // if the folder isn't in the full control of the current user
            // THEN
            // we're not "only updating the local user
            if ((updateFrom.InstallingTo & InstallingTo.BaseDir) != 0 && !(SystemFolders.IsDirInDir(userProfileFolder, baseDirectory) || HaveFolderPermissions(baseDirectory)))
            {
                return(false);
            }

            // if the client data file isn't in the userprofile folder (or otherwise writable)
            // then bail out.
            if (!(SystemFolders.IsFileInDirectory(userProfileFolder, clientFileLoc) || HaveFolderPermissions(Path.GetDirectoryName(clientFileLoc))))
            {
                return(false);
            }

            // when self-updating, if this client isn't in the userprofile folder
            if ((SelfUpdateState == SelfUpdateState.WillUpdate ||
                 SelfUpdateState == SelfUpdateState.FullUpdate ||
                 SelfUpdateState == SelfUpdateState.Extracted) &&
                !(SystemFolders.IsFileInDirectory(userProfileFolder, VersionTools.SelfLocation) ||
                  HaveFolderPermissions(Path.GetDirectoryName(VersionTools.SelfLocation))))
            {
                return(false);
            }

            return(true);
        }
        /// <summary>Gets or creates the cache folder for a GUID.</summary>
        /// <param name="guid">The GUID.</param>
        /// <returns>The directory to the cache folder</returns>
        static string GetCacheFolder(string guid)
        {
            string userprofile = SystemFolders.GetUserProfile();

            // if getting the userprofile folder fails, then try the app data folder
            if (string.IsNullOrEmpty(userprofile))
            {
                userprofile = SystemFolders.GetCurrentUserAppData();
            }

            if (string.IsNullOrEmpty(userprofile))
            {
                throw new Exception("Failed to retrieve the user profile folder.");
            }

            // C:\Users\USERNAME\wc
            string temp = Path.Combine(userprofile, "wc");

            // if the folder temp folder doesn't exist, create the folder with hidden attributes
            if (!Directory.Exists(temp))
            {
                Directory.CreateDirectory(temp);
                File.SetAttributes(temp, FileAttributes.System | FileAttributes.Hidden);
            }

            string fullGuidFolder = Path.Combine(temp, guid);

            // Workaround for the "pyramid of death" bug.
            // Note: This still doesn't address the root cause of the "pyramid of death"
            //       namely, why aren't the folders being cleaned up on the failure of wyUpdate?
            // Perhaps it's a crashing bug. Further investigation is needed. We need to look into
            // possible causes for cached files being left around. This problem was first spotted
            // when a user's app crashed when they were debugging. It was crashing over and over again
            if (Directory.Exists(fullGuidFolder))
            {
                string guidFile = Path.Combine(fullGuidFolder, guid);

                // if the GUID file doesn't already exist then the cache is busted.
                if (!File.Exists(guidFile))
                {
                    // delete every file and folder in the directory because it's an invalid cache
                    string[] obs = Directory.GetDirectories(fullGuidFolder);

                    // remove all directories
                    foreach (var dir in obs)
                    {
                        Directory.Delete(dir, true);
                    }

                    obs = Directory.GetFiles(fullGuidFolder);

                    // remove all the files
                    foreach (var file in obs)
                    {
                        File.Delete(file);
                    }

                    // create the blank GUID file
                    using (File.Create(guidFile));
                }

                return(fullGuidFolder);
            }

            // try to create the smallest possible folder name (using the GUID)
            string closestMatch = null;

            string[] dirs = Directory.GetDirectories(temp);

            // loop through the directories - stop at the first partial match this GUID
            for (int i = 0; i < dirs.Length; i++)
            {
                string name = Path.GetFileName(dirs[i]);

                if (string.IsNullOrEmpty(name) || guid.IndexOf(name) != 0)
                {
                    continue;
                }

                // see if the partial-matching folder contains an empty GUID file
                if (File.Exists(Path.Combine(dirs[i], guid)))
                {
                    return(dirs[i]);
                }

                closestMatch = name;
            }

            // the folder doesn't exist, so we'll create it
            string guidCacheFolder = Path.Combine(temp, guid.Substring(0, closestMatch == null ? 1 : closestMatch.Length + 1));

            Directory.CreateDirectory(guidCacheFolder);

            // create the blank GUID file
            using (File.Create(Path.Combine(guidCacheFolder, guid)));

            return(guidCacheFolder);
        }