internal void SaveSolutionProj(MFSolution solution)
        {
            if (!string.IsNullOrEmpty(solution.ProjectPath))
            {
                try
                {
                    //if(File.Exists(solution.ProjectPath)
                    string fullpath = ExpandEnvVars(solution.ProjectPath, "");

                    Project proj = LoadProject(fullpath);
                    proj.ProjectCollection.UnloadProject(proj);
                    
                    proj = new Project();
                    proj.Xml.DefaultTargets = "Build";

                    string dir = Path.GetDirectoryName(fullpath);

                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }

                    ProjectPropertyGroupElement mainGrp = proj.Xml.AddPropertyGroup();

                    mainGrp.AddProperty("Author", solution.Author);
                    mainGrp.AddProperty("Description", solution.Description);
                    mainGrp.AddProperty("Documentation", solution.Documentation);
                    mainGrp.AddProperty("PlatformGuid", solution.Guid);

                    if (solution.DefaultISA != null && solution.DefaultISA.Name != null)
                    {
                        ProjectPropertyElement bp = mainGrp.AddProperty("INSTRUCTION_SET", solution.DefaultISA.Name);
                        bp.Condition = solution.DefaultISA.Conditional;
                    }
                    mainGrp.AddProperty("TARGETPLATFORM", solution.Name);
                    mainGrp.AddProperty("PLATFORM", solution.Name);
                    mainGrp.AddProperty("IsSolutionWizardVisible", solution.IsSolutionWizardVisible.ToString());
                    mainGrp.AddProperty("ENDIANNESS", solution.ENDIANNESS.ToString());

                    Dictionary<string,object> nameLookup = new Dictionary<string,object>();

                    foreach (MFProperty prop in solution.Properties)
                    {
                        switch (prop.Name.ToLower())
                        {
                            case "author":
                            case "description":
                            case "documentation":
                            case "platformguid":
                            case "targetplatform":
                            case "platform":
                            case "issolutionwizardvisible":
                            case "endianness":
                            case "tcp_ip_stack":
                            case "instruction_set":
                                // these properties are reset in this method - this prevents duplication
                                break;

                            default:
                                string key = prop.Name.ToLower();
                                if(!nameLookup.ContainsKey(key))
                                {
                                    ProjectPropertyElement bp = mainGrp.AddProperty(prop.Name, prop.Value);
                                    bp.Condition = prop.Condition;
                                    nameLookup[key] = bp;
                                }
                                break;
                        }
                    }


                    MFProject defProj = null;

                    foreach (MFProject prj in solution.Projects)
                    {
                        if (prj.IsClrProject)
                        {
                            defProj = prj;
                            break;
                        }
                    }

                    if (defProj != null)
                    {
                        ///
                        /// If we have the LWIP feature project then we need to add the following property to the 
                        /// solutions settings file
                        /// 
                        bool AddLWIP = false;
                        foreach (MFComponent f in defProj.Features)
                        {
                            if (f.Name.Equals("Network (RTIP)", StringComparison.InvariantCultureIgnoreCase))
                            {
                                AddLWIP = false;
                                break;
                            }
                            else if (f.Name.Equals("Network (LWIP)", StringComparison.InvariantCultureIgnoreCase))
                            {
                                AddLWIP = true;
                            }
                        }
                        if (AddLWIP)
                        {
                            mainGrp.AddProperty("TCP_IP_STACK", "LWIP");
                        }
                    }

                    ProjectItemGroupElement big = proj.Xml.AddItemGroup();

                    string solPath = RemoveSpoClient(Path.GetDirectoryName(solution.ProjectPath));
                    bool fFoundSolPath = false;

                    foreach (MFBuildFile item in solution.Items)
                    {
                        if (string.Equals(item.ItemName, "IncludePaths", StringComparison.InvariantCultureIgnoreCase) &&
                            string.Equals(item.File, solPath, StringComparison.InvariantCultureIgnoreCase))
                        {
                            fFoundSolPath = true;
                        }

                        ProjectItemElement bi = big.AddItem(item.ItemName, item.File);
                        bi.Condition = item.Condition;
                    }

                    if (!fFoundSolPath)
                    {
                        big.AddItem("IncludePaths", solPath);
                    }

                    Processor prc = null;

                    if (!string.IsNullOrEmpty(solution.Processor.Guid))
                    {
                        prc = m_helper.FindProcessor(solution.Processor.Guid);
                    }
                    else
                    {
                        prc = m_helper.FindProcessorByName(solution.Processor.Name);
                        if (prc != null)
                        {
                            solution.Processor.Guid = prc.Guid;
                            solution.Processor.Name = prc.Name;
                            solution.Processor.ProjectPath = prc.ProjectPath;
                        }
                    }

                    if (prc != null)
                    {
                        proj.Xml.AddImport(prc.ProjectPath);
                    }

                    proj.Save(fullpath);

                    
                    if (solution.m_cloneSolution != null)
                    {
                        string cloneRoot = Path.GetDirectoryName(ExpandEnvVars(solution.m_cloneSolution.ProjectPath, "")) + "\\";
                        string newRoot = Path.GetDirectoryName(ExpandEnvVars(solution.ProjectPath, "")) + "\\";
                        CopyClonedFile(cloneRoot + "platform_selector.h", newRoot + "platform_selector.h", solution.m_cloneSolution.Name, solution.Name);

                        ///
                        /// Copy the LWIP_selector file for the cloned solution
                        /// 
                        if (File.Exists(cloneRoot + "lwip_selector.h"))
                        {
                            CopyClonedFile(cloneRoot + "lwip_selector.h", newRoot + "lwip_selector.h", solution.m_cloneSolution.Name, solution.Name);
                        }
                        //CopyClonedFile(cloneRoot + "dotnetmf.proj", newRoot + "dotnetmf.proj", solution.m_cloneSolution.Name, solution.Name);
                        //CopyClonedFiles(cloneRoot + "DeviceCode\\", newRoot + "DeviceCode\\", solution.m_cloneSolution.Name, solution.Name);
                    }

                    ///
                    /// copy the generic lwip_selector file in the case the cloned solution doesn't have one or we are creating a
                    /// new solution with LWIP
                    /// 
                    if (!File.Exists(Path.Combine(dir, "lwip_selector.h")))
                    {
                        string lwipSel = ExpandEnvVars("$(SPOCLIENT)\\DeviceCode\\PAL\\LWIP\\Config\\lwip_selector.h", "");
                        if (File.Exists(lwipSel) && defProj != null)
                        {
                            foreach (MFComponent f in defProj.Features)
                            {
                                if (f.Name.Equals("Network (LWIP)", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    CopyClonedFile(lwipSel, Path.Combine(dir, "lwip_selector.h"), "<TEMPLATE>", solution.Name);
                                    break;
                                }
                            }
                        }
                    }

                    string platSelectorFile = Path.Combine(dir, "platform_selector.h");
                    bool fNewSelector = false;

                    if (!File.Exists(platSelectorFile))
                    {
                        Processor proc = m_helper.FindProcessor(solution.Processor.Guid);

                        if(proc != null)
                        {
                            string template = Path.GetDirectoryName(ExpandEnvVars(proc.ProjectPath, "")) + "\\" + proc.Name + "_template_selector.h";
                            string newRoot = Path.GetDirectoryName(ExpandEnvVars(solution.ProjectPath, "")) + "\\";

                            if (File.Exists(template))
                            {
                                CopyClonedFile(template, newRoot + "platform_selector.h", "<TEMPLATE>", solution.Name);
                                fNewSelector = true;
                            }
                        }
                    }

                    // only modify if we are cloning or creating a new solution
                    if (File.Exists(platSelectorFile))
                    {
                        if (fNewSelector || (solution.m_cloneSolution != null))
                        {
                            FileAttributes attribs = File.GetAttributes(platSelectorFile);

                            if (0 != (attribs & FileAttributes.ReadOnly))
                            {
                                throw new Exception("File Access Exception: File " + platSelectorFile + " is not accessible");
                            }

                            string tmpFile = Path.GetTempFileName();
                            using (TextWriter tw = File.CreateText(tmpFile))
                            {
                                using (TextReader tr = File.OpenText(platSelectorFile))
                                {
                                    string data = tr.ReadToEnd();

                                    Regex rx = new Regex("#define\\s+SYSTEM_CLOCK_HZ\\s+[^\\r^\\n]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define SYSTEM_CLOCK_HZ                 " + solution.SystemClockSpeed.ToString());

                                    rx = new Regex("#define\\s+SLOW_CLOCKS_PER_SECOND\\s+[^\\r^\\n]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define SLOW_CLOCKS_PER_SECOND          " + solution.SlowClockSpeed.ToString());

                                    rx = new Regex("#define\\s+SRAM1_MEMORY_Base\\s+[^\\r^\\n]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define SRAM1_MEMORY_Base   0x" + solution.RamBase.ToString("X08"));

                                    rx = new Regex("#define\\s+SRAM1_MEMORY_Size\\s+[^\\r^\\n]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define SRAM1_MEMORY_Size   0x" + solution.RamLength.ToString("X08"));

                                    rx = new Regex("#define\\s+FLASH_MEMORY_Base\\s+[^\\r^\\n]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define FLASH_MEMORY_Base   0x" + solution.FlashBase.ToString("X08"));

                                    rx = new Regex("#define\\s+FLASH_MEMORY_Size\\s+[^\\r^\\n]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define FLASH_MEMORY_Size   0x" + solution.FlashLength.ToString("X08"));

                                    rx = new Regex("#define\\s+DEBUG_TEXT_PORT\\s+[^\\s]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define DEBUG_TEXT_PORT    " + solution.DebuggerPort);

                                    rx = new Regex("#define\\s+STDIO\\s+[\\w\\d_]+");
                                    data = rx.Replace(data, "#define STDIO              " + solution.DebuggerPort);

                                    rx = new Regex("#define\\s+DEBUGGER_PORT\\s+[^\\s]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define DEBUGGER_PORT      " + solution.DebuggerPort);

                                    rx = new Regex("#define\\s+MESSAGING_PORT\\s+[^\\s]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define MESSAGING_PORT     " + solution.DebuggerPort);

                                    rx = new Regex("#define\\s+RUNTIME_MEMORY_PROFILE__[\\w]+", RegexOptions.Singleline);
                                    data = rx.Replace(data, "#define RUNTIME_MEMORY_PROFILE__" + solution.MemoryProfile);

                                    tw.Write(data);
                                }
                            }

                            File.Delete(platSelectorFile);
                            File.Move(tmpFile, platSelectorFile);
                        }
                    }
                    else
                    {
                        using (TextWriter tw = File.CreateText(platSelectorFile))
                        {
                            tw.WriteLine(string.Format("#ifndef _PLATFORM_{0}_SELECTOR_H_\r\n#define _PLATFORM_{0}_SELECTOR_H_ 1", solution.Name));

                            tw.WriteLine(string.Format("#define HAL_SYSTEM_NAME                 \"{0}\"", solution.Name));
                            tw.WriteLine(string.Format("#define PLATFORM_{0}    ", prc.Name.ToUpper()));
                            tw.WriteLine(string.Format("#define PLATFORM_{0}_{1}", prc.PlatformFamily.ToUpper(), prc.Name.ToUpper()));
                            tw.WriteLine(string.Format("#define PLATFORM_{0}_{1}", prc.PlatformFamily.ToUpper(), solution.Name.ToUpper()));
                            if (0 == string.Compare(prc.Name, "MC9328", true))
                            {
                                tw.WriteLine("#define PLATFORM_ARM_MC9328MXL");
                            }

                            tw.WriteLine("#define PLATFORM_SUPPORTS_SOFT_REBOOT   TRUE");

                            tw.WriteLine(string.Format("#define SYSTEM_CLOCK_HZ                 {0}", solution.SystemClockSpeed));
                            tw.WriteLine(string.Format("#define SLOW_CLOCKS_PER_SECOND          {0}", solution.SlowClockSpeed));
                            tw.WriteLine("#define CLOCK_COMMON_FACTOR             1");
                            tw.WriteLine("#define SLOW_CLOCKS_TEN_MHZ_GCD         1");
                            tw.WriteLine("#define SLOW_CLOCKS_MILLISECOND_GCD     1");

                            tw.WriteLine(string.Format("#define SRAM1_MEMORY_Base               0x{0:X08}", solution.RamBase));
                            tw.WriteLine(string.Format("#define SRAM1_MEMORY_Size               0x{0:X08}", solution.RamLength));
                            tw.WriteLine(string.Format("#define FLASH_MEMORY_Base               0x{0:X08}", solution.FlashBase));
                            tw.WriteLine(string.Format("#define FLASH_MEMORY_Size               0x{0:X08}", solution.FlashLength));

                            tw.WriteLine(@"
#define TXPROTECTRESISTOR               RESISTOR_DISABLED
#define RXPROTECTRESISTOR               RESISTOR_DISABLED
#define CTSPROTECTRESISTOR              RESISTOR_DISABLED
#define RTSPROTECTRESISTOR              RESISTOR_DISABLED
");

                            tw.WriteLine(@"
#define GLOBAL_LOCK(x)             SmartPtr_IRQ x
#define DISABLE_INTERRUPTS()       SmartPtr_IRQ::ForceDisabled()
#define ENABLE_INTERRUPTS()        SmartPtr_IRQ::ForceEnabled()
#define INTERRUPTS_ENABLED_STATE() SmartPtr_IRQ::GetState()
#define GLOBAL_LOCK_SOCKETS(x)     SmartPtr_IRQ x

#if defined(_DEBUG)
#define ASSERT_IRQ_MUST_BE_OFF()   ASSERT(!SmartPtr_IRQ::GetState())
#define ASSERT_IRQ_MUST_BE_ON()    ASSERT( SmartPtr_IRQ::GetState())
#else
#define ASSERT_IRQ_MUST_BE_OFF()
#define ASSERT_IRQ_MUST_BE_ON()
#endif

#define TOTAL_USART_PORT       1
#define COM1                   ConvertCOM_ComHandle(0)
#define COM2                   ConvertCOM_ComHandle(1)

#define TOTAL_USB_CONTROLLER   1
#define USB1                   ConvertCOM_UsbHandle(0)

#define TOTAL_SOCK_PORT        0

#define TOTAL_DEBUG_PORT       1
#define COM_DEBUG              ConvertCOM_DebugHandle(0)

#define COM_MESSAGING          ConvertCOM_MessagingHandle(0)

#define USART_TX_IRQ_INDEX(x)       ( (x) ? 0 : 0 )     // TODO set right indexes
#define USART_DEFAULT_PORT          COM1
#define USART_DEFAULT_BAUDRATE      115200

#define USB_IRQ_INDEX               0                   // TODO set right index


#define PLATFORM_DEPENDENT_TX_USART_BUFFER_SIZE    512  // there is one TX for each usart port
#define PLATFORM_DEPENDENT_RX_USART_BUFFER_SIZE    512  // there is one RX for each usart port
#define PLATFORM_DEPENDENT_USB_QUEUE_PACKET_COUNT  32  // there is one queue for each pipe of each endpoint and the size of a single packet is sizeof(USB_PACKET64) == 68 bytes
");


                            tw.WriteLine(string.Format("#define DEBUG_TEXT_PORT         {0}", solution.DebuggerPort));
                            tw.WriteLine(string.Format("#define STDIO                   {0}", solution.DebuggerPort));
                            tw.WriteLine(string.Format("#define DEBUGGER_PORT           {0}", solution.DebuggerPort));
                            tw.WriteLine(string.Format("#define MESSAGING_PORT          {0}", solution.DebuggerPort));

                            tw.WriteLine(string.Format("#define RUNTIME_MEMORY_PROFILE__{0} 1", solution.MemoryProfile));

                            tw.WriteLine("#include <processor_selector.h>");

                            tw.WriteLine(string.Format("#endif // _PLATFORM_{0}_SELECTOR_H_ 1", solution.Name));
                        }
                    }

                    //foreach (MFProject prj in solution.Projects)
                    //{
                    //    SaveProjectProj(prj);
                    //}
                }
                catch
                {
                    Console.WriteLine("Error: Unable to save solution file " + solution.ProjectPath);
                }
            }
        }
        public List<MFComponentDescriptor> GetAvailableSolutions(string spoClientRoot)
        {
            List<MFComponentDescriptor> list = new List<MFComponentDescriptor>();
            string fullpath = ExpandEnvVars(Path.Combine(spoClientRoot, "Solutions"), "");

            foreach (string subdir in Directory.GetDirectories(fullpath))
            {
                foreach (string solution in Directory.GetFiles(subdir, "*.settings"))
                {
                    try
                    {
                        Project proj = LoadProject(solution);
                        Processor proc = null;

                        MFSolution sol = new MFSolution();

                        Dictionary<string, string> tbl = new Dictionary<string, string>();
                        tbl["PLATFORM"] = "Name";
                        tbl["PlatformGuid"] = "Guid";

                        LoadStringProps(proj, sol, tbl);

                        foreach (ProjectImportElement imp in proj.Xml.Imports)
                        {
                            if (imp.Project.ToLower().Contains(@"\devicecode\targets\"))
                            {
                                proc = LoadProcessorProj(imp.Project, "");
                            }
                        }

                        if (sol.IsSolutionWizardVisible)
                        {
                            list.Add(new MFComponentDescriptor(new MFComponent(MFComponentType.MFSolution, sol.Name, sol.Guid, solution), sol.Description, sol.Documentation, proj.FullPath, proc));
                        }
                    }
                    catch (Exception e)
                    {
                        System.Diagnostics.Debug.WriteLine("Error: loading solution file: " + solution + "\r\n", e.Message);
                    }
                }
            }
            return list;
        }
        public MFSolution CloneSolution(MFSolution solution, string name)
        {
            MFSolution solNew = new MFSolution();

            solution.CopyTo(solNew, name);

            return solNew;
        }
        public Library[] GetLibrariesOfType(LibraryCategory LibraryCategory, MFProject proj, MFSolution solution)
        {
            List<Library> ret = new List<Library>();

            foreach (Inventory inv in m_invs)
            {
                foreach (Library lib in inv.Libraries)
                {
                    if (lib.LibraryCategory != null)
                    {
                        if (string.IsNullOrEmpty(lib.LibraryCategory.Guid)) continue;

                        if (0 == string.Compare(lib.LibraryCategory.Guid, LibraryCategory.Guid, true))
                        {
                            ret.Add(lib);
                        }
                    }
                }
            }

            return ret.ToArray();
        }
        private void addPlatformToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode parent = treeViewInventory.Nodes[0].Nodes["Solutions"];
            MFSolution newPlat = new MFSolution();

            newPlat.Guid = Guid.NewGuid().ToString("B").ToUpper();

            TreeNode newNode = AddTreeElement(parent, "<New Solution>", newPlat, true, DefaultInventory.Solutions, c_defaultInventoryKey);

            DefaultInventory.Solutions.Add(newPlat);

            treeViewInventory.SelectedNode = newNode;
            newNode.BeginEdit();
        }
        public void AnalyzeLibraries(InventoryHelper helper, MFSolution solution, List<LibraryCategory> unresolved, List<LibraryCategory> removed)
        {
            Dictionary<string, MFComponent> reqLibList = new Dictionary<string, MFComponent>();
            Dictionary<string, MFComponent> unresolvedTypes = new Dictionary<string, MFComponent>();
            List<MFComponent> features = new List<MFComponent>();
            Dictionary<string, MFComponent> preferredLibrary = new Dictionary<string, MFComponent>();
            
            Processor proc = helper.FindProcessor(solution.Processor.Guid);

            libraryCategoriesField.Clear();

            ///
            /// First add all the features and there dependencies
            ///
            if (this.IsClrProject)
            {
                foreach (MFComponent cmpFeat in featuresField)
                {
                    RecurseFeatureDeps(cmpFeat, features, helper);
                }

                ///
                /// get debug transport
                ///
                if (solution.TransportType != null)
                {
                    string key = solution.TransportType.Guid.ToLower();

                    foreach (MFComponent transportFeat in solution.TransportType.FeatureAssociations)
                    {
                        if (!features.Contains(transportFeat))
                        {
                            features.Add(transportFeat);
                        }
                    }
                }
            }

            this.featuresField.Clear();
            foreach (MFComponent cmpFeat in features)
            {
                Feature feat = helper.FindFeature(cmpFeat.Guid);

                this.featuresField.Add(cmpFeat);

                foreach (MFComponent cmp in feat.ComponentDependencies)
                {
                    string key = cmp.Guid.ToLower();

                    if (cmp.ComponentType == MFComponentType.LibraryCategory)
                    {
                        if (!unresolvedTypes.ContainsKey(key))
                        {
                            unresolvedTypes[key] = cmp;
                        }
                    }
                    else if (cmp.ComponentType == MFComponentType.Library)
                    {
                        reqLibList[key] = cmp;
                        RecurseLibCatDeps(cmp, unresolvedTypes, helper, false);
                    }
                }
            }

            ///
            /// Add any required libraries before analyzing all project libraries
            ///
            foreach (Library lib in helper.GetRequiredLibraries())
            {
                // Only add CLR libraries to CLR projects
                if (lib.Level == LibraryLevel.CLR && !this.IsClrProject)
                    continue;

                string key = lib.Guid.ToLower();

                if (!reqLibList.ContainsKey(key))
                {
                    MFComponent cmpNew = new MFComponent(MFComponentType.Library, lib.Name, lib.Guid, lib.ProjectPath);

                    reqLibList[key] = cmpNew;

                    RecurseLibCatDeps(cmpNew, unresolvedTypes, helper, false);
                }
            }

            ///
            /// Now add all required library categories
            ///
            foreach (LibraryCategory lc in helper.GetRequiredLibraryCategories())
            {
                if (lc.Level == LibraryLevel.CLR && !this.isClrProjectField) continue;

                string key = lc.Guid.ToLower();

                if (!unresolvedTypes.ContainsKey(key))
                {
                    MFComponent cmp = new MFComponent(MFComponentType.LibraryCategory, lc.Name, lc.Guid, lc.ProjectPath);

                    unresolvedTypes[lc.Guid.ToLower()] = cmp;
                }
            }

            ///
            /// Add cloned solution's solution-dependent projects
            /// 
            if (solution.m_cloneSolution != null && m_cloneProj != null)
            {
                foreach (MFComponent lib in m_cloneProj.librariesField)
                {
                    // If we have already added a library for the current solution, then just add a new component to the project
                    if (solution.m_clonedLibraryMap.ContainsKey(lib.Guid.ToUpper()))
                    {
                        Library newLib = solution.m_clonedLibraryMap[lib.Guid.ToUpper()];

                        librariesField.Add(new MFComponent(lib.ComponentType, newLib.Name, newLib.Guid, newLib.ProjectPath, lib.Conditional));
                    }
                    // otherwise, create a new library based on the cloned solution's library
                    else if (lib.ProjectPath.ToUpper().Contains("\\SOLUTIONS\\" + solution.m_cloneSolution.Name.ToUpper() + "\\"))
                    {
                        string name = CopyHelper.ReplaceText(lib.Name, solution.m_cloneSolution.Name, solution.Name);
                        string path = CopyHelper.ReplaceText(lib.ProjectPath, solution.m_cloneSolution.Name, solution.Name);
                        string guid = System.Guid.NewGuid().ToString("B").ToUpper();

                        // find cloned solution's library in the intventory
                        Library l = helper.FindLibrary(lib);
                        if (l != null)
                        {
                            Library l2 = new Library();

                            // copy and rename 
                            l.CopyTo(l2);

                            CopyHelper.Rename(l2, solution.m_cloneSolution.Name, solution.Name);

                            l2.Name = name;
                            l2.Guid = guid;
                            l2.ProjectPath = path;

                            // add library to inventory
                            helper.AddLibraryToInventory(l2, false, helper.DefaultInventory);

                            // hash to used so that we don't add multiple libraries for each project
                            solution.m_clonedLibraryMap[lib.Guid.ToUpper()] = l2;
                            // Add the component to this projects library list
                            MFComponent newCmp = new MFComponent(lib.ComponentType, name, guid, path, lib.Conditional);
                            librariesField.Add(newCmp);

                            if (l.HasLibraryCategory)
                            {
                                preferredLibrary[l.LibraryCategory.Guid.ToLower()] = newCmp;
                            }
                        }
                    }
                }
            }

            ///
            /// HACK - fix this to make it data driven (add a field on library categories that allows them to be required by a solution)
            /// 
            if (this.isClrProjectField)
            {
                LibraryCategory lc = helper.FindLibraryCategoryByName("WearLeveling_HAL");

                if (lc != null)
                {
                    string key = lc.Guid.ToLower();
                    if (unresolvedTypes.ContainsKey(key))
                    {
                        solution.m_solRequiredLibCats[key] = unresolvedTypes[key];
                    }
                }
            }
            else if(solution.m_solRequiredLibCats != null)
            {
                foreach (MFComponent cmp in solution.m_solRequiredLibCats.Values)
                {
                    string key = cmp.Guid.ToLower();

                    if (!unresolvedTypes.ContainsKey(key))
                    {
                        unresolvedTypes[key] = cmp;
                    }
                }
            }

            /// 
            /// Use a copy of the libraries, because the libraryField may be updated inside the loop
            /// 
            MFComponent[] __libs = new MFComponent[librariesField.Count];
            librariesField.CopyTo(__libs);

            List<MFComponent> libs = new List<MFComponent>(__libs);
            Dictionary<string, MFComponent> resolvedTypes = new Dictionary<string, MFComponent>();
            List<string> duplicateLibList = new List<string>();

            while (true)
            {
                List<MFComponent> remList = new List<MFComponent>();
                Dictionary<string, MFComponent> newUnresolvedTypes = new Dictionary<string, MFComponent>();

                foreach (MFComponent cmpLib in libs)
                {
                    Library lib = helper.FindLibrary(cmpLib);

                    bool fKeepingLib = false;

                    if (duplicateLibList.Contains(cmpLib.Guid.ToLower()) || lib == null || !ValidateLibrary(lib, solution, proc, helper))
                    {
                        librariesField.Remove(cmpLib);
                        remList.Add(cmpLib);
                        continue;
                    }

                    if (lib.HasLibraryCategory)
                    {
                        if (preferredLibrary.ContainsKey(lib.LibraryCategory.Guid.ToLower()) &&
                            string.Compare(cmpLib.Guid, preferredLibrary[lib.LibraryCategory.Guid.ToLower()].Guid, true) != 0)
                        {
                            fKeepingLib = true;
                        }
                        ///
                        /// Make sure the library selection matches the feature selection
                        ///
                        else if (this.isClrProjectField)
                        {
                            LibraryCategory lc = helper.FindLibraryCategory(lib.LibraryCategory.Guid);

                            if (lc != null)
                            {
                                if (lc.FeatureAssociations.Count > 0)
                                {
                                    bool fFeatureSelected = false;

                                    foreach (MFComponent feat in lc.FeatureAssociations)
                                    {
                                        if (features.Contains(feat))
                                        {
                                            fFeatureSelected = true;
                                            break;
                                        }
                                    }

                                    if (((!fFeatureSelected && !lib.IsStub) || (fFeatureSelected && lib.IsStub)) &&
                                        string.IsNullOrEmpty(cmpLib.Conditional))
                                    {
                                        librariesField.Remove(cmpLib);
                                        remList.Add(cmpLib);
                                        continue;
                                    }
                                }
                            }
                        }

                        if (!fKeepingLib)
                        {
                            string key = lib.LibraryCategory.Guid.ToLower();

                            if (unresolvedTypes.ContainsKey(key) || (!string.IsNullOrEmpty(cmpLib.Conditional) && resolvedTypes.ContainsKey(key)))
                            {
                                unresolvedTypes.Remove(key);
                                resolvedTypes[key] = lib.LibraryCategory;
                                fKeepingLib = true;
                                RecurseLibCatDeps(cmpLib, newUnresolvedTypes, helper, true);
                            }
                        }
                    }
                    else
                    {
                        fKeepingLib = true;
                    }

                    if (fKeepingLib)
                    {
                        remList.Add(cmpLib);

                        duplicateLibList.Add(cmpLib.Guid.ToLower());

                        foreach (MFComponent dep in lib.Dependencies)
                        {
                            if (dep.ComponentType == MFComponentType.Library)
                            {
                                if (duplicateLibList.Contains(dep.Guid.ToLower()) || librariesField.Contains(dep))
                                {
                                    continue;
                                }

                                Library libDep = helper.FindLibrary(dep);

                                if (libDep != null && libDep.HasLibraryCategory)
                                {
                                    string key = libDep.LibraryCategory.Guid.ToLower();
                                    if(!unresolvedTypes.ContainsKey(key) && !resolvedTypes.ContainsKey(key) && !newUnresolvedTypes.ContainsKey(key))
                                    {
                                        newUnresolvedTypes[key] = libDep.LibraryCategory;
                                    }
                                }
                                else
                                {
                                    remList.Add(dep);
                                    librariesField.Add(dep);
                                }
                            }
                        }
                    }
                }

                foreach (MFComponent cmp in remList)
                {
                    if (libs.Contains(cmp))
                    {
                        libs.Remove(cmp);
                    }
                }

                if (newUnresolvedTypes.Count == 0) break;

                foreach (string key in newUnresolvedTypes.Keys)
                {
                    if (!unresolvedTypes.ContainsKey(key) && !resolvedTypes.ContainsKey(key))
                    {
                        unresolvedTypes[key] = newUnresolvedTypes[key];
                    }
                }
            }

            foreach (MFComponent cmp in resolvedTypes.Values)
            {
                libraryCategoriesField.Add(cmp);
            }

            foreach (MFComponent cmp in libs)
            {
                librariesField.Remove(cmp);
            }

            foreach (MFComponent cmp in reqLibList.Values)
            {
                if (!librariesField.Contains(cmp))
                {
                    Library lib = helper.FindLibrary(cmp);
                    if (lib != null && ValidateLibrary(lib, solution, proc, helper))
                    {
                        librariesField.Add(cmp);
                    }
                }
            }

            foreach (MFComponent cmp in unresolvedTypes.Values)
            {
                LibraryCategory lc = helper.FindLibraryCategory(cmp.Guid);

                unresolved.Add(lc);
            }
        }
        public void CopyTo(MFSolution dest, string newName)
        {
            Dictionary<string, string> hash = new Dictionary<string, string>();

            dest.m_cloneSolution = this;
            
            hash[this.nameField] = newName;
            hash[@"\$\(PLATFORM\)"] = newName;
            hash[@"\$\(TARGETPLATFORM\)"] = newName;

            CopyHelper.CopyTo(this, dest, hash);
        }
        internal void CopyProjFilesFromClone(MFProject proj, MFSolution solution)
        {
            if (proj.m_cloneProj != null)
            {
                string dirSource = MsBuildWrapper.ExpandEnvVars(Path.GetDirectoryName(proj.m_cloneProj.ProjectPath), "");
                string dirTarg = MsBuildWrapper.ExpandEnvVars(Path.GetDirectoryName(proj.ProjectPath), "");
                string dirSourceRoot = Path.GetDirectoryName(dirSource);
                string dirTargRoot = Path.GetDirectoryName(dirTarg);

                try
                {
                    CopyClonedFiles(dirSourceRoot, dirTargRoot, solution.m_cloneSolution == null ? "$(PLATFORM)" : solution.m_cloneSolution.Name, solution.Name, false);
                    CopyClonedFiles(dirSource, dirTarg, solution.m_cloneSolution == null ? "$(PLATFORM)" : solution.m_cloneSolution.Name, solution.Name, true);
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine("Error: Copying clone files\r\n\tsrc:" + dirSource + "\r\n\tdst:" + dirTarg + "\r\n", e.Message);
                }
                
            }
        }
        private void wpCreatePlatform_CloseFromNext(object sender, Gui.Wizard.PageEventArgs e)
        {
            MFSolution sol = null;

            Regex expUnsupportedChars = new Regex("[^\\w\\d_]+");

            if (expUnsupportedChars.IsMatch(tb_PlatformName.Text))
            {
                MessageBox.Show(this, Properties.Resources.InvalidSolutionName, Properties.Resources.SolutionWizard, MessageBoxButtons.OK, MessageBoxIcon.Error);
                e.Page = wpCreatePlatform;
                return;
            }

            if (m_IsSolutionCloned && (m_solution == null || m_solution.m_cloneSolution == null))
            {
                sol = new MFSolution();

                m_solution.CopyTo(sol, tb_PlatformName.Text);
            }
            else if (m_solution != null)
            {
                sol = m_solution;
            }
            else
            {
                sol = new MFSolution();
            }

            sol.Name = tb_PlatformName.Text;
            sol.Description = tb_PlatformDescription.Text;
            sol.Author = tb_SolutionAuthor.Text;

            m_solution = sol;

            if (m_selectedSolution != null && IsWindowsSolution(m_solution))
            {
                Processor proc = m_bw.LoadProcessorProj(m_spoClientPath + "\\devicecode\\Targets\\OS\\Windows\\Windows.settings", "");
                if(proc != null)
                {
                    m_solution.Processor = new MFComponent(MFComponentType.Processor, proc.Name, proc.Guid, proc.ProjectPath);
                }

                m_solution.Projects[0].Name = m_solution.Name;

                e.Page = wpChooseFeatures;
            }


            Wiz.NextEnabled = true;
        }
 public MFSolution()
 {
     this.m_cloneSolution = null;
     this.m_solRequiredLibCats = new Dictionary<string,MFComponent>();
     this.m_clonedLibraryMap = new Dictionary<string, Library>();
     this.descriptionField = "";
     this.documentationField = "";
     this.guidField = System.Guid.NewGuid().ToString("B");
     this.nameField = "";
     this.projectsField = new System.Collections.Generic.List<MFProject>(); 
     this.versionField = new Version();
     this.propertiesField = new System.Collections.Generic.List<MFProperty>();
     this.isSolutionWizardVisibleField = true;
     this.authorField = "";
     this.itemsField = new List<MFBuildFile>();
     this.customFilterField = "";
     this.m_transportType = null;
     this.ENDIANNESS = "le";
 }
 private bool IsWindowsSolution(MFSolution solution)
 {
     return (0 == string.Compare(solution.Processor.Name, "windows", true));
 }
 void m_worker_DoWork(object sender, DoWorkEventArgs e)
 {
     lock (m_bw)
     {
         switch((BackgroundWorkerType)e.Argument)
         {
             case BackgroundWorkerType.LoadFeatures:
                 if (m_solution == null && m_selectedSolution != null)
                 {
                     m_solution = m_bw.LoadSolutionProj(m_selectedSolution.Component.ProjectPath, "");
                 }
                 if (IsWindowsSolution(m_solution))
                 {
                     m_bw.LoadDefaultLibraries(m_spoClientPath);
                     m_bw.LoadDefaultLibraryCategories(m_spoClientPath);
                     //m_bw.LoadDefaultManifestFiles(m_spoClientPath);
                 }
                 m_bw.LoadDefaultFeatures(m_spoClientPath);
                 break;
             case BackgroundWorkerType.LoadSolution:
                 m_solution = m_bw.LoadSolutionProj(m_selectedSolution.Component.ProjectPath, "");
                 m_bw.LoadLibraries( m_solution.ProjectPath);
                 m_bw.LoadDefaultLibraryCategories(m_spoClientPath);
                 break;
             case BackgroundWorkerType.LoadProjects:
                 if (m_inv.ProjectTemplates.Count == 0)
                 {
                     m_bw.LoadTemplateProjects(m_spoClientPath + "\\ProjectTemplates");
                 }
                 break;
             case BackgroundWorkerType.LoadSolutions:
                 m_solutionRefs = m_bw.GetAvailableSolutions(m_spoClientPath);
                 break;
             case BackgroundWorkerType.LoadLibraries:
                 m_bw.LoadDefaultLibraries(m_spoClientPath);
                 //m_bw.LoadDefaultManifestFiles(m_spoClientPath);
                 m_bw.LoadDefaultLibraryCategories(m_spoClientPath);
                 m_bw.LoadDefaultFeatures(m_spoClientPath);
                 break;
             case BackgroundWorkerType.LoadProcessors:
                 m_bw.LoadProcessors(m_spoClientPath + "\\DeviceCode\\Targets\\Native");
                 m_bw.LoadProcessors(m_spoClientPath + "\\DeviceCode\\Targets\\OS");
                 break;
         }
     }
     e.Result = e.Argument;
 }
        private void cloneSolutionToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            TreeNode tn = treeViewInventory.SelectedNode;

            if(tn == null) return;

            TreeNodeData tnd = (tn.Tag as TreeNodeData);

            if (tnd != null)
            {
                MFSolution sol = tnd.Data as MFSolution;

                if (sol != null)
                {
                    MFSolution solNew = new MFSolution();

                    sol.CopyTo(solNew, "<Cloned " + sol.Name + " Solution>");

                    this.DefaultInventory.Solutions.Add(solNew);

                    RefreshTree();
                }
            }
        }
        internal MFSolution LoadSolutionProj(string solutionProjFile, string path)
        {
            MFSolution sol = new MFSolution();
            Project proj;
            string fullpath = ExpandEnvVars(solutionProjFile, path);

            string codebase = "";
            string codebasetype = "";
            string processor = "";

            try
            {
                proj = LoadProject(fullpath);

                path = Path.GetDirectoryName(fullpath);

                // load solution libraries

                LoadLibraries(Path.Combine(path, "DeviceCode"));

                Dictionary<string, string> tbl = new Dictionary<string, string>();
                tbl["PLATFORM"] = "Name";
                tbl["PlatformGuid"] = "Guid";

                LoadStringProps(proj, sol, tbl);

                foreach (ProjectItemGroupElement big in proj.Xml.ItemGroups)
                {
                    foreach (ProjectItemElement bi in big.Items)
                    {
                        MFBuildFile bf = new MFBuildFile();
                        bf.File = bi.Include;
                        bf.ItemName = bi.ItemType;
                        bf.Condition = bi.Condition;

                        sol.Items.Add(bf);
                    }
                }

                foreach (ResolvedImport imp in proj.Imports)
                {
                    if (imp.ImportedProject.FullPath.ToLower().Contains("\\devicecode\\targets\\"))
                    {
                        Processor proc = LoadProcessorProj(imp.ImportedProject.FullPath, "");

                        if (proc != null)
                        {
                            sol.Processor = new MFComponent(MFComponentType.Processor, proc.Name, proc.Guid, proc.ProjectPath);
                        }
                    }
                }

                if (sol.Processor == null || string.IsNullOrEmpty(sol.Processor.Name))
                {
                    foreach (ProjectProperty prop in proj.Properties)
                    {
                        if (prop.IsImported)
                        {
                            if (prop.Name == "TARGETPROCESSOR")
                            {
                                Processor proc = m_helper.FindProcessorByName(prop.EvaluatedValue);
                                if (proc != null)
                                {
                                    sol.Processor = new MFComponent(MFComponentType.Processor, proc.Name, proc.Guid);
                                }
                                else
                                {
                                    foreach (ProjectImportElement imp in proj.Xml.Imports)
                                    {
                                        if (imp.Project.ToUpper().Contains("\\DEVICECODE\\TARGETS\\"))
                                        {
                                            proc = LoadProcessorProj(imp.Project, "");
                                            break;
                                        }
                                    }
                                }

                                if (proc == null)
                                {
                                    sol.Processor = new MFComponent(MFComponentType.Processor, prop.EvaluatedValue);
                                    sol.Processor.Guid = "";
                                }
                                else
                                {
                                    sol.Processor = new MFComponent(MFComponentType.Processor, proc.Name, proc.Guid, proc.ProjectPath);
                                }
                            }
                        }
                    }
                }

                foreach (ProjectPropertyGroupElement pg in proj.Xml.PropertyGroups)
                {
                    foreach (ProjectPropertyElement bp in pg.Properties)
                    {
                        string cond = CombineConditionals(pg.Condition, bp.Condition);

                        switch (bp.Name)
                        {
                            case "Description":
                                sol.Description = bp.Value;
                                break;
                            case "Documentation":
                                sol.Documentation = bp.Value;
                                break;
                            case "INSTRUCTION_SET":
                                ISA isa = m_helper.FindISAByName(bp.Value);
                                if (isa == null)
                                {
                                    sol.DefaultISA = new MFComponent(MFComponentType.ISA, bp.Value);
                                }
                                else
                                {
                                    sol.DefaultISA = new MFComponent(MFComponentType.ISA, isa.Name, isa.Guid);
                                }
                                break;
                            case "PLATFORM":
                            case "TARGETPLATFORM":
                                sol.Name = bp.Value;
                                break;
                            case "PlatformGuid":
                                sol.Guid = bp.Value;
                                break;
                            case "TARGETPROCESSOR":
                                Processor proc = m_helper.FindProcessorByName(bp.Value);
                                if (proc != null)
                                {
                                    sol.Processor = new MFComponent(MFComponentType.Processor, proc.Name, proc.Guid);
                                }
                                else
                                {
                                    processor = bp.Value;
                                }
                                break;
                            //obsolete props (moved to processor settings)
                            case "PLATFORM_FAMILY":
                            case "ARM_TYPE":
                            case "MDK_DEVICE_TYPE":
                            case "CPUName":
                                break;
                            case "TARGETCODEBASE":
                                codebase = bp.Value;
                                break;
                            case "TARGETCODEBASETYPE":
                                codebasetype = bp.Value;
                                break;
                            default:
                                MFProperty prop = new MFProperty();
                                prop.Name = bp.Name;
                                prop.Value = bp.Value;
                                prop.Condition = cond;
                                sol.Properties.Add(prop);
                                break;
                        }
                    }
                }

                // for legacy settings files
                if (sol.Processor == null)
                {
                    string procFile = Path.Combine(Environment.GetEnvironmentVariable("SPOCLIENT"), "DeviceCode\\Targets\\" + codebasetype + "\\" + codebase + "\\" + processor + ".settings");

                    if (File.Exists(procFile))
                    {
                        Processor proc = LoadProcessorProj(procFile, "");

                        sol.Processor = new MFComponent(MFComponentType.Processor, proc.Name, proc.Guid);
                    }
                    else // delay load
                    {
                        sol.Processor = new MFComponent(MFComponentType.Processor, processor);
                        sol.Processor.Guid = "";
                    }
                }

                if (string.IsNullOrEmpty(sol.Name)) sol.Name = Path.GetFileNameWithoutExtension(solutionProjFile);
                if (string.IsNullOrEmpty(sol.Guid)) sol.Guid = System.Guid.NewGuid().ToString("B");

                sol.ProjectPath = ConvertPathToEnv(solutionProjFile);

                foreach (string subdir in Directory.GetDirectories(Path.GetDirectoryName(fullpath)))
                {
                    if (subdir.TrimEnd().ToUpper().EndsWith("DEVICECODE")) continue;

                    foreach (string projFile in Directory.GetFiles(subdir, "*.proj"))
                    {
                        MFProject mfproj = LoadProjectProj(projFile, Path.GetDirectoryName(projFile));

                        if (mfproj != null) sol.Projects.Add(mfproj);
                    }
                }

                // load platform selector file for memory data
                string platSelectorFile = Path.Combine(path, "platform_selector.h");
                if (File.Exists(platSelectorFile))
                {
                    string data = "";

                    using (TextReader tr = File.OpenText(platSelectorFile))
                    {
                        data = tr.ReadToEnd();
                    }


                    sol.SystemClockSpeed = ParseHexInt(data, "SYSTEM_CLOCK_HZ");
                    sol.SlowClockSpeed = ParseHexInt(data, "SLOW_CLOCKS_PER_SECOND");

                    Regex rx = null;
                    Match m = null;

                    if (sol.SlowClockSpeed == -1)
                    {
                        rx = new Regex("\\sSLOW_CLOCKS_PER_SECOND\\s+SYSTEM_CLOCK_HZ");
                        if (rx.IsMatch(data))
                        {
                            sol.SlowClockSpeed = sol.SystemClockSpeed;
                        }
                    }

                    sol.RamBase = ParseHexInt(data, "SRAM1_MEMORY_Base");
                    sol.RamLength = ParseHexInt(data, "SRAM1_MEMORY_Size");
                    sol.FlashBase = ParseHexInt(data, "FLASH_MEMORY_Base");
                    sol.FlashLength = ParseHexInt(data, "FLASH_MEMORY_Size");

                    rx = new Regex("#define\\s+DEBUGGER_PORT\\s+([\\w\\d_]+)", RegexOptions.IgnoreCase);
                    m = rx.Match(data);
                    if (m.Success)
                    {
                        sol.DebuggerPort = m.Groups[1].Value;
                    }
                    else
                    {
                        sol.DebuggerPort = "COM1";
                    }

                    rx = new Regex("\\sRUNTIME_MEMORY_PROFILE__([\\w]+)");
                    m = rx.Match(data);
                    if (m.Success)
                    {
                        sol.MemoryProfile = m.Groups[1].Value;
                    }
                    else
                    {
                        sol.MemoryProfile = "medium";
                    }
                }

                MFSolution dbSol = m_helper.FindSolutionByName(sol.Name);

                if (null == dbSol)
                {
                    m_helper.DefaultInventory.Solutions.Add(sol);
                }
                else
                {
                    sol = dbSol;
                }
            }
            catch(Exception e)
            {
                System.Diagnostics.Debug.WriteLine("Error: Exception in load solution " + e.Message);
                sol = null;
            }

            return sol;
        }
        public void Rename(string newName)
        {
            if (m_cloneSolution == null)
            {
                MFSolution sol = new MFSolution();
                
                CopyHelper.CopyTo(this, sol);

                m_cloneSolution = sol;
            }

            CopyHelper.Rename(this, this.nameField, newName);
        }
        internal void CreateSolutionDirProj(MFSolution solution)
        {
            string solutionDir = @"$(SPOCLIENT)\Solutions\" + solution.Name;
            string fullpath = ExpandEnvVars(Path.Combine(solutionDir, "dotnetmf.proj"), "");

            Project proj = LoadProject(fullpath);

            proj.ProjectCollection.UnloadProject(proj);

            proj = new Project();
            proj.Xml.DefaultTargets = "Build";

            try
            {
                ProjectPropertyGroupElement bpg = proj.Xml.AddPropertyGroup();
                bpg.AddProperty("Directory", RemoveSpoClient(solutionDir));
                bpg.AddProperty("MFSettingsFile", Path.Combine(solutionDir, solution.Name + ".settings"));

                ProjectItemGroupElement big = proj.Xml.AddItemGroup();
                foreach (MFProject mfproj in solution.Projects)
                {
                    if (!string.IsNullOrEmpty(mfproj.Directory) && !string.IsNullOrEmpty(mfproj.ProjectPath))
                    {
                        ProjectItemElement bi = big.AddItem("RequiredProjects", Path.Combine(Path.GetFileName(mfproj.Directory), Path.GetFileName(mfproj.ProjectPath)));
                    }
                }

                proj.Xml.AddImport(@"$(SPOCLIENT)\tools\targets\Microsoft.SPOT.System.Settings");
                proj.Xml.AddImport(@"$(SPOCLIENT)\tools\targets\Microsoft.SPOT.System.Targets");

                proj.Save(fullpath);
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("Error: loading LibCat file: " + fullpath + "\r\n", e.Message);
            }
        }
        public bool ValidateLibrary(Library lib, MFSolution solution, Processor proc, InventoryHelper helper)
        {
            try
            {
                if (!lib.IsSolutionWizardVisible)
                {
                    return false;
                }

                // don't show processor specific libraries
                if ((lib.ProcessorSpecific != null) && !string.IsNullOrEmpty(lib.ProcessorSpecific.Guid) &&
                    (0 != string.Compare(lib.ProcessorSpecific.Guid, solution.Processor.Guid, true)))
                {
                    return false;
                }

                if (!string.IsNullOrEmpty(lib.CustomFilter))
                {
                    bool OK = false;

                    // don't show custom specific libraries
                    foreach (string libFilter in lib.CustomFilter.Split(';'))
                    {
                        string[] customAttribs = proc.CustomFilter.Split(';');

                        foreach (string attrib in customAttribs)
                        {
                            if (string.Compare(attrib, libFilter, true) == 0)
                            {
                                OK = true;
                                break;
                            }
                        }
                        if (!OK)
                        {
                            foreach (string attrib in solution.CustomFilter.Split(';'))
                            {
                                if (0 == string.Compare(attrib, libFilter, true))
                                {
                                    OK = true;
                                    break;
                                }
                            }
                        }

                        /// 
                        /// Now lets check to see if one of the selected features contains this filter.
                        /// This is used for Network (LWIP) to enable the libraries to be auto selected
                        /// based on which Network feature was choosen
                        /// 
                        if (!OK)
                        {
                            MFProject defProj = null;
                            foreach(MFProject proj in solution.Projects)
                            {
                                if(proj.IsClrProject)
                                {
                                    defProj = proj; 
                                    break;
                                }
                            }

                            foreach (MFComponent feat in defProj.Features)
                            {
                                Feature f = helper.FindFeature(feat.Guid);
                                
                                if (f != null && 0 == string.Compare(f.Filter, libFilter, true))
                                {
                                    OK = true;
                                    break;
                                }
                            }
                        }

                        if (!OK)
                        {
                            OK = (0 == string.Compare(lib.CustomFilter, solution.Name, true));
                        }
                        if (OK) break;
                    }

                    if (!OK) return false;
                }

                if (!IsBootloaderProject() && lib.IsBootloaderLibrary())
                {
                    return false;
                }

                // only add CLR libraries to a CLR project
                if (lib.Level == LibraryLevel.CLR && !this.IsClrProject)
                {
                    return false;
                }

                string projPath = lib.ProjectPath.ToLower();
                if (projPath.Contains(@"\devicecode\drivers\sample\"))
                {
                    return false;
                }

                if (projPath.Contains("\\solutions\\") && !projPath.Contains("\\solutions\\" + solution.Name.ToLower() + "\\"))
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("Exception validating solution libraries: " + e.ToString());
                return false;
            }

            return true;
        }
        internal void CopyTemplateFiles(LibraryCategory libType, MFSolution solution, MFComponent compLibTemplate)
        {
            const string c_FastCompile      = @"fastcompile.cpp";
            const string c_FastCompileTag   = @"FastCompileCPPFile";

            string dstPath = Path.Combine(ExpandEnvVars(Path.GetDirectoryName(solution.ProjectPath), ""), "DeviceCode\\");

            List<string> reloadProjs = new List<string>();

            //Regex expRelPath = new Regex("([\\w\\W]*\\\\)([^\\\\]+\\\\[^\\\\]+)");
            //Regex expRemoveDeviceCode = new Regex("\\\\DeviceCode\\\\", RegexOptions.IgnoreCase);
            //Regex expRemoveStubDir = new Regex("\\\\stub[s]?\\\\", RegexOptions.IgnoreCase);
            Regex expStubReplace = new Regex("(?<!Is)(stub[s]?)", RegexOptions.IgnoreCase);
            //string relPath = "";

            foreach (ApiTemplate api in libType.Templates)
            {
                string src = ExpandEnvVars( api.FilePath, Environment.GetEnvironmentVariable("SPOCLIENT") );
                
                //
                // Make relative path based on path after \DeviceCode\ if it exists, otherwise up to two directories deep
                //
                //relPath = Path.GetDirectoryName(src);
                //string devCode = "\\devicecode\\";

                /*
                int idx = relPath.ToLower().IndexOf(devCode);
                
                if (idx != -1)
                {
                    idx += devCode.Length;

                    relPath = relPath.Substring(idx, relPath.Length - idx);
                }
                else
                {
                    Match m = expRelPath.Match(Path.GetDirectoryName(api.FilePath));
                    relPath = m.Groups[1].Value.ToLower();
                }
                */

                string dst = dstPath + libType.Name + "\\" + Path.GetFileName(api.FilePath);

                bool isProcFile = src.ToLower().Contains("\\processor\\");

                try
                {
                    // ignore fast compiles
                    if (-1 != dst.IndexOf(c_FastCompile, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    //dst = expRemoveStubDir.Replace(dst, "\\");

                    if (isProcFile)
                    {
                        dst = expStubReplace.Replace(dst, solution.Processor.Name);
                    }
                    else
                    {
                        dst = expStubReplace.Replace(dst, solution.Name);
                    }

                    if (!Directory.Exists(Path.GetDirectoryName(dst)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(dst));
                    }

                    if (File.Exists(dst))
                    {
                        continue;
                    }

                    //
                    // The source file may refer to "stubs" for function names or includes, we need to replace this
                    // with the solution (or processor) name
                    //
                    TextWriter tw = File.CreateText(dst);
                    TextReader tr = File.OpenText(src);

                    try
                    {
                        string txt = tr.ReadToEnd();

                        if (isProcFile)
                        {
                            txt = expStubReplace.Replace(txt, solution.Processor.Name);
                        }
                        else
                        {
                            txt = expStubReplace.Replace(txt, solution.Name);
                        }

                        Regex exp = new Regex("<IsStub>([\\w\\W]+)</IsStub>", RegexOptions.IgnoreCase);

                        txt = exp.Replace(txt, "<IsStub>false</IsStub>");

                        tw.Write(txt);
                    }
                    finally
                    {
                        tr.Close();
                        tw.Close();
                    }

                    File.SetAttributes(dst, FileAttributes.Normal);

                    if (0 == string.Compare(".proj", Path.GetExtension(dst), true))
                    {
                        Project p = LoadProject(dst);
                        p.Xml.DefaultTargets = "Build";

                        compLibTemplate.ProjectPath = ConvertPathToEnv(dst);

                        foreach (ProjectPropertyGroupElement pg in p.Xml.PropertyGroups)
                        {
                            foreach (ProjectPropertyElement bp in pg.Properties)
                            {
                                switch (bp.Name.ToLower())
                                {
                                    case "directory":
                                        bp.Value = RemoveSpoClient(Path.GetDirectoryName(dst));
                                        break;
                                    case "assemblyname":
                                        bp.Value = compLibTemplate.Name;
                                        break;
                                    case "projectpath":
                                        bp.Value = ConvertPathToEnv(dst);
                                        break;
                                    case "projectguid":
                                        bp.Value = compLibTemplate.Guid;
                                        break;
                                    case "libraryfile":
                                        bp.Value = compLibTemplate.Name + ".$(LIB_EXT)";
                                        break;
                                    case "manifestfile":
                                        bp.Value = compLibTemplate.Name + ".$(LIB_EXT).manifest";
                                        break;

                                }
                            }
                        }
                        foreach (ProjectItemGroupElement ig in p.Xml.ItemGroups)
                        {
                            ArrayList remove_list = new ArrayList();
                            foreach (ProjectItemElement bi in ig.Items)
                            {
                                if (bi.ItemType == c_FastCompileTag)
                                {
                                    remove_list.Add(bi);
                                    continue;
                                }

                                //dst = expRemoveStubDir.Replace(dst, "\\");

                                if (-1 != src.IndexOf("\\processor\\", StringComparison.CurrentCultureIgnoreCase))
                                {
                                    bi.Include = expStubReplace.Replace(bi.Include, solution.Processor.Name);
                                }
                                else
                                {
                                    bi.Include = expStubReplace.Replace(bi.Include, solution.Name);
                                }
                            }
                            foreach (ProjectItemElement bi in remove_list)
                            {
                                ig.RemoveChild(bi);
                            }
                        }
                        p.Save(dst);

                        reloadProjs.Add(dst);
                    }
                }
                catch(Exception e)
                {
                    System.Diagnostics.Debug.Print(e.ToString());
                    System.Diagnostics.Debug.Print("Unable to copy file: " + src + " to " + dst );
                }
            }
            foreach (string prj in reloadProjs)
            {
                LoadLibraryProj(prj, "", true);
            }
        }
        public SolutionWrapper CreateSolution(string Name, string Description, string Author, bool IsSolutionWizardVisible)
        {
            MFSolution solution = new MFSolution();
            solution.Name = Name;
            solution.Description = Description;
            solution.Author = Author;
            solution.IsSolutionWizardVisible = IsSolutionWizardVisible;

            return SolutionWrapper.Wrap<SolutionWrapper>(solution);
        }