protected void AddParams(FUNCDESC funcDesc,
                                 String[] names,
                                 int paramCount)
        {
            IntPtr elemPtr = funcDesc.lprgelemdescParam;

            for (int i = 0; i < paramCount; i++)
            {
                ELEMDESC elemDesc =
                    (ELEMDESC)Marshal.PtrToStructure(elemPtr,
                                                     typeof(ELEMDESC));
                ComParamInfo pi = new ComParamInfo
                                      (names[i + 1],
                                      TypeLibUtil.TYPEDESCToString
                                          (_typeLib,
                                          _typeInfo,
                                          elemDesc.tdesc,
                                          TypeLibUtil.COMTYPE),
                                      elemDesc.desc.paramdesc.wParamFlags);
                _parameters.Add(pi);
                // Point to the next one
                elemPtr = new IntPtr(elemPtr.ToInt64() +
                                     Marshal.SizeOf(elemDesc));
            }
        }
        protected void AddDomParams(FUNCDESC funcDesc,
                                    CodeMemberMethod meth,
                                    int limit)
        {
            IntPtr elemPtr = funcDesc.lprgelemdescParam;

            for (int i = 0; i < limit; i++)
            {
                ELEMDESC elemDesc =
                    (ELEMDESC)Marshal.PtrToStructure(elemPtr,
                                                     typeof(ELEMDESC));
                ComParamInfo parameter = (ComParamInfo)
                                         _parameters[i];
                String paramType = TypeLibUtil.TYPEDESCToString
                                       (_typeLib,
                                       _typeInfo,
                                       elemDesc.tdesc,
                                       !TypeLibUtil.COMTYPE);
                String paramInOut = null;
                if ((parameter._paramFlags & PARAMFLAG.PARAMFLAG_FIN) != 0)
                {
                    paramInOut = "In";
                }
                else if
                ((parameter._paramFlags & PARAMFLAG.PARAMFLAG_FOUT) != 0)
                {
                    paramInOut = "Out";
                    // Ref becomes out for an output parameter
                    if (paramType.StartsWith("ref "))
                    {
                        paramType = "out " + paramType.Substring(4);
                    }
                    else
                    {
                        paramType = "out " + paramType;
                    }
                }
                CodeParameterDeclarationExpression paramExpr =
                    new CodeParameterDeclarationExpression
                        (paramType, parameter._name);
                if (paramInOut != null)
                {
                    paramExpr.CustomAttributes.Add
                        (new CodeAttributeDeclaration
                            ("System.Runtime.InteropServices." + paramInOut));
                }
                meth.Parameters.Add(paramExpr);
                // Point to the next one
                elemPtr = new IntPtr(elemPtr.ToInt64() +
                                     Marshal.SizeOf(elemDesc));
            }
        }
        protected override CodeObject GenerateCodeDom()
        {
            CodeTypeMember codeDom;
            IntPtr         funcDescPtr;
            FUNCDESC       funcDesc;

            // Have to get the FUNCDESC from the _typeInfo because
            // it cannot be saved.  The reason for this is that a TYPEDESC
            // may have a pointer to another TYPEDESC which is allocated
            // in the unmanaged memory and that pointer won't be any good
            // outside of the scope where the FUNCDESC is held.
            _typeInfo.GetFuncDesc(_index, out funcDescPtr);
            funcDesc =
                (FUNCDESC)Marshal.PtrToStructure(funcDescPtr,
                                                 typeof(FUNCDESC));
            if (funcDesc.invkind == INVOKEKIND.INVOKE_FUNC)
            {
                CodeMemberMethod meth;
                meth    = new CodeMemberMethod();
                codeDom = meth;
                TYPEDESC retType = funcDesc.elemdescFunc.tdesc;
                if (_parameters.Count > 0)
                {
                    int limit = _parameters.Count;
                    // If the last parameter is a retval and the
                    // function returns an HRESULT, then make
                    // the function return the last parameter
                    if ((VarEnum)funcDesc.elemdescFunc.tdesc.vt
                        == VarEnum.VT_HRESULT)
                    {
                        ComParamInfo lastParam = (ComParamInfo)
                                                 _parameters[_parameters.Count - 1];
                        if ((lastParam._paramFlags &
                             PARAMFLAG.PARAMFLAG_FRETVAL) != 0)
                        {
                            IntPtr   elemPtr  = funcDesc.lprgelemdescParam;
                            ELEMDESC elemDesc = new ELEMDESC();
                            // Point to the last one
                            elemPtr = new IntPtr(elemPtr.ToInt64() +
                                                 ((_parameters.Count - 1) *
                                                  Marshal.SizeOf(elemDesc)));
                            elemDesc = (ELEMDESC)
                                       Marshal.PtrToStructure(elemPtr,
                                                              typeof(ELEMDESC));
                            // Make the return type the last parameter's
                            retType = elemDesc.tdesc;
                            limit--;
                        }
                    }
                    // Only add up to the limit
                    // (may omit the last paremeter)
                    AddDomParams(funcDesc, meth, limit);
                }
                // HRESULT becomes void because its handled by the exception
                // mechanism, we just leave the return type null
                if ((VarEnum)retType.vt != VarEnum.VT_HRESULT)
                {
                    String typeName = TypeLibUtil.TYPEDESCToString
                                          (_typeLib,
                                          _typeInfo,
                                          retType,
                                          !TypeLibUtil.COMTYPE);
                    // Get rid of the ref since this is now a return type
                    if (typeName.StartsWith("ref "))
                    {
                        typeName = typeName.Substring(4);
                    }
                    if (TraceUtil.If(this, TraceLevel.Info))
                    {
                        Trace.WriteLine(this, "CG -  " + Name
                                        + " return: " + typeName);
                    }
                    meth.ReturnType = new CodeTypeReference(typeName);
                }
            }
            else
            {
                CodeMemberProperty prop;
                prop      = new CodeMemberProperty();
                codeDom   = prop;
                prop.Type = new CodeTypeReference
                                (TypeLibUtil.TYPEDESCToString
                                    (_typeLib,
                                    _typeInfo,
                                    funcDesc.elemdescFunc.tdesc,
                                    !TypeLibUtil.COMTYPE));
            }
            codeDom.Name       = Name;
            codeDom.Attributes = MemberAttributes.Public;
            _typeInfo.ReleaseFuncDesc(funcDescPtr);
            return(codeDom);
        }
		protected void AddParams(FUNCDESC funcDesc,
								 String[] names,
								 int paramCount)
		{
			IntPtr elemPtr = funcDesc.lprgelemdescParam;
			for (int i = 0; i < paramCount; i++)
			{
				ELEMDESC elemDesc =
					(ELEMDESC)Marshal.PtrToStructure(elemPtr, 
													 typeof(ELEMDESC));
				ComParamInfo pi = new ComParamInfo
					(names[i + 1],
					 TypeLibUtil.TYPEDESCToString
					 (_typeLib,
					  _typeInfo,
					  elemDesc.tdesc,
					  TypeLibUtil.COMTYPE),
					 elemDesc.desc.paramdesc.wParamFlags);
				_parameters.Add(pi);
				// Point to the next one
				elemPtr = new IntPtr(elemPtr.ToInt64() + 
									 Marshal.SizeOf(elemDesc));
			}
		}