public static string GetURNPrefix(string urn)
 {
     int len;
     DText p = new DText();
     p.ATTRMARK = ":";
     p[0] = urn;
     len = p[p.DCOUNT()].Length;
     return(urn.Substring(0, urn.Length - len));
 }
        public static string GetURNPrefix(string urn)
        {
            int   len;
            DText p = new DText();

            p.ATTRMARK = ":";
            p[0]       = urn;
            len        = p[p.DCOUNT()].Length;
            return(urn.Substring(0, urn.Length - len));
        }
        private void OnReceiveSink2(byte[] buffer, IPEndPoint remote, IPEndPoint local)
        {
            HTTPMessage msg;

            try
            {
                msg = HTTPMessage.ParseByteArray(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                OpenSource.Utilities.EventLogger.Log(ex);
                msg              = new HTTPMessage();
                msg.Directive    = "---";
                msg.DirectiveObj = "---";
                msg.BodyBuffer   = buffer;
            }
            msg.LocalEndPoint  = local;
            msg.RemoteEndPoint = remote;

            HandleSniffer(remote, local, msg);

            DText parser = new DText();

            String Location = msg.GetTag("Location");
            int    MaxAge   = 0;
            String ma       = msg.GetTag("Cache-Control").Trim();

            if (ma != "")
            {
                parser.ATTRMARK = ",";
                parser.MULTMARK = "=";
                parser[0]       = ma;
                for (int i = 1; i <= parser.DCOUNT(); ++i)
                {
                    if (parser[i, 1].Trim().ToUpper() == "MAX-AGE")
                    {
                        MaxAge = int.Parse(parser[i, 2].Trim());
                        break;
                    }
                }
            }
            ma = msg.GetTag("USN");
            String USN = ma.Substring(ma.IndexOf(":") + 1);
            String ST  = msg.GetTag("ST");

            if (USN.IndexOf("::") != -1)
            {
                USN = USN.Substring(0, USN.IndexOf("::"));
            }
            OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, msg.RemoteEndPoint.ToString());
            if (OnSearch != null)
            {
                OnSearch(msg.RemoteEndPoint, msg.LocalEndPoint, new Uri(Location), USN, ST, MaxAge);
            }
        }
        public static MediaItem PopulateMetaData(MediaResource R, FileInfo F)
        {
            MediaItem RetVal;
            MediaBuilder.item Item = null;
            DText parser = new DText();
            parser.ATTRMARK = "-";
            parser.MULTMARK = ".";

            switch(F.Extension.ToUpper())
            {
                case ".MP3":
                    Item = ParseMP3_V1(F);
                    if(Item==null)
                    {
                        parser[0] = F.Name;
                        if(parser.DCOUNT()==2)
                        {
                            Item = new MediaBuilder.musicTrack(parser[2,1].Trim());
                            Item.creator = parser[1].Trim();
                            ((MediaBuilder.musicTrack)Item).artist = new PersonWithRole[1]{new PersonWithRole()};
                            ((MediaBuilder.musicTrack)Item).artist[0].Name = Item.creator;
                            ((MediaBuilder.musicTrack)Item).artist[0].Role = null;
                        }
                    }
                    break;
            }

            if(Item!=null)
            {
                RetVal = MediaBuilder.CreateItem(Item);
                RetVal.AddResource(R);
                return(RetVal);
            }
            else
            {
                // Create a Generic Item
                string fname = F.Name;
                int fnameidx = fname.IndexOf(".");
                if(fnameidx!=-1) fname=fname.Substring(0,fnameidx);
                MediaBuilder.item genericItem = new MediaBuilder.item(fname);
                RetVal = MediaBuilder.CreateItem(genericItem);
                RetVal.AddResource(R);
                return(RetVal);
            }
        }
        private void GenerateControlSchemas(UPnPDevice d, System.IO.DirectoryInfo dirInfo, bool cleanSchema)
        {
            System.IO.MemoryStream ms = new MemoryStream();
            System.Xml.XmlTextWriter X = new System.Xml.XmlTextWriter(ms,System.Text.Encoding.UTF8);
            X.Formatting = System.Xml.Formatting.Indented;

            foreach(UPnPDevice ed in d.EmbeddedDevices)
            {
                GenerateControlSchemas(ed,dirInfo,cleanSchema);
            }
            foreach(UPnPService s in d.Services)
            {
                Hashtable h = new Hashtable();
                int j=1;

                foreach(string sn in s.GetSchemaNamespaces())
                {
                    h[sn] = "CT"+j.ToString();
                    ++j;
                }
                X.WriteStartDocument();
                X.WriteStartElement("xsd","schema","http://www.w3.org/2001/XMLSchema");
                X.WriteAttributeString("targetNamespace",s.ServiceURN);
                X.WriteAttributeString("xmlns",s.ServiceURN);
                X.WriteAttributeString("xmlns","upnp",null,"http://www.upnp.org/Schema/DataTypes");
                IDictionaryEnumerator NE = h.GetEnumerator();
                while(NE.MoveNext())
                {
                    X.WriteAttributeString("xmlns",NE.Value.ToString(),null,NE.Key.ToString());
                }

                foreach(UPnPAction a in s.Actions)
                {
                    X.WriteStartElement("xsd","element",null);
                    X.WriteAttributeString("name",a.Name);
                    X.WriteAttributeString("type",a.Name+"Type");
                    X.WriteEndElement();
                    X.WriteStartElement("xsd","element",null);
                    X.WriteAttributeString("name",a.Name+"Response");
                    X.WriteAttributeString("type",a.Name+"ResponseType");
                    X.WriteEndElement();

                    if (!cleanSchema)
                    {
                        X.WriteComment("Note: Some schema validation tools may consider the following xsd:any element ambiguous in this placement");
                        X.WriteStartElement("xsd","any",null);
                        X.WriteAttributeString("namespace","##other");
                        X.WriteAttributeString("minOccurs","0");
                        X.WriteAttributeString("maxOccurs","unbounded");
                        X.WriteAttributeString("processContents","lax");
                        X.WriteEndElement(); // ANY
                    }

                    X.WriteStartElement("xsd","complexType",null);
                    X.WriteAttributeString("name",a.Name+"Type");

                    X.WriteStartElement("xsd","sequence",null);

                    foreach(UPnPArgument arg in a.Arguments)
                    {
                        if (arg.Direction=="in")
                        {
                            X.WriteStartElement("xsd","element",null);
                            X.WriteAttributeString("name",arg.Name);
                            if (arg.RelatedStateVar.ComplexType==null)
                            {
                                // Simple Types
                                X.WriteStartElement("xsd","complexType",null);
                                X.WriteStartElement("xsd","simpleContent",null);
                                X.WriteStartElement("xsd","extension",null);
                                X.WriteAttributeString("base","upnp:"+arg.RelatedStateVar.ValueType);

                                if (!cleanSchema)
                                {
                                    X.WriteStartElement("xsd","anyAttribute",null);
                                    X.WriteAttributeString("namespace","##other");
                                    X.WriteAttributeString("processContents","lax");
                                    X.WriteEndElement(); // anyAttribute
                                }

                                X.WriteEndElement(); // Extension
                                X.WriteEndElement(); // simpleConent
                                X.WriteEndElement(); // complexType
                            }
                            else
                            {
                                // Complex Types
                                X.WriteAttributeString("type",h[arg.RelatedStateVar.ComplexType.Name_NAMESPACE].ToString()+":"+arg.RelatedStateVar.ComplexType.Name_LOCAL);
                            }
                            X.WriteEndElement(); // element
                        }
                    }

                    if (!cleanSchema)
                    {
                        X.WriteStartElement("xsd","any",null);
                        X.WriteAttributeString("namespace","##other");
                        X.WriteAttributeString("minOccurs","0");
                        X.WriteAttributeString("maxOccurs","unbounded");
                        X.WriteAttributeString("processContents","lax");
                        X.WriteEndElement(); // any
                    }

                    X.WriteEndElement(); // sequence

                    if (!cleanSchema)
                    {
                        X.WriteStartElement("xsd","anyAttribute",null);
                        X.WriteAttributeString("namespace","##other");
                        X.WriteAttributeString("processContents","lax");
                        X.WriteEndElement(); // anyAttribute
                    }
                    X.WriteEndElement(); // complexType

                    // ActionResponse
                    X.WriteStartElement("xsd","complexType",null);
                    X.WriteAttributeString("name",a.Name+"ResponseType");
                    X.WriteStartElement("xsd","sequence",null);

                    foreach(UPnPArgument arg in a.Arguments)
                    {
                        if (arg.Direction=="out" || arg.IsReturnValue)
                        {
                            X.WriteStartElement("xsd","element",null);
                            X.WriteAttributeString("name",arg.Name);
                            if (arg.RelatedStateVar.ComplexType==null)
                            {
                                // Simple
                                X.WriteStartElement("xsd","complexType",null);
                                X.WriteStartElement("xsd","simpleContent",null);
                                X.WriteStartElement("xsd","extension",null);
                                X.WriteAttributeString("base","upnp:"+arg.RelatedStateVar.ValueType);
                                if (!cleanSchema)
                                {
                                    X.WriteStartElement("xsd","anyAttribute",null);
                                    X.WriteAttributeString("namespace","##other");
                                    X.WriteAttributeString("processContents","lax");
                                    X.WriteEndElement(); // anyAttribute
                                }
                                X.WriteEndElement(); // extension
                                X.WriteEndElement(); // simpleContent
                                X.WriteEndElement(); // complexType
                            }
                            else
                            {
                                // Complex
                                X.WriteAttributeString("type",h[arg.RelatedStateVar.ComplexType.Name_NAMESPACE].ToString()+":"+arg.RelatedStateVar.ComplexType.Name_LOCAL);
                            }
                            X.WriteEndElement(); // Element
                        }
                    }
                    // After all arguments
                    if (!cleanSchema)
                    {
                        X.WriteStartElement("xsd","any",null);
                        X.WriteAttributeString("namespace","##other");
                        X.WriteAttributeString("minOccurs","0");
                        X.WriteAttributeString("maxOccurs","unbounded");
                        X.WriteAttributeString("processContents","lax");
                        X.WriteEndElement(); // any
                    }
                    X.WriteEndElement(); // sequence
                    if (!cleanSchema)
                    {
                        X.WriteStartElement("xsd","anyAttribute",null);
                        X.WriteAttributeString("namespace","##other");
                        X.WriteAttributeString("processContents","lax");
                        X.WriteEndElement(); // anyAttribute
                    }
                    X.WriteEndElement(); // complexType
                }

                X.WriteEndElement(); //schema
                X.WriteEndDocument();

                StreamWriter writer3;

                DText PP = new DText();
                PP.ATTRMARK = ":";
                PP[0] = s.ServiceURN;
                writer3 = File.CreateText(dirInfo.FullName + "\\"+PP[PP.DCOUNT()-1]+".xsd");

                System.Text.UTF8Encoding U = new System.Text.UTF8Encoding();
                X.Flush();
                ms.Flush();
                writer3.Write(U.GetString(ms.ToArray(),2,ms.ToArray().Length-2));
                writer3.Close();
                ms = new MemoryStream();
                X = new System.Xml.XmlTextWriter(ms,System.Text.Encoding.UTF8);
                X.Formatting = System.Xml.Formatting.Indented;
            }
        }
        private void startMenuItem_Click(object sender, System.EventArgs e)
        {
            startMenuItem.Enabled = false;
            foreach (MenuItem i in pfcMenuItem.MenuItems) {i.Enabled = false;}
            foreach (MenuItem i in menuItem3.MenuItems) {i.Enabled = false;}
            InfoStringBox.Enabled = false;

            device = UPnPDevice.CreateRootDevice(900,1,"");
            device.UniqueDeviceName = Guid.NewGuid().ToString();
            device.StandardDeviceType = "MediaRenderer";
            device.FriendlyName = "Media Renderer (" + System.Net.Dns.GetHostName() + ")";
            device.HasPresentation = false;

            device.Manufacturer = "OpenSource";
            device.ManufacturerURL = "http://opentools.homeip.net/";
            device.PresentationURL = "/";
            device.HasPresentation = true;
            device.ModelName = "AV Renderer";
            device.ModelDescription = "Media Renderer Device";
            device.ModelURL = new Uri("http://opentools.homeip.net/");

            UPnPService ts = new UPnPService(1, "EmptyService", "EmptyService", true, this);
            ts.AddMethod("NullMethod");
            //device.AddService(ts);

            DText p = new DText();
            p.ATTRMARK = "\r\n";
            p[0] = this.InfoStringBox.Text;
            int len = p.DCOUNT();
            ProtocolInfoString[] istring = new ProtocolInfoString[len];
            for(int i=1;i<=len;++i)
            {
                istring[i-1] = new ProtocolInfoString(p[i]);
            }
            r = new AVRenderer(MaxConnections, istring, new AVRenderer.ConnectionHandler(NewConnectionSink));

            r.OnClosedConnection += new AVRenderer.ConnectionHandler(ClosedConnectionSink);

            if (supportRecordMenuItem.Checked == false)
            {
                r.AVT.RemoveAction_Record();
            }

            if (supportRecordQualityMenuItem.Checked == false)
            {
                r.AVT.RemoveAction_SetRecordQualityMode();
            }

            if (supportNextContentUriMenuItem.Checked == false)
            {
                r.AVT.RemoveAction_SetNextAVTransportURI();
            }

            if (MaxConnections == 0)
            {
                r.Manager.RemoveAction_PrepareForConnection();
                r.Manager.RemoveAction_ConnectionComplete();
            }

            r.AVT.GetUPnPService().GetStateVariableObject("CurrentPlayMode").AllowedStringValues = new String[3]{"NORMAL","REPEAT_ALL","INTRO"};

            r.Control.GetUPnPService().GetStateVariableObject("A_ARG_TYPE_Channel").AllowedStringValues = new String[3]{"Master","LF","RF"};
            r.Control.GetUPnPService().GetStateVariableObject("RedVideoBlackLevel").SetRange((ushort)0,(ushort)100,(ushort)1);
            r.Control.GetUPnPService().GetStateVariableObject("GreenVideoBlackLevel").SetRange((ushort)0,(ushort)100,(ushort)1);
            r.Control.GetUPnPService().GetStateVariableObject("BlueVideoBlackLevel").SetRange((ushort)0,(ushort)100,(ushort)1);
            r.Control.GetUPnPService().GetStateVariableObject("RedVideoGain").SetRange((ushort)0,(ushort)100,(ushort)1);
            r.Control.GetUPnPService().GetStateVariableObject("GreenVideoGain").SetRange((ushort)0,(ushort)100,(ushort)1);
            r.Control.GetUPnPService().GetStateVariableObject("BlueVideoGain").SetRange((ushort)0,(ushort)100,(ushort)1);

            r.Control.GetUPnPService().GetStateVariableObject("Brightness").SetRange((ushort)0,(ushort)100,(ushort)1);
            r.Control.GetUPnPService().GetStateVariableObject("Contrast").SetRange((ushort)0,(ushort)100,(ushort)1);
            r.Control.GetUPnPService().GetStateVariableObject("Sharpness").SetRange((ushort)0,(ushort)100,(ushort)1);
            r.Control.GetUPnPService().GetStateVariableObject("Volume").SetRange((UInt16)0,(UInt16)100,(ushort)1);

            device.AddService(r.Control);
            device.AddService(r.AVT);
            device.AddService(r.Manager);

            //device.AddDevice(r);

            device.StartDevice();

            //r.Start();
        }
Beispiel #7
0
        private void OnReceiveSink2(byte[] buffer, IPEndPoint remote, IPEndPoint local)
        {
            HTTPMessage msg;

            try
            {
                msg = HTTPMessage.ParseByteArray(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                OpenSource.Utilities.EventLogger.Log(ex);
                msg = new HTTPMessage();
                msg.Directive = "---";
                msg.DirectiveObj = "---";
                msg.BodyBuffer = buffer;
            }
            msg.LocalEndPoint = local;
            msg.RemoteEndPoint = remote;

            DText parser = new DText();

            String Location = msg.GetTag("Location");
            int MaxAge = 0;
            String ma = msg.GetTag("Cache-Control").Trim();
            if (ma != "")
            {
                parser.ATTRMARK = ",";
                parser.MULTMARK = "=";
                parser[0] = ma;
                for (int i = 1; i <= parser.DCOUNT(); ++i)
                {
                    if (parser[i, 1].Trim().ToUpper() == "MAX-AGE")
                    {
                        MaxAge = int.Parse(parser[i, 2].Trim());
                        break;
                    }
                }
            }
            ma = msg.GetTag("USN");
            String USN = ma.Substring(ma.IndexOf(":") + 1);
            String ST = msg.GetTag("ST");
            if (USN.IndexOf("::") != -1) USN = USN.Substring(0, USN.IndexOf("::"));
            OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, msg.RemoteEndPoint.ToString());
            if (OnSearch != null) OnSearch(msg.RemoteEndPoint, msg.LocalEndPoint, new Uri(Location), USN, ST, MaxAge);
        }
        private static UPnPComplexType ParseComplexType(XmlTextReader X, UPnPComplexType RetVal)
        {
            string elementName = X.LocalName;
            int    count       = 0;
            bool   done        = false;
            DText  P           = new DText();

            P.ATTRMARK = ":";

            RetVal.AddContainer(new GenericContainer());

            do
            {
                switch (X.NodeType)
                {
                case XmlNodeType.Element:
                    switch (X.LocalName)
                    {
                    case "complexType":
                    case "group":
                        ++count;
                        if (X.HasAttributes)
                        {
                            for (int i = 0; i < X.AttributeCount; i++)
                            {
                                X.MoveToAttribute(i);
                                if (X.Name == "name")
                                {
                                    P[0] = X.Value;
                                    if (P.DCOUNT() == 1)
                                    {
                                        RetVal.LocalName = X.Value;
                                        RetVal.NameSpace = X.LookupNamespace("");
                                    }
                                    else
                                    {
                                        RetVal.LocalName = P[2];
                                        RetVal.NameSpace = X.LookupNamespace(P[1]);
                                    }
                                }
                                else if (X.Name == "ref")
                                {
                                    // NOP
                                }
                            }
                            X.MoveToElement();
                        }
                        break;

                    case "sequence":
                    case "choice":
                        RetVal.CurrentContainer.AddCollection(ParseComplexType_SequenceChoice(X));
                        //ParseComplexType_Sequence(X,RetVal);
                        break;

                    case "complexContent":
                        RetVal.AddContainer(new ComplexContent());
                        break;

                    case "simpleContent":
                        RetVal.AddContainer(new SimpleContent());
                        break;

                    case "restriction":
                        Restriction r = new Restriction();
                        if (RetVal.CurrentContainer.GetType() == typeof(ComplexContent))
                        {
                            ((ComplexContent)RetVal.CurrentContainer).RestExt = r;
                        }
                        else if (RetVal.CurrentContainer.GetType() == typeof(SimpleContent))
                        {
                            ((SimpleContent)RetVal.CurrentContainer).RestExt = r;
                        }
                        if (X.HasAttributes)
                        {
                            for (int i = 0; i < X.AttributeCount; i++)
                            {
                                X.MoveToAttribute(i);
                                if (X.Name == "base")
                                {
                                    P[0] = X.Value;
                                    if (P.DCOUNT() == 1)
                                    {
                                        r.baseType   = X.Value;
                                        r.baseTypeNS = X.LookupNamespace("");
                                    }
                                    else
                                    {
                                        r.baseType   = P[2];
                                        r.baseTypeNS = X.LookupNamespace(P[1]);
                                    }
                                }
                            }
                            X.MoveToElement();
                        }
                        break;
                    }
                    break;

                case XmlNodeType.EndElement:
                    if (X.LocalName == elementName)
                    {
                        --count;
                        if (count == 0)
                        {
                            done = true;
                        }
                    }
                    break;

                case XmlNodeType.Text:
                    break;
                }
            }while(!done && X.Read());
            return(RetVal);
        }
        // For files with filenames that have the format: "creator - title"
        private DvMediaItem CreateItemFromFormatedNameFile(FileInfo file)
        {
            string mime, mediaClass;
            MimeTypes.ExtensionToMimeType(file.Extension, out mime, out mediaClass);

            string protInfo = new System.Text.StringBuilder().AppendFormat("http-get:*:{0}:*", mime).ToString();
            string ct = Path.GetFileNameWithoutExtension(file.Name);

            DText DT = new DText();
            DT.ATTRMARK = "-";
            string title;
            string creator;

            DT[0] = ct;
            if (DT.DCOUNT() == 1)
            {
                creator = "";
                title = DT[1].Trim();
            }
            else
            {
                creator = DT[1].Trim();
                title = DT[2].Trim();
            }

            MediaBuilder.item info = new MediaBuilder.item(title);
            info.creator = creator;
            DvMediaItem newMedia = DvMediaBuilder.CreateItem(info);

            //DvMediaResource res = DvResourceBuilder.CreateResource_HttpGet(file,false);
            ResourceBuilder.VideoItem resInfo = new ResourceBuilder.VideoItem();
            resInfo.contentUri = DvMediaResource.AUTOMAPFILE + file.FullName;
            resInfo.protocolInfo = new ProtocolInfoString(protInfo);
            resInfo.size = new _ULong((ulong)file.Length);
            DvMediaResource res = DvResourceBuilder.CreateResource(resInfo, true);
            res.Tag = file;
            newMedia.AddResource(res);

            return newMedia;
        }
Beispiel #10
0
        private void GetNonRootDeviceXML(IPEndPoint local, XmlTextWriter XDoc)
        {
            IDictionaryEnumerator de = CustomField.GetEnumerator();
            DText pp = new DText();
            ;
            pp.ATTRMARK = ":";

            XDoc.WriteStartElement("device");

            //
            // Always advertise version :1
            //
            XDoc.WriteElementString("deviceType", DeviceURN);

            if (HasPresentation == true)
            {
                XDoc.WriteElementString("presentationURL", PresentationURL);
            }

            while (de.MoveNext())
            {
                IDictionaryEnumerator ede = ((Hashtable)de.Value).GetEnumerator();
                while (ede.MoveNext())
                {
                    string localName = (string)ede.Key;
                    string elementValue = (string)ede.Value;
                    string ns = (string)de.Key;

                    pp[0] = localName;
                    if (pp.DCOUNT() == 2)
                    {
                        XDoc.WriteStartElement(pp[1], pp[2], ns);
                        XDoc.WriteString(elementValue);
                        XDoc.WriteEndElement();
                    }
                    else
                    {
                        if (ns != "")
                        {
                            XDoc.WriteElementString(localName, ns, elementValue);
                        }
                        else
                        {
                            XDoc.WriteElementString(localName, elementValue);
                        }
                    }
                }
            }

            XDoc.WriteElementString("friendlyName", FriendlyName);
            if (Manufacturer != null)
                XDoc.WriteElementString("manufacturer", Manufacturer);
            if (ManufacturerURL != null)
                XDoc.WriteElementString("manufacturerURL", ManufacturerURL);
            if (ModelDescription != null)
                XDoc.WriteElementString("modelDescription", ModelDescription);
            if (ModelName != null)
                XDoc.WriteElementString("modelName", ModelName);
            if (ModelNumber != null)
                XDoc.WriteElementString("modelNumber", ModelNumber);
            if (ModelURL != null)
                XDoc.WriteElementString("modelURL", HTTPMessage.UnEscapeString(ModelURL.AbsoluteUri));
            if (SerialNumber != null)
                XDoc.WriteElementString("serialNumber", SerialNumber);
            XDoc.WriteElementString("UDN", "uuid:" + UniqueDeviceName);

            /*
            if (_icon != null)
            {
                lock (_icon)
                {
                    XDoc.WriteStartElement("iconList");
                    XDoc.WriteStartElement("icon");
                    XDoc.WriteElementString("mimetype", "image/png");
                    XDoc.WriteElementString("width", _icon.Width.ToString());
                    XDoc.WriteElementString("height", _icon.Height.ToString());
                    XDoc.WriteElementString("depth", System.Drawing.Image.GetPixelFormatSize(_icon.PixelFormat).ToString());
                    XDoc.WriteElementString("url", "/icon.png");
                    XDoc.WriteEndElement();

                    XDoc.WriteStartElement("icon");
                    XDoc.WriteElementString("mimetype", "image/jpg");
                    XDoc.WriteElementString("width", _icon.Width.ToString());
                    XDoc.WriteElementString("height", _icon.Height.ToString());
                    XDoc.WriteElementString("depth", System.Drawing.Image.GetPixelFormatSize(_icon.PixelFormat).ToString());
                    XDoc.WriteElementString("url", "/icon.jpg");
                    XDoc.WriteEndElement();

                    if (_icon2 != null)
                    {
                        XDoc.WriteStartElement("icon");
                        XDoc.WriteElementString("mimetype", "image/png");
                        XDoc.WriteElementString("width", _icon2.Width.ToString());
                        XDoc.WriteElementString("height", _icon2.Height.ToString());
                        XDoc.WriteElementString("depth", System.Drawing.Image.GetPixelFormatSize(_icon.PixelFormat).ToString());
                        XDoc.WriteElementString("url", "/icon2.png");
                        XDoc.WriteEndElement();

                        XDoc.WriteStartElement("icon");
                        XDoc.WriteElementString("mimetype", "image/jpg");
                        XDoc.WriteElementString("width", _icon2.Width.ToString());
                        XDoc.WriteElementString("height", _icon2.Height.ToString());
                        XDoc.WriteElementString("depth", System.Drawing.Image.GetPixelFormatSize(_icon2.PixelFormat).ToString());
                        XDoc.WriteElementString("url", "/icon2.jpg");
                        XDoc.WriteEndElement();
                    }

                    XDoc.WriteEndElement();
                }
            }
            */

            if (Services.Length > 0)
            {
                XDoc.WriteStartElement("serviceList");
                for (int sid = 0; sid < Services.Length; ++sid)
                {
                    Services[sid].GetServiceXML(XDoc);
                }
                XDoc.WriteEndElement();
            }

            if (EmbeddedDevices.Length > 0)
            {
                XDoc.WriteStartElement("deviceList");
                for (int ei = 0; ei < EmbeddedDevices.Length; ++ei)
                {
                    EmbeddedDevices[ei].GetNonRootDeviceXML(local, XDoc);
                }
                XDoc.WriteEndElement();
            }

            XDoc.WriteEndElement();
        }
        internal UPnPDevice(double version, String UDN)
        {
            // Full Device
            IsRoot = false;

            VirtualDir_Table = new Hashtable();
            VirtualDir_Header_Table = new Hashtable();

            parent = null;
            HasPresentation = true;
            ControlPointOnly = false;
            RootPath = "";

            if (version == 0)
            {
                Major = 1;
                Minor = 0;
            }
            else
            {
                DText TempNum = new DText();
                TempNum.ATTRMARK = ".";
                TempNum[0] = version.ToString();

                Major = int.Parse(TempNum[1]);
                if (TempNum.DCOUNT() == 2)
                {
                    Minor = int.Parse(TempNum[2]);
                }
                else
                {
                    Minor = 0;
                }
            }
            Services = new UPnPService[0];
            if (UDN == "")
            {
                UniqueDeviceName = Guid.NewGuid().ToString();
            }
            else
            {
                UniqueDeviceName = UDN;
            }

            SSDPServer = new SSDP(ExpirationTimeout);
            SSDPServer.OnRefresh += new SSDP.RefreshHandler(SendNotify);
            SSDPServer.OnSearch += new SSDP.SearchHandler(HandleSearch);
        }
        private static UPnPComplexType ParseComplexType(XmlTextReader X, UPnPComplexType RetVal)
        {
            string elementName = X.LocalName;
            int count = 0;
            bool done = false;
            DText P = new DText();
            P.ATTRMARK = ":";

            RetVal.AddContainer(new GenericContainer());

            do
            {
                switch (X.NodeType)
                {
                case XmlNodeType.Element:
                    switch (X.LocalName)
                    {
                    case "complexType":
                    case "group":
                        ++count;
                        if (X.HasAttributes)
                        {
                            for (int i = 0; i < X.AttributeCount; i++)
                            {
                                X.MoveToAttribute(i);
                                if (X.Name == "name")
                                {
                                    P[0] = X.Value;
                                    if (P.DCOUNT() == 1)
                                    {
                                        RetVal.LocalName = X.Value;
                                        RetVal.NameSpace = X.LookupNamespace("");
                                    }
                                    else
                                    {
                                        RetVal.LocalName = P[2];
                                        RetVal.NameSpace = X.LookupNamespace(P[1]);
                                    }
                                }
                                else if (X.Name == "ref")
                                {
                                    // NOP
                                }
                            }
                            X.MoveToElement();
                        }
                        break;
                    case "sequence":
                    case "choice":
                        RetVal.CurrentContainer.AddCollection(ParseComplexType_SequenceChoice(X));
                                //ParseComplexType_Sequence(X,RetVal);
                        break;
                    case "complexContent":
                        RetVal.AddContainer(new ComplexContent());
                        break;
                    case "simpleContent":
                        RetVal.AddContainer(new SimpleContent());
                        break;
                    case "restriction":
                        Restriction r = new Restriction();
                        if (RetVal.CurrentContainer.GetType() == typeof(ComplexContent))
                        {
                            ((ComplexContent)RetVal.CurrentContainer).RestExt = r;
                        }
                        else if (RetVal.CurrentContainer.GetType() == typeof(SimpleContent))
                        {
                            ((SimpleContent)RetVal.CurrentContainer).RestExt = r;
                        }
                        if (X.HasAttributes)
                        {
                            for (int i = 0; i < X.AttributeCount; i++)
                            {
                                X.MoveToAttribute(i);
                                if (X.Name == "base")
                                {
                                    P[0] = X.Value;
                                    if (P.DCOUNT() == 1)
                                    {
                                        r.baseType = X.Value;
                                        r.baseTypeNS = X.LookupNamespace("");
                                    }
                                    else
                                    {
                                        r.baseType = P[2];
                                        r.baseTypeNS = X.LookupNamespace(P[1]);
                                    }
                                }
                            }
                            X.MoveToElement();
                        }
                        break;
                    }
                    break;
                case XmlNodeType.EndElement:
                    if (X.LocalName == elementName)
                    {
                        --count;
                        if (count == 0)
                        {
                            done = true;
                        }
                    }
                    break;
                case XmlNodeType.Text:
                    break;
                }
            } while(!done && X.Read());
            return(RetVal);
        }
        /// <summary>
        /// This method changes the source or sink protocolInfo sets 
        /// for the media server.
        /// </summary>
        /// <param name="sourceProtocolInfo">true, if changing source protocolInfo set</param>
        /// <param name="protocolInfoSet">new protocolInfo strings, separated by commas</param>
        private void UpdateProtocolInfoSet(bool sourceProtocolInfo, string protocolInfoSet)
        {
            DText parser = new DText();
            parser.ATTRMARK = ",";
            parser[0] = protocolInfoSet;

            int cnt = parser.DCOUNT();
            ArrayList prots = new ArrayList();

            for (int i=1; i <= cnt; i++)
            {
                string val = parser[i].Trim();

                if (val != "")
                {
                    ProtocolInfoString protInfo = new ProtocolInfoString("*:*:*:*");
                    bool error = false;
                    try
                    {
                        protInfo = new ProtocolInfoString(val);
                    }
                    catch
                    {
                        error = true;
                    }

                    if (error == false)
                    {
                        prots.Add(protInfo);
                    }
                }
            }

            ProtocolInfoString[] protArray = null;

            if (prots.Count > 0)
            {
                protArray = (ProtocolInfoString[]) prots.ToArray(prots[0].GetType());
            }

            this.UpdateProtocolInfoSet(sourceProtocolInfo, protArray);
        }
        /// <summary>
        /// Method executes when a control point invokes the ContentDirectory.UpdateObject action.
        /// The caller must specify the object to be modified, the old XML values to replace,
        /// and the new XML values to use.
        /// </summary>
        /// <param name="objectID">update media object with this ID</param>
        /// <param name="currentTagValue">
        /// Comma separated value list of current XML elements in the object.
        /// Empty value or double comma indicates that a new XML element is to be created.
        /// CDS spec defines that the text of the XML elements must match
        /// exactly with the text provided by the server. This means
        /// XML attributes have to be in the correct order within the XML element.
        /// XML elements need not be in any particular order though.. just the
        /// text between the commas separating things need to be that way.
        /// The order of XML elements correspond with the order of replacement
        /// XML elements.
        /// </param>
        /// <param name="newTagValue">
        /// Comma separated value list of new/replace XML elements in the object.
        /// Empty value or double comma indicates that an existing XML element is to be deleted.
        /// The order of XML elements correspond with the order of current
        /// XML elements.
        /// </param>
        private void SinkCd_UpdateObject(System.String objectID, System.String currentTagValue, System.String newTagValue)
        {
            try
            {
                // Ensure that the specified object actually exists
                IDvMedia obj = (IDvMedia) this.GetCdsEntry(objectID);

                if (obj == null)
                {
                    throw new Error_NoSuchObject("("+objectID+")");
                }
                else if (obj.IsReference)
                {
                    throw new UPnPCustomException(830, "This server will not allow UpdateObject() on a reference.");
                }

                // Set up text parsers.
                DText currentTagParser = new DText();
                DText newTagParser = new DText();

                currentTagParser.ATTRMARK = ",";
                newTagParser.ATTRMARK = ",";

                currentTagParser[0] = currentTagValue;
                newTagParser[0] = newTagValue;

                // ensure that the number of old xml values is equal
                // to the number of new values

                // BUG - Need to fix a case where the XML values include commas.

                int nFrags = currentTagParser.DCOUNT();
                int nFrags2 = newTagParser.DCOUNT();

                if (nFrags != nFrags2)
                {
                    throw new Error_ParameterMismatch("The number of tag/value pairs is not the same between currentTagValue and newTagValue.");
                }

                // determine the base URL using the IP address and port
                // where the request came in from and then
                // build an DIDL-Lite representation of the
                // object that needs updating

                //TODO: get all interfaces
                string baseUrl = this.GetBaseUrlByInterface();
                ArrayList properties = new ArrayList();
                ArrayList entries = new ArrayList();
                entries.Add(obj);

                string oldXml;
                try
                {
                    oldXml = BuildXmlRepresentation(baseUrl, properties, entries);
                }
                catch (Exception e)
                {
                    throw (e);
                }

                //  At this point oldXml represents the object we're trying to
                //  update, in an xml string format. Now go and replace (or add) all
                //  of the text values appropriately.
                //

                string newXml = oldXml;
                for (int i=1; i <= nFrags; i++)
                {
                    // grab the old and new value XML fragments

                    string oldFrag = currentTagParser[i].Trim();
                    string newFrag = newTagParser[i].Trim();

                    if (
                        ((oldFrag.StartsWith("<") == false) || (oldFrag.EndsWith(">") == false)) &&
                        (oldFrag != "")
                        )
                    {
                        throw new Error_InvalidCurrentTagValue("Invalid args. (" + oldFrag + ") is not an xml element.");
                    }

                    int pos = newXml.IndexOf(oldFrag);
                    if ((oldFrag != "") && (pos < 0))
                    {
                        throw new Error_InvalidCurrentTagValue("Cannot find xml element (" +oldFrag+ ").");
                    }

                    if (oldFrag == "")
                    {
                        // The old value XML fragment indicates that a completely
                        // new XML element needs to be added.
                        if (obj.IsContainer)
                        {
                            StringBuilder newVal = new StringBuilder(newFrag.Length + 10);
                            newVal.AppendFormat("{0}</container>");
                            newXml = newXml.Replace("</container>", newVal.ToString());
                        }
                        else
                        {
                            StringBuilder newVal = new StringBuilder(newFrag.Length + 10);
                            newVal.AppendFormat("{0}</item>", newFrag);
                            newXml = newXml.Replace("</item>", newVal.ToString());
                        }
                    }
                    else
                    {
                        // The new value XML fragment indicates that a current
                        // XML fragment must be deleted.
                        if (newFrag == "")
                        {
                            newXml = newXml.Replace(oldFrag, "");
                        }
                        else
                        {
                            newXml = newXml.Replace(oldFrag, newFrag);
                        }
                    }
                }

                // At this point newXml represents what the proposed object should
                // look like with new changes. We'll continue by casting the
                // string into an xmldocument and instantiating a new IDvMedia
                // instance, making sure to keep the ID specified within the newXml.
                //

                // Cast the string into an XmlDocument so that we can instantiate
                // a media object using an XmlElement object.

                XmlDocument xmldoc = new XmlDocument();
                xmldoc.LoadXml(newXml);

                XmlNodeList didlheader = xmldoc.GetElementsByTagName(T[_DIDL.DIDL_Lite]);
                XmlNode didlRoot = didlheader[0];
                XmlElement xmlElement = (XmlElement) didlRoot.ChildNodes[0];

                IDvMedia newObj;
                if (obj.IsContainer)
                {
                    newObj = new DvMediaContainer(xmlElement);
                }
                else
                {
                    newObj = new DvMediaItem(xmlElement);
                }

                // Iterate through the resources of the new object
                // and ensure that resources that carried over
                // from the original object's metadata are
                // properly mapped in the new object's list.
                // This way, upper software layers cannot effectively
                // tell the difference if a comparison-by-value is done.

                foreach (IMediaResource newRes in newObj.Resources)
                {
                    string uri = newRes.ContentUri;
                    int pos = uri.IndexOf(this.m_VirtualDirName);

                    if (pos > 0)
                    {
                        // ensure that contentUri and importUri values don't violate automapping rule
                        string subUri = uri.Substring(pos + this.m_VirtualDirName.Length);
                        DText DirectiveParser = new DText();
                        DirectiveParser.ATTRMARK = "/";

                        DirectiveParser[0] = subUri;
                        string resourceID = DirectiveParser[2];
                        string objID = DirectiveParser[3];
                        System.Diagnostics.Debug.Assert(objID == objectID);
                        IDvResource res = this.GetResource(objectID, resourceID);

                        newRes[T[_RESATTRIB.importUri]] = null;
                        newRes.ContentUri = res.ContentUri;
                    }
                }

                // Request upper software components to accept/reject
                // request to change metadata. The delegate should
                // throw an exception (preferably UPnPCustomExeption)
                // to indicate a rejection.
                if (this.OnRequestChangeMetadata != null)
                {
                    this.OnRequestChangeMetadata (this, obj, newObj);
                }

                // If no rejection, then use the metadata of the new object
                // and apply it to the existing object.
                obj.UpdateObject(newObj);
            }
            catch (Exception e)
            {
                Exception ne = new Exception("MediaServer.SinkCd_UpdateObject()", e);
                throw ne;
            }

            this.m_Stats.UpdateObject++;
            this.FireStatsChange();
        }
        /// <summary>
        /// Takes a comma separated value list of tag names
        /// and returns them individually in an arraylist.
        /// Method is primarily used to get an ArrayList used with the 
        /// "desiredProperties" argument of
        /// <see cref="IUPnPMedia.ToXml"/> and <see cref="IUPnPMedia.ToAlternateXml()"/>
        /// methods.
        /// </summary>
        /// <param name="filters">Comma separated value list of metadata property names.</param>
        /// <returns>
        /// ArrayList where each item is a metadata property name in the input.
        /// The return value is null to indicate an empty string was used as input.
        /// The intent is slightly different from an empty ArrayList, which indicates
        /// the control point specified * for all metadata properties.
        /// </returns>
        private ArrayList GetFilters(string filters)
        {
            ArrayList properties = new ArrayList();
            filters = filters.Trim();
            if (filters == "")
            {
                return null;
            }
            if ((filters == ",") || (filters.IndexOf('*') >= 0))
            {
            }
            else
            {
                DText filterParser = new DText();
                filterParser.ATTRMARK = ",";
                filterParser[0] = filters;
                int size = filterParser.DCOUNT();

                //indicates if the "res" element related attribute was added to the filter list
                bool addRes = false;

                //indicates if the "res" element was added to the filter list
                bool addedRes = false;

                //Iterate through the comma seaparted value list

                for (int i=1; i <= size; i++)
                {
                    // Generally speaking, we're only obligated to support the @attribute
                    // syntax for top level DIDL-Lite elements. This includes
                    // "item", "container", "res", and "desc" elements. Some XML attributes
                    // of those tags are always required, so we may not even bother checking
                    // for those attributes because ToXml() and ToAlternateXml()
                    // will always print those values.

                    string prop = filterParser[i].Trim();

                    if (prop == "res")
                    {
                        // res explicitly added
                        addedRes = true;
                    }

                    // If the property begins with an ampersand,
                    // then we check all possible CDS-normative
                    // top level element names for a matching XML attribute.
                    // Most attributes are related to resource elements,
                    // so make note when a resource related attribute
                    // was added because we may need to explicitly add
                    // the "res" element in the filter list to properly
                    // indicate that the "res" elements in DIDL-Lite
                    // response are to be returned.

                    if (prop.StartsWith("@"))
                    {
                        prop = prop.Substring(1);

                        if (string.Compare(prop, T[_ATTRIB.parentID], true) == 0)
                        {
                            properties.Add(Tags.PropertyAttributes.item_parentID);
                            properties.Add(Tags.PropertyAttributes.container_parentID);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.childCount], true) == 0)
                        {
                            properties.Add(Tags.PropertyAttributes.container_childCount);
                        }

                        else if (string.Compare(prop, T[_ATTRIB.bitrate], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_bitrate);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.bitsPerSample], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_bitsPerSample);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.colorDepth], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_colorDepth);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.duration], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_duration);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.importUri], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_importUri);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.nrAudioChannels], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_nrAudioChannels);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.protocolInfo], true) == 0)
                        {
                            addRes = true;
                        }
                        else if (string.Compare(prop, T[_ATTRIB.protection], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_protection);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.resolution], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_resolution);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.sampleFrequency], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_sampleFrequency);
                        }
                        else if (string.Compare(prop, T[_ATTRIB.size], true) == 0)
                        {
                            addRes = true;
                            properties.Add(Tags.PropertyAttributes.res_size);
                        }

                        else if (string.Compare(prop, T[_ATTRIB.name], true) == 0)
                        {
                            // handle optional "name" attribute for various elements
                            properties.Add(Tags.PropertyAttributes.upnp_class);
                            properties.Add(Tags.PropertyAttributes.upnp_className);
                            properties.Add(Tags.PropertyAttributes.upnp_searchClass);
                            properties.Add(Tags.PropertyAttributes.upnp_searchClassName);
                        }
                    }
                    else
                    {
                        properties.Add(prop);
                    }
                }

                if ((addRes) && (!addedRes))
                {
                    // only explicitly add "res" element if the other elements
                    // were not added
                    properties.Add("res");
                }
            }

            return properties;
        }
        /// <summary>
        /// Parses 'rangeStr' for HTTP range sets, and adds the sets into
        /// 'rangeSets'... should an overlapping range set be provided
        /// or if an otherwise invalid range is requested, then we clear
        /// the 'rangeSets'... behavior is taken from http://www.freesoft.org/CIE/RFC/2068/178.htm.
        ///
        /// <para>
        /// If the server ignores a byte-range-spec because it is invalid, 
        /// the server should treat the request as if the invalid Range header 
        /// field did not exist. 
        /// (Normally, this means return a 200 response containing the full entity). 
        /// The reason is that the only time a client will make such an invalid 
        /// request is when the entity is smaller than the entity retrieved by a prior request.
        /// [source: http://www.freesoft.org/CIE/RFC/2068/178.htm]
        /// </para>
        /// </summary>
        /// <param name="rangeSets">this ArrayList has range sets added to it</param>
        /// <param name="rangeStr">
        /// This is the HTTP header with the desired ranges.
        /// Text is assumed to be all lower case and trimmed.
        /// </param>
        /// <param name="contentLength">
        /// The entire length of the content, from byte 0.
        /// </param>
        private ArrayList AddRangeSets(ArrayList rangeSets, string rangeStr, long contentLength)
        {
            bool errorEncountered = true;

            errorEncountered = false;
            DText dt = new DText();
            dt.ATTRMARK = "=";
            dt.MULTMARK = ",";
            dt.SUBVMARK = "-";
            dt[0] = rangeStr;

            int numSets = dt.DCOUNT(2);

            for (int i=1; i <= numSets; i++)
            {
                string sOffset = dt[2,i,1].Trim();
                string sEnd = dt[2,i,2].Trim();
                long offset=-1, length=-1, end=-1;

                if ((sOffset == "") && (sEnd == ""))
                {
                    // royally screwed up request
                    errorEncountered = true;
                    break;
                }
                else if ((sOffset == "") && (sEnd != ""))
                {
                    // retrieve the last set of bytes identified by sEnd
                    try
                    {
                        offset = 0;
                        end = long.Parse(sEnd);
                        length = end + 1;
                    }
                    catch
                    {
                        errorEncountered = true;
                        break;
                    }
                }
                else if ((sOffset != "") && (sEnd == ""))
                {
                    // retrieve all bytes starting from sOffset
                    try
                    {
                        offset = long.Parse(sOffset);
                        end = contentLength - 1;
                        length = contentLength - offset;
                    }
                    catch
                    {
                        errorEncountered = true;
                        break;
                    }
                }
                else
                {
                    // retrieve bytes from sOffset through sEnd,
                    // inclusive so be sure to add 1 to difference
                    try
                    {
                        offset = long.Parse(sOffset);
                        end = long.Parse(sEnd);

                        if (offset <= end)
                        {
                            length = end - offset + 1;
                        }
                        else
                        {
                            errorEncountered = true;
                        }
                    }
                    catch
                    {
                        errorEncountered = true;
                        break;
                    }
                }

                if (errorEncountered == false)
                {
                    System.Diagnostics.Debug.Assert(offset >= 0);
                    System.Diagnostics.Debug.Assert(length >= 0);
                    System.Diagnostics.Debug.Assert(end >= 0);

                    HTTPSession.Range newRange = new HTTPSession.Range(offset, length);
                    rangeSets.Add(newRange);
                }
            }

            if (errorEncountered)
            {
                // error parsing value, this is invalid so clear and return
                rangeSets.Clear();
            }

            return rangeSets;
        }
        /// <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();
        }
        private static ItemCollection ParseComplexType_SequenceChoice(XmlTextReader X)
        {
            bool done = false;
            ItemCollection RetVal = null;
            string elementName = X.LocalName;
            DText p = new DText();
            p.ATTRMARK = ":";

            if (X.LocalName == "choice")
            {
                RetVal = new Choice();
            }
            else
            {
                RetVal = new Sequence();
            }

            if (X.HasAttributes)
            {
                for (int i = 0; i < X.AttributeCount; i++)
                {
                    X.MoveToAttribute(i);
                    switch (X.LocalName)
                    {
                    case "minOccurs":
                        RetVal.MinOccurs = X.Value;
                        break;
                    case "maxOccurs":
                        RetVal.MaxOccurs = X.Value;
                        break;
                    }
                }
                X.MoveToElement();
            }
            X.Read();

            do
            {
                switch (X.NodeType)
                {
                case XmlNodeType.Element:
                    switch (X.LocalName)
                    {
                    case "group":
                        if (X.HasAttributes)
                        {
                            for (int i = 0; i < X.AttributeCount; i++)
                            {
                                X.MoveToAttribute(i);
                                switch (X.LocalName)
                                {
                                case "ref":
                                    string sample = X.Value;
                                    break;
                                }
                            }
                            X.MoveToElement();
                        }
                        break;
                    case "sequence":
                    case "choice":
                        RetVal.AddCollection(ParseComplexType_SequenceChoice(X));
                        break;
                    case "element":
                        RetVal.AddContentItem(new Element());
                        if (X.HasAttributes)
                        {
                            for (int i = 0; i < X.AttributeCount; i++)
                            {
                                X.MoveToAttribute(i);
                                switch (X.LocalName)
                                {
                                case "name":
                                    RetVal.CurrentItem.Name = X.Value;
                                    break;
                                case "type":
                                    p[0] = X.Value;
                                    if (p.DCOUNT() == 1)
                                    {
                                        RetVal.CurrentItem.Type = X.Value;
                                        RetVal.CurrentItem.TypeNS = X.LookupNamespace("");
                                    }
                                    else
                                    {
                                        RetVal.CurrentItem.Type = p[2];
                                        RetVal.CurrentItem.TypeNS = X.LookupNamespace(p[1]);
                                    }
                                    break;
                                case "minOccurs":
                                    RetVal.CurrentItem.MinOccurs = X.Value;
                                    break;
                                case "maxOccurs":
                                    RetVal.CurrentItem.MaxOccurs = X.Value;
                                    break;
                                }
                            }
                            X.MoveToElement();
                        }
                        break;
                    case "attribute":
                        break;
                    }
                    break;
                case XmlNodeType.EndElement:
                    if (X.LocalName == elementName)
                    {
                        done = true;
                    }
                    break;
                case XmlNodeType.Text:
                    break;
                }
            } while(!done && X.Read());

            return(RetVal);
        }
        public static void BuildComplexTypeParser_Collection(string cx, Hashtable SequenceTable, Hashtable ChoiceTable, ref int SeqX, ref int ChoX, CodeProcessor cs, UPnPComplexType.ItemCollection ic, string pc_methodPrefix)
        {
            int x = 0;
            string prefix = "";
            int SeqX2 = 0;
            int ChoX2 = 0;

            if (ic.GetType() == typeof(UPnPComplexType.Sequence))
            {
                ++SeqX;
                if (cx == "")
                {
                    cx += "_sequence_" + SeqX.ToString();
                }
                else
                {
                    cx += "->_sequence_" + SeqX.ToString();
                }
                prefix = cx + "->";
            }
            else if (ic.GetType() == typeof(UPnPComplexType.Choice))
            {
                ++ChoX;
                if (cx == "")
                {
                    cx += "_choice_" + ChoX.ToString();
                }
                else
                {
                    cx += "->_choice_" + ChoX.ToString();
                }
                prefix = cx + "->";
            }

            foreach (UPnPComplexType.ContentData cd in ic.Items)
            {
                ++x;
                cs.Append("	if (node->NameLength==" + cd.Name.Length.ToString() + " && memcmp(node->Name,\"" + cd.Name + "\"," + cd.Name.Length.ToString() + ")==0)" + cl);
                cs.Append("	{" + cl);
                if (x == 1)
                {
                    Stack st = new Stack();
                    UPnPComplexType.ItemCollection tc = ic;
                    DText pp = new DText();
                    pp.ATTRMARK = "->";
                    pp[0] = cx;
                    int ppx = pp.DCOUNT();
                    while (tc != null)
                    {
                        string ps;

                        ps = "RetVal";
                        for (int i = 1; i <= ppx; ++i)
                        {
                            ps += ("->" + pp[i]);
                        }
                        st.Push(new object[2] { ps, tc });
                        --ppx;
                        tc = tc.ParentCollection;
                    }
                    while (st.Count > 0)
                    {
                        object[] foo = (object[])st.Pop();
                        cs.Append("	if (" + (string)foo[0] + " == NULL)" + cl);
                        cs.Append("	{" + cl);
                        if (foo[1].GetType() == typeof(UPnPComplexType.Sequence))
                        {
                            cs.Append("	if ((" + (string)foo[0] + " = (struct SEQUENCE_" + SequenceTable[foo[1]].ToString() + "*)malloc(sizeof(struct SEQUENCE_" + SequenceTable[foo[1]].ToString() + "))) == NULL) ILIBCRITICALEXIT(254);" + cl);
                            cs.Append("	memset(" + (string)foo[0] + ",0,sizeof(struct SEQUENCE_" + SequenceTable[foo[1]].ToString() + "));" + cl);
                        }
                        else if (foo[1].GetType() == typeof(UPnPComplexType.Choice))
                        {
                            cs.Append("	if ((" + (string)foo[0] + " = (struct CHOICE_" + ChoiceTable[foo[1]].ToString() + "*)malloc(sizeof(struct CHOICE_" + ChoiceTable[foo[1]].ToString() + "))) == NULL) ILIBCRITICALEXIT(254);" + cl);
                            cs.Append("	memset(" + (string)foo[0] + ",0,sizeof(struct CHOICE_" + ChoiceTable[foo[1]].ToString() + "));" + cl);
                        }
                        cs.Append("	}" + cl);
                    }

                    //					if (ic.GetType()==typeof(UPnPComplexType.Sequence))
                    //					{
                    //						cs.Append("	RetVal->"+cx+" = (struct SEQUENCE_"+SequenceTable[ic].ToString()+"*)malloc(sizeof(struct SEQUENCE_"+SequenceTable[ic].ToString()+"));"+cl);
                    //					}
                    //					else if (ic.GetType()==typeof(UPnPComplexType.Choice))
                    //					{
                    //						cs.Append("	RetVal->"+cx+" = (struct CHOICE_"+ChoiceTable[ic].ToString()+"*)malloc(sizeof(struct CHOICE_"+ChoiceTable[ic].ToString()+"));"+cl);
                    //					}
                }
                if (cd.TypeNS == "http://www.w3.org/2001/XMLSchema")
                {
                    // XSD Simple Type
                    switch (cd.Type)
                    {
                        case "boolean":
                        case "int":
                        case "integer":
                        case "positiveInteger":
                        case "negativeInteger":
                        case "nonNegativeInteger":
                        case "nonPositiveInteger":
                        case "long":
                        case "short":
                            cs.Append("	RetVal->" + prefix + cd.Name + " = atoi(text);" + cl);
                            break;
                    }
                }
                else
                {
                    // XSD User Defined Type
                    cs.Append("	RetVal->" + prefix + cd.Name + " = " + pc_methodPrefix + "Parse_" + cd.Type + "(node->Next);" + cl);
                }
                cs.Append("	}" + cl);
            }
            foreach (UPnPComplexType.ItemCollection ec in ic.NestedCollections)
            {
                BuildComplexTypeParser_Collection(cx, SequenceTable, ChoiceTable, ref SeqX2, ref ChoX2, cs, ec, pc_methodPrefix);
            }
        }
        private void networkOpenMenuItem_Click(object sender, System.EventArgs e)
        {
            UPnPDeviceLocator devicelocator = new UPnPDeviceLocator();
            if (devicelocator.ShowDialog(this) == DialogResult.OK && devicelocator.SelectedDevice != null)
            {
                //				ClearTreeNodeTags(deviceRootTreeNode);
                //				deviceRootTreeNode.Text = devicelocator.SelectedDevice.FriendlyName;
                //				treeView.Nodes.Clear();
                //				deviceRootTreeNode.Nodes.Clear();

                UPnPDevice device = UPnPDevice.CreateRootDevice(6000, 1.0, ".");
                device.FriendlyName = devicelocator.SelectedDevice.FriendlyName;
                device.DeviceURN = devicelocator.SelectedDevice.DeviceURN;
                device.Manufacturer = devicelocator.SelectedDevice.Manufacturer;
                device.ManufacturerURL = devicelocator.SelectedDevice.ManufacturerURL;
                device.ModelDescription = devicelocator.SelectedDevice.ModelDescription;
                device.ModelName = devicelocator.SelectedDevice.ModelName;
                device.ModelNumber = devicelocator.SelectedDevice.ModelNumber;
                device.ProductCode = devicelocator.SelectedDevice.ProductCode;
                device.SerialNumber = devicelocator.SelectedDevice.SerialNumber;
                device.User = new ServiceGenerator.Configuration("UPnP", ServiceGenerator.ConfigurationType.DEVICE);

                TreeNode n = new TreeNode(device.FriendlyName);
                n.Tag = device;

                treeView.Nodes.Add(n);

                foreach (UPnPDevice embeddeddevice in devicelocator.SelectedDevice.EmbeddedDevices)
                {
                    AddEmbeddedDevice(n, embeddeddevice);
                }

                foreach (UPnPService service in devicelocator.SelectedDevice.Services)
                {
                    DText p = new DText();
                    p.ATTRMARK = ":";

                    string servicename = service.ServiceURN;
                    p[0] = servicename;

                    servicename = p[p.DCOUNT() - 1];

                    service.User = new ServiceGenerator.ServiceConfiguration(servicename, service);
                    TreeNode serviceTreeNode = new TreeNode(servicename, 2, 2);
                    serviceTreeNode.Tag = service;
                    n.Nodes.Add(serviceTreeNode);
                }

                treeView.SelectedNode = n;
                selectedItem = n.Tag;
                n.Expand();

                this.Text = AppTitle;
                saveMenuItem.Enabled = false;
                saveAsMenuItem.Enabled = true;

                treeView_AfterSelect(this, null);
                updateStatusText();
            }
        }
        private void ProcessPacket(HTTPMessage msg, IPEndPoint src, IPEndPoint local)
        {
            if (OnSniffPacket != null) OnSniffPacket(src, null, msg);

            DText parser = new DText();
            parser.ATTRMARK = "::";

            bool Alive = false;
            String UDN = msg.GetTag("USN");

            parser[0] = UDN;
            String USN = parser[1];
            USN = USN.Substring(USN.IndexOf(":") + 1);
            String ST = parser[2];
            int MaxAge = 0;

            String NTS = msg.GetTag("NTS").ToUpper();
            if (NTS == "SSDP:ALIVE")
            {
                Alive = true;
                String ma = msg.GetTag("Cache-Control").Trim();
                if (ma != "")
                {
                    parser.ATTRMARK = ",";
                    parser.MULTMARK = "=";
                    parser[0] = ma;
                    for (int i = 1; i <= parser.DCOUNT(); ++i)
                    {
                        if (parser[i, 1].Trim().ToUpper() == "MAX-AGE")
                        {
                            MaxAge = int.Parse(parser[i, 2].Trim());
                            break;
                        }
                    }
                }
            }

            if (msg.Directive == "NOTIFY" && OnNotify != null)
            {
                Uri locuri = null;
                string location = msg.GetTag("Location");
                if (location != null && location.Length > 0) { try { locuri = new Uri(location); } catch (Exception) { } }
                OnNotify(src, msg.LocalEndPoint, locuri, Alive, USN, ST, MaxAge, msg);
            }
            else if (msg.Directive == "M-SEARCH" && OnSearch != null)
            {
                if (ValidateSearchPacket(msg) == false) return;
                int MaxTimer = int.Parse(msg.GetTag("MX"));
                SearchStruct SearchData = new SearchStruct();
                SearchData.ST = msg.GetTag("ST");
                SearchData.Source = src;
                SearchData.Local = local;
                SearchTimer.Add(SearchData, RandomGenerator.Next(0, MaxTimer));
            }
        }
Beispiel #22
0
        /// <summary>
        /// Parses a Byte Array at a specific location, and builds a Packet.
        /// </summary>
        /// <param name="buffer">The Array of Bytes</param>
        /// <param name="indx">The Start Index</param>
        /// <param name="count">The number of Bytes to process</param>
        /// <returns></returns>
        static public HTTPMessage ParseByteArray(byte[] buffer, int indx, int count)
        {
            HTTPMessage  TheMessage = new HTTPMessage();
            UTF8Encoding UTF8       = new UTF8Encoding();
            String       TempData   = UTF8.GetString(buffer, indx, count);
            DText        parser     = new DText();
            String       TempString;

            int idx = TempData.IndexOf("\r\n\r\n");

            if (idx < 0)
            {
                return(null);
            }
            TempData = TempData.Substring(0, idx);

            parser.ATTRMARK = "\r\n";
            parser.MULTMARK = ":";
            parser[0]       = TempData;
            string CurrentLine = parser[1];

            DText HdrParser = new DText();

            HdrParser.ATTRMARK = " ";
            HdrParser.MULTMARK = "/";
            HdrParser[0]       = CurrentLine;

            if (CurrentLine.ToUpper().StartsWith("HTTP/") == true)
            {
                TheMessage.ResponseCode = int.Parse(HdrParser[2]);
                int s1 = CurrentLine.IndexOf(" ");
                s1 = CurrentLine.IndexOf(" ", s1 + 1);
                TheMessage.ResponseData = HTTPMessage.UnEscapeString(CurrentLine.Substring(s1));
                try
                {
                    TheMessage.Version = HdrParser[1, 2];
                }
                catch (Exception ex)
                {
                    OpenSource.Utilities.EventLogger.Log(ex);
                    TheMessage.Version = "0.9";
                }
            }
            else
            {
                TheMessage.Directive = HdrParser[1];
                TempString           = CurrentLine.Substring(CurrentLine.LastIndexOf(" ") + 1);
                if (TempString.ToUpper().StartsWith("HTTP/") == false)
                {
                    TheMessage.Version      = "0.9";
                    TheMessage.DirectiveObj = HTTPMessage.UnEscapeString(TempString);
                }
                else
                {
                    TheMessage.Version = TempString.Substring(TempString.IndexOf("/") + 1);
                    int fs = CurrentLine.IndexOf(" ") + 1;
                    TheMessage.DirectiveObj = HTTPMessage.UnEscapeString(CurrentLine.Substring(
                                                                             fs,
                                                                             CurrentLine.Length - fs - TempString.Length - 1));
                }
            }
            String Tag     = "";
            String TagData = "";

            for (int line = 2; line <= parser.DCOUNT(); ++line)
            {
                if (Tag != "" && parser[line, 1].StartsWith(" "))
                {
                    TagData = parser[line, 1].Substring(1);
                }
                else
                {
                    Tag     = parser[line, 1];
                    TagData = "";
                    for (int i = 2; i <= parser.DCOUNT(line); ++i)
                    {
                        if (TagData == "")
                        {
                            TagData = parser[line, i];
                        }
                        else
                        {
                            TagData = TagData + parser.MULTMARK + parser[line, i];
                        }
                    }
                }
                TheMessage.AppendTag(Tag, TagData);
            }
            int cl = 0;

            if (TheMessage.HasTag("Content-Length"))
            {
                try
                {
                    cl = int.Parse(TheMessage.GetTag("Content-Length"));
                }
                catch (Exception ex)
                {
                    OpenSource.Utilities.EventLogger.Log(ex);
                    cl = -1;
                }
            }
            else
            {
                cl = -1;
            }

            byte[] tbuffer;
            if (cl > 0)
            {
                tbuffer = new byte[cl];
                if ((idx + 4 + cl) > count)
                {
                    // NOP
                }
                else
                {
                    Array.Copy(buffer, idx + 4, tbuffer, 0, cl);
                    TheMessage.DataBuffer = tbuffer;
                }
            }
            if (cl == -1)
            {
                tbuffer = new Byte[count - (idx + 4)];
                Array.Copy(buffer, idx + 4, tbuffer, 0, tbuffer.Length);
                TheMessage.DataBuffer = tbuffer;
            }
            if (cl == 0)
            {
                TheMessage.DataBuffer = new byte[0];
            }
            return(TheMessage);
        }
Beispiel #23
0
        internal UPnPDevice(int DeviceExpiration, double version, String RootDir)
        {
            //OpenSource.Utilities.InstanceTracker.Add(this);
            // Full Device
            IsRoot = true;

            parent = null;
            HasPresentation = true;
            ControlPointOnly = false;
            RootPath = RootDir;
            ExpirationTimeout = DeviceExpiration;
            WebServerTable = Hashtable.Synchronized(new Hashtable());

            VirtualDir_Table = new Hashtable();
            VirtualDir_Header_Table = new Hashtable();

            if (version == 0)
            {
                Major = 1;
                Minor = 0;
            }
            else
            {
                DText TempNum = new DText();
                TempNum.ATTRMARK = ".";
                TempNum[0] = version.ToString();

                Major = int.Parse(TempNum[1]);
                if (TempNum.DCOUNT() == 2)
                {
                    Minor = int.Parse(TempNum[2]);
                }
                else
                {
                    Minor = 0;
                }
            }
            Services = new UPnPService[0];
            UniqueDeviceName = Guid.NewGuid().ToString();

            SSDPServer = new SSDP(ExpirationTimeout);
            SSDPServer.OnRefresh += SendNotify;
            SSDPServer.OnSearch += HandleSearch;
        }
        private void ParseStateVarXml(String evented, String multicasted, XmlTextReader XMLDoc)
        {
            //			if (XML=="")
            //			{
            //				return;
            //			}

            string ComplexType = "";
            string ComplexTypeNS = "";
            UPnPComplexType CT = null;
            DText P = new DText();
            P.ATTRMARK = ":";

            string minval = null;
            string maxval = null;
            string stepval = null;
            bool HasDef = false;

            string name = "";
            string DataType = "";
            string DefaultValue = null;
            ArrayList allowedValueList = new ArrayList();
            string LocalName = "";
            string lname2 = "";

            //			StringReader MyString = new StringReader(XML);
            //			XmlTextReader XMLDoc = new XmlTextReader(MyString);

            //			XMLDoc.Read();
            //			XMLDoc.MoveToContent();

            bool done = false;
            while (!done && XMLDoc.Read())
            {
                switch (XMLDoc.NodeType)
                {
                    case XmlNodeType.Element:
                        LocalName = XMLDoc.LocalName;
                        switch (XMLDoc.LocalName)
                        {
                            case "dataType":
                                if (XMLDoc.HasAttributes)
                                {
                                    for (int i = 0; i < XMLDoc.AttributeCount; i++)
                                    {
                                        XMLDoc.MoveToAttribute(i);
                                        if (XMLDoc.LocalName == "type")
                                        {
                                            P[0] = XMLDoc.Value;
                                            if (P.DCOUNT() == 1)
                                            {
                                                ComplexType = P[1];
                                            }
                                            else
                                            {
                                                ComplexType = P[2];
                                                ComplexTypeNS = P[1];
                                            }
                                            CT = (UPnPComplexType)ComplexTypeTable[ComplexType + ":" + XMLDoc.LookupNamespace(ComplexTypeNS)];
                                        }
                                    }
                                }
                                break;
                            case "allowedValueList":
                                bool done2 = false;

                                while (!done2 && XMLDoc.Read())
                                {
                                    switch (XMLDoc.NodeType)
                                    {
                                        case XmlNodeType.Element:
                                            lname2 = XMLDoc.LocalName;
                                            break;
                                        case XmlNodeType.EndElement:
                                            if (XMLDoc.LocalName == "allowedValueList")
                                            {
                                                done2 = true;
                                            }
                                            break;
                                        case XmlNodeType.Text:
                                            if (lname2 == "allowedValue")
                                            {
                                                allowedValueList.Add(XMLDoc.Value);
                                            }
                                            break;
                                    }
                                }
                                break;
                            case "allowedValueRange":
                                bool done3 = false;

                                while (!done3 && XMLDoc.Read())
                                {
                                    switch (XMLDoc.NodeType)
                                    {
                                        case XmlNodeType.Element:
                                            lname2 = XMLDoc.LocalName;
                                            break;
                                        case XmlNodeType.EndElement:
                                            if (XMLDoc.LocalName == "allowedValueRange")
                                            {
                                                done3 = true;
                                            }
                                            break;
                                        case XmlNodeType.Text:
                                            switch (lname2)
                                            {
                                                case "minimum":
                                                    minval = XMLDoc.Value;
                                                    break;
                                                case "maximum":
                                                    maxval = XMLDoc.Value;
                                                    break;
                                                case "step":
                                                    stepval = XMLDoc.Value;
                                                    break;
                                            }
                                            break;
                                    }
                                }
                                break;
                        }
                        break;
                    case XmlNodeType.EndElement:
                        if (XMLDoc.LocalName == "stateVariable")
                        {
                            done = true;
                        }
                        break;
                    case XmlNodeType.Text:
                        switch (LocalName)
                        {
                            case "name":
                                name = XMLDoc.Value.Trim();
                                break;
                            case "dataType":
                                DataType = XMLDoc.Value.Trim();
                                break;
                            case "defaultValue":
                                DefaultValue = XMLDoc.Value;
                                HasDef = true;
                                break;
                        }
                        break;
                }
            }

            UPnPStateVariable var;
            if (CT == null)
            {
                var = new UPnPStateVariable(name);
            }
            else
            {
                var = new UPnPStateVariable(name, CT);
            }
            var.ParentService = this;
            if (evented == "yes")
            {
                var.SendEvent = true;
            }
            if (multicasted == "yes")
            {
                var.MulticastEvent = true;
            }
            var.VarType = DataType;
            if (allowedValueList.Count > 0)
            {
                var.AllowedStringValues = (string[])allowedValueList.ToArray(typeof(string));
            }

            if (HasDef)
            {
                var.DefaultValue = UPnPService.CreateObjectInstance(var.GetNetType(), DefaultValue);
            }
            if ((minval != null) && (maxval != null))
            {
                Object stepobj = null;
                if (stepval != null)
                {
                    try
                    {
                        stepobj = UPnPService.CreateObjectInstance(var.GetNetType(), stepval);
                    }
                    catch (Exception)
                    {
                        stepobj = null;
                    }
                }

                object MIN;
                object MAX;

                try
                {
                    MIN = UPnPService.CreateObjectInstance(var.GetNetType(), minval);
                }
                catch (Exception)
                {
                    FieldInfo mi = var.GetNetType().GetField("MinValue");
                    MIN = mi.GetValue(null);
                }

                try
                {
                    MAX = UPnPService.CreateObjectInstance(var.GetNetType(), maxval);
                }
                catch (Exception)
                {
                    FieldInfo mi = var.GetNetType().GetField("MaxValue");
                    MAX = mi.GetValue(null);
                }

                var.SetRange(MIN,
                    MAX,
                    stepobj);
            }

            //StateVariables.Add(name,var);
            StateVariables[name] = var; // TempPatch Only

            /*
            IDictionaryEnumerator en = RemoteMethods.GetEnumerator();
            UPnPAction a;
            while(en.MoveNext())
            {
                a = (UPnPAction)en.Value;
                for(int x =0;x<a.ArgumentList.Length;++x)
                {
                    if (a.ArgumentList[x].RelatedStateVar.Name == name)
                    {
                        a.ArgumentList[x].RelatedStateVar.VarType = DataType;
                        a.ArgumentList[x].RelatedStateVar.AllowedStringValues = var.AllowedStringValues;
                        a.ArgumentList[x].RelatedStateVar.DefaultValue = DefaultValue;
                    }
                }
            }*/
        }
		/// <summary>
		/// This method is called automatically by the UPNP stack when eventing the
		/// ContainerUpdateIDs. Programmers need only set the value of the ContainerUpdateIDs
		/// state variable with a single elem
		/// </summary>
		/// <param name="current">Comma-separated-value list in the string form of "[containerID] UpdateID= [container.UpdateID], [containerIDn] UpdateID= [container.UpdatedID]"</param>
		/// <param name="newObject">String that should overwrite an existing comma-separated-value item or append to the existing list, in form "[containerID] UpdateID= [container.UpdateID]"</param>
		/// <returns></returns>
		public object Merge(object current, object newObject)
		{
			DText Parser = new DText();
			Parser.ATTRMARK = Accumulator_ContainerUpdateIDs.CSV_Delimitor;

			DText Parser2 = new DText();
			Parser2.ATTRMARK = Accumulator_ContainerUpdateIDs.Delimitor;

			if (current == null) current = "";
			if (newObject == null) newObject = "";

			string curStr = current.ToString();
			string newStr = newObject.ToString();

			if (newStr == "") return "";

			int i;
			Hashtable hash = new Hashtable();
			if (curStr != "")
			{

				Parser[0] = curStr;
				int cnt = Parser.DCOUNT();
				for (i=1; i <= cnt; i++)
				{
					string id, update;
					if (Accumulator_ContainerUpdateIDs.Delimitor == Accumulator_ContainerUpdateIDs.CSV_Delimitor)
					{
						id = Parser[i];
						i++;
						update = Parser[i];
						hash[id] = update;
					}
					else
					{
						string pair = Parser[i];
						Parser2[0] = pair;
						id = Parser2[1];;
						update = Parser2[2];
						hash[id] = update;
					}

					if (id == "")
					{
						throw new ApplicationException("Bad evil. Container ID is empty string.");
					}
					if (update == "")
					{
						throw new ApplicationException("Bad evil. Update ID is empty string.");
					}
				}
			}

			/*
			 * add or overwrite a container update value
			 */ 

			Parser2[0] = newStr;
			string id2 = Parser2[1];
			string update2 = Parser2[2];
			hash[id2] = update2;

			StringBuilder sb = new StringBuilder(hash.Count * 20);
			i=0;
			foreach (string key in hash.Keys)
			{
				if (i > 0)
				{
					sb.Append(",");
				}
				i++;

				string val = hash[key].ToString();
				if (key == "")
				{
					throw new ApplicationException("Bad evil. Accumulator has empty string for key.");
				}
				if (val == "")
				{
					throw new ApplicationException("Bad evil. Accumulator has empty string for value.");
				}
				sb.AppendFormat("{0}{1}{2}", key, Delimitor, val);
			}

			return sb.ToString();
		}
        private static ItemCollection ParseComplexType_SequenceChoice(XmlTextReader X)
        {
            bool           done        = false;
            ItemCollection RetVal      = null;
            string         elementName = X.LocalName;
            DText          p           = new DText();

            p.ATTRMARK = ":";

            if (X.LocalName == "choice")
            {
                RetVal = new Choice();
            }
            else
            {
                RetVal = new Sequence();
            }

            if (X.HasAttributes)
            {
                for (int i = 0; i < X.AttributeCount; i++)
                {
                    X.MoveToAttribute(i);
                    switch (X.LocalName)
                    {
                    case "minOccurs":
                        RetVal.MinOccurs = X.Value;
                        break;

                    case "maxOccurs":
                        RetVal.MaxOccurs = X.Value;
                        break;
                    }
                }
                X.MoveToElement();
            }
            X.Read();


            do
            {
                switch (X.NodeType)
                {
                case XmlNodeType.Element:
                    switch (X.LocalName)
                    {
                    case "group":
                        if (X.HasAttributes)
                        {
                            for (int i = 0; i < X.AttributeCount; i++)
                            {
                                X.MoveToAttribute(i);
                                switch (X.LocalName)
                                {
                                case "ref":
                                    string sample = X.Value;
                                    break;
                                }
                            }
                            X.MoveToElement();
                        }
                        break;

                    case "sequence":
                    case "choice":
                        RetVal.AddCollection(ParseComplexType_SequenceChoice(X));
                        break;

                    case "element":
                        RetVal.AddContentItem(new Element());
                        if (X.HasAttributes)
                        {
                            for (int i = 0; i < X.AttributeCount; i++)
                            {
                                X.MoveToAttribute(i);
                                switch (X.LocalName)
                                {
                                case "name":
                                    RetVal.CurrentItem.Name = X.Value;
                                    break;

                                case "type":
                                    p[0] = X.Value;
                                    if (p.DCOUNT() == 1)
                                    {
                                        RetVal.CurrentItem.Type   = X.Value;
                                        RetVal.CurrentItem.TypeNS = X.LookupNamespace("");
                                    }
                                    else
                                    {
                                        RetVal.CurrentItem.Type   = p[2];
                                        RetVal.CurrentItem.TypeNS = X.LookupNamespace(p[1]);
                                    }
                                    break;

                                case "minOccurs":
                                    RetVal.CurrentItem.MinOccurs = X.Value;
                                    break;

                                case "maxOccurs":
                                    RetVal.CurrentItem.MaxOccurs = X.Value;
                                    break;
                                }
                            }
                            X.MoveToElement();
                        }
                        break;

                    case "attribute":
                        break;
                    }
                    break;

                case XmlNodeType.EndElement:
                    if (X.LocalName == elementName)
                    {
                        done = true;
                    }
                    break;

                case XmlNodeType.Text:
                    break;
                }
            }while(!done && X.Read());

            return(RetVal);
        }
        private Uri[] ParseEventURL(String URLList)
        {
            DText parser = new DText();
            String temp;
            ArrayList TList = new ArrayList();

            parser.ATTRMARK = ">";
            parser[0] = URLList;

            int cnt = parser.DCOUNT();
            for (int x = 1; x <= cnt; ++x)
            {
                temp = parser[x];
                try
                {
                    temp = temp.Substring(temp.IndexOf("<") + 1);
                    TList.Add(new Uri(temp));
                }
                catch (Exception) { }
            }
            Uri[] RetVal = new Uri[TList.Count];
            for (int x = 0; x < RetVal.Length; ++x) RetVal[x] = (Uri)TList[x];
            return RetVal;
        }
        protected bool GenerateEx(UPnPDevice device,DirectoryInfo outputDirectory, Hashtable serviceNames, ref string SampleApp)
        {
            #region Initialization
            //StreamWriter W;
            DText PP = new DText();
            PP.ATTRMARK = ":";

            bool OkToDo=false;
            string WS,tmp;
            StreamWriter writer;

            SequenceTable.Clear();
            ChoiceTable.Clear();
            SequenceCounter=0;
            ChoiceCounter=0;

            if (this.SubTarget==SUBTARGETS.NONE)
            {
                UseSystem = this.Platform.ToString();
            }
            else
            {
                UseSystem = this.SubTarget.ToString();
            }
            UseInfoString = UseSystem + ", UPnP/1.0, MicroStack/" + UseVersion;

            if (this.Language == LANGUAGES.C)
            {
                pc_methodPrefix = ((ServiceGenerator.Configuration)device.User).Prefix;
                pc_methodLibPrefix = Configuration.prefixlib;
                pc_methodPrefixDef = CallingConvention + pc_methodPrefix;
            }

            AllServices.Clear();
            AddAllServices(device);
            Fix(device,0, serviceNames);

            SortedList SL = new SortedList();
            IDictionaryEnumerator en = serviceNames.GetEnumerator();
            DText Parser = new DText();
            Parser.ATTRMARK = ":";
            Parser[0] = device.DeviceURN;
            string DeviceName = Parser[4];

            // *** Generate Main Code
            Log("Writing main stack module...");

            while(en.MoveNext())
            {
                SL[en.Value] = en.Key;
            }
            en = SL.GetEnumerator();

            PrivateClassDeclarations = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            PublicClassDeclarations = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            CodeProcessor cs = new CodeProcessor(new StringBuilder(), this.Language == LANGUAGES.CPP);
            cs.NewLine = this.CodeNewLine;
            cs.ClassDefinitions = PrivateClassDeclarations;
            cs.PublicClassDefinitions = PublicClassDeclarations;
            PrivateClassDeclarations.CodeTab = Indent;
            PublicClassDeclarations.CodeTab = Indent;
            cs.CodeTab = Indent;

            if (this.Language == LANGUAGES.CPP)
            {
                AddLicense(cs,pc_methodPrefix + "ControlPoint.cpp");
            }
            else
            {
                AddLicense(cs,pc_methodPrefix + "ControlPoint.c");
            }
            cs.Append(cl);
            #endregion

            #region UPnPControlPoint.h
            WS = SourceCodeRepository.GetControlPoint_H_Template(this.pc_methodPrefix);

            #region GetService
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            en.Reset();
            while(en.MoveNext())
            {
                string name = (string)en.Key;
                cs.Append("	struct UPnPService *"+pc_methodPrefixDef+"GetService_"+name+"(struct UPnPDevice *device);"+cl);
            }
            WS = WS.Replace("//{{{UPnPGetService}}}",cs.ToString());
            #endregion
            #region Event Callbacks
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            en.Reset();
            while(en.MoveNext())
            {
                UPnPService s = (UPnPService)en.Value;
                string name = (string)en.Key;
                foreach(UPnPStateVariable variable in s.GetStateVariables())
                {
                    if (variable.SendEvent == true)
                    {
                        cs.Append("extern void (*"+pc_methodPrefix+"EventCallback_"+name+"_"+variable.Name+")(struct UPnPService* Service,");
                        cs.Append(ToCType(variable.GetNetType().FullName)+" "+variable.Name);
                        if (variable.GetNetType()==typeof(byte[]))
                        {
                            cs.Append(", int " + variable.Name+"Length");
                        }
                        cs.Append(");"+cl);
                    }
                }
            }
            WS = WS.Replace("//{{{ExternEventCallbacks}}}",cs.ToString());
            #endregion
            #region Invoke Methods
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            en.Reset();
            while(en.MoveNext())
            {
                UPnPService s = (UPnPService)en.Value;
                ServiceGenerator.ServiceConfiguration SConf = (ServiceGenerator.ServiceConfiguration)s.User;

                string name = (string)en.Key;
                foreach(UPnPAction A in s.Actions)
                {
                    cs.Append("	void "+pc_methodPrefix+"Invoke_"+name+"_"+A.Name+"(struct UPnPService *service, void (*CallbackPtr)(struct UPnPService *sender,int ErrorCode,void *user");
                    if (A.HasReturnValue)
                    {
                        if (A.GetRetArg().RelatedStateVar.ComplexType==null)
                        {
                            // NonComplex
                            cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName)+" "+A.GetRetArg().Name);
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(", int " + A.GetRetArg().Name+"Length");
                            }
                        }
                        else
                        {
                            // Complex
                            cs.Append(", struct " + A.GetRetArg().RelatedStateVar.ComplexType.Name_LOCAL+" *"+A.GetRetArg().Name);
                        }
                    }
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (!Arg.IsReturnValue && Arg.Direction=="out")
                        {
                            if (Arg.RelatedStateVar.ComplexType==null)
                            {
                                //NonComplex
                                cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName)+" "+Arg.Name);
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(",int " + Arg.Name+"Length");
                                }
                            }
                            else
                            {
                                //Complex
                                cs.Append(",struct "+Arg.RelatedStateVar.ComplexType.Name_LOCAL+" *_"+Arg.Name);
                            }
                        }
                    }
                    cs.Append(")");
                    cs.Append(",void* _user");
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in")
                        {
                            if (Arg.RelatedStateVar.ComplexType==null)
                            {
                                //NonComplex
                                cs.Append(", "+ToCType(Arg.RelatedStateVar.GetNetType().FullName)+" ");
                                if (Arg.RelatedStateVar.GetNetType()==typeof(string) && !SConf.Actions_ManualEscape.Contains(A))
                                {
                                    cs.Append("unescaped_");
                                }
                                cs.Append(Arg.Name);
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(", int " + Arg.Name+"Length");
                                }
                            }
                            else
                            {
                                //Complex
                                cs.Append(", struct "+Arg.RelatedStateVar.ComplexType.Name_LOCAL+" *"+Arg.Name);
                            }
                        }
                    }
                    cs.Append(");"+cl);
                }
                bool NeedManualComment = false;
                foreach(UPnPAction A in s.Actions)
                {
                    if (SConf.Actions_ManualEscape.Contains(A))
                    {
                        // Manual Escape
                        NeedManualComment = true;
                        break;
                    }
                }
                if (NeedManualComment)
                {
                    cs.Append(cl);
                    cs.Comment("The string parameters for the following actions MUST be MANUALLY escaped");
                    foreach(UPnPAction A in s.Actions)
                    {
                        if (SConf.Actions_ManualEscape.Contains(A))
                        {
                            // Manual Escape
                            cs.Comment("	void "+pc_methodPrefix+"Invoke_"+name+"_"+A.Name);
                        }
                    }
                    cs.Append(cl);
                }
            }
            WS = WS.Replace("//{{{UPnPInvoke_Methods}}}",cs.ToString());
            #endregion

            #region Complex Types
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            EmbeddedCGenerator.BuildComplexTypeDefinitionsAndHeaders(SL,cs,SequenceTable,ChoiceTable,ref SequenceCounter,ref ChoiceCounter,this.pc_methodPrefix,this.pc_methodLibPrefix);
            WS = WS.Replace("//{{{UPnPComplexTypes}}}",cs.ToString());
            #endregion

            #region XML Custom Tags
            #region Custom Processing

            CustomTagList.Clear();
            IDictionaryEnumerator NamespaceEnumerator = ((ServiceGenerator.Configuration)device.User).CustomFieldTable.GetEnumerator();
            while(NamespaceEnumerator.MoveNext())
            {
                IDictionaryEnumerator EntryEnumerator = ((Hashtable)NamespaceEnumerator.Value).GetEnumerator();
                while(EntryEnumerator.MoveNext())
                {
                    CustomTagList.Add(new object[2]{EntryEnumerator.Key,NamespaceEnumerator.Key});
                }
            }

            if (this.CustomTagList.Count>0)
            {
                WS = SourceCodeRepository.RemoveTag("//{{{BEGIN_CustomTagSpecific}}}","//{{{END_CustomTagSpecific}}}",WS);
            }
            else
            {
                WS = SourceCodeRepository.RemoveAndClearTag("//{{{BEGIN_CustomTagSpecific}}}","//{{{END_CustomTagSpecific}}}",WS);
            }
            #endregion
            #region #define
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);

            foreach(object[] foo in this.CustomTagList)
            {
                PP[0] = (string)foo[0];
                string FieldName;
                string FieldNameSpace = (string)foo[1];

                if (PP.DCOUNT()==1)
                {
                    FieldName = PP[1];
                }
                else
                {
                    FieldName = PP[2];
                }

                cs.Append("/*! \\def "+FieldName.ToUpper()+cl);
                cs.Append("	\\brief Custom XML Element: Local Name"+cl);
                cs.Append("*/"+cl);
                cs.Append("#define " + FieldName.ToUpper() + " \"" + FieldName + "\""+cl);
                cs.Append("/*! \\def "+FieldName.ToUpper()+"_NAMESPACE"+cl);
                cs.Append("	\\brief Custom XML Element: Fully Qualified Namespace"+cl);
                cs.Append("*/"+cl);
                cs.Append("#define " + FieldName.ToUpper() + "_NAMESPACE \"" + FieldNameSpace + "\""+cl);
            }
            cs.Append(cl);
            foreach(object[] foo in this.CustomTagList)
            {
                PP[0] = (string)foo[0];
                string FieldName;
                string FieldNameSpace = (string)foo[1];

                if (PP.DCOUNT()==1)
                {
                    FieldName = PP[1];
                }
                else
                {
                    FieldName = PP[2];
                }
                cs.Append(" char *UPnPGetCustomXML_" + FieldName + "(struct UPnPDevice *d);"+cl);
            }
            WS = WS.Replace("//{{{CustomXMLTags}}}",cs.ToString());
            #endregion
            #endregion

            #region Prefixes
            WS = WS.Replace("UPnP/","upnp/");
            WS = WS.Replace("UPnPControlPointStructs.h","upnpcontrolpointstructs.h");
            WS = WS.Replace("UPnPDevice","upnpdevice");
            WS = WS.Replace("UPnPService","upnpservice");
            WS = WS.Replace("UPnPAction","upnpaction");
            WS = WS.Replace("UPnPStateVariable","upnpstatevariable");
            WS = WS.Replace("UPnPAllowedValue","upnpallowedvalue");
            WS = WS.Replace("DeviceDescriptionInterruptSink","devicedescriptioninterruptsink");
            WS = WS.Replace("DeviceExpired","deviceexpired");
            WS = WS.Replace("SubscribeForUPnPEvents","subscribeforupnpevents");
            WS = WS.Replace("UnSubscribeUPnPEvents","unsubscribeupnpevents");

            WS = WS.Replace("UPnP",this.pc_methodPrefix);
            WS = WS.Replace("ILib",this.pc_methodLibPrefix);

            WS = WS.Replace("upnp/","UPnP/");
            WS = WS.Replace("upnpaction","UPnPAction");
            WS = WS.Replace("upnpstatevariable","UPnPStateVariable");
            WS = WS.Replace("upnpallowedvalue","UPnPAllowedValue");
            WS = WS.Replace("devicedescriptioninterruptsink","DeviceDescriptionInterruptSink");
            WS = WS.Replace("deviceexpired","deviceexpired");
            WS = WS.Replace("upnpdevice","UPnPDevice");
            WS = WS.Replace("upnpservice","UPnPService");
            WS = WS.Replace("subscribeforupnpevents","SubscribeForUPnPEvents");
            WS = WS.Replace("unsubscribeupnpevents","UnSubscribeUPnPEvents");
            WS = WS.Replace("upnpcontrolpointstructs.h","UPnPControlPointStructs.h");

            #endregion

            #region Write to disk

            writer = File.CreateText(outputDirectory.FullName + "\\"+pc_methodPrefix+"ControlPoint.h");
            writer.Write(WS);
            writer.Close();
            #endregion

            #endregion
            #region UPnPControlPoint.c
            WS = SourceCodeRepository.GetControlPoint_C_Template(this.pc_methodPrefix);

            #region Event Callback Methods
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            en = SL.GetEnumerator();
            while(en.MoveNext())
            {
                UPnPService s = (UPnPService)en.Value;
                string name = (string)en.Key;
                foreach(UPnPStateVariable variable in s.GetStateVariables())
                {
                    if (variable.SendEvent == true)
                    {
                        cs.Append("void (*"+pc_methodPrefix+"EventCallback_"+name+"_"+variable.Name+")(struct UPnPService* Service,");
                        cs.Append(ToCType(variable.GetNetType().FullName)+" value");
                        if (variable.GetNetType()==typeof(byte[]))
                        {
                            cs.Append(", int valueLength");
                        }
                        cs.Append(");"+cl);
                    }
                }
            }
            WS = WS.Replace("//{{{EventCallbacks}}}",cs.ToString());
            #endregion
            #region GetDevice2 If Statement
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            cs.Append("if (strncmp(device->DeviceType,\""+device.DeviceURN_Prefix+"\","+device.DeviceURN_Prefix.Length.ToString()+")==0 && atoi(device->DeviceType+"+device.DeviceURN_Prefix.Length.ToString()+")>=1)"+cl);
            WS = WS.Replace("//{{{UPnPGetDevice2_if_statement}}}",cs.ToString());
            #endregion
            #region GetService Methods
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);

            en = SL.GetEnumerator();
            while(en.MoveNext())
            {
                UPnPService S = (UPnPService)en.Value;
                string name = (string)en.Key;
                cs.Append("/*! \\fn "+pc_methodPrefix+"GetService_"+name+"(struct UPnPDevice *device)"+cl);
                cs.Append("	\\brief Returns the "+name+" service from the specified device");
                cs.Append("	\\par"+cl);
                cs.Append("	Service Type = " + S.ServiceURN_Prefix.Substring(0,S.ServiceURN_Prefix.Length-1) + "<br>"+cl);
                cs.Append("	Version >= " + S.Version+cl);
                cs.Append("	\\param device The device object to query"+cl);
                cs.Append("	\\returns A pointer to the service object"+cl);
                cs.Append("*/"+cl);
                cs.Append("struct UPnPService *"+pc_methodPrefix+"GetService_"+name+"(struct UPnPDevice *device)"+cl);
                cs.Append("{"+cl);
                cs.Append("	return("+pc_methodPrefix+"GetService(device,\""+S.ServiceURN+"\","+S.ServiceURN.Length.ToString()+"));"+cl);
                cs.Append("}"+cl);
            }
            WS = WS.Replace("//{{{UPnPGetServiceMethods}}}",cs.ToString());
            #endregion
            #region GetDeviceCount If Statement
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            cs.Append("	if (strncmp(device->DeviceType,\"" + device.DeviceURN + "\","+device.DeviceURN.Length.ToString()+")==0)"+cl);
            cs.Append("	{"+cl);
            cs.Append("		++RetVal;"+cl);
            cs.Append("	}"+cl);
            WS = WS.Replace("//{{{GetDeviceCountIfStatement}}}",cs.ToString());
            #endregion
            #region Service Event Sink
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            Hashtable ES = new Hashtable();
            en.Reset();
            while(en.MoveNext())
            {
                UPnPService s = (UPnPService)en.Value;
                string sname = (string)en.Key;
                string surn = s.ServiceURN;
                surn = surn.Substring(0,surn.LastIndexOf(":"));
                if (ES.ContainsKey(surn)==false)
                {
                    ES[surn] = true;
                    BuildEventParser(cs,s,surn,sname);
                }
            }
            WS = WS.Replace("//{{{Service_EventSink}}}",cs.ToString());
            #endregion
            #region OnEvent_Sink If Statement
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);

            ES = new Hashtable();
            en.Reset();
            bool isfirst = true;
            while(en.MoveNext())
            {
                UPnPService s = (UPnPService)en.Value;
                string surn = s.ServiceURN;
                surn = surn.Substring(0,surn.LastIndexOf(":"));
                if (ES.ContainsKey(surn)==false)
                {
                    ES[surn] = true;
                    if (surn.StartsWith("urn:schemas-upnp-org:"))
                    {
                        // Standard Service
                        surn = surn.Substring(surn.LastIndexOf(":")+1);
                    }
                    else
                    {
                        // Proprietary Service
                        surn = surn.Replace(":","_");
                        surn = surn.Replace("-","_");
                        surn = surn.Replace(".","_");
                    }
                    if (isfirst == false) cs.Append("else"+cl);
                    cs.Append("if (type_length>"+s.ServiceURN.Substring(0,s.ServiceURN.LastIndexOf(":")+1).Length.ToString() + " && strncmp(\""+s.ServiceURN.Substring(0,s.ServiceURN.LastIndexOf(":")+1)+"\",service->ServiceType,"+s.ServiceURN.Substring(0,s.ServiceURN.LastIndexOf(":")+1).Length.ToString()+")==0)"+cl);
                    cs.Append("{"+cl);
                    cs.Append("	"+this.pc_methodPrefix+surn+"_EventSink(buffer, BufferSize, service);"+cl);
                    cs.Append("}"+cl);
                    isfirst = false;
                }
            }
            WS = WS.Replace("//{{{EventSink_IfStatement}}}",cs.ToString());
            #endregion

            #region CreateSSDPClient
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            cs.Append("	cp->SSDP = "+pc_methodLibPrefix+"CreateSSDPClientModule(Chain,\""+device.DeviceURN+"\", "+device.DeviceURN.Length.ToString()+", &"+pc_methodPrefix+"SSDP_Sink,cp);"+cl);
            WS = WS.Replace("//{{{CreateSSDPClientModule}}}",cs.ToString());
            #endregion

            #region Invocation Sink
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            en.Reset();
            while(en.MoveNext())
            {
                UPnPService S = (UPnPService)en.Value;
                string name = (string)en.Key;

                foreach(UPnPAction A in S.Actions)
                {
                    #region Invoke Sink Method
                    cs.Append("void "+pc_methodPrefixDef+"Invoke_"+name+"_"+A.Name+"_Sink(");

                    cs.Append(cl);
                    cs.Append("		void *WebReaderToken,"+cl);
                    cs.Append("		int IsInterrupt,"+cl);
                    cs.Append("		struct packetheader *header,"+cl);
                    cs.Append("		char *buffer,"+cl);
                    cs.Append("		int *p_BeginPointer,"+cl);
                    cs.Append("		int EndPointer,"+cl);
                    cs.Append("		int done,"+cl);
                    cs.Append("		void *_service,"+cl);
                    cs.Append("		void *state,"+cl);
                    cs.Append("		int *PAUSE)"+cl);

                    cs.Append("{"+cl);
                    cs.Append("	struct UPnPService *Service = (struct UPnPService*)_service;"+cl);
                    cs.Append("	struct InvokeStruct *_InvokeData = (struct InvokeStruct*)state;"+cl);
                    int NumArgs = 0;
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.IsReturnValue||Arg.Direction=="out") ++NumArgs;
                    }
                    if (NumArgs>0)
                    {
                        cs.Append("	int ArgLeft = "+NumArgs.ToString()+";"+cl);
                        cs.Append("	struct "+this.pc_methodLibPrefix+"XMLNode *xml;"+cl);
                        cs.Append("	struct "+this.pc_methodLibPrefix+"XMLNode *__xml;"+cl);
                        cs.Append("	char *tempBuffer;"+cl);
                        cs.Append("	int tempBufferLength;"+cl);

                        bool needlongvar = false;
                        bool needulongvar = false;
                        bool hascomplex = false;
                        foreach(UPnPArgument arg in A.Arguments)
                        {
                            if (arg.IsReturnValue || arg.Direction=="out")
                            {
                                if (arg.RelatedStateVar.ComplexType!=null)
                                {
                                    hascomplex = true;
                                }
                                switch(arg.RelatedStateVar.GetNetType().FullName)
                                {
                                    case "System.SByte":
                                    case "System.Int16":
                                    case "System.Int32":
                                        needlongvar = true;
                                        break;
                                    case "System.Byte":
                                    case "System.UInt16":
                                    case "System.UInt32":
                                        needulongvar = true;
                                        break;
                                }
                            }
                        }
                        if (needlongvar == true) cs.Append("long TempLong;"+cl);
                        if (needulongvar == true) cs.Append("unsigned long TempULong;"+cl);
                        if (hascomplex == true) cs.Append("struct "+this.pc_methodLibPrefix+"XMLNode *t_node;"+cl);
                        if (A.HasReturnValue)
                        {
                            cs.Append("	"+this.ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName)+" ");
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append("__");
                            }
                            cs.Append(A.GetRetArg().Name);
                            if (this.ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName).EndsWith("*"))
                            {
                                cs.Append(" = NULL");
                            }
                            else
                            {
                                cs.Append(" = 0");
                            }
                            cs.Append(";"+cl);
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append("	int __"+A.GetRetArg().Name+"Length=0;"+cl);
                            }
                        }
                        foreach(UPnPArgument arg in A.Arguments)
                        {
                            if (arg.Direction=="out" && !arg.IsReturnValue)
                            {
                                if (arg.RelatedStateVar.ComplexType==null)
                                {
                                    cs.Append("	"+ToCType(arg.RelatedStateVar.GetNetType().FullName)+" ");
                                    if (arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                    {
                                        cs.Append("__");
                                    }
                                    cs.Append(arg.Name);
                                    if (ToCType(arg.RelatedStateVar.GetNetType().FullName).EndsWith("*"))
                                    {
                                        cs.Append(" = NULL");
                                    }
                                    else
                                    {
                                        cs.Append(" = 0");
                                    }
                                    cs.Append(";"+cl);
                                    if (arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                    {
                                        cs.Append("	int __"+arg.Name+"Length = 0;"+cl);
                                    }
                                }
                                else
                                {
                                    // Complex Type
                                    cs.Append(" struct "+arg.RelatedStateVar.ComplexType.Name_LOCAL+"* "+arg.Name+";"+cl);
                                }
                            }
                        }
                        cs.Append("	LVL3DEBUG(char *DebugBuffer;)"+cl);
                        cs.Append(cl);

                        cs.Append("	UNREFERENCED_PARAMETER( WebReaderToken );" + cl);
                        cs.Append("	UNREFERENCED_PARAMETER( IsInterrupt );" + cl);
                        cs.Append("	UNREFERENCED_PARAMETER( PAUSE );" + cl);
                        cs.Append(cl);

                        cs.Append("	if (done == 0) return;"+cl);
                        cs.Append("	LVL3DEBUG(if ((DebugBuffer = (char*)malloc(EndPointer + 1)) == NULL) ILIBCRITICALEXIT(254);)" + cl);
                        cs.Append("	LVL3DEBUG(memcpy(DebugBuffer,buffer,EndPointer);)"+cl);
                        cs.Append("	LVL3DEBUG(DebugBuffer[EndPointer]=0;)"+cl);
                        cs.Append("	LVL3DEBUG(printf(\"\\r\\n SOAP Recieved:\\r\\n%s\\r\\n\",DebugBuffer);)"+cl);
                        cs.Append("	LVL3DEBUG(free(DebugBuffer);)"+cl);

                        cs.Append("	if (_InvokeData->CallbackPtr == NULL)"+cl);
                        cs.Append("	{"+cl);
                        cs.Append("		"+this.pc_methodPrefix+"Release(Service->Parent);"+cl);
                        cs.Append("		free(_InvokeData);"+cl);
                        //						cs.Append("		"+pc_methodLibPrefix+"CloseRequest(reader);"+cl);
                        cs.Append("		return;"+cl);
                        cs.Append("	}"+cl);
                        cs.Append("	else"+cl);
                        cs.Append("	{"+cl);
                        cs.Append("		if (header == NULL)"+cl);
                        cs.Append("		{"+cl);
                        cs.Comment("Connection Failed");
                        cs.Append("			((void (*)(struct UPnPService*,int,void*");
                        if (A.HasReturnValue)
                        {
                            cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName));
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName));
                            }
                        }
                        cs.Append("))_InvokeData->CallbackPtr)(Service,IsInterrupt==0?-1:IsInterrupt,_InvokeData->User");
                        if (A.HasReturnValue)
                        {
                            cs.Append(",INVALID_DATA");
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(",INVALID_DATA");
                            }
                        }
                        cs.Append(");"+cl);
                        cs.Append("			"+this.pc_methodPrefix+"Release(Service->Parent);"+cl);
                        cs.Append("			free(_InvokeData);"+cl);
                        //						cs.Append("			"+pc_methodLibPrefix+"CloseRequest(reader);"+cl);
                        cs.Append("			return;"+cl);
                        cs.Append("		}"+cl);
                        cs.Append("		else if (!ILibWebClientIsStatusOk(header->StatusCode))"+cl);
                        cs.Append("		{"+cl);
                        cs.Comment("SOAP Fault");
                        cs.Append("			((void (*)(struct UPnPService*,int,void*");
                        if (A.HasReturnValue)
                        {
                            cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName));
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(", "+ToCType(Arg.RelatedStateVar.GetNetType().FullName));
                            }
                        }
                        cs.Append("))_InvokeData->CallbackPtr)(Service, "+this.pc_methodPrefix+"GetErrorCode(buffer, EndPointer-(*p_BeginPointer)), _InvokeData->User");
                        if (A.HasReturnValue)
                        {
                            cs.Append(", INVALID_DATA");
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(", INVALID_DATA");
                            }
                        }
                        cs.Append(");"+cl);
                        cs.Append("			"+this.pc_methodPrefix+"Release(Service->Parent);"+cl);
                        cs.Append("			free(_InvokeData);"+cl);
                        cs.Append("			return;"+cl);
                        cs.Append("		}"+cl);
                        cs.Append("	}"+cl);
                        cs.Append(cl);

                        cs.Append("	__xml = xml = "+this.pc_methodLibPrefix+"ParseXML(buffer,0,EndPointer-(*p_BeginPointer));"+cl);
                        cs.Append("	if ("+this.pc_methodLibPrefix+"ProcessXMLNodeList(xml)==0)"+cl);
                        cs.Append("	{"+cl);
                        cs.Append("	while(xml != NULL)"+cl);
                        cs.Append("	{"+cl);
                        cs.Append("		if (xml->NameLength == "+(A.Name.Length+8).ToString()+" && memcmp(xml->Name, \"" + A.Name+"Response\", "+(A.Name.Length+8).ToString()+") == 0)"+cl);
                        cs.Append("		{"+cl);
                        cs.Append("			xml = xml->Next;"+cl);
                        cs.Append("			while(xml != NULL)"+cl);
                        cs.Append("			{"+cl);

                        bool IsFirst = true;
                        foreach(UPnPArgument arg in A.Arguments)
                        {
                            if (arg.IsReturnValue || arg.Direction=="out")
                            {
                                if (IsFirst == false) cs.Append("else "+cl);
                                cs.Append("					if (xml->NameLength == "+arg.Name.Length.ToString()+" && memcmp(xml->Name, \""+arg.Name+"\", "+arg.Name.Length.ToString()+") == 0)"+cl);
                                cs.Append("					{"+cl);
                                cs.Append("						--ArgLeft;"+cl);
                                if (arg.RelatedStateVar.ComplexType==null)
                                {
                                    cs.Append("						tempBufferLength = "+this.pc_methodLibPrefix+"ReadInnerXML(xml, &tempBuffer);"+cl);
                                    if (ToCType(arg.RelatedStateVar.GetNetType().FullName)=="char*")
                                    {
                                        cs.Append("						if (tempBufferLength != 0)"+cl);
                                        cs.Append("						{"+cl);
                                        cs.Append("							tempBuffer[tempBufferLength] = '\\0';"+cl);
                                        cs.Append("							"+arg.Name+" = tempBuffer;"+cl);
                                        if (arg.RelatedStateVar.GetNetType()==typeof(string))
                                        {
                                            cs.Append("							ILibInPlaceXmlUnEscape("+arg.Name+");"+cl);
                                        }
                                        cs.Append("						}"+cl);
                                    }
                                    else
                                    {
                                        switch(arg.RelatedStateVar.GetNetType().FullName)
                                        {
                                            case "System.Byte[]":
                                                cs.Append("								__"+arg.Name+"Length="+this.pc_methodLibPrefix+"Base64Decode(tempBuffer, tempBufferLength, &__"+arg.Name+");"+cl);
                                                break;
                                            case "System.Boolean":
                                                cs.Append("								"+arg.Name+" = 1;"+cl);
                                                cs.Append("								if (strncasecmp(tempBuffer, \"false\", 5)==0 || strncmp(tempBuffer, \"0\", 1)==0 || strncasecmp(tempBuffer, \"no\", 2) == 0)"+cl);
                                                cs.Append("								{"+cl);
                                                cs.Append("									"+arg.Name+" = 0;"+cl);
                                                cs.Append("								}"+cl);
                                                break;
                                            case "System.DateTime":
                                                cs.Append("								if (tempBufferLength!=0)"+cl);
                                                cs.Append("								{"+cl);
                                                cs.Append("									tempBuffer[tempBufferLength] = '\\0';"+cl);
                                                cs.Append("									"+arg.Name+" = "+this.pc_methodLibPrefix+"Time_Parse(tempBuffer);"+cl);
                                                cs.Append("								}"+cl);
                                                break;
                                            case "System.SByte":
                                            case "System.Int16":
                                            case "System.Int32":
                                                cs.Append("								if ("+this.pc_methodLibPrefix+"GetLong(tempBuffer,tempBufferLength,&TempLong)==0)"+cl);
                                                cs.Append("								{"+cl);
                                                cs.Append("									"+arg.Name+" = ("+ToCType(arg.RelatedStateVar.GetNetType().FullName)+") TempLong;"+cl);
                                                cs.Append("								}"+cl);
                                                break;
                                            case "System.Byte":
                                            case "System.UInt16":
                                            case "System.UInt32":
                                                cs.Append("								if ("+this.pc_methodLibPrefix+"GetULong(tempBuffer,tempBufferLength,&TempULong)==0)"+cl);
                                                cs.Append("								{"+cl);
                                                cs.Append("									"+arg.Name+" = ("+ToCType(arg.RelatedStateVar.GetNetType().FullName)+") TempULong;"+cl);
                                                cs.Append("								}"+cl);
                                                break;
                                        }
                                    }
                                }
                                else
                                {
                                    // Complex Type
                                    cs.Append("						if (!"+this.pc_methodPrefix+"IsLegacyDevice(header))"+cl);
                                    cs.Append("						{"+cl);
                                    cs.Append("							"+arg.Name+" = "+this.pc_methodPrefix+"Parse_"+arg.RelatedStateVar.ComplexType.Name_LOCAL+"(xml->Next);"+cl);
                                    cs.Append("						}"+cl);
                                    cs.Append("						else"+cl);
                                    cs.Append("						{"+cl);
                                    cs.Append("							tempBufferLength = "+this.pc_methodLibPrefix+"ReadInnerXML(xml,&tempBuffer);"+cl);
                                    cs.Append("							tempBufferLength = "+this.pc_methodLibPrefix+"InPlaceXmlUnEscape(tempBuffer);"+cl);
                                    cs.Append("							t_node = "+this.pc_methodLibPrefix+"ParseXML(tempBuffer,0,tempBufferLength);"+cl);
                                    cs.Append("							"+this.pc_methodLibPrefix+"ProcessXMLNodeList(t_node);"+cl);
                                    cs.Append("							"+arg.Name+" = "+this.pc_methodPrefix+"Parse_"+arg.RelatedStateVar.ComplexType.Name_LOCAL+"(t_node);"+cl);
                                    cs.Append("							"+this.pc_methodLibPrefix+"DestructXMLNodeList(t_node);"+cl);
                                    cs.Append("						}"+cl);
                                }
                                /*
                                if (ToCType(arg.RelatedStateVar.GetNetType().FullName)=="char*")
                                {
                                    cs.Append("							else"+cl);
                                    cs.Append("							{"+cl);
                                    cs.Append("								"+arg.Name+" = NULL;"+cl);
                                    cs.Append("							}"+cl);
                                }
                                */
                                //cs.Append("						}"+cl);
                                cs.Append("					}"+cl);
                                IsFirst = false;
                            }
                        }

                        cs.Append("			xml = xml->Peer;"+cl);
                        cs.Append("		  }"+cl);
                        cs.Append("     }"+cl);
                        cs.Append("		if (xml!=NULL) {xml = xml->Next;}"+cl);
                        cs.Append("	}"+cl);
                        cs.Append("	"+this.pc_methodLibPrefix+"DestructXMLNodeList(__xml);"+cl);
                        cs.Append("	}"+cl); // End of the if{} for ILibProcessXMLNodeList()
                    }
                    else
                    {
                        cs.Append("	UNREFERENCED_PARAMETER(WebReaderToken);" + cl);
                        cs.Append("	UNREFERENCED_PARAMETER(IsInterrupt);"+cl);
                        cs.Append("	UNREFERENCED_PARAMETER(PAUSE);"+cl);

                        cs.Append("	if (done == 0) return;"+cl);
                        //						cs.Append("	"+pc_methodLibPrefix+"CloseRequest(reader);"+cl);
                        cs.Append("	if (_InvokeData->CallbackPtr == NULL)"+cl);
                        cs.Append("	{"+cl);
                        cs.Append("		"+pc_methodPrefix+"Release(Service->Parent);"+cl);
                        cs.Append("		free(_InvokeData);"+cl);
                        //						cs.Append("		"+pc_methodLibPrefix+"CloseRequest(reader);"+cl);
                        cs.Append("		return;"+cl);
                        cs.Append("	}"+cl);
                        cs.Append("	else"+cl);
                        cs.Append("	{"+cl);
                        cs.Append("		if (header == NULL)"+cl);
                        cs.Append("		{"+cl);
                        cs.Comment("Connection Failed");
                        cs.Append("			((void (*)(struct UPnPService*,int,void*");
                        if (A.HasReturnValue)
                        {
                            cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName));
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(",int");
                            }
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName));
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(",int");
                                }
                            }
                        }
                        cs.Append("))_InvokeData->CallbackPtr)(Service,-1,_InvokeData->User");
                        if (A.HasReturnValue)
                        {
                            cs.Append(",INVALID_DATA");
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(",INVALID_DATA");
                            }
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(",INVALID_DATA");
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(",INVALID_DATA");
                                }
                            }
                        }
                        cs.Append(");"+cl);
                        cs.Append("			"+this.pc_methodPrefix+"Release(Service->Parent);"+cl);
                        cs.Append("			free(_InvokeData);"+cl);
                        //						cs.Append("			"+pc_methodLibPrefix+"CloseRequest(reader);"+cl);
                        cs.Append("			return;"+cl);
                        cs.Append("		}"+cl);
                        cs.Append("		else if (!ILibWebClientIsStatusOk(header->StatusCode))"+cl);
                        cs.Append("		{"+cl);
                        cs.Comment("SOAP Fault");
                        cs.Append("			((void (*)(struct UPnPService*,int,void*");
                        if (A.HasReturnValue)
                        {
                            cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName));
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(",int");
                            }
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName));
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(",int");
                                }
                            }
                        }
                        cs.Append("))_InvokeData->CallbackPtr)(Service,"+this.pc_methodPrefix+"GetErrorCode(buffer,EndPointer-(*p_BeginPointer)),_InvokeData->User");
                        if (A.HasReturnValue)
                        {
                            cs.Append(",INVALID_DATA");
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(",INVALID_DATA");
                            }
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(",INVALID_DATA");
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(",INVALID_DATA");
                                }
                            }
                        }
                        cs.Append(");"+cl);
                        cs.Append("			"+this.pc_methodPrefix+"Release(Service->Parent);"+cl);
                        cs.Append("			free(_InvokeData);"+cl);
                        cs.Append("			return;"+cl);
                        cs.Append("		}"+cl);

                        cs.Append("	}"+cl);
                    }
                    cs.Append(cl);
                    if (NumArgs>0)
                    {
                        cs.Append("	if (ArgLeft!=0)"+cl);
                        cs.Append("	{"+cl);
                        cs.Append("		((void (*)(struct UPnPService*,int,void*");
                        if (A.HasReturnValue)
                        {
                            cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName));
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(",int");
                            }
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName));
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(",int");
                                }
                            }
                        }
                        cs.Append("))_InvokeData->CallbackPtr)(Service,-2,_InvokeData->User");
                        if (A.HasReturnValue)
                        {
                            cs.Append(",INVALID_DATA");
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(",INVALID_DATA");
                            }
                        }
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (!Arg.IsReturnValue && Arg.Direction=="out")
                            {
                                cs.Append(",INVALID_DATA");
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(",INVALID_DATA");
                                }
                            }
                        }
                        cs.Append(");"+cl);
                        cs.Append("	}"+cl);

                        cs.Append("	else"+cl);
                        cs.Append("{"+cl);
                    }
                    cs.Append("		((void (*)(struct UPnPService*,int,void*");
                    if (A.HasReturnValue)
                    {
                        cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName));
                        if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                        {
                            cs.Append(",int");
                        }
                    }
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (!Arg.IsReturnValue && Arg.Direction=="out")
                        {
                            cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName));
                            if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(",int");
                            }
                        }
                    }
                    cs.Append("))_InvokeData->CallbackPtr)(Service,0,_InvokeData->User");
                    if (A.HasReturnValue)
                    {
                        if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                        {
                            cs.Append(",__"+A.GetRetArg().Name+",__"+A.GetRetArg().Name+"Length");
                        }
                        else
                        {
                            cs.Append(","+A.GetRetArg().Name);
                        }
                    }
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (!Arg.IsReturnValue && Arg.Direction=="out")
                        {
                            if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(",__"+Arg.Name+",__"+Arg.Name+"Length");
                            }
                            else
                            {
                                cs.Append(","+Arg.Name);
                            }
                        }
                    }
                    cs.Append(");"+cl);
                    if (NumArgs>0)
                    {
                        cs.Append("	}"+cl);
                    }
                    cs.Append("	"+this.pc_methodPrefix+"Release(Service->Parent);"+cl);
                    cs.Append("	free(_InvokeData);"+cl);
                    //					cs.Append("	"+pc_methodLibPrefix+"CloseRequest(reader);"+cl);
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.IsReturnValue || Arg.Direction=="out")
                        {
                            if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append("	if (__"+Arg.Name+"!=NULL)"+cl);
                                cs.Append("	{"+cl);
                                cs.Append("		free(__"+Arg.Name+");"+cl);
                                cs.Append("	}"+cl);
                            }
                        }
                    }
                    cs.Append("}"+cl);
                    #endregion
                }
            }
            WS = WS.Replace("//{{{Invocation_Sinks}}}",cs.ToString());
            #endregion
            #region Invocation Methods
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            en.Reset();
            while(en.MoveNext())
            {
                UPnPService S = (UPnPService)en.Value;
                ServiceGenerator.ServiceConfiguration SConf = (ServiceGenerator.ServiceConfiguration)S.User;

                string name = (string)en.Key;

                foreach(UPnPAction A in S.Actions)
                {
                    #region Invoke Method -- Doxygen Comments
                    cs.Append("/*! \\fn "+pc_methodPrefixDef+"Invoke_"+name+"_"+A.Name+"(struct UPnPService *service,void (*CallbackPtr)(struct UPnPService *sender,int ErrorCode,void *user");
                    if (A.HasReturnValue)
                    {
                        if (A.GetRetArg().RelatedStateVar.ComplexType==null)
                        {
                            // Non Complex Type
                            cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName)+" "+A.GetRetArg().Name);
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                // length
                                cs.Append(",int "+A.GetRetArg().Name+"Length");
                            }
                        }
                        else
                        {
                            // Complex Type
                            cs.Append(", struct " + A.GetRetArg().RelatedStateVar.ComplexType.Name_LOCAL+" *"+A.GetRetArg().Name);
                        }
                    }
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (!Arg.IsReturnValue && Arg.Direction=="out")
                        {
                            if (Arg.RelatedStateVar.ComplexType==null)
                            {
                                // NonComplex
                                cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName)+" " + Arg.Name);
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    //length
                                    cs.Append(",int "+Arg.Name+"Length");
                                }
                            }
                            else
                            {
                                // Complex
                                cs.Append(",struct " + Arg.RelatedStateVar.ComplexType.Name_LOCAL+"* "+Arg.Name);
                            }
                        }
                    }

                    cs.Append("), void *_user");
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in")
                        {
                            if (Arg.RelatedStateVar.ComplexType==null)
                            {
                                // Non Complex
                                cs.Append(", "+ToCType(Arg.RelatedStateVar.GetNetType().FullName)+" ");
                                if (Arg.RelatedStateVar.GetNetType()==typeof(string) && !SConf.Actions_ManualEscape.Contains(A))
                                {
                                    cs.Append("unescaped_");
                                }
                                cs.Append(Arg.Name);
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(", int " + Arg.Name+"Length");
                                }
                            }
                            else
                            {
                                // Complex
                                cs.Append(", struct " + Arg.RelatedStateVar.ComplexType.Name_LOCAL+"* _"+Arg.Name);
                            }
                        }
                    }
                    cs.Append(")"+cl);
                    cs.Append("	\\brief Invokes the "+A.Name+" action in the "+name+" service"+cl);
                    cs.Append("	\\param service The UPnPService instance to invoke the action on"+cl);
                    cs.Append("	\\param CallbackPtr The function pointer to be called when the invocation returns"+cl);
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in")
                        {
                            //
                            // Loop through the Arguments, so we can add comments for the
                            // in arguments
                            //
                            if (Arg.RelatedStateVar.ComplexType==null)
                            {
                                // Non Complex
                                cs.Append("	\\param ");
                                if (Arg.RelatedStateVar.GetNetType()==typeof(string) && !SConf.Actions_ManualEscape.Contains(A))
                                {
                                    cs.Append("unescaped_");
                                }
                                cs.Append(Arg.Name);
                                cs.Append(" Value of the "+Arg.Name+" parameter. ");
                                if (Arg.RelatedStateVar.GetNetType()==typeof(string))
                                {
                                    if (!SConf.Actions_ManualEscape.Contains(A))
                                    {
                                        // Automatic Escaping
                                        cs.Append(" <b>Automatically</b> escaped");
                                    }
                                    else
                                    {
                                        // User Must Escape
                                        cs.Append(" <b>MUST</b> be properly escaped.");
                                    }
                                    cs.Append(cl);
                                }
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append("	\\param "+Arg.Name+"Length Size of \\a "+Arg.Name+cl);
                                }
                            }
                            else
                            {
                                // Complex
                                cs.Append(" \\param _"+Arg.Name+" Value of the "+Arg.Name+" parameter. "+cl);
                            }
                        }
                    }
                    cs.Append("*/"+cl);
                    #endregion
                    #region Invoke Method -- Implementation
                    cs.Append("void "+pc_methodPrefixDef+"Invoke_"+name+"_"+A.Name+"(struct UPnPService *service,void (*CallbackPtr)(struct UPnPService *sender,int ErrorCode,void *user");
                    if (A.HasReturnValue)
                    {
                        if (A.GetRetArg().RelatedStateVar.ComplexType==null)
                        {
                            // Non Complex Type
                            cs.Append(","+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName)+" "+A.GetRetArg().Name);
                            if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                // length
                                cs.Append(",int "+A.GetRetArg().Name+"Length");
                            }
                        }
                        else
                        {
                            // Complex Type
                            cs.Append(", struct " + A.GetRetArg().RelatedStateVar.ComplexType.Name_LOCAL+" *"+A.GetRetArg().Name);
                        }
                    }
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (!Arg.IsReturnValue && Arg.Direction=="out")
                        {
                            if (Arg.RelatedStateVar.ComplexType==null)
                            {
                                // NonComplex
                                cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName)+" "+Arg.Name);
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    //length
                                    cs.Append(",int "+Arg.Name+"Length");
                                }
                            }
                            else
                            {
                                // Complex
                                cs.Append(",struct " + Arg.RelatedStateVar.ComplexType.Name_LOCAL+" *"+Arg.Name);
                            }
                        }
                    }

                    cs.Append("), void* user");
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in")
                        {
                            if (Arg.RelatedStateVar.ComplexType==null)
                            {
                                // Non Complex
                                cs.Append(", "+ToCType(Arg.RelatedStateVar.GetNetType().FullName)+" ");
                                if (Arg.RelatedStateVar.GetNetType()==typeof(string) && !SConf.Actions_ManualEscape.Contains(A))
                                {
                                    cs.Append("unescaped_");
                                }
                                cs.Append(Arg.Name);
                                if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(", int " + Arg.Name+"Length");
                                }
                            }
                            else
                            {
                                // Complex
                                cs.Append(", struct " + Arg.RelatedStateVar.ComplexType.Name_LOCAL+"* _"+Arg.Name);
                            }
                        }
                    }
                    cs.Append(")"+cl);
                    cs.Append("{"+cl);
                    cs.Append("	int headerLength;"+cl);
                    cs.Append("	char *headerBuffer;"+cl);
                    cs.Append("	char *SoapBodyTemplate;"+cl);
                    cs.Append("	char* buffer;"+cl);
                    cs.Append("	int bufferLength;"+cl);
                    cs.Append("	char* IP;"+cl);
                    cs.Append("	unsigned short Port;"+cl);
                    cs.Append("	char* Path;"+cl);
                    cs.Append("	size_t len;" + cl);
                    cs.Append("	struct InvokeStruct *invoke_data;" + cl);

                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in" && (Arg.RelatedStateVar.GetNetType()==typeof(DateTime) || Arg.RelatedStateVar.GetNetType()==typeof(byte[])))
                        {
                            cs.Append("	char* __"+Arg.Name+";"+cl);
                            if (Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append("	int __"+Arg.Name+"Length;"+cl);
                            }
                        }
                        else if (Arg.Direction=="in" && Arg.RelatedStateVar.GetNetType()==typeof(string) &&!SConf.Actions_ManualEscape.Contains(A))
                        {
                            cs.Append(" char* "+Arg.Name+";"+cl);
                        }
                        else if (Arg.Direction=="in" && Arg.RelatedStateVar.GetNetType()==typeof(bool))
                        {
                            cs.Append("	int __"+Arg.Name+";"+cl);
                        }
                    }
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in" && Arg.RelatedStateVar.ComplexType!=null)
                        {
                            // Need to Serialize complex type to XML
                            cs.Append("	char* " + Arg.Name + ";"+cl);
                        }
                    }
                    cs.Append("	if ((invoke_data = (struct InvokeStruct*)malloc(sizeof(struct InvokeStruct))) == NULL) ILIBCRITICALEXIT(254);" + cl);
                    cs.Append(cl);
                    cs.Append("	if (service == NULL)"+cl);
                    cs.Append("	{"+cl);
                    cs.Append("		free(invoke_data);"+cl);
                    cs.Append("		return;"+cl);
                    cs.Append("	}"+cl);
                    cs.Append(cl);
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in" && Arg.RelatedStateVar.ComplexType!=null)
                        {
                            // Need to Serialize complex type to XML
                            cs.Append("	"+Arg.Name + " = "+this.pc_methodPrefix+"Serialize_"+Arg.RelatedStateVar.ComplexType.Name_LOCAL+"(_"+Arg.Name+");"+cl);
                        }
                    }
                    cs.Append(cl);
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in" && Arg.RelatedStateVar.GetNetType()==typeof(bool))
                        {
                            cs.Append("	("+Arg.Name+"!=0)?(__"+Arg.Name+"=1):(__"+Arg.Name+"=0);"+cl);
                        }
                        if (Arg.Direction=="in" && Arg.RelatedStateVar.GetNetType()==typeof(DateTime))
                        {
                            cs.Append("	__"+Arg.Name+"="+this.pc_methodLibPrefix+"Time_Serialize("+Arg.Name+");"+cl);
                        }
                    }
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in" && Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                        {
                            cs.Append("	__"+Arg.Name+"Length = "+this.pc_methodLibPrefix+"Base64Encode("+Arg.Name+","+Arg.Name+"Length,&__"+Arg.Name+");"+cl);
                        }
                    }
                    if (!SConf.Actions_ManualEscape.Contains(A))
                    {
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (Arg.Direction=="in" && Arg.RelatedStateVar.GetNetType()==typeof(string))
                            {
                                cs.Append("	if ((" + Arg.Name + " = (char*)malloc(1 + ILibXmlEscapeLength(unescaped_" + Arg.Name + "))) == NULL) ILIBCRITICALEXIT(254);" + cl);
                                cs.Append("	ILibXmlEscape("+Arg.Name+",unescaped_"+Arg.Name+");"+cl);
                            }
                        }
                    }

                    string TotalBufferSizeDynamic = "(int)strlen(service->ServiceType)";
                    int TotalBufferSizeStatic = 232 + (A.Name.Length*2);
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in")
                        {
                            TotalBufferSizeStatic += (Arg.Name.Length*2)+5;
                            switch(Arg.RelatedStateVar.GetNetType().ToString())
                            {
                                case "System.Uri":
                                case "System.String":
                                    TotalBufferSizeDynamic += "+(int)strlen("+Arg.Name+")";
                                    break;
                                case "System.Boolean":
                                    TotalBufferSizeStatic += 5;
                                    break;
                                case "System.Char":
                                    TotalBufferSizeStatic += 4;
                                    break;
                                case "System.Byte[]":
                                    TotalBufferSizeDynamic += "+__"+Arg.Name+"Length";
                                    break;
                                case "System.Byte":
                                    TotalBufferSizeStatic += 3;
                                    break;
                                case "System.SByte":
                                    TotalBufferSizeStatic += 4;
                                    break;
                                case "System.Int16":
                                    TotalBufferSizeStatic += 6;
                                    break;
                                case "System.Int32":
                                    TotalBufferSizeStatic += 11;
                                    break;
                                case "System.Int64":
                                    TotalBufferSizeStatic += 21;
                                    break;
                                case "System.UInt16":
                                    TotalBufferSizeStatic += 5;
                                    break;
                                case "System.UInt32":
                                    TotalBufferSizeStatic += 10;
                                    break;
                                case "System.UInt64":
                                    TotalBufferSizeStatic += 20;
                                    break;
                                case "System.Single":
                                    TotalBufferSizeStatic += 40;
                                    break;
                                case "System.Double":
                                    TotalBufferSizeStatic += 50;
                                    break;
                                case "System.DateTime":
                                    TotalBufferSizeStatic += 20;
                                    break;
                            }
                        }
                    }

                    //cs.Append("	dxx = "+TotalBufferSizeDynamic+"+"+TotalBufferSizeStatic+";"+cl);
                    //cs.Append("	buffer = (char*)malloc(dxx);"+cl);

                    cs.Append("	len = " + TotalBufferSizeDynamic + "+" + TotalBufferSizeStatic + ";" + cl);
                    cs.Append("	if ((buffer = (char*)malloc(len)) == NULL) ILIBCRITICALEXIT(254);" + cl);

                    string bufferString = this.PrintfTransform(A.Name+" xmlns:u=\"%s\">");
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in")
                        {
                            bufferString += "<"+Arg.Name+">"+ToSPrintfType(Arg.RelatedStateVar.GetNetType().FullName)+"</"+Arg.Name+">";
                        }
                    }
                    cs.Append("	SoapBodyTemplate = \"%s" + bufferString + "</u:"+A.Name+"%s\";"+cl);

                    cs.Append("	bufferLength = snprintf(buffer, len, SoapBodyTemplate, UPNPCP_SOAP_BodyHead, service->ServiceType");
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in")
                        {
                            if (Arg.RelatedStateVar.GetNetType()==typeof(DateTime) || Arg.RelatedStateVar.GetNetType()==typeof(bool) || Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append(", __"+Arg.Name);
                            }
                            else
                            {
                                cs.Append(", "+Arg.Name);
                            }
                        }
                    }
                    cs.Append(", UPNPCP_SOAP_BodyTail);"+cl);

                    cs.Append("	LVL3DEBUG(printf(\"\\r\\n SOAP Sent: \\r\\n%s\\r\\n\",buffer);)"+cl);

                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in")
                        {
                            if (Arg.RelatedStateVar.GetNetType()==typeof(DateTime) || Arg.RelatedStateVar.GetNetType()==typeof(byte[]))
                            {
                                cs.Append("	free(__"+Arg.Name+");"+cl);
                            }
                        }
                    }
                    foreach(UPnPArgument Arg in A.Arguments)
                    {
                        if (Arg.Direction=="in" && Arg.RelatedStateVar.ComplexType!=null)
                        {
                            // Need to Serialize complex type to XML
                            cs.Append("	free(" + Arg.Name + ");"+cl);
                        }
                    }
                    if (!SConf.Actions_ManualEscape.Contains(A))
                    {
                        foreach(UPnPArgument Arg in A.Arguments)
                        {
                            if (Arg.Direction=="in" && Arg.RelatedStateVar.GetNetType()==typeof(string))
                            {
                                cs.Append("	free(" + Arg.Name + ");"+cl);
                            }
                        }
                    }
                    cs.Append(cl);
                    cs.Append("	"+pc_methodPrefix+"AddRef(service->Parent);"+cl);
                    cs.Append("	"+pc_methodLibPrefix+"ParseUri(service->ControlURL, &IP, &Port, &Path, NULL);"+cl);
                    cs.Append(cl);

                    cs.Append("	len = " + (10+A.Name.Length+96+15+UseInfoString.Length) + " + (int)strlen("+this.pc_methodPrefix+"PLATFORM) + (int)strlen(Path) + (int)strlen(IP) + (int)strlen(service->ServiceType);"+cl);
                    cs.Append("	if ((headerBuffer = (char*)malloc(len)) == NULL) ILIBCRITICALEXIT(254);" + cl);
                    //cs.Append(" dxx = " + (A.Name.Length+96) + " + (int)strlen(service->ServiceType) + (int)strlen(Path) + (int)strlen(IP) + (int)strlen(service->ServiceType);");
                    //cs.Append("	headerBuffer = (char*)malloc(dxx);"+cl);
                    cs.Append("	headerLength = snprintf(headerBuffer, len, UPNPCP_SOAP_Header, Path, IP, Port, "+this.pc_methodPrefix+"PLATFORM, service->ServiceType, \""+A.Name+"\", bufferLength);"+cl);

                    cs.Append(cl);
                    cs.Append("	invoke_data->CallbackPtr = (voidfp)CallbackPtr;"+cl);
                    cs.Append("	invoke_data->User = user;"+cl);
                    cs.Append("	//"+this.pc_methodLibPrefix+"WebClient_SetQosForNextRequest(((struct "+this.pc_methodPrefix+"CP*)service->Parent->CP)->HTTP, "+this.pc_methodPrefix+"InvocationPriorityLevel);"+cl);
                    cs.Append("	"+this.pc_methodLibPrefix+"WebClient_PipelineRequestEx("+cl);
                    cs.Append("		((struct "+this.pc_methodPrefix+"CP*)service->Parent->CP)->HTTP,"+cl);
                    cs.Append("		(struct sockaddr*)&(service->Parent->LocationAddr)," + cl);
                    cs.Append("		headerBuffer,"+cl);
                    cs.Append("		headerLength,"+cl);
                    cs.Append("		0,"+cl);
                    cs.Append("		buffer,"+cl);
                    cs.Append("		bufferLength,"+cl);
                    cs.Append("		0,"+cl);
                    cs.Append("		&"+pc_methodPrefix+"Invoke_"+name+"_"+A.Name+"_Sink,"+cl);
                    cs.Append("		service,"+cl);
                    cs.Append("		invoke_data);"+cl);

                    cs.Append(cl);
                    cs.Append("	free(IP);"+cl);
                    cs.Append("	free(Path);"+cl);
                    cs.Append("}"+cl);
                    #endregion
                }
            }
            WS = WS.Replace("//{{{Invocation_Methods}}}",cs.ToString());
            #endregion

            #region Custom XML Tags in Device Description
            #region Custom Processing
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            OkToDo = false;
            foreach(object[] foo in this.CustomTagList)
            {
                PP[0] = (string)foo[0];

                string FieldName;
                string FieldNameSpace = (string)foo[1];

                if (PP.DCOUNT()==1)
                {
                    FieldName = PP[1];
                }
                else
                {
                    FieldName = PP[2];
                }
                OkToDo = true;

                cs.Append("if (xml->NameLength == "+FieldName.Length.ToString()+" && memcmp(xml->Name, \""+FieldName+"\", "+FieldName.Length.ToString()+") == 0)"+cl);
                cs.Append("{"+cl);
                cs.Append("	tempString = ILibXML_LookupNamespace(xml, xml->NSTag, xml->NSLength);"+cl);
                cs.Append("	if (strcmp(tempString,\""+FieldNameSpace+"\")==0)"+cl);
                cs.Append("	{"+cl);
                cs.Append("		tempStringLength = ILibReadInnerXML(xml,&tempString);"+cl);
                cs.Append("		if ((tempString2 = (char*)malloc(tempStringLength + 1)) == NULL) ILIBCRITICALEXIT(254);" + cl);
                cs.Append("		memcpy(tempString2, tempString, tempStringLength);"+cl);
                cs.Append("		tempString2[tempStringLength] = 0;"+cl);
                cs.Append("		if (ILibGetEntry(device->CustomTagTable, \""+FieldNameSpace+"\", "+FieldNameSpace.Length.ToString()+") == NULL)"+cl);
                cs.Append("		{"+cl);
                cs.Append("			ILibAddEntry(device->CustomTagTable, \""+FieldNameSpace+"\", "+FieldNameSpace.Length.ToString()+", ILibInitHashTree());"+cl);
                cs.Append("		}"+cl);
                cs.Append("		ILibAddEntry(ILibGetEntry(device->CustomTagTable, \""+FieldNameSpace+"\", "+FieldNameSpace.Length.ToString()+"), xml->Name, xml->NameLength, tempString2);"+cl);
                cs.Append("	}"+cl);
                cs.Append("} "+cl);
                cs.Append("else"+cl);
            }

            WS = WS.Replace("//{{{CustomXMLTags}}}",cs.ToString());
            if (OkToDo)
            {
                WS = SourceCodeRepository.RemoveTag("//{{{BEGIN_CustomTagSpecific}}}","//{{{END_CustomTagSpecific}}}",WS);
            }
            else
            {
                WS = SourceCodeRepository.RemoveAndClearTag("//{{{BEGIN_CustomTagSpecific}}}","//{{{END_CustomTagSpecific}}}",WS);
            }
            #endregion
            #region HasXXX
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            foreach(object[] foo in this.CustomTagList)
            {
                PP[0] = (string)foo[0];
                string FieldName;
                string FieldNameSpace = (string)foo[1];

                if (PP.DCOUNT()==1)
                {
                    FieldName = PP[1];
                }
                else
                {
                    FieldName = PP[2];
                }

                cs.Append("	/*! \\fn UPnPGetCustomXML_" + FieldName + "(struct UPnPDevice *d)"+cl);
                cs.Append("	\\brief Obtains the meta data associated with \\a "+FieldName.ToUpper()+" and "+FieldName.ToUpper()+"_NAMESPACE"+cl);
                cs.Append("	\\param d The UPnPDevice to query"+cl);
                cs.Append("	\\returns The associated meta-data. NULL if this tag was not present on the device"+cl);
                cs.Append("*/"+cl);
                cs.Append("char* UPnPGetCustomXML_" + FieldName + "(struct UPnPDevice *d)"+cl);
                cs.Append("{"+cl);
                cs.Append("	return(UPnPGetCustomTagFromDevice(d,"+FieldName.ToUpper()+"_NAMESPACE, "+FieldName.ToUpper()+"));"+cl);
                cs.Append("}"+cl);
            }
            WS = WS.Replace("//{{{CustomXMLTags2}}}",cs.ToString());
            #endregion
            #endregion

            #region Complex Types
            cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
            EmbeddedCGenerator.BuildComplexTypeParser(SequenceTable,ChoiceTable,cs,SL,this.pc_methodPrefix,this.pc_methodLibPrefix);
            BuildComplexTypeSerializer(SequenceTable,ChoiceTable,cs,SL,this.pc_methodPrefix,this.pc_methodLibPrefix);
            WS = WS.Replace("//{{{UPnPComplexTypes}}}",cs.ToString());
            #endregion

            #region Version Information
            if (!Configuration.HTTP_1dot1)
            {
                WS = WS.Replace("!HTTPVERSION!","1.0");
                WS = SourceCodeRepository.RemoveAndClearTag("//{{{ REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT--> }}}","//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}}",WS);
            }
            else
            {
                WS = WS.Replace("!HTTPVERSION!","1.1");
                WS = SourceCodeRepository.RemoveTag("//{{{ REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT--> }}}","//{{{ <--REMOVE_THIS_FOR_HTTP/1.0_ONLY_SUPPORT }}}",WS);
            }
            WS = WS.Replace("!MICROSTACKVERSION!",this.UseVersion);
            if (device.ArchitectureVersion=="1.0")
            {
                WS = WS.Replace("!UPNPVERSION!","1.0");
            }
            else
            {
                WS = WS.Replace("!UPNPVERSION!","1.1");
            }
            #endregion

            #region Prefixes
            WS = this.FixPrefix_DeviceService(device,WS);
            WS = WS.Replace("UPnP/","upnp/");
            WS = WS.Replace("UPnPControlPointStructs.h","upnpcontrolpointstructs.h");
            WS = WS.Replace("UPnPDevice","upnpdevice");
            WS = WS.Replace("UPnPService","upnpservice");
            WS = WS.Replace("UPnPAction","upnpaction");
            WS = WS.Replace("UPnPStateVariable","upnpstatevariable");
            WS = WS.Replace("UPnPAllowedValue","upnpallowedvalue");
            WS = WS.Replace("DeviceDescriptionInterruptSink","devicedescriptioninterruptsink");
            WS = WS.Replace("DeviceExpired","deviceexpired");
            WS = WS.Replace("SubscribeForUPnPEvents","subscribeforupnpevents");
            WS = WS.Replace("UnSubscribeUPnPEvents","unsubscribeupnpevents");
            WS = WS.Replace("UPnPSSDP_NOTIFY","upnpssdpnotify");
            WS = WS.Replace("UPnPSSDP_MSEARCH","upnpssdpmsearch");
            WS = WS.Replace("UPnPSSDP_MESSAGE","upnpssdpmessage");
            WS = WS.Replace(" UPnP "," _upnp_ ");
            WS = WS.Replace(" UPnPIcon","_upnpicon_");

            WS = WS.Replace("UPnP",this.pc_methodPrefix);
            WS = WS.Replace("\"" + this.pc_methodPrefix + "Error\"", "\"UPnPError\""); // There is one case where we have to turn the string back to "UPnPError", canceling the change made the line before
            WS = WS.Replace("ILib",this.pc_methodLibPrefix);

            WS = WS.Replace(" _upnp_ "," UPnP ");
            WS = WS.Replace("upnp/","UPnP/");
            WS = WS.Replace("upnpaction","UPnPAction");
            WS = WS.Replace("upnpstatevariable","UPnPStateVariable");
            WS = WS.Replace("upnpallowedvalue","UPnPAllowedValue");
            WS = WS.Replace("devicedescriptioninterruptsink","DeviceDescriptionInterruptSink");
            WS = WS.Replace("deviceexpired","deviceexpired");
            WS = WS.Replace("upnpdevice","UPnPDevice");
            WS = WS.Replace("upnpservice","UPnPService");
            WS = WS.Replace("subscribeforupnpevents","SubscribeForUPnPEvents");
            WS = WS.Replace("unsubscribeupnpevents","UnSubscribeUPnPEvents");
            WS = WS.Replace("upnpcontrolpointstructs.h","UPnPControlPointStructs.h");
            WS = WS.Replace("upnpssdpnotify","UPnPSSDP_NOTIFY");
            WS = WS.Replace("upnpssdpmsearch","UPnPSSDP_MSEARCH");
            WS = WS.Replace("upnpssdpmessage","UPnPSSDP_MESSAGE");
            WS = WS.Replace("_upnpicon_"," UPnPIcon");
            WS = this.FixPrefix2_DeviceService(device,WS);

            #endregion

            #region Reformat String
            WS = CodeProcessor.ProcessCode(WS,Indent);
            #endregion

            #region Write to disk

            writer = File.CreateText(outputDirectory.FullName + "\\"+pc_methodPrefix+"ControlPoint.c");
            writer.Write(WS);
            writer.Close();
            #endregion

            #endregion

            #region Sample Application

            #region Main.c / SampleProjectDlg.cpp
            if (SampleApp!=null)
            {
                WS = SampleApp;

                #region ControlPoint Variable
                WS = WS.Replace("//{{{MICROSTACK_VARIABLE}}}","//{{{MICROSTACK_VARIABLE}}}"+cl+"void *UPnP_CP = NULL;");
                #endregion
                #region CreateControlPoint
                if (!Configuration.BareBonesSample)
                {
                    tmp = "\tUPnP_CP = UPnPCreateControlPoint(MicroStackChain,&UPnPDeviceDiscoverSink,&UPnPDeviceRemoveSink);"+cl;
                    tmp = tmp.Replace("UPnP",((ServiceGenerator.Configuration)device.User).Prefix);
                    WS = SourceCodeRepository.InsertTextBeforeTag(WS,"//{{{CreateControlPoint}}}",tmp);
                }
                #endregion
                #region ControlPoint Includes
                WS = SourceCodeRepository.InsertTextBeforeTag(WS,"//{{{MicroStack_Include}}}","#include \""+this.pc_methodPrefix+"ControlPoint.h\""+cl);
                #endregion
                #region Discover/Remove Sink
                if (!Configuration.BareBonesSample)
                {
                    tmp = SourceCodeRepository.GetTextBetweenTags(WS,"//{{{BEGIN_CP_DISCOVER_REMOVE_SINK}}}","//{{{END_CP_DISCOVER_REMOVE_SINK}}}");
                    tmp = tmp.Replace("{{{PREFIX}}}", this.pc_methodPrefix);
                    #region Sample Invocations
                    cs = new CodeProcessor(new StringBuilder(), this.Language == LANGUAGES.CPP);
                    cs.ident = 1;
                    Build_SampleInvoke(device, cs, serviceNames);
                    tmp = tmp.Replace("//{{{CP_SampleInvoke}}}", cs.ToString());
                    #endregion
                    WS = SourceCodeRepository.InsertTextBeforeTag(WS,"//{{{BEGIN_CP_DISCOVER_REMOVE_SINK}}}",tmp);
                }
                #endregion

                #region IPAddress Monitor
                if (Configuration.DefaultIPAddressMonitor)
                {
                    WS = WS.Replace("//{{{IPAddress_Changed}}}","//{{{IPAddress_Changed}}}"+cl+"    UPnP_CP_IPAddressListChanged(UPnP_CP);");

                    if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_WINSOCK2)
                    {
                        WS = SourceCodeRepository.RemoveTag("//{{{BEGIN_WINSOCK2_IPADDRESS_MONITOR}}}","//{{{END_WINSOCK2_IPADDRESS_MONITOR}}}",WS);
                        WS = SourceCodeRepository.RemoveAndClearTag("//{{{BEGIN_POSIX/WINSOCK1_IPADDRESS_MONITOR}}}","//{{{END_POSIX/WINSOCK1_IPADDRESS_MONITOR}}}",WS);
                    }
                    else
                    {
                        WS = SourceCodeRepository.RemoveTag("//{{{BEGIN_POSIX/WINSOCK1_IPADDRESS_MONITOR}}}","//{{{END_POSIX/WINSOCK1_IPADDRESS_MONITOR}}}",WS);
                        WS = SourceCodeRepository.RemoveAndClearTag("//{{{BEGIN_WINSOCK2_IPADDRESS_MONITOR}}}","//{{{END_WINSOCK2_IPADDRESS_MONITOR}}}",WS);
                    }
                }
                else
                {
                    WS = WS.Replace("//{{{IPAddress_Changed}}}","");
                    WS = SourceCodeRepository.RemoveAndClearTag("//{{{BEGIN_WINSOCK2_IPADDRESS_MONITOR}}}","//{{{END_WINSOCK2_IPADDRESS_MONITOR}}}",WS);
                    WS = SourceCodeRepository.RemoveAndClearTag("//{{{BEGIN_POSIX/WINSOCK1_IPADDRESS_MONITOR}}}","//{{{END_POSIX/WINSOCK1_IPADDRESS_MONITOR}}}",WS);
                }
                #endregion

                #region Invoke Sink
                if (!Configuration.BareBonesSample)
                {
                    cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
                    en = SL.GetEnumerator();
                    while(en.MoveNext())
                    {
                        UPnPService s = (UPnPService)en.Value;
                        string name = (string)en.Key;
                        foreach(UPnPAction A in s.Actions)
                        {
                            #region ResponseSink
                            #region Header
                            cs.Append("void "+pc_methodPrefix+"ResponseSink_"+name+"_"+A.Name+"(struct UPnPService* Service, int ErrorCode, void *User");
                            if (A.HasReturnValue)
                            {
                                cs.Append(", "+ToCType(A.GetRetArg().RelatedStateVar.GetNetType().FullName)+" "+A.GetRetArg().Name);
                                if (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(Byte[]))
                                {
                                    cs.Append(", int "+A.GetRetArg().Name+"Length");
                                }
                            }
                            foreach(UPnPArgument Arg in A.Arguments)
                            {
                                if (!Arg.IsReturnValue && Arg.Direction=="out")
                                {
                                    cs.Append(","+ToCType(Arg.RelatedStateVar.GetNetType().FullName)+" "+Arg.Name);
                                    if (Arg.RelatedStateVar.GetNetType()==typeof(Byte[]))
                                    {
                                        cs.Append(", int " + Arg.Name+"Length");
                                    }
                                }
                            }
                            cs.Append(")"+cl);
                            #endregion
                            #region Body
                            cs.Append("{"+cl);
                            cs.Append(" UNREFERENCED_PARAMETER( Service );" + cl);
                            cs.Append(" UNREFERENCED_PARAMETER( User );" + cl);
                            cs.Append(cl);

                            if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                            {
                                #region PocketPC Specific
                                cs.Append("	CString display;"+cl);
                                if (A.HasReturnValue && (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(string)||
                                    A.GetRetArg().RelatedStateVar.GetNetType()==typeof(Uri)))
                                {
                                    cs.Append("	wchar_t *wc_"+A.GetRetArg().Name+"=NULL;"+cl);
                                    cs.Append("	int wc_"+A.GetRetArg().Name+"Length=0;"+cl);
                                }
                                foreach (UPnPArgument Arg in A.Arguments)
                                {
                                    if (Arg.Direction=="out" && !Arg.IsReturnValue && (Arg.RelatedStateVar.GetNetType()==typeof(string)||
                                        Arg.RelatedStateVar.GetNetType()==typeof(Uri)))
                                    {
                                        cs.Append("	wchar_t *wc_"+Arg.Name+" = NULL;"+cl);
                                        cs.Append("	int wc_"+Arg.Name+"Length = 0;"+cl);
                                    }
                                }
                                cs.Append(cl);
                                foreach (UPnPArgument Arg in A.Arguments)
                                {
                                    if (Arg.Direction=="out" && (Arg.RelatedStateVar.GetNetType()==typeof(string)||
                                        Arg.RelatedStateVar.GetNetType()==typeof(Uri)))
                                    {
                                        cs.Append("	if ("+Arg.Name+" != NULL)"+cl);
                                        cs.Append("	{"+cl);
                                        cs.Append("		wc_"+Arg.Name+"Length = MultiByteToWideChar(CP_UTF8, 0, "+Arg.Name+", -1, wc_"+Arg.Name+", 0);"+cl);
                                        cs.Append("		if ((wc_" + Arg.Name + " = (wchar_t*)malloc(sizeof(wchar_t)*wc_" + Arg.Name + "Length)) == NULL) ILIBCRITICALEXIT(254);" + cl);
                                        cs.Append("		MultiByteToWideChar(CP_UTF8, 0, "+Arg.Name+", -1, wc_"+Arg.Name+", wc_"+Arg.Name+"Length);"+cl);
                                        cs.Append("	}"+cl);
                                    }
                                }
                                cs.Append(cl);
                            }
                            #endregion

                            if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                            {
                                cs.Append("	 display.Format(_T(\""+pc_methodPrefix+" Invoke Response: "+ name + "/" + A.Name + "[ErrorCode:%d](");
                            }
                            else
                            {
                                cs.Append("	 printf(\""+pc_methodPrefix+" Invoke Response: "+ name + "/" + A.Name + "[ErrorCode:%d](");
                            }
                            bool firstag = true;
                            if (A.HasReturnValue)
                            {
                                cs.Append(ToPrintfType(A.GetRetArg().RelatedStateVar.GetNetType().FullName));
                                firstag = false;
                            }
                            foreach(UPnPArgument Arg in A.Arguments)
                            {
                                if (!Arg.IsReturnValue && Arg.Direction=="out")
                                {
                                    if (firstag==false)
                                    {
                                        cs.Append(",");
                                    }
                                    cs.Append(ToPrintfType(Arg.RelatedStateVar.GetNetType().FullName));
                                    firstag = false;
                                }
                            }
                            if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                            {
                                cs.Append(")\\r\\n\")");
                            }
                            else
                            {
                                cs.Append(")\\r\\n\"");
                            }
                            cs.Append(",ErrorCode");
                            if (A.HasReturnValue == true)
                            {
                                if (	Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC &&
                                    (A.GetRetArg().RelatedStateVar.GetNetType()==typeof(string)||
                                    A.GetRetArg().RelatedStateVar.GetNetType()==typeof(Uri)))
                                {
                                    cs.Append(",wc_" + A.GetRetArg().Name);
                                }
                                else
                                {
                                    cs.Append("," + A.GetRetArg().Name);
                                }
                            }
                            foreach (UPnPArgument Arg in A.Arguments)
                            {
                                if (!Arg.IsReturnValue && Arg.Direction=="out")
                                {
                                    if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC &&
                                        (Arg.RelatedStateVar.GetNetType()==typeof(string)||
                                        Arg.RelatedStateVar.GetNetType()==typeof(Uri)))
                                    {
                                        cs.Append(",wc_" + Arg.Name);
                                    }
                                    else
                                    {
                                        cs.Append("," + Arg.Name);
                                    }
                                }
                            }
                            cs.Append(");"+cl);

                            if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                            {
                                cs.Append("	if (that->m_Text.GetLength() > 16384)"+cl);
                                cs.Append("	{"+cl);
                                cs.Append("		that->m_Text = display;"+cl);
                                cs.Append("	}"+cl);
                                cs.Append("	else"+cl);
                                cs.Append("	{"+cl);
                                cs.Append("		that->m_Text += display;"+cl);
                                cs.Append("	}"+cl);
                                cs.Append("	that->SendMessage(WM_USER_UPDATE);"+cl);

                                foreach (UPnPArgument Arg in A.Arguments)
                                {
                                    if (Arg.Direction=="out" && (Arg.RelatedStateVar.GetNetType()==typeof(string)||
                                        Arg.RelatedStateVar.GetNetType()==typeof(Uri)))
                                    {
                                        cs.Append("	if (wc_"+Arg.Name+"!=NULL) {free(wc_"+Arg.Name+");}"+cl);
                                    }
                                }
                            }

                            cs.Append("}"+cl);
                            cs.Append(cl);
                            #endregion
                            #endregion
                        }
                    }
                    WS = WS.Replace("//{{{CP_InvokeSink}}}","//{{{CP_InvokeSink}}}"+cl+cs.ToString());
                }
                #endregion
                #region Event Sink
                if (!Configuration.BareBonesSample)
                {
                    cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);
                    en = SL.GetEnumerator();
                    while(en.MoveNext())
                    {
                        UPnPService s = (UPnPService)en.Value;
                        string name = (string)en.Key;
                        foreach(UPnPStateVariable variable in s.GetStateVariables())
                        {
                            if (variable.SendEvent == true)
                            {
                                #region Event Sink
                                cs.Append("void "+pc_methodPrefix+"EventSink_"+name+"_"+variable.Name+"(struct UPnPService* Service,");
                                cs.Append(ToCType(variable.GetNetType().FullName)+" "+variable.Name);
                                if (variable.GetNetType()==typeof(byte[]))
                                {
                                    cs.Append(",int " + variable.Name+"Length");
                                }
                                cs.Append(")"+cl);
                                cs.Append("{"+cl);
                                if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                                {
                                    #region PocketPC Specific
                                    cs.Append("	CString display;"+cl);
                                    cs.Append("	wchar_t *FriendlyName = NULL;"+cl);
                                    cs.Append("	int FriendlyNameLength = 0;"+cl);
                                    if (variable.GetNetType()==typeof(string)||
                                        variable.GetNetType()==typeof(Uri))
                                    {
                                        cs.Append("	wchar_t *wc_var = NULL;"+cl);
                                        cs.Append("	int wc_varLength = 0;"+cl);
                                    }

                                    cs.Append(cl);
                                    cs.Append("	if (Service->Parent->FriendlyName!=NULL)"+cl);
                                    cs.Append("	{"+cl);
                                    cs.Append("		FriendlyNameLength = MultiByteToWideChar(CP_UTF8, 0, Service->Parent->FriendlyName, -1, FriendlyName, 0);"+cl);
                                    cs.Append("		if ((FriendlyName = (wchar_t*)malloc(sizeof(wchar_t)*FriendlyNameLength)) == NULL) ILIBCRITICALEXIT(254);" + cl);
                                    cs.Append("		MultiByteToWideChar(CP_UTF8, 0, Service->Parent->FriendlyName, -1, FriendlyName, FriendlyNameLength);"+cl);
                                    cs.Append("	}"+cl);
                                    #endregion
                                }

                                if (variable.GetNetType()==typeof(byte[]))
                                {
                                    if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                                    {
                                        cs.Append("	 display.Format(_T(\""+pc_methodPrefix+" Event from %s/"+name+"/"+variable.Name+": [BINARY:%d]\\r\\n\"),FriendlyName, "+variable.Name+"Length);"+cl);
                                    }
                                    else
                                    {
                                        cs.Append("	 printf(\""+pc_methodPrefix+" Event from %s/"+name+"/"+variable.Name+": [BINARY:%d]\\r\\n\", Service->Parent->FriendlyName, "+variable.Name+"Length);"+cl);
                                    }
                                }
                                else if (variable.GetNetType()==typeof(string)||variable.GetNetType()==typeof(Uri))
                                {
                                    cs.Append("	if ("+variable.Name+"!=NULL)"+cl);
                                    cs.Append("	{"+cl);
                                    if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                                    {
                                        cs.Append("		wc_varLength = MultiByteToWideChar(CP_UTF8, 0, "+variable.Name+", -1, wc_var, 0);"+cl);
                                        cs.Append("		if ((wc_var = (wchar_t*)malloc(sizeof(wchar_t)*wc_varLength)) == NULL) ILIBCRITICALEXIT(254);" + cl);
                                        cs.Append("		MultiByteToWideChar(CP_UTF8,0,"+variable.Name+",-1,wc_var,wc_varLength);"+cl);
                                        cs.Append("		display.Format(_T(\""+pc_methodPrefix+" Event from %s/"+name+"/"+variable.Name+": %s\\r\\n\"), FriendlyName, wc_var);"+cl);
                                    }
                                    else
                                    {
                                        cs.Append("		printf(\""+pc_methodPrefix+" Event from %s/"+name+"/"+variable.Name+": %s\\r\\n\", Service->Parent->FriendlyName, "+variable.Name+");"+cl);
                                    }
                                    cs.Append("	}"+cl);
                                }
                                else
                                {
                                    if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                                    {
                                        cs.Append("	 display.Format(_T(\""+pc_methodPrefix+" Event from %s/"+name+"/"+variable.Name+": " + ToPrintfType(variable.GetNetType().FullName) + "\\r\\n\"),FriendlyName,"+variable.Name+");"+cl);
                                    }
                                    else
                                    {
                                        cs.Append("	 printf(\""+pc_methodPrefix+" Event from %s/"+name+"/"+variable.Name+": " + ToPrintfType(variable.GetNetType().FullName) + "\\r\\n\",Service->Parent->FriendlyName,"+variable.Name+");"+cl);
                                    }
                                }
                                if (Configuration.TargetPlatform==ServiceGenerator.PLATFORMS.MICROSTACK_POCKETPC)
                                {
                                    #region PocketPC Specific
                                    cs.Append("	if (that->m_Text.GetLength() > 16384)"+cl);
                                    cs.Append("	{"+cl);
                                    cs.Append("		that->m_Text = display;"+cl);
                                    cs.Append("	}"+cl);
                                    cs.Append("	else"+cl);
                                    cs.Append("	{"+cl);
                                    cs.Append("		that->m_Text += display;"+cl);
                                    cs.Append("	}"+cl);
                                    cs.Append("	that->SendMessage(WM_USER_UPDATE);"+cl);
                                    cs.Append("	if (FriendlyName!=NULL) {free(FriendlyName);}"+cl);
                                    if (variable.GetNetType()==typeof(string)||variable.GetNetType()==typeof(Uri))
                                    {
                                        cs.Append("	if (wc_var!=NULL) {free(wc_var);}"+cl);
                                    }
                                    #endregion
                                }
                                cs.Append("}"+cl);
                                cs.Append(cl);
                                #endregion
                            }
                        }
                    }
                    WS = WS.Replace("//{{{CP_EventSink}}}","//{{{CP_EventSink}}}"+cl+cs.ToString());
                }
                #endregion
                #region Event Sink Registrations
                if (!Configuration.BareBonesSample)
                {
                    cs = new CodeProcessor(new StringBuilder(),this.Language == LANGUAGES.CPP);

                    en = SL.GetEnumerator();
                    while(en.MoveNext())
                    {
                        UPnPService s = (UPnPService)en.Value;
                        string name = (string)en.Key;
                        foreach(UPnPStateVariable variable in s.GetStateVariables())
                        {
                            if (variable.SendEvent == true)
                            {
                                cs.Append("    " + pc_methodPrefix+"EventCallback_"+name+"_"+variable.Name+" = &"+pc_methodPrefix+"EventSink_"+name+"_"+variable.Name+";" + cl);
                            }
                        }
                    }

                    WS = WS.Replace("//{{{CP_EventRegistrations}}}","//{{{CP_EventRegistrations}}}"+cl+cs.ToString());
                }
                #endregion

                #region C++ Specific
                if (Configuration.CPlusPlusWrapper)
                {
                    // Set the Callback
                    string CPSINK = "pUPnP->Set_ControlPoint_Handler_"+device.User2.ToString()+"(&"+pc_methodPrefix+"OnAddSink,&"+pc_methodPrefix+"OnRemoveSink);";
                    WS = SourceCodeRepository.InsertTextBeforeTag(WS,"//{{{CP_CONNECTING_ADD/REMOVE_SINKS}}}",CPSINK);

                    // Add the Sinks
                    tmp = SourceCodeRepository.GetTextBetweenTags(WS,"//{{{CP_DISCOVER/REMOVE_SINKS_BEGIN}}}","//{{{CP_DISCOVER/REMOVE_SINKS_END}}}");
                    tmp = tmp.Replace("{{{PREFIX}}}",this.pc_methodPrefix);
                    tmp = tmp.Replace("{{{DEVICE}}}",device.User2.ToString());
                    WS = SourceCodeRepository.InsertTextBeforeTag(WS,"//{{{CP_DISCOVER/REMOVE_SINKS_BEGIN}}}",tmp);
                }
                #endregion

                #region Prefixes

                WS = WS.Replace("UPnPAbstraction.h", "_upnpabstraction.h_");
                WS = WS.Replace("pUPnP","_pupnp_");
                WS = WS.Replace("CUPnP_","_cupnp_");

                WS = WS.Replace("UPnP/","upnp/");
                WS = WS.Replace("UPnPControlPointStructs.h","upnpcontrolpointstructs.h");
                WS = WS.Replace("UPnPDevice","upnpdevice");
                WS = WS.Replace("UPnPService","upnpservice");
                WS = WS.Replace("SubscribeForUPnPEvents","subscribeforupnpevents");
                WS = WS.Replace("UnSubscribeUPnPEvents","unsubscribeupnpevents");

                WS = WS.Replace("UPnPError","_upnperror_");
                WS = WS.Replace(" UPnP "," _upnp_ ");
                WS = WS.Replace("UPnP",this.pc_methodPrefix);
                WS = WS.Replace("ILib",this.pc_methodLibPrefix);
                WS = WS.Replace("_upnperror_","UPnPError");
                WS = WS.Replace("upnp/","UPnP/");
                WS = WS.Replace(" _upnp_ ", " UPnP ");

                WS = WS.Replace("_pupnp_","pUPnP");
                WS = WS.Replace("_cupnp_","CUPnP_");

                WS = WS.Replace("upnpdevice","UPnPDevice");
                WS = WS.Replace("upnpservice","UPnPService");
                WS = WS.Replace("upnpcontrolpointstructs.h","UPnPControlPointStructs.h");
                WS = WS.Replace("subscribeforupnpevents","SubscribeForUPnPEvents");
                WS = WS.Replace("unsubscribeupnpevents","UnSubscribeUPnPEvents");
                WS = WS.Replace("_upnpabstraction.h_","UPnPAbstraction.h");

                #endregion

                SampleApp = WS;
            }
            #endregion
            #endregion

            Log("UPnP Stack Generation Complete.");
            return true;
        }
        internal UPnPService(double version)
        {
            OpenSource.Utilities.InstanceTracker.Add(this);
            InvocationPipeline.OnResponse += new HTTPRequest.RequestHandler(HandleInvokeRequest);

            this.SubscribeCycleCallback = new LifeTimeMonitor.LifeTimeHandler(SubscribeCycleSink);
            SubscribeCycle.OnExpired += this.SubscribeCycleCallback;
            VarAssociation = new Hashtable();
            LocalMethodList = new Hashtable();
            RemoteMethods = new SortedList();
            SIDLock = new object();
            EventSID = 0;

            StateVariables = Hashtable.Synchronized(new Hashtable());
            SubscriberTable = Hashtable.Synchronized(new Hashtable());
            CurrentSID = "";

            if (version == 0)
            {
                Major = 1;
                Minor = 0;
            }
            else
            {
                DText TempNum = new DText();
                TempNum.ATTRMARK = ".";
                TempNum[0] = version.ToString();

                Major = int.Parse(TempNum[1]);
                Minor = 0;
                if (TempNum.DCOUNT() == 2) int.TryParse(TempNum[2], out Minor);
            }
        }
Beispiel #30
0
		/// <summary>
		/// This method is triggered whenever a ConnectionManagerEvent arrives, which tells us
		/// all of the current ConnectionIDs
		/// </summary>
		/// <param name="sender">The CpConnectionManager class that sent the event</param>
		/// <param name="CurrentIDs">A CSV list of ConnectionIDs</param>
		protected void ConnectionIDEventSink(CpConnectionManager sender, string CurrentIDs)
		{
			// We need to return immediately if this flag is set.
			// This flag is only set if PrepareForConnection in not implemented on this
			// renderer, in which case, there will be a default ConnectionID of 0, which
			// must never disappear.
			if(DontEverDelete == true) return;

			// This is a temp collection used to create an index of the ConnectionIDs that
			// were recieved in this event
			Hashtable h = new Hashtable();
			// This is a temp parser used to parse the CSV list of IDs
			DText p = new DText();
			p.ATTRMARK = ",";

			if(CurrentIDs!="")
			{
				p[0] = CurrentIDs;
				int len = p.DCOUNT();
				for(int i=1;i<=len;++i)
				{
					// Adding a ConnectionID into the temp collection
					h[Int32.Parse(p[i])] = "";
				}
			}

			// Lets find ones that were removed first
			foreach(AVConnection a in Connections)
			{
				if(h.ContainsKey(a.ConnectionID)==false)
				{
					// This ID was removed
					InstanceList.Remove(a);
					a.Dispose();
					OnRemovedConnectionEvent.Fire(this,a,Guid.NewGuid().GetHashCode());	
				}
			}

			// Now lets look for new ones... This is easy
			IDSink(sender, CurrentIDs,null,Guid.NewGuid().GetHashCode());
		}
Beispiel #31
0
        private void ProcessPacket(HTTPMessage msg, IPEndPoint src, IPEndPoint local)
        {
            if (OnSniffPacket != null)
            {
                OnSniffPacket(src, null, msg);
            }

            DText parser = new DText();

            parser.ATTRMARK = "::";

            bool   Alive = false;
            String UDN   = msg.GetTag("USN");

            parser[0] = UDN;
            String USN = parser[1];

            USN = USN.Substring(USN.IndexOf(":") + 1);
            String ST     = parser[2];
            int    MaxAge = 0;

            String NTS = msg.GetTag("NTS").ToUpper();

            if (NTS == "SSDP:ALIVE")
            {
                Alive = true;
                String ma = msg.GetTag("Cache-Control").Trim();
                if (ma != "")
                {
                    parser.ATTRMARK = ",";
                    parser.MULTMARK = "=";
                    parser[0]       = ma;
                    for (int i = 1; i <= parser.DCOUNT(); ++i)
                    {
                        if (parser[i, 1].Trim().ToUpper() == "MAX-AGE")
                        {
                            MaxAge = int.Parse(parser[i, 2].Trim());
                            break;
                        }
                    }
                }
            }

            if (msg.Directive == "NOTIFY" && OnNotify != null)
            {
                Uri    locuri   = null;
                string location = msg.GetTag("Location");
                if (location != null && location.Length > 0)
                {
                    try
                    {
                        locuri = new Uri(location);
                    }
                    catch (Exception ex)
                    {
                        OpenSource.Utilities.EventLogger.Log(ex);
                    }
                }
                OnNotify(src, msg.LocalEndPoint, locuri, Alive, USN, ST, MaxAge, msg);
            }
            else if (msg.Directive == "M-SEARCH" && OnSearch != null)
            {
                if (ValidateSearchPacket(msg) == false)
                {
                    return;
                }
                int          MaxTimer   = int.Parse(msg.GetTag("MX"));
                SearchStruct SearchData = new SearchStruct();
                SearchData.ST     = msg.GetTag("ST");
                SearchData.Source = src;
                SearchData.Local  = local;
                SearchTimer.Add(SearchData, RandomGenerator.Next(0, MaxTimer));
            }
        }
Beispiel #32
0
		/// <summary>
		/// This method is called when an AsyncCall to GetProtocolInfo completes
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="Source"></param>
		/// <param name="Sink"></param>
		/// <param name="e"></param>
		/// <param name="Handle"></param>
		protected void GetProtocolInfoSink(CpConnectionManager sender, System.String Source, System.String Sink, UPnPInvokeException e, object Handle)
		{
			if(e!=null) return;
			if(Sink=="") return;

			// This is a temp parser to parse the supported ProtocolInfo values
			DText p = new DText();
			p.ATTRMARK = ",";
			p[0] = Sink;
			int len = p.DCOUNT();
			ProtocolInfoString istring;
			for(int i=1;i<=len;++i)
			{
				istring = new ProtocolInfoString(p[i]);
				// Add each individual entry
				ProtocolInfoList.Add(istring);
			}
			if(!this.__Init)
			{
				this.__Init = true;
				// Upon discovery of a renderer, we can't return the renderer to the user
				// until we at least parsed the supported ProtocolInfo values, otherwise
				// the user will experience incorrect behavior. Since we have just parsed
				// these values, we can fire this event.
				if(this.OnInitialized!=null) OnInitialized(this);
			}
		}
        /// <summary>
        /// Parses a Byte Array at a specific location, and builds a Packet.
        /// </summary>
        /// <param name="buffer">The Array of Bytes</param>
        /// <param name="indx">The Start Index</param>
        /// <param name="count">The number of Bytes to process</param>
        /// <returns></returns>
        public static HTTPMessage ParseByteArray(byte[] buffer, int indx, int count)
        {
            HTTPMessage TheMessage = new HTTPMessage();
            UTF8Encoding UTF8 = new UTF8Encoding();
            String TempData = UTF8.GetString(buffer,indx,count);
            DText parser = new DText();
            String TempString;

            int idx = TempData.IndexOf("\r\n\r\n");
            if (idx < 0) return null;
            TempData = TempData.Substring(0,idx);

            parser.ATTRMARK = "\r\n";
            parser.MULTMARK = ":";
            parser[0] = TempData;
            string CurrentLine = parser[1];

            DText HdrParser = new DText();
            HdrParser.ATTRMARK = " ";
            HdrParser.MULTMARK = "/";
            HdrParser[0] = CurrentLine;

            if (CurrentLine.ToUpper().StartsWith("HTTP/")==true)
            {
                TheMessage.ResponseCode = int.Parse(HdrParser[2]);
                int s1 = CurrentLine.IndexOf(" ");
                s1 = CurrentLine.IndexOf(" ",s1+1);
                TheMessage.ResponseData = HTTPMessage.UnEscapeString(CurrentLine.Substring(s1));
                try
                {
                    TheMessage.Version = HdrParser[1,2];
                }
                catch(Exception)
                {
                    TheMessage.Version = "0.9";
                }
            }
            else
            {
                TheMessage.Directive = HdrParser[1];
                TempString = CurrentLine.Substring(CurrentLine.LastIndexOf(" ") + 1);
                if (TempString.ToUpper().StartsWith("HTTP/")==false)
                {
                    TheMessage.Version = "0.9";
                    TheMessage.DirectiveObj = HTTPMessage.UnEscapeString(TempString);
                }
                else
                {
                    TheMessage.Version = TempString.Substring(TempString.IndexOf("/")+1);
                    int fs = CurrentLine.IndexOf(" ") + 1;
                    TheMessage.DirectiveObj = HTTPMessage.UnEscapeString(CurrentLine.Substring(
                        fs,
                        CurrentLine.Length-fs-TempString.Length-1));
                }
            }
            String Tag="";
            String TagData="";

            for(int line=2;line<=parser.DCOUNT();++line)
            {
                if (Tag!="" && parser[line,1].StartsWith(" "))
                {
                    TagData = parser[line,1].Substring(1);
                }
                else
                {
                    Tag = parser[line,1];
                    TagData = "";
                    for(int i=2;i<=parser.DCOUNT(line);++i)
                    {
                        if (TagData=="")
                        {
                            TagData = parser[line,i];
                        }
                        else
                        {
                            TagData = TagData + parser.MULTMARK + parser[line,i];
                        }
                    }
                }
                TheMessage.AppendTag(Tag,TagData);
            }
            int cl=0;
            if (TheMessage.HasTag("Content-Length"))
            {
                try
                {
                    cl = int.Parse(TheMessage.GetTag("Content-Length"));
                }
                catch(Exception)
                {
                    cl = -1;
                }
            }
            else
            {
                cl = -1;
            }

            byte[] tbuffer;
            if (cl>0)
            {
                tbuffer = new byte[cl];
                if ((idx+4+cl)>count)
                {
                    // NOP
                }
                else
                {
                    Array.Copy(buffer,idx+4,tbuffer,0,cl);
                    TheMessage.DataBuffer = tbuffer;
                }
            }
            if (cl==-1)
            {
                tbuffer = new Byte[count-(idx+4)];
                Array.Copy(buffer,idx+4,tbuffer,0,tbuffer.Length);
                TheMessage.DataBuffer = tbuffer;
            }
            if (cl==0)
            {
                TheMessage.DataBuffer = new byte[0];
            }
            return(TheMessage);
        }
Beispiel #34
0
		/// <summary>
		/// This method is called whenever we need to inspect a list of ConnectionIDs
		/// to see if any of them are new
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="IDString"></param>
		/// <param name="e"></param>
		/// <param name="Handle"></param>
		protected void IDSink(CpConnectionManager sender, string IDString, UPnPInvokeException e, object Handle)
		{
			if((e!=null) || (IDString=="")) return;

			// This is a temp parser that will parse the CSV list of IDs
			DText p = new DText();
			p.ATTRMARK = ",";
			p[0] = IDString;
			int len = p.DCOUNT();
			for(int i=1;i<=len;++i)
			{
//				bool FOUND = false;
				int cid = int.Parse(p[i].Trim());
				
//				lock(InstanceList)
//				{	
//					foreach(AVConnection _AVC in InstanceList)
//					{
//						if(_AVC.ConnectionID == cid)
//						{
//							FOUND = true;
//							break;
//						}
//					}
//				}

				lock(this.CreateConnectionLock)
				{
					if(this.PendingCreateConnection==0)
					{
						ConnectionManager.GetCurrentConnectionInfo(cid,null,new CpConnectionManager.Delegate_OnResult_GetCurrentConnectionInfo(ConnectionInfoSink));				
					}
					else
					{
						// We possible need to wait a maximum of 30 seconds, just in case events arrive
						// that involve this connection ID. When/if that happens, we will remove this 
						// object from the monitor, and continue directly.
						this.ConnectionMonitor.Add(cid,30);
					}
				}
			}
		}
        private void GenerateEventSchemas(UPnPDevice d, System.IO.DirectoryInfo dirInfo, bool cleanSchema)
        {
            System.IO.MemoryStream ms = new MemoryStream();
            System.Xml.XmlTextWriter X = new System.Xml.XmlTextWriter(ms,System.Text.Encoding.UTF8);
            X.Formatting = System.Xml.Formatting.Indented;

            foreach(UPnPDevice ed in d.EmbeddedDevices)
            {
                GenerateEventSchemas(ed,dirInfo,cleanSchema);
            }
            foreach(UPnPService s in d.Services)
            {
                Hashtable h = new Hashtable();
                int j=1;

                foreach(string sn in s.GetSchemaNamespaces())
                {
                    h[sn] = "CT"+j.ToString();
                    ++j;
                }
                X.WriteStartDocument();
                X.WriteStartElement("xsd","schema","http://www.w3.org/2001/XMLSchema");
                X.WriteAttributeString("targetNamespace","urn:schemas-upnp-org:event-1-0");
                X.WriteAttributeString("xmlns","upnp",null,"http://www.upnp.org/Schema/DataTypes");
                X.WriteAttributeString("xmlns","urn:schemas-upnp-org:event-1-0");

                foreach(UPnPStateVariable v in s.GetStateVariables())
                {
                    if (v.SendEvent)
                    {
                        X.WriteStartElement("xsd","element",null); // Element1
                        X.WriteAttributeString("name","propertyset");
                        X.WriteAttributeString("type","propertysetType");

                        if (!cleanSchema)
                        {
                            X.WriteComment("Note: Some schema validation tools may consider the following xsd:any element to be ambiguous in its placement");
                            X.WriteStartElement("xsd","any",null);
                            X.WriteAttributeString("namespace","##other");
                            X.WriteAttributeString("minOccurs","0");
                            X.WriteAttributeString("maxOccurs","unbounded");
                            X.WriteAttributeString("processContents","lax");
                            X.WriteEndElement(); //ANY
                        }

                        X.WriteStartElement("xsd","complexType",null);
                        X.WriteAttributeString("name","propertysetType");

                        X.WriteStartElement("xsd","sequence",null);
                        X.WriteStartElement("xsd","element",null); // Element2
                        X.WriteAttributeString("name","property");
                        X.WriteAttributeString("maxOccurs","unbounded");
                        X.WriteStartElement("xsd","complexType",null);
                        X.WriteStartElement("xsd","sequence",null);

                        X.WriteStartElement("xsd","element",null); // Element3
                        X.WriteAttributeString("name",v.Name);
                        if (v.ComplexType==null)
                        {
                            // Simple Type
                            X.WriteStartElement("xsd","complexType",null);
                            X.WriteStartElement("xsd","simpleContent",null);
                            X.WriteStartElement("xsd","extension",null);
                            X.WriteAttributeString("base","upnp:"+v.ValueType);
                            if (!cleanSchema)
                            {
                                X.WriteStartElement("xsd","anyAttribute",null);
                                X.WriteAttributeString("namespace","##other");
                                X.WriteAttributeString("processContents","lax");
                                X.WriteEndElement(); // anyAttribute
                            }
                            X.WriteEndElement(); // extension
                            X.WriteEndElement(); // simpleContent
                            X.WriteEndElement(); // complexType
                        }
                        else
                        {
                            // Complex Type
                            X.WriteAttributeString("type",h[v.ComplexType.Name_NAMESPACE].ToString()+":"+v.ComplexType.Name_LOCAL);
                        }
                        X.WriteEndElement(); // Element3
                        if (!cleanSchema)
                        {
                            X.WriteStartElement("xsd","any",null);
                            X.WriteAttributeString("namespace","##other");
                            X.WriteAttributeString("minOccurs","0");
                            X.WriteAttributeString("maxOccurs","unbounded");
                            X.WriteAttributeString("processContents","lax");
                            X.WriteEndElement(); // any
                        }
                        X.WriteEndElement(); // sequence
                        if (!cleanSchema)
                        {
                            X.WriteStartElement("xsd","anyAttribute",null);
                            X.WriteAttributeString("namespace","##other");
                            X.WriteAttributeString("processContents","lax");
                            X.WriteEndElement(); // anyAttribute
                        }
                        X.WriteEndElement(); // complexType
                        X.WriteEndElement(); // Element2
                        if (!cleanSchema)
                        {
                            X.WriteStartElement("xsd","any",null);
                            X.WriteAttributeString("namespace","##other");
                            X.WriteAttributeString("minOccurs","0");
                            X.WriteAttributeString("maxOccurs","unbounded");
                            X.WriteAttributeString("processContents","lax");
                            X.WriteEndElement(); // any
                        }
                        X.WriteEndElement(); // sequence
                        if (!cleanSchema)
                        {
                            X.WriteStartElement("xsd","anyAttribute",null);
                            X.WriteAttributeString("namespace","##other");
                            X.WriteAttributeString("processContents","lax");
                            X.WriteEndElement(); // anyAttribute
                        }
                        X.WriteEndElement(); // complexType;
                        X.WriteEndElement(); // Element1
                    }
                }

                X.WriteEndElement(); // schema
                X.WriteEndDocument();

                StreamWriter writer3;

                DText PP = new DText();
                PP.ATTRMARK = ":";
                PP[0] = s.ServiceURN;
                writer3 = File.CreateText(dirInfo.FullName + "\\"+PP[PP.DCOUNT()-1]+"_Events.xsd");

                System.Text.UTF8Encoding U = new System.Text.UTF8Encoding();
                X.Flush();
                ms.Flush();
                writer3.Write(U.GetString(ms.ToArray(),2,ms.ToArray().Length-2));
                writer3.Close();
                ms = new MemoryStream();
                X = new System.Xml.XmlTextWriter(ms,System.Text.Encoding.UTF8);
                X.Formatting = System.Xml.Formatting.Indented;
            }
        }
        private void BuildMSEARCHHandler_device(UPnPDevice device, CodeProcessor cs, int number)
        {
            if (number == 0)
            {
                cs.Append("				else if (STLength == (int)strlen(upnp->UUID) && memcmp(ST,upnp->UUID,(int)strlen(upnp->UUID))==0)" + cl);
                cs.Append("				{" + cl);
                cs.Append("						rcode = " + pc_methodPrefix + "BuildSendSsdpResponsePacket(response_socket, upnp, (struct sockaddr*)&(mss->localIPAddress), (struct sockaddr*)&(mss->dest_addr), 0,\"\",upnp->UUID,\"\");" + cl);
                cs.Append("				}" + cl);
            }
            else if (number > 0)
            {
                cs.Append("				else if (STLength == (int)strlen(upnp->UUID) + " + (number.ToString().Length + 1).ToString() + ")" + cl);
                cs.Append("				{" + cl);
                cs.Append("					if (memcmp(ST,upnp->UUID,(int)strlen(upnp->UUID))==0)" + cl);
                cs.Append("					{" + cl);
                cs.Append("						if (memcmp(ST+(int)strlen(upnp->UUID),\"_" + number.ToString() + "\"," + (number.ToString().Length + 1).ToString() + ")==0)" + cl);
                cs.Append("						{" + cl);
                cs.Append("								rcode = " + pc_methodPrefix + "BuildSendSsdpResponsePacket(response_socket, upnp, (struct sockaddr*)&(mss->localIPAddress), (struct sockaddr*)&(mss->dest_addr), " + number.ToString() + ", \"\", ST, \"\");" + cl);
                cs.Append("						}" + cl);
                cs.Append("					}" + cl);
                cs.Append("				}" + cl);
            }
            cs.Append("				else if (STLength >= " + device.DeviceURN_Prefix.Length.ToString() + " && memcmp(ST,\"" + device.DeviceURN_Prefix + "\"," + device.DeviceURN_Prefix.Length.ToString() + ")==0 && atoi(ST+" + device.DeviceURN_Prefix.Length.ToString() + ")<=" + device.Version.ToString() + ")" + cl);
            cs.Append("				{" + cl);
            cs.Append("						rcode = " + pc_methodPrefix + "BuildSendSsdpResponsePacket(response_socket, upnp, (struct sockaddr*)&(mss->localIPAddress), (struct sockaddr*)&(mss->dest_addr), " + number.ToString() + ", \"::" + device.DeviceURN_Prefix + "1\", ST, \"\");" + cl);
            if (device.Major > 1)
            {
                DText p = new DText();
                p.ATTRMARK = ":";
                p[0] = device.DeviceURN;
                cs.Append("						// packetlength = " + pc_methodPrefix + "FixVersion(b, \"" + p[p.DCOUNT() - 1] + ":1\", atoi(ST + " + device.DeviceURN_Prefix.Length.ToString() + "));" + cl);
            }
            cs.Append("				}" + cl);

            foreach (UPnPService service in device.Services)
            {
                cs.Append("				else if (STLength >= " + service.ServiceURN_Prefix.Length.ToString() + " && memcmp(ST,\"" + service.ServiceURN_Prefix + "\"," + service.ServiceURN_Prefix.Length.ToString() + ")==0 && atoi(ST+" + service.ServiceURN_Prefix.Length.ToString() + ")<=" + service.Version.ToString() + ")" + cl);
                cs.Append("				{" + cl);
                cs.Append("						rcode = " + pc_methodPrefix + "BuildSendSsdpResponsePacket(response_socket, upnp, (struct sockaddr*)&(mss->localIPAddress), (struct sockaddr*)&(mss->dest_addr), " + number.ToString() + ", \"::" + service.ServiceURN_Prefix + "1\", ST, \"\");" + cl);
                if (service.Major > 1)
                {
                    DText p = new DText();
                    p.ATTRMARK = ":";
                    p[0] = service.ServiceURN;
                    cs.Append("						// packetlength = " + pc_methodPrefix + "FixVersion(b, \"" + p[p.DCOUNT() - 1] + ":1\", atoi(ST + " + service.ServiceURN_Prefix.Length.ToString() + "));" + cl);
                }
                cs.Append("				}" + cl);
            }
            foreach (UPnPDevice d in device.EmbeddedDevices)
            {
                BuildMSEARCHHandler_device(d, cs, ++number);
            }
        }