Implements a managed Stream object on top of a COM IStream.
Inheritance: Stream, IDisposable
        /// <summary>
        /// Called by the shell if the _strSolutionUserOptionsKey section declared in LoadUserOptions() as 
        /// being written by this package has been found in the suo file
        /// </summary>
        public int ReadUserOptions([In] IStream pOptionsStream, [In] string pszKey)
        {
            // This function is called by the shell if the _strSolutionUserOptionsKey section declared
            // in LoadUserOptions() as being written by this package has been found in the suo file. 
            // Note this can be during opening a new solution, or may be during merging of 2 solutions.
            // A good source control provider may need to persist this data until OnAfterOpenSolution or OnAfterMergeSolution is called

            // The easiest way to read/write the data of interest is by using a binary formatter class
            DataStreamFromComStream pStream = new DataStreamFromComStream(pOptionsStream);
            Hashtable hashProjectsUserData = new Hashtable(); 
            if (pStream.Length > 0)
            {
                BinaryFormatter formatter = new BinaryFormatter();
                hashProjectsUserData = formatter.Deserialize(pStream) as Hashtable;
            }

            IVsSolution solution = (IVsSolution)GetService(typeof(SVsSolution));
            foreach (string projUniqueName in hashProjectsUserData.Keys)
            {
                // If this project is recognizable as part of the solution
                IVsHierarchy pHier = null;
                if (solution.GetProjectOfUniqueName(projUniqueName, out pHier) == VSConstants.S_OK &&
                    pHier != null)
                {
                    sccService.ToggleOfflineStatus(pHier);
                }
            }

            return VSConstants.S_OK;
        }
        /// <summary>
        /// Called by the shell to let the package write user options under the specified key.
        /// </summary>
        public int WriteUserOptions([In] IStream pOptionsStream, [In] string pszKey)
        {
            // This function gets called by the shell to let the package write user options under the specified key.
            // The key was declared in SaveUserOptions(), when the shell started saving the suo file.
            Debug.Assert(pszKey.CompareTo(_strSolutionUserOptionsKey) == 0, "The shell called to read an key that doesn't belong to this package");

            Hashtable hashProjectsUserData = new Hashtable();
            IVsSolution solution = (IVsSolution)GetService(typeof(SVsSolution));
            // get the list of controllable projects
            Hashtable hash = GetLoadedControllableProjectsEnum();
            // add the solution to the controllable projects list
            IVsHierarchy solHier = (IVsHierarchy)GetService(typeof(SVsSolution));
            hash[solHier] = true;
            // collect all projects that are controlled and offline
            foreach (IVsHierarchy pHier in hash.Keys)
            {
                if (sccService.IsProjectControlled(pHier) &&
                    sccService.IsProjectOffline(pHier))
                {
                    // The information we'll persist in the suo file needs to be usable if the solution is moved in a diffrent location
                    // therefore we'll store project names as known by the solution (mostly relativized to the solution's folder)
                    string projUniqueName;
                    if (solution.GetUniqueNameOfProject(pHier, out projUniqueName) == VSConstants.S_OK)
                    {
                        hashProjectsUserData[projUniqueName] = true;
                    }
                }
            }

            // The easiest way to read/write the data of interest is by using a binary formatter class
            // This way, we can write a map of information about projects with one call 
            // (each element in the map needs to be serializable though)
            // The alternative is to write binary data in any byte format you'd like using pOptionsStream.Write
            DataStreamFromComStream pStream = new DataStreamFromComStream(pOptionsStream);
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(pStream, hashProjectsUserData);

            return VSConstants.S_OK;
        }