protected static void GenerateStateVariableLookupTable_Service(UPnPService s, Hashtable t)
        {
            Hashtable lookupTable = new Hashtable();
            t[s] = lookupTable;

            int i=0;

            foreach(UPnPStateVariable v in s.GetStateVariables())
            {
                StringBuilder sb = new StringBuilder();
                StringWriter SW = new StringWriter(sb);
                XmlTextWriter X = new XmlTextWriter(SW);

                UPnPDebugObject dobj = new UPnPDebugObject(v);
                dobj.InvokeNonStaticMethod("GetStateVariableXML",new object[1]{X});

                lookupTable[v] = new object[3]{i,sb.Length,sb.ToString()};
                i+=sb.Length;
            }
        }
        protected static void BuildStateVariableStructs(CodeProcessor cs, UPnPDevice d)
        {
            foreach(UPnPDevice ed in d.EmbeddedDevices)
            {
                BuildStateVariableStructs(cs,ed);
            }
            foreach(UPnPService s in d.Services)
            {
                string stringX;
                int stringXLen;
                StringBuilder sb = new StringBuilder();
                StringWriter SW = new StringWriter(sb);
                XmlTextWriter X = new XmlTextWriter(SW);

                foreach(UPnPStateVariable v in s.GetStateVariables())
                {
                    UPnPDebugObject dobj = new UPnPDebugObject(v);
                    dobj.InvokeNonStaticMethod("GetStateVariableXML",new object[1]{X});
                }
                InjectCompressedString(out stringX,out stringXLen,sb.ToString(),cs.NewLine);

                cs.Append("struct UPnP_StateVariableTable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+cs.NewLine);
                cs.Append("{"+cs.NewLine);
                cs.Append("	char Reserved["+stringXLen.ToString()+"];"+cs.NewLine);
                cs.Append("	int ReservedXL;"+cs.NewLine);
                cs.Append("	int ReservedUXL;"+cs.NewLine);
                cs.Append("};"+cs.NewLine);

                foreach(UPnPStateVariable v in s.GetStateVariables())
                {
                    cs.Append("struct UPnP_StateVariable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+"_"+v.Name+cs.NewLine);
                    cs.Append("{"+cs.NewLine);
                    cs.Append("	int Reserved1;"+cs.NewLine);
                    cs.Append("	int Reserved1L;"+cs.NewLine);
                    if (v.AllowedStringValues!=null)
                    {
                        cs.Append("	int Reserved2;"+cs.NewLine);
                        cs.Append("	int Reserved2L;"+cs.NewLine);
                        cs.Append("	int Reserved3;"+cs.NewLine);
                        cs.Append("	int Reserved3L;"+cs.NewLine);
                        cs.Append("	char *AllowedValues[UPnP_StateVariable_AllowedValues_MAX];"+cs.NewLine);
                    }
                    if (v.Minimum!=null || v.Maximum!=null)
                    {
                        cs.Append("	int Reserved4;"+cs.NewLine);
                        cs.Append("	int Reserved4L;"+cs.NewLine);
                        cs.Append("	int Reserved5;"+cs.NewLine);
                        cs.Append("	int Reserved5L;"+cs.NewLine);
                        cs.Append("	char *MinMaxStep[3];"+cs.NewLine);
                    }
                    if (v.DefaultValue!=null)
                    {
                        cs.Append("	int Reserved6;"+cs.NewLine);
                        cs.Append("	int Reserved6L;"+cs.NewLine);
                        cs.Append("	int Reserved7;"+cs.NewLine);
                        cs.Append("	int Reserved7L;"+cs.NewLine);
                        cs.Append("	char *DefaultValue;"+cs.NewLine);
                    }
                    cs.Append("	int Reserved8;"+cs.NewLine);
                    cs.Append("	int Reserved8L;"+cs.NewLine);
                    cs.Append("};"+cs.NewLine);
                }
            }
        }
        protected static void GenerateActionLookupTable_Service(UPnPService s, Hashtable t)
        {
            Hashtable lookupTable = new Hashtable();
            t[s] = lookupTable;

            int i=0;

            foreach(UPnPAction a in s.Actions)
            {
                StringBuilder sb = new StringBuilder();
                StringWriter SW = new StringWriter(sb);
                XmlTextWriter X = new XmlTextWriter(SW);

                UPnPDebugObject dobj = new UPnPDebugObject(a);
                dobj.InvokeNonStaticMethod("GetXML",new object[1]{X});

                lookupTable[a] = new object[2]{i,sb.Length};
                i+=sb.Length;
            }
        }
        protected static void BuildActionStructs(CodeProcessor cs, UPnPDevice d)
        {
            foreach(UPnPDevice ed in d.EmbeddedDevices)
            {
                BuildActionStructs(cs,ed);
            }
            foreach(UPnPService s in d.Services)
            {
                string stringX;
                int stringXLen;
                StringBuilder sb = new StringBuilder();
                StringWriter SW = new StringWriter(sb);
                XmlTextWriter X = new XmlTextWriter(SW);

                foreach(UPnPAction a in s.Actions)
                {
                    UPnPDebugObject dobj = new UPnPDebugObject(a);
                    dobj.InvokeNonStaticMethod("GetXML",new object[1]{X});
                }
                InjectCompressedString(out stringX,out stringXLen,sb.ToString(),cs.NewLine);

                cs.Append("struct UPnP_ActionTable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+cs.NewLine);
                cs.Append("{"+cs.NewLine);
                cs.Append("	char Reserved["+stringXLen.ToString()+"];"+cs.NewLine);
                cs.Append("	int ReservedXL;"+cs.NewLine);
                cs.Append("	int ReservedUXL;"+cs.NewLine);
                cs.Append("};"+cs.NewLine);

                foreach(UPnPAction a in s.Actions)
                {
                    cs.Append("struct UPnP_Action_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+"_"+a.Name+cs.NewLine);
                    cs.Append("{"+cs.NewLine);
                    cs.Append("	int Reserved;"+cs.NewLine);
                    cs.Append("	int Reserved2;"+cs.NewLine);
                    cs.Append("};"+cs.NewLine);
                }
            }
        }
        protected static void PopulateStateVariableStructs(CodeProcessor cs, UPnPDevice d, Hashtable VarTable)
        {
            foreach(UPnPDevice ed in d.EmbeddedDevices)
            {
                PopulateStateVariableStructs(cs,ed,VarTable);
            }
            foreach(UPnPService s in d.Services)
            {
                cs.Append("struct UPnP_StateVariableTable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+" UPnP_StateVariableTable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+"_Impl = "+cs.NewLine);
                cs.Append("{"+cs.NewLine);
                string stringX;
                int stringXLen;
                StringBuilder sb = new StringBuilder();
                StringWriter SW = new StringWriter(sb);
                XmlTextWriter X = new XmlTextWriter(SW);

                foreach(UPnPStateVariable v in s.GetStateVariables())
                {
                    UPnPDebugObject dobj = new UPnPDebugObject(v);
                    dobj.InvokeNonStaticMethod("GetStateVariableXML",new object[1]{X});
                }
                X.Flush();
                InjectCompressedString(out stringX,out stringXLen,sb.ToString(),cs.NewLine);
                cs.Append("	"+stringX+","+cs.NewLine);
                cs.Append("	"+stringXLen.ToString()+","+cs.NewLine);
                cs.Append("	"+sb.Length.ToString()+cs.NewLine);
                cs.Append("};"+cs.NewLine);

                foreach(UPnPStateVariable v in s.GetStateVariables())
                {
                    Hashtable t = (Hashtable)VarTable[s];
                    int startingIndex = (int)((object[])t[v])[0];
                    string varString = (string)((object[])t[v])[2];

                    cs.Append("struct UPnP_StateVariable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+"_"+v.Name+" UPnP_StateVariable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+"_"+v.Name+"_Impl = "+cs.NewLine);
                    cs.Append("{"+cs.NewLine);
                    cs.Append("	"+startingIndex.ToString()+","+cs.NewLine); // Start Index
                    cs.Append("	"+(varString.IndexOf("</dataType>")+11).ToString()+","+cs.NewLine);

                    if (v.AllowedStringValues!=null)
                    {
                        int avlen=0;
                        foreach(string avs in v.AllowedStringValues)
                        {
                            avlen += avs.Length;
                        }
                        cs.Append("	"+(varString.IndexOf("<allowedValueList>")+startingIndex).ToString()+","+cs.NewLine); // Start of Allowed Value List
                        cs.Append("	18,"+cs.NewLine); // Length of allowedValueList
                        cs.Append("	"+(varString.IndexOf("</allowedValueList>")+startingIndex).ToString()+","+cs.NewLine); // Start of endTag
                        cs.Append("	19,"+cs.NewLine); // Length of end tag
                        cs.Append("	{");
                        foreach(string av in v.AllowedStringValues)
                        {
                            cs.Append("\""+av+"\",");
                        }
                        cs.Append("NULL");
                        cs.Append("}");
                    }
                    if (v.Minimum!=null || v.Maximum!=null)
                    {
                        if (v.AllowedStringValues!=null)
                        {
                            cs.Append(","+cs.NewLine);
                        }

                        cs.Append("	"+(startingIndex+varString.IndexOf("<allowedValueRange>")).ToString()+","+cs.NewLine);
                        cs.Append("	19,"+cs.NewLine);
                        cs.Append("	"+(startingIndex+varString.IndexOf("</allowedValueRange>")).ToString()+","+cs.NewLine);
                        cs.Append("	20,"+cs.NewLine);
                        cs.Append("	{");
                        if (v.Minimum!=null)
                        {
                            cs.Append("\""+v.Minimum.ToString()+"\",");
                        }
                        else
                        {
                            cs.Append("NULL,");
                        }
                        if (v.Maximum!=null)
                        {
                            cs.Append("\""+v.Maximum.ToString()+"\",");
                        }
                        else
                        {
                            cs.Append("NULL,");
                        }
                        if (v.Step!=null)
                        {
                            cs.Append("\""+v.Step.ToString()+"\"");
                        }
                        else
                        {
                            cs.Append("NULL");
                        }
                        cs.Append("}");
                    }
                    if (v.DefaultValue!=null)
                    {
                        if (v.AllowedStringValues!=null || v.Maximum!=null || v.Maximum!=null)
                        {
                            cs.Append(","+cs.NewLine);
                        }
                        cs.Append("	"+(startingIndex+varString.IndexOf("<defaultValue>")).ToString()+","+cs.NewLine);
                        cs.Append("	14,"+cs.NewLine);
                        cs.Append("	"+(startingIndex+varString.IndexOf("</defaultValue>")).ToString()+","+cs.NewLine);
                        cs.Append("	15,"+cs.NewLine);
                        cs.Append("\""+UPnPService.SerializeObjectInstance(v.DefaultValue)+"\"");
                    }
                    if (v.DefaultValue!=null || v.AllowedStringValues!=null || v.Maximum!=null || v.Maximum!=null)
                    {
                        cs.Append(","+cs.NewLine);
                    }
                    cs.Append((varString.IndexOf("</stateVariable>")+startingIndex).ToString()+","+cs.NewLine);
                    cs.Append("	16"+cs.NewLine);

                    cs.Append("};"+cs.NewLine);
                }
            }
        }
        protected static void PopulateActionStructs(CodeProcessor cs, UPnPDevice d, Hashtable VarTable)
        {
            foreach(UPnPDevice ed in d.EmbeddedDevices)
            {
                PopulateActionStructs(cs,ed,VarTable);
            }
            foreach(UPnPService s in d.Services)
            {
                cs.Append("struct UPnP_ActionTable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+" UPnP_ActionTable_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+"_Impl = "+cs.NewLine);
                cs.Append("{"+cs.NewLine);
                string stringX;
                int stringXLen;
                StringBuilder sb = new StringBuilder();
                StringWriter SW = new StringWriter(sb);
                XmlTextWriter X = new XmlTextWriter(SW);

                foreach(UPnPAction a in s.Actions)
                {
                    UPnPDebugObject dobj = new UPnPDebugObject(a);
                    dobj.InvokeNonStaticMethod("GetXML",new object[1]{X});
                }
                X.Flush();
                InjectCompressedString(out stringX,out stringXLen,sb.ToString(),cs.NewLine);
                cs.Append("	"+stringX+","+cs.NewLine);
                cs.Append("	"+stringXLen.ToString()+","+cs.NewLine);
                cs.Append("	"+sb.Length.ToString()+cs.NewLine);
                cs.Append("};"+cs.NewLine);

                foreach(UPnPAction a in s.Actions)
                {
                    Hashtable t = (Hashtable)VarTable[s];

                    cs.Append("struct UPnP_Action_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+"_"+a.Name+" UPnP_Action_"+((ServiceGenerator.ServiceConfiguration)s.User).Name+"_"+a.Name+"_Impl = "+cs.NewLine);
                    cs.Append("{"+cs.NewLine);
                    cs.Append("	"+((object[])t[a])[0].ToString()+","+cs.NewLine);
                    cs.Append("	"+((object[])t[a])[1].ToString()+cs.NewLine);
                    cs.Append("};"+cs.NewLine);
                }
            }
        }
        /// <summary>
        /// Generates a UPnPService object from an SCPD XML
        /// </summary>
        /// <param name="SCPD_XML">XML String</param>
        /// <returns>UPnPService</returns>
        public static UPnPService GenerateServiceFromSCPD(string SCPD_XML)
        {
            if (SCPD_XML == null) return null;
            UPnPService s = new UPnPService(1, null);
            UPnPDebugObject obj = new UPnPDebugObject(s);
            obj.InvokeNonStaticMethod("ParseSCPD", new Object[1] { SCPD_XML });

            return (s);
        }
        /// <summary>
        /// Generates Device side implementation from SCPD XML
        /// </summary>
        /// <param name="ClassName">Class Name to build</param>
        /// <param name="ns">Namespace to use</param>
        /// <param name="SavePath">Path to save source</param>
        /// <param name="ServiceID">Service ID to use</param>
        /// <param name="ServiceURN">Service URN to use</param>
        /// <param name="SCPD_XML">SCPD XML String</param>
        public static void Generate(String ClassName, String ns, String SavePath, String ServiceID, String ServiceURN, String SCPD_XML)
        {
            UPnPService s = ServiceGenerator.GenerateServiceFromSCPD(SCPD_XML);
            UPnPDebugObject dobj = new UPnPDebugObject(s);

            int ServiceURversion = 1;
            string[] xx = ServiceURN.Split(':');
            if (xx.Length > 2) int.TryParse(xx[xx.Length - 1], out ServiceURversion);

            DText p = new DText();
            p.ATTRMARK = ":";
            p[0] = ServiceURN;

            string v = p[p.DCOUNT()];
            dobj.InvokeNonStaticMethod("SetVersion", new Object[1] { v });
            String cl = "\r\n";

            StringBuilder cs = new StringBuilder();
            UPnPArgument[] Args;
            UPnPArgument arg;
            UPnPStateVariable[] SV = s.GetStateVariables();

            cs.Append("using OpenSource.UPnP;" + cl + cl);
            cs.Append("namespace " + ns + cl);
            cs.Append("{\r\n");
            cs.Append("    /// <summary>" + cl);
            cs.Append("    /// Transparent DeviceSide UPnP Service" + cl);
            cs.Append("    /// </summary>" + cl);
            cs.Append("    public class " + ClassName + " : IUPnPService" + cl);
            cs.Append("    {" + cl + cl);
            cs.Append("        // Place your declarations above this line\r\n");
            cs.Append("\r\n");
            cs.Append("        #region AutoGenerated Code Section [Do NOT Modify, unless you know what you're doing]\r\n");
            cs.Append("        //{{{{{ Begin Code Block\r\n");
            cs.Append("\r\n");
            cs.Append("        private _" + ClassName + " _S;\r\n");
            cs.Append("        public static string URN = \"" + ServiceURN + "\";\r\n");
            cs.Append("        public double VERSION\r\n");
            cs.Append("        {\r\n");
            cs.Append("           get\r\n");
            cs.Append("           {\r\n");
            cs.Append("               return(double.Parse(_S.GetUPnPService().Version));\r\n");
            cs.Append("           }\r\n");
            cs.Append("        }\r\n\r\n");

            // Build Enumerations
            Hashtable elist = BuildEnumerations(SV);
            IDictionaryEnumerator el = elist.GetEnumerator();
            VarData vd;
            while (el.MoveNext())
            {
                vd = (VarData)el.Value;
                cs.Append("        public enum Enum_" + vd.VariableName + "\r\n");
                cs.Append("        {\r\n");
                foreach (EnumStruct vs in vd.Enumerations)
                {
                    cs.Append("            " + vs.EnumName + ",\r\n");
                }
                cs.Append("        }\r\n");

                cs.Append("        public Enum_" + vd.VariableName + " ");
                if (s.GetStateVariableObject(vd.VariableName).SendEvent == true)
                {
                    cs.Append("Evented_");
                }
                cs.Append(vd.VariableName + "\r\n");
                cs.Append("        {\r\n");
                cs.Append("            set\r\n");
                cs.Append("            {\r\n");
                cs.Append("               string v = \"\";\r\n");
                cs.Append("               switch(value)\r\n");
                cs.Append("               {\r\n");
                foreach (EnumStruct vs in vd.Enumerations)
                {
                    cs.Append("                  case Enum_" + vd.VariableName + "." + vs.EnumName + ":\r\n");
                    cs.Append("                     v = \"" + vs.EnumValue + "\";\r\n");
                    cs.Append("                     break;\r\n");
                }
                cs.Append("               }\r\n");
                cs.Append("               _S.SetStateVariable(\"" + vd.VariableName + "\",v);\r\n");
                cs.Append("            }\r\n");
                cs.Append("            get\r\n");
                cs.Append("            {\r\n");
                cs.Append("               Enum_" + vd.VariableName + " RetVal = 0;\r\n");
                cs.Append("               string v = (string)_S.GetStateVariable(\"" + vd.VariableName + "\");\r\n");
                cs.Append("               switch(v)\r\n");
                cs.Append("               {\r\n");
                foreach (EnumStruct vs in vd.Enumerations)
                {
                    cs.Append("                  case \"" + vs.EnumValue + "\":\r\n");
                    cs.Append("                     RetVal = Enum_" + vd.VariableName + "." + vs.EnumName + ";\r\n");
                    cs.Append("                     break;\r\n");
                }
                cs.Append("               }\r\n");
                cs.Append("               return(RetVal);\r\n");
                cs.Append("           }\r\n");
                cs.Append("        }\r\n");
            }

            el.Reset();
            while (el.MoveNext())
            {
                vd = (VarData)el.Value;
                cs.Append("        static public string Enum_" + vd.VariableName + "_ToString(Enum_" + vd.VariableName + " en)\r\n");
                cs.Append("        {\r\n");
                cs.Append("            string RetVal = \"\";\r\n");
                cs.Append("            switch(en)\r\n");
                cs.Append("            {\r\n");
                foreach (EnumStruct vs in vd.Enumerations)
                {
                    cs.Append("                case Enum_" + vd.VariableName + "." + vs.EnumName + ":\r\n");
                    cs.Append("                    RetVal = \"" + vs.EnumValue + "\";\r\n");
                    cs.Append("                    break;\r\n");
                }
                cs.Append("            }\r\n");
                cs.Append("            return(RetVal);\r\n");
                cs.Append("        }\r\n");

                // Build Easy Way to get All Values
                cs.Append("        static public string[] Values_" + vd.VariableName + "\r\n");
                cs.Append("        {\r\n");
                cs.Append("            get\r\n");
                cs.Append("            {\r\n");
                cs.Append("                string[] RetVal = new string[" + vd.Enumerations.Count.ToString() + "]{");
                string EasyStrings = "";
                foreach (EnumStruct vs in vd.Enumerations)
                {
                    if (EasyStrings == "")
                    {
                        EasyStrings = "\"" + vs.EnumValue + "\"";
                    }
                    else
                    {
                        EasyStrings = "\"" + vs.EnumValue + "\"," + EasyStrings;
                    }
                }
                cs.Append(EasyStrings + "};\r\n");
                cs.Append("                return(RetVal);\r\n");
                cs.Append("            }\r\n");
                cs.Append("        }\r\n");
            }

            cs.Append("        public delegate void OnStateVariableModifiedHandler(" + ClassName + " sender);\r\n");
            foreach (UPnPStateVariable V in SV)
            {
                cs.Append("        public event OnStateVariableModifiedHandler OnStateVariableModified_" + V.Name + ";\r\n");
            }

            foreach (UPnPStateVariable V in SV)
            {
                if (elist.ContainsKey(V.Name) == false)
                {
                    // Build Accessors
                    cs.Append("        public " + V.GetNetType().FullName + " ");
                    if (V.SendEvent == true)
                    {
                        cs.Append("Evented_");
                    }
                    cs.Append(V.Name + "\r\n");
                    cs.Append("        {\r\n");
                    cs.Append("            get\r\n");
                    cs.Append("            {\r\n");
                    cs.Append("               return((" + V.GetNetType().FullName + ")_S.GetStateVariable(\"" + V.Name + "\"));\r\n");
                    cs.Append("            }\r\n");
                    cs.Append("            set\r\n");
                    cs.Append("            {\r\n");
                    cs.Append("               _S.SetStateVariable(\"" + V.Name + "\", value);\r\n");
                    cs.Append("            }\r\n");
                    cs.Append("        }\r\n");
                }
            }
            foreach (UPnPStateVariable V in SV)
            {
                cs.Append("        public UPnPModeratedStateVariable.IAccumulator Accumulator_");
                cs.Append(V.Name + "\r\n");
                cs.Append("        {\r\n");
                cs.Append("            get\r\n");
                cs.Append("            {\r\n");
                cs.Append("                 return(((UPnPModeratedStateVariable)_S.GetUPnPService().GetStateVariableObject(\"" + V.Name + "\")).Accumulator);\r\n");
                cs.Append("            }\r\n");
                cs.Append("            set\r\n");
                cs.Append("            {\r\n");
                cs.Append("                 ((UPnPModeratedStateVariable)_S.GetUPnPService().GetStateVariableObject(\"" + V.Name + "\")).Accumulator = value;\r\n");
                cs.Append("            }\r\n");
                cs.Append("        }\r\n");
                cs.Append("        public double ModerationDuration_" + V.Name + "\r\n");
                cs.Append("        {\r\n");
                cs.Append("            get\r\n");
                cs.Append("            {\r\n");
                cs.Append("                 return(((UPnPModeratedStateVariable)_S.GetUPnPService().GetStateVariableObject(\"" + V.Name + "\")).ModerationPeriod);\r\n");
                cs.Append("            }\r\n");
                cs.Append("            set\r\n");
                cs.Append("            {\r\n");
                cs.Append("                 ((UPnPModeratedStateVariable)_S.GetUPnPService().GetStateVariableObject(\"" + V.Name + "\")).ModerationPeriod = value;\r\n");
                cs.Append("            }\r\n");
                cs.Append("        }\r\n");
            }

            // Build MethodDelegates
            foreach (UPnPAction A in s.Actions)
            {
                cs.Append("        public delegate ");
                if (A.HasReturnValue == false)
                {
                    cs.Append("void ");
                }
                else
                {
                    cs.Append(A.GetRetArg().RelatedStateVar.GetNetType().FullName + " ");
                }
                cs.Append("Delegate_" + A.Name + "(");
                Args = A.ArgumentList;
                for (int i = 0; i < Args.Length; ++i)
                {
                    arg = Args[i];
                    if (arg.IsReturnValue == false)
                    {
                        if (arg.Direction == "out")
                        {
                            cs.Append("out ");
                        }
                        if (arg.RelatedStateVar.AllowedStringValues == null)
                        {
                            cs.Append(arg.RelatedStateVar.GetNetType().FullName + " ");
                        }
                        else
                        {
                            cs.Append(ClassName + ".Enum_" + arg.RelatedStateVar.Name + " ");
                        }
                        cs.Append(arg.Name);
                        if (i < Args.Length - 1)
                        {
                            cs.Append(", ");
                        }
                    }
                }
                cs.Append(");\r\n");
            }

            // Build Overriding Delegates
            cs.Append("\r\n");
            foreach (UPnPAction A in s.Actions)
            {
                cs.Append("        public Delegate_" + A.Name + " External_" + A.Name + " = null;\r\n");
            }
            cs.Append("\r\n");

            // Build Ability to remove Optional State Variables
            foreach (UPnPStateVariable V in s.GetStateVariables())
            {
                cs.Append("        public void RemoveStateVariable_" + V.Name + "()\r\n");
                cs.Append("        {\r\n");
                cs.Append("            _S.GetUPnPService().RemoveStateVariable(_S.GetUPnPService().GetStateVariableObject(\"" + V.Name + "\"));\r\n");
                cs.Append("        }\r\n");
            }

            // Build Ability to remove Optional Actions
            foreach (UPnPAction A in s.Actions)
            {
                cs.Append("        public void RemoveAction_" + A.Name + "()\r\n");
                cs.Append("        {\r\n");
                cs.Append("             _S.GetUPnPService().RemoveMethod(\"" + A.Name + "\");\r\n");
                cs.Append("        }\r\n");
            }
            // Add Helper Methods
            cs.Append("        public System.Net.IPEndPoint GetCaller()\r\n");
            cs.Append("        {\r\n");
            cs.Append("             return(_S.GetUPnPService().GetCaller());\r\n");
            cs.Append("        }\r\n");
            cs.Append("        public System.Net.IPEndPoint GetReceiver()\r\n");
            cs.Append("        {\r\n");
            cs.Append("             return(_S.GetUPnPService().GetReceiver());\r\n");
            cs.Append("        }\r\n");
            cs.Append("\r\n");

            // Build Private Class
            cs.Append("        private class _" + ClassName + "\r\n");
            cs.Append("        {\r\n");
            cs.Append("            private " + ClassName + " Outer = null;\r\n");
            cs.Append("            private UPnPService S;\r\n");
            cs.Append("            internal _" + ClassName + "(" + ClassName + " n)\r\n");
            cs.Append("            {\r\n");
            cs.Append("                Outer = n;\r\n");
            cs.Append("                S = BuildUPnPService();\r\n");
            cs.Append("            }\r\n");
            cs.Append("            public UPnPService GetUPnPService()\r\n");
            cs.Append("            {\r\n");
            cs.Append("                return(S);\r\n");
            cs.Append("            }\r\n");
            cs.Append("            public void SetStateVariable(string VarName, object VarValue)\r\n");
            cs.Append("            {\r\n");
            cs.Append("               S.SetStateVariable(VarName,VarValue);\r\n");
            cs.Append("            }\r\n");
            cs.Append("            public object GetStateVariable(string VarName)\r\n");
            cs.Append("            {\r\n");
            cs.Append("               return(S.GetStateVariable(VarName));\r\n");
            cs.Append("            }\r\n");
            cs.Append("            protected UPnPService BuildUPnPService()\r\n");
            cs.Append("            {\r\n");
            cs.Append("                UPnPStateVariable[] RetVal = new UPnPStateVariable[" + SV.Length.ToString() + "];\r\n");
            for (int i = 0; i < SV.Length; ++i)
            {
                cs.Append("                RetVal[" + i.ToString() + "] = new UPnPModeratedStateVariable(\"" + SV[i].Name + "\", typeof(" + SV[i].GetNetType().FullName + "), " + SV[i].SendEvent.ToString().ToLower() + ");\r\n");

                if ((SV[i].Maximum != null) ||
                    (SV[i].Minimum != null) ||
                    (SV[i].Step != null))
                {
                    cs.Append("                RetVal[" + i.ToString() + "].SetRange(");
                    if (SV[i].Minimum == null)
                    {
                        cs.Append("null");
                    }
                    else
                    {
                        cs.Append("(" + SV[i].Minimum.GetType().FullName + ")(" + SV[i].Minimum.ToString() + ")");
                    }
                    cs.Append(",");

                    if (SV[i].Maximum == null)
                    {
                        cs.Append("null");
                    }
                    else
                    {
                        cs.Append("(" + SV[i].Maximum.GetType().FullName + ")(" + SV[i].Maximum.ToString() + ")");
                    }
                    cs.Append(",");

                    if (SV[i].Step == null)
                    {
                        cs.Append("null");
                    }
                    else
                    {
                        cs.Append("(" + SV[i].Step.GetType().FullName + ")" + SV[i].Step.ToString());
                    }
                    cs.Append(");\r\n");
                }

                if (SV[i].DefaultValue != null)
                {
                    cs.Append("                RetVal[" + i.ToString() + "].DefaultValue = UPnPService.CreateObjectInstance(typeof(" + SV[i].GetNetType().FullName + "),\"" + UPnPService.SerializeObjectInstance(SV[i].DefaultValue) + "\");\r\n");
                    //cs.Append("                RetVal[" + i.ToString() + "].DefaultValue = (" + SV[i].GetNetType().FullName + ")(\"" + UPnPService.SerializeObjectInstance(SV[i].DefaultValue) + "\";\r\n");
                }
                if (SV[i].AllowedStringValues != null)
                {
                    cs.Append("                RetVal[" + i.ToString() + "].AllowedStringValues = new string[" +
                        SV[i].AllowedStringValues.Length.ToString() + "]{");
                    for (int ai = 0; ai < SV[i].AllowedStringValues.Length; ++ai)
                    {
                        cs.Append("\"" + SV[i].AllowedStringValues[ai] + "\"");
                        if (ai < SV[i].AllowedStringValues.Length - 1)
                        {
                            cs.Append(", ");
                        }
                    }
                    cs.Append("};\r\n");
                }

                System.Collections.IList e = s.Actions;
                foreach (UPnPAction A in e)
                {
                    foreach (UPnPArgument ag in A.ArgumentList)
                    {
                        if (ag.RelatedStateVar.Name == SV[i].Name)
                        {
                            cs.Append("                RetVal[" + i.ToString() + "].AddAssociation(\"" + A.Name + "\", \"" + ag.Name + "\");\r\n");
                        }
                    }
                }
            }
            // Build UPnPService
            cs.Append("\r\n");
            cs.Append("                UPnPService S = new UPnPService(" +
                ServiceURversion.ToString() + ", \"" + ServiceID + "\", URN, true, this);\r\n");           // WAS: s.Version + ", \"" + ServiceID + "\", \"" + ServiceURN + "\", true, this);\r\n");
            cs.Append("                for(int i=0;i<RetVal.Length;++i)\r\n");
            cs.Append("                {\r\n");
            cs.Append("                   S.AddStateVariable(RetVal[i]);\r\n");
            cs.Append("                }\r\n");
            foreach (UPnPAction A in s.Actions)
            {
                cs.Append("                S.AddMethod(\"" + A.Name + "\");\r\n");
            }

            cs.Append("                return(S);\r\n");
            cs.Append("            }\r\n\r\n");

            System.Collections.IList ee = s.Actions;
            foreach (UPnPAction A in ee)
            {
                if (A.HasReturnValue)
                {
                    cs.Append("            [OpenSource.UPnP.ReturnArgument(\"" + A.GetRetArg().Name + "\")]" + cl);
                }
                cs.Append("            public ");
                if (A.HasReturnValue == false)
                {
                    cs.Append("void ");
                }
                else
                {
                    cs.Append(A.GetRetArg().RelatedStateVar.GetNetType().FullName + " ");
                }

                cs.Append(A.Name + "(");
                Args = A.ArgumentList;
                for (int i = 0; i < Args.Length; ++i)
                {
                    arg = Args[i];
                    if (arg.IsReturnValue == false)
                    {
                        if (arg.Direction == "out")
                        {
                            cs.Append("out ");
                        }
                        cs.Append(arg.RelatedStateVar.GetNetType().FullName + " ");
                        cs.Append(arg.Name);
                        if (i < Args.Length - 1)
                        {
                            cs.Append(", ");
                        }
                    }
                }
                cs.Append(")" + cl);
                cs.Append("            {\r\n");

                // Convert to Enum if neccessary
                Args = A.ArgumentList;
                for (int i = 0; i < Args.Length; ++i)
                {
                    arg = Args[i];
                    if ((arg.IsReturnValue == false) &&
                    (arg.RelatedStateVar.AllowedStringValues != null))
                    {
                        cs.Append("                Enum_" + arg.RelatedStateVar.Name + " e_" + arg.Name + ";\r\n");
                        if (arg.Direction == "in")
                        {
                            cs.Append("                switch(" + arg.Name + ")\r\n");
                            cs.Append("                {\r\n");
                            vd = (VarData)elist[arg.RelatedStateVar.Name];
                            foreach (EnumStruct ss in vd.Enumerations)
                            {
                                cs.Append("                    case \"" + ss.EnumValue + "\":\r\n");
                                cs.Append("                        e_" + arg.Name + " = Enum_" + arg.RelatedStateVar.Name + "." + ss.EnumName + ";\r\n");
                                cs.Append("                        break;\r\n");
                            }
                            cs.Append("                    default:\r\n");
                            cs.Append("                        e_" + arg.Name + " = 0;\r\n");
                            cs.Append("                        break;\r\n");
                            cs.Append("                }\r\n");

                        }
                    }
                }

                // Make Method Call
                if (A.HasReturnValue == true)
                {
                    cs.Append("                object RetObj = null;\r\n");
                }
                cs.Append("                if (Outer.External_" + A.Name + " != null)\r\n");
                cs.Append("                {\r\n");
                cs.Append("                    ");
                if (A.HasReturnValue == true)
                {
                    cs.Append("RetObj = ");
                }
                cs.Append("Outer.External_" + A.Name + "(");
                Args = A.ArgumentList;
                for (int i = 0; i < Args.Length; ++i)
                {
                    arg = Args[i];
                    if (arg.IsReturnValue == false)
                    {
                        if (arg.Direction == "out")
                        {
                            cs.Append("out ");
                        }
                        if (arg.RelatedStateVar.AllowedStringValues != null)
                        {
                            cs.Append("e_");
                        }
                        cs.Append(arg.Name);
                        if (i < Args.Length - 1)
                        {
                            cs.Append(", ");
                        }
                    }
                }
                cs.Append(");\r\n");
                cs.Append("                }\r\n");
                cs.Append("                else\r\n");
                cs.Append("                {\r\n");
                cs.Append("                    ");
                if (A.HasReturnValue == true)
                {
                    cs.Append("RetObj = ");
                }
                cs.Append("Sink_" + A.Name + "(");
                Args = A.ArgumentList;
                for (int i = 0; i < Args.Length; ++i)
                {
                    arg = Args[i];
                    if (arg.IsReturnValue == false)
                    {
                        if (arg.Direction == "out")
                        {
                            cs.Append("out ");
                        }
                        if (arg.RelatedStateVar.AllowedStringValues != null)
                        {
                            cs.Append("e_");
                        }
                        cs.Append(arg.Name);
                        if (i < Args.Length - 1)
                        {
                            cs.Append(", ");
                        }
                    }
                }
                cs.Append(");\r\n");
                cs.Append("                }\r\n");

                Args = A.ArgumentList;
                for (int i = 0; i < Args.Length; ++i)
                {
                    arg = Args[i];
                    if ((arg.IsReturnValue == false) &&
                        (arg.RelatedStateVar.AllowedStringValues != null))
                    {
                        if (arg.Direction == "out")
                        {
                            cs.Append("                switch(e_" + arg.Name + ")\r\n");
                            cs.Append("                {\r\n");
                            vd = (VarData)elist[arg.RelatedStateVar.Name];
                            foreach (EnumStruct ss in vd.Enumerations)
                            {
                                cs.Append("                    case Enum_" + arg.RelatedStateVar.Name + "." + ss.EnumName + ":\r\n");
                                cs.Append("                        " + arg.Name + " = \"" + ss.EnumValue + "\";\r\n");
                                cs.Append("                        break;\r\n");
                            }
                            cs.Append("                    default:\r\n");
                            cs.Append("                        " + arg.Name + " = \"\";\r\n");
                            cs.Append("                        break;\r\n");
                            cs.Append("                }\r\n");

                        }
                    }
                }

                if (A.HasReturnValue == true)
                {
                    cs.Append("                return((" + A.GetRetArg().RelatedStateVar.GetNetType().FullName + ")RetObj);\r\n");
                }
                cs.Append("            }\r\n");
            }

            cs.Append("\r\n");
            foreach (UPnPAction A in s.Actions)
            {
                cs.Append("            public Delegate_" + A.Name + " Sink_" + A.Name + ";\r\n");
            }
            cs.Append("        }\r\n"); // End of Private Class

            // Build Constructor
            cs.Append("        public " + ClassName + "()\r\n");
            cs.Append("        {\r\n");
            cs.Append("            _S = new _" + ClassName + "(this);\r\n");
            foreach (UPnPStateVariable V in SV)
            {
                cs.Append("            _S.GetUPnPService().GetStateVariableObject(\"" + V.Name + "\").OnModified += new UPnPStateVariable.ModifiedHandler(OnModifiedSink_" + V.Name + ");\r\n");
            }
            foreach (UPnPAction A in s.Actions)
            {
                cs.Append("            _S.Sink_" + A.Name + " = new Delegate_" + A.Name + "(" + A.Name + ");\r\n");
            }

            cs.Append("        }\r\n");
            cs.Append("        public " + ClassName + "(string ID):this()\r\n");
            cs.Append("        {\r\n");
            cs.Append("            _S.GetUPnPService().ServiceID = ID;\r\n");
            cs.Append("        }\r\n");
            cs.Append("        public UPnPService GetUPnPService()\r\n");
            cs.Append("        {\r\n");
            cs.Append("            return(_S.GetUPnPService());\r\n");
            cs.Append("        }\r\n");
            foreach (UPnPStateVariable V in SV)
            {
                cs.Append("        private void OnModifiedSink_" + V.Name + "(UPnPStateVariable sender, object NewValue)\r\n");
                cs.Append("        {\r\n");
                cs.Append("            if (OnStateVariableModified_" + V.Name + " != null) OnStateVariableModified_" + V.Name + "(this);\r\n");
                cs.Append("        }\r\n");
            }
            cs.Append("        //}}}}} End of Code Block\r\n\r\n");
            cs.Append("        #endregion\r\n");
            cs.Append("\r\n");

            foreach (UPnPAction A in s.Actions)
            {
                cs.Append("        /// <summary>\r\n");
                cs.Append("        /// Action: " + A.Name + "\r\n");
                cs.Append("        /// </summary>\r\n");
                Args = A.ArgumentList;
                for (int i = 0; i < Args.Length; ++i)
                {
                    arg = Args[i];
                    if (arg.IsReturnValue == false)
                    {
                        cs.Append("        /// <param name=\"" + arg.Name + "\">Associated State Variable: " + arg.RelatedStateVar.Name + "</param>\r\n");
                    }
                }
                if (A.HasReturnValue == true)
                {
                    cs.Append("        /// <returns>Associated StateVariable: " + A.GetRetArg().RelatedStateVar.Name + "</returns>\r\n");
                }
                cs.Append("        public ");
                if (A.HasReturnValue == false)
                {
                    cs.Append("void ");
                }
                else
                {
                    cs.Append(A.GetRetArg().RelatedStateVar.GetNetType().FullName + " ");
                }

                cs.Append(A.Name + "(");
                Args = A.ArgumentList;
                for (int i = 0; i < Args.Length; ++i)
                {
                    arg = Args[i];
                    if (arg.IsReturnValue == false)
                    {
                        if (arg.Direction == "out")
                        {
                            cs.Append("out ");
                        }

                        if (arg.RelatedStateVar.AllowedStringValues != null)
                        {
                            cs.Append("Enum_" + arg.RelatedStateVar.Name + " ");
                        }
                        else
                        {
                            cs.Append(arg.RelatedStateVar.GetNetType().FullName + " ");
                        }
                        cs.Append(arg.Name);
                        if (i < Args.Length - 1)
                        {
                            cs.Append(", ");
                        }
                    }
                }
                cs.Append(")" + cl);
                cs.Append("        {\r\n");
                cs.Append("            //ToDo: Add Your implementation here, and remove exception\r\n");
                cs.Append("            throw(new UPnPCustomException(800,\"This method has not been completely implemented...\"));\r\n");
                cs.Append("        }\r\n");
            }

            cs.Append("    }\r\n");
            cs.Append("}");

            UTF8Encoding UTF8 = new UTF8Encoding();
            FileStream ws = new FileStream(SavePath, FileMode.Create, FileAccess.Write);
            byte[] buffer = UTF8.GetBytes(cs.ToString());
            ws.Write(buffer, 0, buffer.Length);
            ws.Close();
        }