public void Invoke(UPnPService S, string Action, byte[] InArgs, out byte[] OutArgs)
        {
            UPnPAction A = S.GetAction(Action);
            ArrayList AList = new ArrayList();

            foreach(UPnPArgument arg in A.ArgumentList)
            {
                if(arg.IsReturnValue==false && arg.Direction=="out")
                {
                    UPnPArgument _arg = (UPnPArgument)arg.Clone();
                    _arg.DataValue = UPnPService.CreateObjectInstance(arg.RelatedStateVar.GetNetType(),null);
                    AList.Add(_arg);
                }
            }

            UPnPArgument[] Temp = ParseArguments(InArgs);
            foreach(UPnPArgument _arg in Temp)
            {
                _arg.DataType = A.GetArg(_arg.Name).RelatedStateVar.ValueType;
                _arg.Direction = "in";
                AList.Add(_arg);
            }

            UPnPArgument[] Arguments = (UPnPArgument[])AList.ToArray(typeof(UPnPArgument));

            (new UPnPDebugObject(S)).SetProperty("ValidationMode",false);
            object RetVal = null;

            try
            {
                RetVal = S.InvokeSync(Action,Arguments);
            }
            catch(UPnPInvokeException ie)
            {
                if(ie.UPNP!=null)
                {
                    throw(ie.UPNP);
                }
                else
                {
                    throw(ie);
                }
            }

            ArrayList RetList = new ArrayList();

            if(A.HasReturnValue==true)
            {
                UPnPArgument RA = (UPnPArgument)A.GetRetArg().Clone();
                RA.DataValue = RetVal;
                RetList.Add(RA);
            }

            foreach(UPnPArgument OA in Arguments)
            {
                if(OA.Direction=="out")
                {
                    RetList.Add(OA);
                }
            }

            OutArgs = BuildArguments((UPnPArgument[])RetList.ToArray(typeof(UPnPArgument)));
        }
        private bool BasicControlTest_ACTION_BadAllowedValues(UPnPService s, UPnPAction A)
        {
            (new UPnPDebugObject(s)).SetProperty("ValidationMode",false);
            ArrayList ArgList = null;
            foreach(UPnPArgument arg in A.ArgumentList)
            {
                if(arg.IsReturnValue==false && arg.Direction=="in")
                {
                    if(arg.RelatedStateVar.AllowedStringValues!=null)
                    {
                        ArgList = BasicControlTest_BuildActionArgs(A);
                        for(int i=0;i<ArgList.Count;++i)
                        {
                            if(((UPnPArgument)ArgList[i]).Name==arg.Name)
                            {
                                string val = "!@#$";
                                bool OK = true;
                                do
                                {
                                    OK = true;
                                    for(int j=0;j<arg.RelatedStateVar.AllowedStringValues.Length;++j)
                                    {
                                        if(val==arg.RelatedStateVar.AllowedStringValues[j])
                                        {
                                            OK = false;
                                            break;
                                        }
                                    }
                                    if(OK==false) val += val;
                                }while (OK==false);
                                ((UPnPArgument)ArgList[i]).DataValue = val;

                                AddEvent(LogImportance.Remark,"Allowed Values","Invoke <<Bad " + arg.Name + ">> " + A.Name);
                                try
                                {
                                    s.InvokeSync(A.Name,(UPnPArgument[])ArgList.ToArray(typeof(UPnPArgument)));
                                    WARN_ALLOWED = true;
                                    AddEvent(LogImportance.High,"Allowed Values","   Device failed to validate argument");
                                }
                                catch(UPnPInvokeException ex)
                                {
                                    if(ex.UPNP!=null)
                                    {
                                        if(ex.UPNP.ErrorCode<501)
                                        {
                                            AddEvent(LogImportance.Remark,"Allowed Values","   Device SUCCESSFULLY validated argument");
                                        }
                                        else
                                        {
                                            WARN_ALLOWED = true;
                                            AddEvent(LogImportance.Remark,"Allowed Values","   Device returned code: " + ex.UPNP.ErrorCode.ToString() + " but failed to validate argument");
                                        }
                                    }
                                    else
                                    {
                                        FAIL_ALLOWED = true;
                                        AddEvent(LogImportance.Critical,"Allowed Values","   Device returned non SOAP-Encoded Error");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            (new UPnPDebugObject(s)).SetProperty("ValidationMode",true);
            return true;
        }
        private bool BasicControlTest_ACTION_BadRange(UPnPService s, UPnPAction A)
        {
            (new UPnPDebugObject(s)).SetProperty("ValidationMode",false);

            ArrayList ArgList = null;
            foreach(UPnPArgument arg in A.ArgumentList)
            {
                if(arg.IsReturnValue==false && arg.Direction=="in")
                {
                    if(arg.RelatedStateVar.Maximum!=null ||
                        arg.RelatedStateVar.Minimum!=null)
                    {
                        ArgList = BasicControlTest_BuildActionArgs(A);
                        for(int i=0;i<ArgList.Count;++i)
                        {
                            if(((UPnPArgument)ArgList[i]).Name==arg.Name)
                            {
                                if(arg.RelatedStateVar.Minimum!=null)
                                {
                                    FieldInfo mi = arg.RelatedStateVar.GetNetType().GetField("MinValue");
                                    if(mi.GetValue(null).ToString()!=arg.RelatedStateVar.Minimum.ToString())
                                    {
                                        ((UPnPArgument)ArgList[i]).DataValue = mi.GetValue(null);

                                        AddEvent(LogImportance.Remark,"Range","Invoke <<" + arg.Name + " value too small>> " + A.Name);
                                        try
                                        {
                                            s.InvokeSync(A.Name,(UPnPArgument[])ArgList.ToArray(typeof(UPnPArgument)));
                                            WARN_RANGE = true;
                                            AddEvent(LogImportance.High,"Range","   Device failed to validate argument");
                                        }
                                        catch(UPnPInvokeException ex)
                                        {
                                            if(ex.UPNP!=null)
                                            {
                                                if(ex.UPNP.ErrorCode<501)
                                                {
                                                    AddEvent(LogImportance.Remark,"Range","   Device SUCCESSFULLY validated argument");

                                                }
                                                else
                                                {
                                                    WARN_RANGE = true;
                                                    AddEvent(LogImportance.High,"Range","   Device returned code: " + ex.UPNP.ErrorCode.ToString() + " but failed to validate argument");
                                                }
                                            }
                                            else
                                            {
                                                FAIL_RANGE = true;
                                                AddEvent(LogImportance.Critical,"Range","   Device returned non SOAP-Encoded Error");
                                            }
                                        }
                                    }
                                }
                                if(arg.RelatedStateVar.Maximum!=null)
                                {
                                    FieldInfo mi = arg.RelatedStateVar.GetNetType().GetField("MaxValue");
                                    if(mi.GetValue(null).ToString()!=arg.RelatedStateVar.Maximum.ToString())
                                    {
                                        ((UPnPArgument)ArgList[i]).DataValue = mi.GetValue(null);

                                        AddEvent(LogImportance.Remark,"Range","Invoke <<" + arg.Name + " value too big>> " + A.Name);
                                        try
                                        {
                                            s.InvokeSync(A.Name,(UPnPArgument[])ArgList.ToArray(typeof(UPnPArgument)));
                                            WARN_RANGE = true;
                                            AddEvent(LogImportance.High,"Range","   Device failed to validate argument");
                                        }
                                        catch(UPnPInvokeException ex)
                                        {
                                            if(ex.UPNP!=null)
                                            {
                                                if(ex.UPNP.ErrorCode<501)
                                                {
                                                    AddEvent(LogImportance.Remark,"Range","   Device SUCCESSFULLY validated argument");

                                                }
                                                else
                                                {
                                                    WARN_RANGE = true;
                                                    AddEvent(LogImportance.High,"Range","   Device returned code: " + ex.UPNP.ErrorCode.ToString() + " but failed to validate argument");
                                                }
                                            }
                                            else
                                            {
                                                FAIL_RANGE = true;
                                                AddEvent(LogImportance.Critical,"Range","   Device returned non SOAP-Encoded Error");
                                            }
                                        }
                                    }
                                }

                            }
                        }
                    }
                }
            }

            (new UPnPDebugObject(s)).SetProperty("ValidationMode",true);
            return true;
        }
        private bool BasicControlTest_ACTION(UPnPService s, UPnPAction A)
        {
            ArrayList ArgList = BasicControlTest_BuildActionArgs(A);
            try
            {
                s.InvokeSync(A.Name,(UPnPArgument[])ArgList.ToArray(typeof(UPnPArgument)));
                AddEvent(LogImportance.Remark,"Valid Values","Invoke: " + A.Name + " << OK >>");
            }
            catch(UPnPInvokeException ex)
            {
                if(ex.UPNP.ErrorCode==401 ||
                    ex.UPNP.ErrorCode==402)
                {
                    // Oh really?
                    WARN_VALID = true;
                    AddEvent(LogImportance.High,"Valid Values",
                        "   Invoke: " + A.Name);
                    AddEvent(LogImportance.High,"Valid Values",
                        "      Cannot return Error Code " + ex.UPNP.ErrorCode.ToString());

                    foreach(UPnPArgument _arg in ex.Arguments)
                    {
                        AddEvent(LogImportance.High,"Valid Values",
                            "         " + _arg.Name + ": " + UPnPService.SerializeObjectInstance(_arg.DataValue));
                    }
                }
                else
                {
                    // Fine, I suppose
                    AddEvent(LogImportance.Remark,"Valid Values",
                        "Invoke: " + A.Name + " << " + ex.UPNP.ErrorCode + " " + ex.UPNP.ErrorDescription + "  OK >>");
                }
            }
            return true;
        }